# Build, preview, and check

> Markdown export of the Gearbox Protocol documentation page for agents and retrieval systems.

Canonical page: https://docs.gearbox.finance/developers/build-preview-check
Source file: content/developers/build-preview-check.mdx
Section router: https://docs.gearbox.finance/developers/llms.txt
Section full export: https://docs.gearbox.finance/developers/llms-full.txt

Turn a prepared operation into transaction calldata, assess its projected
effect, and check its prerequisites. Continue here from
[Open](https://docs.gearbox.finance/developers/open-leveraged-position),
[Manage](https://docs.gearbox.finance/developers/manage-position), or
[Delayed withdrawals](https://docs.gearbox.finance/developers/delayed-withdrawals).

Use the already-connected `sdk` and supply the sender's address as `owner`.
No wallet connection or signer is required. The result is a transaction
payload; signing and execution are up to you.

## Build the transaction

Choose the builder for your operation. Each snippet defines `chainId` and
`tx` for the shared preview below. If an operation already produced `tx`,
such as a [quota update](https://docs.gearbox.finance/developers/manage-position#update-quota), skip to
[Preview and check](#preview-and-check) with its `chainId` and `owner`.

### Open a leveraged position

Use `strategy`, `selectedStrategy`, `params`, and the successful `sim` from
[Open](https://docs.gearbox.finance/developers/open-leveraged-position#prepare-the-transaction).
`owner` is the address funding and owning the new Credit Account.

```typescript
const chainId = strategy.chainId;
const targetToken = params.targetToken ?? selectedStrategy.data.targetCollateral.address;
const tx = await sdk.opportunities.execute.buildTx({
  kind: "open",
  chainId,
  creditManager: strategy.creditManager,
  wallet: owner,
  collateral: params.collateral,
  ethAmount: 0n,
  targetToken,
  sim,
});
```

### Update a leveraged position

Use the selected `position` and successful `sim` from an operation in
[Manage](https://docs.gearbox.finance/developers/manage-position) or from
[finalizing a delayed withdrawal](https://docs.gearbox.finance/developers/delayed-withdrawals#claim-and-complete-the-operation).
For a routed operation, pass the chosen route's result, not the two-route
container. Quota updates already produced `tx` and do not use this builder.

```typescript
const chainId = position.chainId;
const tx = await sdk.opportunities.execute.buildTx({
  kind: "account",
  chainId,
  creditAccount: position.creditAccount,
  wallet: owner,
  sim,
});
```

## Preview and check

`previewOperation()` estimates the transaction's effect. `checkOperation()`
checks the operation's prerequisites, including token approvals, balances,
market limits, and the chosen HF thresholds. For an opening or reopening,
it also checks applicable KYC/registration requirements. Neither call signs
or broadcasts a transaction.

```typescript
const preview = await sdk.preview.previewOperation({
  chainId,
  to: tx.to,
  calldata: tx.callData,
  value: BigInt(tx.value),
  sender: owner,
});
if (!preview.ok) throw preview.error;

const issues = await sdk.preview.checkOperation(
  { chainId, preview: preview.data, sender: owner },
  {
    minHealthFactor: 10_500, // Require HF >= 1.05 at main prices (basis points)
    minSafeHealthFactor: 10_500, // Require HF >= 1.05 at safe prices
  },
);
```

These thresholds leave a buffer above the liquidation boundary, HF 1.0.
Choose the buffer for your risk policy; omitting a threshold disables that
check. They are SDK validation settings, not constraints added to the calldata.

## Read the preview result

`preview.ok` means the SDK could produce a preview; it does not mean the
operation passed validation. Read `preview.data.operation` to identify the
result's structure. It describes the decoded transaction, so do not infer
it solely from the preparation method you called.

| `operation` | Meaning |
| --- | --- |
| `"OpenCreditAccount"` | Opening a leveraged position; also used when borrowing again on an existing account with zero debt and no quotas |
| `"AdjustCreditAccount"` | Account adjustment, including quota changes and partial repayments |
| `"RepayCreditAccount"` | Full repayment |
| `"CloseCreditAccount"` | Exit |
| `"DelayedCreditAccountOperation"` | `instantPreview` describes the account after the request; `delayedPreview` is the best-effort result after claiming and resuming the recorded operation. `estClaimableAt` **Optional** is the estimated claimable time in Unix seconds |

For delayed operations, inspect both nested previews. `checkOperation()` checks
only `instantPreview`; it does not validate the future claim. If no intent was
recorded, `delayedPreview` describes the claim alone. Follow
[Delayed withdrawals](https://docs.gearbox.finance/developers/delayed-withdrawals) when it matures.

The fields below are on `preview.data` for immediate operations, or on each
nested preview for a delayed operation. Compare them with the current
leveraged position, if any, and the outcome you requested. For immediate
operations and `instantPreview`, fields prefixed with `est` use the minimum
swap outputs encoded in calldata; preparation reports expected outputs
instead. `delayedPreview` uses oracle-based estimates for future conversions,
so its amounts are not guaranteed swap minimums.

| Field | Type | Meaning |
| --- | --- | --- |
| `creditAccount` **Optional on opening** | `Address \| undefined` | Account affected; when updating a position, check that it matches the selected account |
| `creditManager` | `Address` | Credit Manager identifying the strategy affected |
| `name` | `string` | Strategy name |
| `underlyingToken` | `UnderlyingToken` | Asset used to denominate value and debt; the unwrapped asset for RWA markets |
| `targetCollateral` **Optional on opening** | `TokenAmount \| undefined` | Opening only: target collateral and its balance at minimum swap output; absent when nothing is quoted |
| `targetCollateral` | `Token \| null` | Adjustment, repayment, exit, or delayed request: target token metadata, without a balance |
| `totalDebt` | `TokenAmount` | Debt after the operation, including interest and fees |
| `estTotalValue` | `TokenAmount` | Projected value remaining in the account |
| `estNetValue` | `TokenAmount` | Remaining equity: account value minus debt |
| `estAssets` | `TokenAmount[]` | Projected token balances remaining in the account |
| `quotas` | `TokenAmount[]` | Resulting quotas; each `token` identifies collateral, but `value` is in market underlying base units |
| `estLeverage` | `number` | Resulting leverage as a multiple: `4` means 4× |
| `estHealthFactor` | `number` | HF in basis points: `12500` means 1.25; below `10000` is liquidatable |
| `estSafeHealthFactor` | `number` | HF using safe collateral prices, in the same units |
| `estBorrowRate.base` | `number` | Annual base borrowing cost including the protocol interest fee, in basis points |
| `estBorrowRate.totalOnDebt` | `number` | Annual borrowing cost including quotas, relative to debt, in basis points |
| `estBorrowRate.total` | `number` | Annual borrowing cost including quotas, relative to account value, in basis points |
| `estBorrowRate.quotas` | `TokenQuotaRate[]` | Per-collateral quota cost; each `rate` is in basis points relative to account value |
| `estTimeToLiquidation` | `bigint \| null` | Estimated milliseconds to HF 1 with fixed collateral value and borrowing rate; excludes collateral yield. `null` if debt has no rate or the account is already liquidatable |
| `estLiquidationPrice` | `bigint \| null` | Immediate HF 1 price threshold, in underlying per collateral token scaled by `10 ** 8`; excludes future accrual and quota caps. `null` unless a single non-underlying collateral applies |
| `collateralAdded`, `collateralWithdrawn` | `TokenAmount[]` | Tokens supplied and returned by an opening, adjustment, or repayment; exits report `receivedAmount` instead |
| `totalDebtChange` | `TokenAmount` | Adjustment only: debt after minus debt before; negative means debt was repaid |
| `assetsChange` | `TokenAmount[]` | Adjustment only: token balances after minus balances before |
| `quotasChange` | `TokenAmount[]` | Adjustment only: quotas after minus quotas before, in market underlying base units, with each `token` identifying the collateral |
| `debtRepaid` | `TokenAmount` | Repayment only: positive amount of debt settled |
| `receivedAmount` | `TokenAmount` | Exit only: output returned to the recipient; minimum for an immediate exit, estimated for delayed completion |
| `permanent` | `boolean` | Repayment or exit only: whether the Credit Account is permanently closed; `false` means it remains open |
| `warning` **Optional** | `UnpriceableTokenError` | A token could not be priced and was excluded from valuation; investigate before relying on the value and HF figures |

`TokenAmount` contains `token`, `value` (`bigint` base units), and `valueUsd`
(`number` or `null` when unavailable). Format amounts using their token's
decimals, except `quotas` and `quotasChange`: those use market underlying
decimals even though their token metadata identifies collateral. Rates use
basis points: `520` means 5.2%.

## Resolve validation issues

`issues` is an `OperationValidationError[]`. An empty array means no issues
were found by the applicable checks, not that a transaction was executed or
successfully simulated. Each issue has a machine-readable `code` and an
explanatory `message`; use `code` to access its details. For example,
`insufficientAllowance` includes `owner`, `spender`, `required`, and `allowed`;
`insufficientCollateral` includes `healthFactor`, `healthFactorThreshold`, and
`safePrices`. Review the projected outcome even when `issues` is empty.

Resolve prerequisites, including the approvals described in the action guide.
`insufficientAllowance` is a pre-transaction validation issue, not a failed
transaction. Approval execution belongs to your chosen execution flow.
After an approval confirms or the inputs change, repeat the action's
preparation and build steps, selecting its route if applicable. For a direct
quota transaction, repeat the quota update steps. Preview and check the new
`tx`, then resolve any remaining issues.

## Transaction payload

The output is `tx`, to hand to your chosen execution system:

| Field | Meaning |
| --- | --- |
| `tx.to` | Destination contract |
| `tx.callData` | Encoded calldata; use as `data` in an Ethereum transaction request |
| `tx.value` | Native-token amount in wei; convert with `BigInt(tx.value)` if required by the executor |

Keep `chainId` and `owner` with this payload: they identify the chain and
sender used for the checks. Signing and execution are up to you. If execution
is delayed, prepare, build, and check again. After execution, use
[Monitor](https://docs.gearbox.finance/developers/monitor-position) to read the leveraged position.

## Source

- [Transaction builder](https://github.com/Gearbox-protocol/sdk/blob/93df7583a73ea533dacdc73aa2a9073460d97185/src/sdk/execute/ExecuteApi.ts)
- [Preview result structures](https://github.com/Gearbox-protocol/sdk/blob/93df7583a73ea533dacdc73aa2a9073460d97185/src/model/previews.ts)
- [Operation checks](https://github.com/Gearbox-protocol/sdk/blob/93df7583a73ea533dacdc73aa2a9073460d97185/src/onchain/validation/checkOperation.ts)
