Skip to main content
Closing sells the wallet’s full holding of a basket’s tokens back to USDC. It is balance-driven — whatever of the basket the wallet holds gets closed, exactly what positions.getHoldings reports. There is no amount and no partial close. Both models share this semantics; they differ only in who signs.
Examples on this page move real mainnet funds. Closing sells real holdings on Solana mainnet — test with small amounts first.

Existing Cesto users

When the wallet belongs to a Cesto account holder, the user approves once by signing a message and Cesto closes the position with their Cesto wallet — no per-transaction signing. Same close.start as the managed flow, plus a consent field:
Identical to the open version minus the amount: the approval binds this wallet and this basket, and start resolves as soon as the job is queued. It is never retried automatically — the approval is single-use.
As on the open path, positions.getExecution / waitForExecution cannot see executions started with consent — they are scoped to the issuing API key, and these are recorded against the user. Track the outcome with getHoldings instead.
External wallets that have never used Cesto return delegatedSigning: false and take the BYOW flow above. See Users.

Results, errors, and security

Terminal statuses (COMPLETED, PARTIALLY_COMPLETED, FAILED), partial-completion semantics, the common-error table, and the security model are identical to opening — see Open a Position. Two close-specific notes:
  • A wallet with no holdings of the basket has nothing to sell — check positions.getHoldings(...).hasPosition before preparing a close.
  • A PARTIALLY_COMPLETED close means some legs sold and some didn’t; the remaining holdings are still in the wallet and a fresh close (close.start or close.prepare) will target exactly what’s left.

Rebalancing

To move a position to the basket’s latest version instead of closing it, see Rebalance a Position.