Sponsored Onboarding via Claimable Balances — Architectural Specification

This document provides a detailed architectural specification for the Sponsored Asset Onboarding via Claimable Balances spec. It details the system components, lifecycle phases, transaction flows, API specifications, and security controls required to execute trustless, sponsored, and gasless onboarding on the Stellar network.

1. System Architecture & Actors

The protocol coordinates interactions between four primary actors:

  • Sender: The account initiating the payment (e.g., wallet, centralized exchange, or custodian).
  • Receiver: The recipient of the assets. The Receiver may hold a funded account, an unfunded account (0 XLM), or be represented by a brand-new keypair not yet present on-ledger.
  • Trustline Provider: An always-online service (hosted by the asset Issuer or a third-party fallback service) that sponsors ledger entry reserves (accounts and trustlines) and pays transaction network fees (gas).
  • Stellar Network: The distributed ledger validating and applying the transactions.

2. Core Protocol Pillars & Terminology

To make this architecture accessible, here are the core concepts used throughout the document, explained simply:

  1. Claimable Balances: A feature that lets a Sender safely lock an asset on the network for a Receiver to pick up later.
  2. Sponsored Reserves: On Stellar, every account and trustline requires a small XLM deposit (0.5 XLM). "Sponsorship" means a Trustline Provider pays this deposit on the user's behalf.
  3. Fee-Bump Transactions: A wrapper that allows the Trustline Provider to pay the network gas fees for a user's transaction.
  4. The "Sponsorship Sandwich": A specific sequence of operations where a Provider begins sponsoring, creates the user's account/trustline, and then ends sponsoring. This guarantees the Provider only pays for exactly what they intended.
  5. Channel Accounts: A pool of secondary accounts used by the Provider behind the scenes to submit hundreds of transactions simultaneously without getting traffic jams.

4. Transaction Flow Specifications

4.0. Universal Phase 1: Creation (Transaction 1)

Regardless of the asset type, the Sender initiates the flow by locking the funds.

  • Option A (Self-Funded): The Sender creates the Claimable Balance directly using their own XLM reserve.
  • Option B (Sponsored): The Sender uses the Provider's /onboarding/balance API. The Provider wraps the transaction in a Fee-Bump, sponsors the 0.5 XLM reserve, and collects a Creation Fee. (Operations: Begin Sponsoring → Create Claimable Balance → End Sponsoring → Pay Creation Fee)

4.1. Native Asset Flow (Create_Acct)

Use case: Sending XLM(Native) to a new wallet or an unfunded wallet.

  • Source: Provider (requested via POST /onboarding/build)
  • Fee: Paid by Provider (Fee-Bump)
  • Account: Created with 0.0 XLM starting balance.
  • Operations: [Begin Sponsoring, Create Account(0 XLM), End Sponsoring, Claim Balance, Pay Fee]
📱 Receiver🌐 Stellar Network🏦 Provider💳 Sender📱 Receiver🌐 Stellar Network🏦 Provider💳 Sender"── PHASE 1 · CREATION ──────────────────────────"alt[Option A · Self-Funded][Option B · Sponsored]"── PHASE 2 · DISCOVERY ─────────────────────────""── PHASE 3 · CLAIM ──────────────────────────────""Verify: fee amount · balance ID· no rogue ops in sandwich""CreateClaimableBalance(XLM)Claimants: Receiver[Always] + Sender[+7d]"1"✅ Balance locked · 0.5 XLM reserve on Sender"2"POST /onboarding/balance"3"Signed Tx1 (sponsor wraps creation + Creation Fee payment)"4"Decode, Verify & 🔏 Sign Tx1"5"Submit Tx1 · Provider sponsors 0.5 XLM reserve"6"✅ Balance locked · 0.5 XLM reserve on Provider · Creation Fee paid"7"GET /claimable_balances?claimant={pubkey}"8"📦 Balance ID returned (XLM)"9"POST /onboarding/build (Receiver, Balance ID)"10"Unsigned Tx2 ([Sponsor] → CreateAccount(0 XLM) → [EndSponsor]→ ClaimBalance → PayFee(Claim Fee))"11"Decode, Verify & 🔏 Sign Tx2 (sig 1 of 2)"12"POST /onboarding/claim · Tx2 XDR"13"Co-sign + wrap in Fee-Bump Tx"14"Fee-Bump XDR (Provider pays gas)"15"Submit Fee-Bump Tx"16"✅ Account created · Balance claimed · Fee paid"17

4.2. Unregulated Asset Flow (Create_trustline)

Use case: Sponsoring trustline for an existing account/wallet.

  • Source: Provider (requested via POST /onboarding/build)
  • Fee: Paid by Provider (Fee-Bump)
  • Operations: [Begin Sponsoring, Change Trust, End Sponsoring, Claim Balance, Pay Fee]
📱 Receiver🌐 Stellar Network🏦 Provider💳 Sender📱 Receiver🌐 Stellar Network🏦 Provider💳 Sender"── PHASE 1 · CREATION ──────────────────────────"alt[Option A · Self-Funded][Option B · Sponsored]"── PHASE 2 · DISCOVERY ─────────────────────────""── PHASE 3 · CLAIM ──────────────────────────────""Verify: fee amount · trustline asset· balance ID · no rogue ops""CreateClaimableBalance(USDC)Claimants: Receiver[Always] + Sender[+7d]"1"✅ Balance locked · Reserve held on Sender"2"POST /onboarding/balance"3"Signed Tx1 (sponsor wraps creation + Creation Fee payment)"4"Decode, Verify & 🔏 Sign Tx1"5"Submit Tx1 · Provider sponsors USDC reserve"6"✅ Balance locked · Reserve held on Provider · Creation Fee paid"7"GET /claimable_balances?claimant={pubkey}"8"📦 Balance ID returned (USDC)"9"POST /onboarding/build (Receiver, Balance ID)"10"Unsigned Tx2 ([Sponsor] → ChangeTrust(USDC) → [EndSponsor]→ ClaimBalance → PayFee(Claim Fee in USDC))"11"Decode, Verify & 🔏 Sign Tx2 (sig 1 of 2)"12"POST /onboarding/claim · Tx2 XDR"13"Co-sign + wrap in Fee-Bump Tx"14"Fee-Bump XDR (Provider pays gas)"15"Submit Fee-Bump Tx"16"✅ Trustline sponsored · USDC claimed · Fee paid"17

4.3. Unregulated Asset Flow (Create_acct_trustline)

Use case: Sponsoring both account reserves and asset trustline for a new receiver (unfunded or unfunded with new keypair).

  • Source: Provider (requested via POST /onboarding/build)
  • Fee: Paid by Provider (Fee-Bump)
  • Account: Created with 0.0 XLM starting balance.
  • Operations: [Begin Sponsoring, Create Account(0 XLM), Change Trust, End Sponsoring, Claim Balance, Pay Fee]
📱 Receiver🌐 Stellar Network🏦 Provider💳 Sender📱 Receiver🌐 Stellar Network🏦 Provider💳 Sender"── PHASE 1 · CREATION ──────────────────────────"alt[Option A · Self-Funded][Option B · Sponsored]"── PHASE 2 · DISCOVERY ─────────────────────────""── PHASE 3 · CLAIM ──────────────────────────────""Verify: account + trustline in sandwich· fee amount · balance ID · no rogue ops""CreateClaimableBalance(USDC)Claimants: Receiver[Always] + Sender[+7d]"1"✅ Balance locked · 0.5 XLM reserve on Sender"2"POST /onboarding/balance"3"Signed Tx1 (sponsor wraps creation + Creation Fee payment)"4"Decode, Verify & 🔏 Sign Tx1"5"Submit Tx1 · Provider sponsors 0.5 XLM reserve"6"✅ Balance locked · 0.5 XLM reserve on Provider · Creation Fee paid"7"GET /claimable_balances?claimant={pubkey}"8"📦 Balance ID returned (USDC)"9"POST /onboarding/build (Receiver, Balance ID)"10"Unsigned Tx2 ([Sponsor] → CreateAccount(0 XLM)→ ChangeTrust(USDC) → [EndSponsor]→ ClaimBalance → PayFee(Claim Fee in USDC))"11"Decode, Verify & 🔏 Sign Tx2 (sig 1 of 2)"12"POST /onboarding/claim · Tx2 XDR"13"Co-sign + wrap in Fee-Bump Tx"14"Fee-Bump XDR (Provider pays gas)"15"Submit Fee-Bump Tx"16"✅ Account + Trustline sponsoredUSDC claimed · Fee paid to Provider"17

4.4. Regulated Asset Flow (AUTH_REQUIRED)

Use case: Onboarding a new wallet to receive regulated assets (e.g., regulated stablecoins, CBDCs) that require explicit issuer authorization. This flow assumed the wallet is new and unfunded. Not wallet with exisiting balance.

Because regulated assets require the Receiver to be authorized by the issuer before they can hold the token, the flow diverges from unregulated assets. Architectural Rule: For regulated assets, the Issuer must support this flow and act as the Trustline provider for their own assets (or an explicitly authorized delegate). A generic third-party provider cannot handle regulated assets because they cannot collect the regulated token as a fee, nor can they safely sponsor reserves prior to KYC (which risks permanent capital lockup if the user abandons the KYC process).

This requires an "Off-Chain First" Atomic Flow.

Off-Chain Approval & Atomic Claim

  1. Detection: When the wallet discovers the pending Claimable Balance, it queries the Horizon GET /accounts/{Issuer} endpoint. If the Issuer account has the auth_required flag set to true, the wallet knows this is a regulated asset.
  2. Off-Chain Approval: The wallet directs the user to complete the Issuer's KYC process. The user authenticates with their unfunded public key using a cryptographic challenge-response (e.g., standard SEP-10 Web Authentication or a similar method supported by the Issuer). This proves ownership of the private key without requiring the account to exist on the ledger. The Issuer approves the keypair in their database. Zero XLM is locked or spent on-ledger during this phase.
  3. Sponsored Claiming (Transaction 2): Once approved off-chain, the wallet requests POST /onboarding/build. The Provider (Issuer) verifies the keypair, builds the atomic transaction, and injects the Set Trust Line Flags operation to authorize the trustline.
    • Operations: [Begin Sponsoring, Create Account, Change Trust, Set Trust Line Flags(Authorize), End Sponsoring, Claim Balance, Pay Fee]
🏦 Provider (Issuer)📱 Receiver Wallet🌐 Stellar Network💳 Sender🏦 Provider (Issuer)📱 Receiver Wallet🌐 Stellar Network💳 Sender"── PHASE 1 · CREATION ──────────────────────────""── PHASE 2 · DETECTION & OFF-CHAIN KYC ───────""── PHASE 3 · ATOMIC CLAIM ───────────────────""Verify: off-chain approval · fee · no rogue ops""Create Regulated Balance (Option A or B)"1"Signed Tx1"2"Submit Tx1"3"✅ Balance locked"4"GET /claimable_balances?claimant={pubkey}"5"📦 Balance ID returned (Regulated Token)"6"GET /accounts/{Issuer}"7"auth_required = true"8"Initiate Off-Chain KYC (using unfunded pubkey)"9"✅ Approved in off-chain database (0 XLM spent)"10"POST /onboarding/build (Receiver, Balance ID)"11"Unsigned Tx2 ([Sponsor] → CreateAccount → ChangeTrust→ SetTrustLineFlags(Authorize) → [EndSponsor]→ ClaimBalance → PayFee)"12"Decode, Verify & 🔏 Sign Tx2 (sig 1 of 2)"13"POST /onboarding/claim · Tx2 XDR"14"Co-sign + wrap in Fee-Bump Tx"15"Fee-Bump XDR"16"Submit Fee-Bump Tx"17"✅ Authorized & Claimed atomically"18

5. Trustline Provider API Specifications

5.1. POST /onboarding/balance

Constructs and signs the sponsored reserve creation transaction (Transaction 1, Option B).

  • Headers: Content-Type: application/json

  • Request Body:

    {
      "sender_public_key": "G...",
      "receiver_public_key": "G...",
      "assetCode": "USDC",
      "assetIssuer": "GBBD47...",
      "amount": "100.0000000"
    }

    Note on Native Assets: For native Stellar Lumens (XLM), the "assetCode" should be "XLM" and the "assetIssuer" field should be omitted or set to null.

    {
      "sender_public_key": "G...",
      "receiver_public_key": "G...",
      "assetCode": "XLM",
      "amount": "100.0000000"
    }
  • Response Body (200 OK):

    {
      "transaction_xdr": "AAAAA...",
      "fee_charged": "0.0100000"
    }

5.2. POST /onboarding/build

Constructs the unsigned claim transaction (Transaction 2) sourced by the Provider. The Provider dynamically checks the Receiver account status (whether it exists or needs a trustline) and adds the appropriate reserve sponsorship, account creation, change trust, and claimable balance claim operations along with the fee payment operation back to the Provider.

  • Headers: Content-Type: application/json
  • Request Body:
    {
      "receiver_public_key": "G...",
      "balance_id": "00000000...",
      "asset_code": "USDC",
      "asset_issuer": "GBBD47..."
    }
  • Response Body (200 OK):
    {
      "transaction_xdr": "AAAAA...",
      "fee_charged": "1.5000000"
    }

5.3. POST /onboarding/claim

Co-signs the claim transaction (Transaction 2) and wraps it inside a Fee-Bump Transaction.

  • Headers: Content-Type: application/json
  • Request Body:
    {
      "transaction_xdr": "AAAAA..."
    }
  • Response Body (200 OK):
    {
      "transaction_xdr": "AAAAA..."
    }

5.4. POST /onboarding/relay

Use case: A user was onboarded with 0.0 XLM and only holds a sponsored token (e.g., USDC). They cannot natively pay gas fees for future network transactions. This flow allows them to relay transactions through the Provider. The Provider fee-bumps the transaction and recovers gas costs in the token being sent.

Prerequisite: GET /onboarding/info

Before constructing a relayed transaction, the wallet must dynamically fetch the Provider's configuration to determine the exact provider_public_key (the destination for the relayer fee) and the specific fee amount required for the asset.

  • Response Body (200 OK):
    {
      "provider_public_key": "G...",
      "whitelisted_assets": [
        {
          "asset_code": "USDC",
          "asset_issuer": "GBBD47...",
          "fee": "0.0200000"
        }
      ]
    }

Relayed Transaction Flow

  • Transaction Sourcing: Sourced by the Receiver (using their own sequence number).
  • Wrapped in a Fee-Bump Transaction (Source: Provider, Fee: Gas).
  • Operations:
    1. [User's Desired Operation] (e.g., Payment to an external address)
    2. Payment (Source: Receiver, Destination: Provider, Asset: AssetCode:Issuer, Amount: [Relay Fee])
🌐 Stellar Network🏦 Provider📱 Receiver (0 XLM)🌐 Stellar Network🏦 Provider📱 Receiver (0 XLM)"── PHASE 4 · RELAY (FUTURE TRANSACTIONS) ──────────""Verify: fee amount · token type""Build Tx: [Desired Ops] + [PayFee(Relay Fee in Token)]"1"🔏 Sign Tx (Receiver Sequence2"POST /onboarding/relay · Signed Tx XDR"3"Wrap in Fee-Bump Tx & Sign"4"Submit Fee-Bump Tx"5"✅ Transaction successful"6"200 OK (Confirmed)"7

API Spec

  • Headers: Content-Type: application/json
  • Request Body:
    {
      "transaction_xdr": "AAAAA..."
    }
  • Response Body (200 OK):
    {
      "status": "success",
      "transaction_hash": "e9a8f..."
    }

5.5. Standard Error Responses (4xx/5xx)

If any of the validation rules fail (see Section 6) or if the Provider encounters an internal error (e.g., out of XLM treasury), the API will return a standard JSON error response:

  • Response Body (400 / 403 / 500):
    {
      "error": "error_code",
      "message": "Human readable description of the error."
    }

Common Error Codes:

  • invalid_transaction: The XDR contains rogue operations or is improperly formatted.
  • invalid_signature: The provided signatures are invalid for the source account.
  • insufficient_fee: The Payment operation for Creation Fee or Claim Fee is too low or missing.
  • asset_not_supported: The requested asset is not whitelisted by the Provider.
  • rate_limit_exceeded: The Sender has requested too many sponsored creations.
  • treasury_depleted: (500) The Provider is currently out of XLM to sponsor reserves or gas.

6. Security Architecture & Validation Rules

To maintain trustless operations and protect both Sender and Provider accounts, the following validation rules must be enforced:

6.1. Validation Matrix

To maintain trustless operations, the three actors MUST verify the following before signing:

Verifier Sandwich Checked Fee Checked Specific Rule
Sender Begin SponsoringCreate BalanceEnd Sponsoring Matches quoted Creation Fee Claimants are Receiver (Always) + Sender (>7 Days). No rogue ops.
Receiver Contains only Create Account/Change Trust Matches quoted Claim Fee Starting balance is exactly 0.0 XLM. No rogue ops.
Provider Exact sequence as requested Matches Claim Fee paid to Provider Receiver signatures valid. Balance ID is valid. No rogue ops.

6.2. Key Security Principles

  • Spam Prevention: Provider API strictly whitelists supported assets (e.g., USDC, EURC) to prevent locking reserves for worthless tokens.
  • Treasury Lockup Protection: Charging a Creation Fee during Option B eliminates zero-cost spam attacks that could exhaust the Provider's XLM treasury.
  • Scaling: Providers MUST use a pool of "Channel Accounts" to source transactions concurrently to avoid sequence number bottlenecks.
  • Regulated Assets: Generic third-party Providers CANNOT sponsor regulated trustlines; the Issuer must act as the Provider via the Off-Chain Atomic Flow to avoid capital lockups during failed KYC. Additionally, during Phase 1, 3rd-party providers cannot use Option B (Sponsored Creation) for regulated assets because they cannot legally hold the regulated token to collect the Creation Fee. Senders must either use Option A or use the Issuer as the Provider.
  • No Lock-in: For unregulated assets, Senders and Receivers can use completely different Trustline Providers since the protocol relies exclusively on native on-chain state (Claimable Balances). Note: This is not the case for regulated assets, where both Sender and Receiver are locked into using the specific Issuer (or their authorized delegate) as the Trustline Provider to handle KYC and authorization flags.