Call a write three ways
Each write method takes the same three shapes. The shape decides how much of the work the SDK does.
Without options a write returns the plan and does nothing else. A plan is either one transaction (
action: 'SIGN_TRANSACTION' with transaction) or ordered steps (action: 'SIGN_TRANSACTIONS' with steps).
{ signer } the SDK signs every step in order, waits for each to mine on the signer’s own provider, and confirms with the hash of the step the API names. The result carries transactions, one entry per step sent.
{ txHash } the SDK only confirms a transaction you broadcast yourself. See confirm a transaction you broadcast.
What the SDK checks before it signs
The SDK reads the instance’s chain from the API once per client. It refuses a signer connected to another chain before it sends a single request, with aValidationError naming both chains. It never switches networks. A plan that names a different chain than the instance is refused with CHAIN_MISMATCH before anything is signed.
A field that names the signing wallet is filled from the signer when you omit it, and refused when it names another wallet. The fields are payer, borrowerAddress, provider, holderAddress, signerAddress, fromAddress and bidder. The API checks balances, allowances and roles against that field, so it has to be the wallet that signs.
Where a write needs a role or an owner that the market can report, the SDK reads it before signing and refuses when the signer lacks it:
bots.connectandbots.disconnectneed the bot owner and the market admin.operators.setAccessRoleandoperators.setLiquidatorRoleneed the market admin or the router admin, by role, and the oracle owner forORACLE_SIGNER.- The
ratessettings and extension steps need the interest model owner, the market issuer or the market admin, as the prepared response names. auctions.wireModuleneeds the market admin and the router admin, and refuses outright when the plan holds a step only the token’s agent can sign.insurance.withdrawneeds the fund owner.
ROLE_UNREADABLE or FUND_OWNER_UNREADABLE with status 503. That is an unread role, not a missing one. Retry shortly.
The signer must expose getAddress and getChainId, and _signTypedData or signMessage for the writes that sign a message. Every ethers v5 Signer does.
How a plan runs
Steps run strictly in order. Each step waits forconfirmations blocks on the signer’s own provider, 1 by default and at most 12, before the next one starts.
confirmStepIndex. Without it the SDK confirms the last step that is not optional. An optional step, such as clearing a leftover allowance after a full repayment, never blocks the confirm. Its failure is recorded in transactions with an error, and the write still succeeds.
The SDK forwards to, data, value, chainId and the API’s gasLimit exactly. Where the API sends no gasLimit and the signer can estimate gas, the SDK sets the limit to 1.5 times the signer’s own estimate. It adds nothing else to a transaction.
A step can be a contract creation with no to, as in the auction venue wiring, and it runs like any other step. A transaction your wallet speeds up counts under the replacement’s hash when the replacement succeeds.
The SDK broadcasts the calldata the API returned without decoding it. If your controls require it, prepare without a signer, decode to and data in your own pinned code, and sign only what you checked.
Writes that sign a message
Some writes sign typed data or a message instead of, or before, a transaction. With{ signer } the SDK handles both parts.
A
markets.configure step that verifies a holder on the token’s registry comes back as a holder onboarding plan. It signs claims and registers identities from the onboarding wallet, so the SDK refuses it with a signer. Prepare it, run the plan from that wallet, and confirm the registration with { txHash }.
Writes with no confirm leg
Six writes change chain state that the API reads back from the chain on the next read. They have no confirm leg, so nothing is recorded and{ txHash } is refused. With { signer } they return only transactions.
operators.nominateandoperators.withdrawNominationliquidity.setVaultLiquidity,liquidity.registerVaultandliquidity.deregisterVaultinsurance.withdraw
auctions.wireModule has no confirm leg either. With { signer } it returns transactions and the moduleAddress of the venue it wired or deployed.
Confirm a transaction you broadcast
Prepare the write, broadcast its steps in order from any wallet, and confirm with the hash of the step the plan names.execTransaction, an ERC-4337 bundle, or the execute call of a smart account, including an EIP-7702 account.
A repayment in mode: 'batch' is one atomic bundle for a wallet that supports wallet_sendCalls. The SDK refuses it with a signer. Prepare it, send the bundle from that wallet, and confirm with the hash of the bundle transaction.
Finish a write that stopped halfway
When a step fails after an earlier step went out, or every step mined but the confirm could not be recorded, the SDK throwsConfirmationError. Its code is TRANSACTION_FAILED in the first case and CONFIRMATION_FAILED in the second. transactions lists every step with its hash, and txHash is the hash to confirm.
When the first signature is rejected and nothing was sent, the SDK rethrows the wallet’s own error untouched.
TRANSACTION_FAILED, check the market before you decide anything. An earlier step, usually an approval, is on chain, but the write itself is not.
The SDK retries a confirm by itself in two cases. A confirm answered TX_NOT_FOUND means the API cannot see the receipt yet, so the SDK asks again after 3, 6 and 12 seconds. A confirm that met an outage (408, 502, 503, 504 or a dropped connection) is retried with backoff, because the API records one mined transaction once.
Four confirms are sent once and never retried, because the API does not record them idempotently. They are the confirm of bots.deploy, and liquidations.withdrawCollateralForSale, liquidations.reportPartialSale and liquidations.handleTimeout. When one of these fails ambiguously, read the bot or the liquidation before you confirm again.
Rate limits
Every lending write route and every statement download shares a limit of 10 requests per minute per API key, the build and the confirm alike. On a429 the SDK waits as long as the server’s Retry-After says, at most 60 seconds, then sends the request again. A burst of writes therefore waits rather than fails. See Lending errors for the full retry rules.