Nonces, retries and refunds
Credits are debited when the action is created, not when it is signed. So:
- Persist the nonce before prompting for a signature — use
onNonce. - Never re-create an action to retry. That debits again. Poll instead:
await turbo.getArNSActionStatus(nonce). - An abandoned action refunds itself — don't build a refund flow.
- Replaying
signArNSActionon a completed action returns{ alreadyCompleted: true }rather than buying twice.
InsufficientCreditsError (HTTP 402) is thrown when the balance is short;
prompt a top-up, then create a fresh action.
The owner has about 30 seconds to sign. Solana accepts the transaction
Turbo builds for only about 30 seconds after the action is created, so prompt
the owner straight away. expiresAt is not that deadline: it is the
~15-minute point at which an uncompleted action is refunded.
signArNSAction throws ArNSActionExpiredError (a FailedRequestError, with
nonce, status and creditsReleased) when the signature arrived too late:
a 409, or a 400 reading Action \<nonce\> expired.... creditsReleased is
true when the service has already returned the credits, and false when
they are held until the ~15-minute refund. Either way, create a new
action if the change is still wanted.
A 503 Blockhash not found is different: the service could not prove the
transaction expired. Re-post the same signed bytes to signArNSAction
rather than creating a new action; a resubmission is idempotent.
/sign needs no payer signature: the owner's signature inside the
transaction authorises it, and the credits were debited at create. So
signArNSAction sends no payer headers by default. Its optional third
argument, headers, is for a service that requires them.
How is this guide?