nora

Burn signing

Sign the SPL Approve that lets Nora burn BRS from the user's wallet, broadcast it on Solana, and submit the signature back via /v2/intents/:id/approve-burn.

Creating an offramp intent leaves it in status: awaiting_burn_approval. To complete the offramp, your user's Solana wallet has to sign an SPL Token Approve instruction that grants Nora's burn authority delegate rights over the exact amount being redeemed. You broadcast that transaction from the client and submit the resulting txSignature back to Nora along with the token-holder's ATA address.

The /v2 endpoint that accepts the submission is:

POST /v2/intents/:id/approve-burn

Gap in the current public contract

The public /v2 response does not currently return the SPL Approve construction details — the BRS mint address, the delegate authority public key, and the amount to approve in token minor units. Integrators today must obtain those values out of band (from the Nora team or from the dashboard) until a future /v2 revision embeds them in the intent response. Plan for this to be documented here once it ships.

Flow

Loading diagram…

Steps

  1. Offramp intent has been created. You have an intentId and the intent's status is awaiting_burn_approval. See Offramp intent.

  2. Obtain the Approve construction parameters. Until the /v2 response embeds them, coordinate with the Nora team for:

    • the BRS SPL mint address,
    • the delegate authority public key (Nora's burn authority),
    • the amount to approve in token minor units (derived from amountCents × 10^decimals).
  3. Client-side: construct + sign + broadcast SPL Approve. Build an SPL Token Approve instruction that grants the delegate rights over the exact amount on the user's associated token account (ATA) for the BRS mint. Sign with the party's Solana wallet. Broadcast to Solana and collect the txSignature the network returns.

  4. Submit the signature. POST /v2/intents/:id/approve-burn with { txSignature, tokenHolder }. tokenHolder is the user's ATA for the BRS mint. The intent advances to burn_approved and the offramp continues.

    Idempotency note. txSignature is the idempotency key for this endpoint. Resubmitting the same signature is accepted and returns the same result; a different signature against the same intent is rejected. There is no separate idempotency-key header here — see Idempotency.

Client outline

The library-agnostic shape is:

// 1. Obtain mint, delegate, and amount out-of-band for now; see Gaps above.
// 2. Build an SPL Approve instruction on the user's ATA for the BRS mint.
// 3. Sign with the user's wallet (adapter-specific).
// 4. Broadcast with your Solana RPC client and capture txSignature.
// 5. POST the signature + the ATA address to Nora.

Then submit to Nora:

curl -X POST "https://staging.api.nora.finance/v2/intents/$INTENT_ID/approve-burn" \
  -H "X-API-Key: $NORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "txSignature": "5h2...",
    "tokenHolder": "FgC...<ATA address>"
  }'

Response:

{ "status": "burn_approved" }

That single field is the entire body — no id, no echo of the intent. Re-fetch GET /v2/intents/:id to observe subsequent state transitions.

Request schema

POST /v2/intents/:id/approve-burn

Path parameter: id (uuid).

Body:

FieldTypeRequiredNotes
txSignaturestringYesBase58-encoded signature from the broadcast SPL Approve transaction. Min length 1.
tokenHolderstringYesThe user's associated token account address for the BRS mint. 32–44 chars.

Errors follow the intents-family envelope { code, message, validationErrors?, details? }:

  • 400 — body validation, signature rejected, wrong signer / amount.
  • 404 — intent not found.

Recovery if the user reloads

Between broadcast and submit is the risky gap. Persist { intentId, tokenHolder, txSignature } in durable client storage as soon as sendRawTransaction returns. On resume, re-run POST /v2/intents/:id/approve-burn with the stored values — the server dedups on txSignature, so the user does not need to sign again.

Notify-side failure modes

If the transaction lands on Solana but the approve-burn call never succeeds and the user abandons the flow, the delegate allowance stays on their ATA. This is a deliberate trade-off:

  • The allowance is scoped to the exact amount of that intent.
  • Only Nora's burn authority can exercise it.
  • Revoking it would require another wallet signature on a failure path.

Your app doesn't need to clean it up. A later offramp creates a fresh Approve for its own amount.

Gotchas

  • Amount is in token minor units. The value you pass into createApproveInstruction must be the raw on-chain amount (BRL cents × 10^decimals of the BRS mint). Do not pass amountCents directly.
  • User-rejected signatures should be treated distinctly. Wallet adapters throw with messages containing "rejected", "declined", "cancelled", or "user denied". Surface "try again" copy, not a generic error.
  • No idempotency-key header. approve-burn dedups on txSignature. Sending a header is not an error, but it is not used.

See also

On this page