Open
A user deposits tokens and borrows more. The combined funds are then swapped into the strategy’s target collateral token, which is held in their Credit Account.
Connect SDK
Follow Connect SDK first. All code below uses the
already-connected instance as sdk.
Find available strategies
Start by listing the strategies on the chains configured in the SDK:
const strategies = await sdk.opportunities.list({ kind: "strategy" });
The response contains the strategy list in data
and per-chain read status, source, block, and timestamp in meta.chains.
Check that metadata before presenting a chain's list as current. A failed read
does not mean the chain has no strategies.
Each strategy is identified by { chainId, creditManager }. Use that key
for the user's selection. An app URL ending in
/earn/strategy/<chainId>/<creditManager> supplies the same key.
Being listed does not guarantee that a particular wallet or deposit can open the strategy. Check the selected strategy's status, eligibility requirements, and available capacity next.
Understand the selected strategy
Let the user choose an entry from strategies.data, then use that entry's
chain ID and Credit Manager to read its details. Here, selectedIndex is the
index chosen in your application's strategy list:
import type { StrategyOpportunity } from "@gearbox-protocol/sdk/model"; const selectedIndex = 0; // Replace with the user's selection const strategy = strategies.data[selectedIndex] as StrategyOpportunity; const selectedStrategy = await sdk.opportunities.getStrategy({ chainId: strategy.chainId, creditManager: strategy.creditManager, });
selectedStrategy.data contains a StrategyOpportunityDetail. The fields
relevant to opening a position are:
| Field | Type | Meaning |
|---|---|---|
chainId | number | Chain where the strategy exists |
creditManager | Address | Credit Manager address identifying the strategy on that chain |
name | string | Strategy display name |
underlyingToken | UnderlyingToken | Asset used to denominate borrowing and the amounts below; for RWA markets, the unwrapped asset |
targetCollateral | Token | Token bought with the combined deposit and borrowed funds |
allowedDepositTokens | Token[] | Tokens the user can deposit from their wallet |
minDebt | Amount | Minimum debt a position may hold |
maxBorrowAmount | Amount | Current maximum borrowing for a new position, accounting for liquidity and debt limits |
availableLiquidity | Amount | Free liquidity in the lending pool |
totalDebtLimit | Amount | Borrowing cap shared by all accounts in this Credit Manager |
maxLeverage | number | Maximum leverage as a multiple: 4 means 4×, unlike the opening input 400n |
collateralApy | ApyBreakdown | undefined | Collateral yield before leverage, supplied by the backend; may be unavailable and is absent in onchain-only mode |
collateralApy.organicApy | number | Yield excluding incentives, in basis points: 610 means 6.10%; available when collateralApy is present |
collateralApy.totalApy | number | undefined | Yield including incentives, in basis points |
collateralApy.rewards | Rewards[] | undefined | Incentive breakdown, including points programs that may have no APY |
borrowApy | number | Annual borrowing cost in basis points, including the protocol interest fee; 520 means 5.2% |
quotaRate | number | Annual quota cost for the target collateral in basis points, including the protocol interest fee |
liquidationThreshold | number | Target collateral's value counted toward solvency before the quota cap, in basis points: 9000 means 90% |
liquidationPremium | number | Share of liquidated account value paid to the liquidator, in basis points |
liquidationFee | number | Share of liquidated account value taken by the protocol, in basis points |
paused | boolean | Whether the Credit Facade or lending pool is paused |
sunset | boolean | Whether the strategy is being wound down and should no longer be entered |
expirationDate | number | null | Credit Facade expiry as a Unix timestamp in seconds, or null if it does not expire |
kyc | KycRequirement | null | undefined | Strategy registration requirements; null means no KYC gate, undefined means unavailable. This is not a wallet eligibility result |
Token includes address, symbol, and decimals. Amount.value is a
bigint in underlyingToken base units; Amount.valueUsd is a dollar value
or null when unavailable. Check selectedStrategy.meta.chains for the
source, block, timestamp, and read status.
The deposit token and target collateral token serve different purposes. The user supplies the deposit token from their wallet; the combined deposited and borrowed funds buy the strategy's configured target collateral token.
Choose opening parameters
Pass the selected strategy and an OpenStrategyParams object to
sdk.opportunities.prepare.openNewStrategy().
| Field | Type | Meaning |
|---|---|---|
collateral[].token | Address | Deposit token address, selected from allowedDepositTokens |
collateral[].balance | bigint | Deposit amount in that token's base units |
leverage | bigint | Requested leverage in hundredths of a multiple: 250n = 2.5×, 400n = 4× |
slippage | number | Swap slippage tolerance in basis points: 5 = 0.05%, 50 = 0.5% |
targetToken | Address | undefined | Optional target token; defaults to the selected strategy's target collateral |
These are SDK fields. The snippet below uses the user's selected deposit token, amount, leverage, and slippage from your application's form. Convert the amount to base units with the deposit token's decimals.
Prepare the transaction
import type { OpenStrategyParams } from "@gearbox-protocol/sdk"; import { parseUnits } from "viem"; const params: OpenStrategyParams = { collateral: [{ token: depositToken.address, balance: parseUnits(depositAmount, depositToken.decimals), }], leverage, slippage, quotaReserve: 100, // Optional: 1% extra quota }; const sim = await sdk.opportunities.prepare.openNewStrategy(strategy, params); if (!sim.ok) throw sim.error;
Validate form inputs before converting them: the amount must be positive and fit the token's decimals; leverage and slippage must use the units above. The SDK calculates borrowing, routing, and the resulting position. If preparation fails, display its error instead of building a transaction.
sim.data.state contains the projected position, including totalDebt,
totalValue, netValue, leverage, health factor, and borrowing cost. The
amounts include their token metadata and use that token's base units.
sim.data.blockNumber and sim.data.timestamp identify the state used for
preparation. The projected leverage can differ from the requested multiple
after fees and price impact.
Resolve the approval spender
For a new Credit Account, owner is the address that will fund and own the
leveraged position. Supply it directly; no wallet connection is needed.
Resolve its approval spender:
const spender = await sdk.onchain .chain(strategy.chainId) .accounts.getApprovalAddress({ creditManager: strategy.creditManager, borrower: owner, });
For each ERC-20 in params.collateral, check its allowance from owner to
spender. If it is below balance, the required approval is
approve(spender, balance) on that token, sent by owner. balance is the
deposit amount in the token's base units. Approve only your deposit, not the
borrowed amount or total leveraged position. Approval execution belongs to
your chosen execution flow.
Build, preview, and check
Continue with strategy, selectedStrategy, params, the successful sim,
and owner in
Build, preview, and check.
That page covers transaction construction, preview fields, validation issues,
and the payload to pass to your chosen execution system.
Next steps
Continue with Monitor to read the Credit Account and Manage to change it.