Settlement to Stellar Contracts

For Merchants With Smart Contracts on Stellar: Learn How to Enable Settlement to a Soroban Contract.

Overview

On-chain merchants with custom Soroban contract logic can choose to settle directly to a smart contract on the Stellar network. Coinflow requires these merchants to pass a transaction to our system as a base64-encoded XDR string. The following section explains how merchants can construct and submit a transaction compatible with their Soroban contracts.

How It Works

When a customer makes a purchase on Stellar, Coinflow’s checkout contract executes a mint_and_redeem call that:

  1. Approves USDC — The Coinflow checkout contract approves a USDC allowance to your merchant contract based on the purchase subtotal
  2. Invokes your contract — Coinflow calls your merchant contract’s function with the parameters you specified in the transaction
  3. Your contract transfers USDC — Your merchant contract uses transfer_from to move USDC from the Coinflow contract to your treasury

This means your merchant contract receives a USDC allowance and is responsible for pulling the funds using the Soroban token transfer_from function.

Stellar checkout does not support Credits settlement or partial purchases where the customer contributes their own USDC alongside a credit card payment.

Specifying the Transaction

Pass your Soroban contract invocation as a base64-encoded XDR string in the stellarTransaction field. Coinflow will automatically extract the contract address, function name, and arguments from your transaction.

Step 1: Generate TypeScript Bindings

Use the Stellar CLI to generate TypeScript bindings for your Soroban contract:

$# Use --network mainnet for production
$stellar contract bindings typescript \
> --network testnet \
> --contract-id YOUR_CONTRACT_ID \
> --output-dir ./your-contract-client

This generates a typed TypeScript client you can use to build transactions.

Step 2: Build the Transaction

Use the generated client to build a transaction that invokes your contract function:

1import {YourContractClient} from './your-contract-client';
2
3const client = new YourContractClient({
4 contractId: 'YOUR_CONTRACT_ID',
5 networkPassphrase: 'Test SDF Network ; September 2015', // Mainnet: 'Public Global Stellar Network ; September 2015'
6 rpcUrl: 'https://soroban-testnet.stellar.org', // Mainnet: use your Soroban RPC provider
7 publicKey: sourceAccountPublicKey,
8});
9
10const tx = await client.your_purchase_function({
11 usdc: 'CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA', // Stellar USDC contract
12 payer: 'CA6F7DX4RBZLENHGLPPTGQA4CRNNH3U6QJ3KD7HQLN46YENHTWJRZUOH', // Coinflow checkout contract
13 recipient: customerWalletAddress,
14});

Step 3: Convert to Base64 XDR

Convert the assembled transaction to a base64-encoded XDR string:

1const stellarTransaction = tx.toXDR();
2// Returns: "AAAAAgAAAABh...(base64 XDR string)..."

Step 4: Pass to Coinflow

Pass the XDR string as stellarTransaction in your checkout request:

1// React SDK
2<CoinflowPurchase
3 wallet={stellarWallet}
4 merchantId="your-merchant-id"
5 env="sandbox"
6 blockchain="stellar"
7 transaction={stellarTransaction}
8 subtotal={{ cents: 500, currency: 'USD' }}
9/>

Or via the API:

1{
2 "subtotal": { "cents": 500, "currency": "USD" },
3 "blockchain": "stellar",
4 "stellarTransaction": "AAAAAgAAAABh...(base64 XDR)..."
5}

Merchant Contract Requirements

Your Soroban smart contract function should follow this pattern:

  1. Accept payer (the Coinflow checkout contract address) and recipient (the customer’s wallet) as parameters
  2. Use the Soroban token client’s transfer_from to pull USDC from the Coinflow contract
  3. Deliver the purchased item to the recipient

Example: NFT Purchase Contract (Rust)

1use soroban_sdk::{contract, contractimpl, token, Address, Env};
2
3#[contract]
4pub struct MerchantContract;
5
6#[contractimpl]
7impl MerchantContract {
8 pub fn purchase_item(
9 e: &Env,
10 usdc: Address, // USDC token contract address
11 payer: Address, // Coinflow checkout contract (pays USDC)
12 recipient: Address, // Customer wallet (receives the item)
13 ) -> u32 {
14 let price = Self::get_price(e);
15
16 // Pull USDC from Coinflow contract to your treasury
17 let usdc_client = token::Client::new(e, &usdc);
18 usdc_client.transfer_from(
19 &e.current_contract_address(), // spender: your contract
20 &payer, // from: Coinflow contract
21 &Self::get_treasury(e), // to: your treasury
22 &price, // amount: item price
23 );
24
25 // Deliver the item to the customer
26 Self::mint_item(e, &recipient)
27 }
28}

The payer parameter should always be the Coinflow checkout contract address. Coinflow approves your contract to spend USDC on its behalf before invoking your function.

EnvironmentCheckout Contract Address
SandboxCA6F7DX4RBZLENHGLPPTGQA4CRNNH3U6QJ3KD7HQLN46YENHTWJRZUOH
ProductionCDUVNW53LTEPPA6SWEGMAV2KJT4YCRECSLRB7XG3KEN3B62YK6HBKG7S

Gas-Only Purchases

If your contract charges $0 USDC for the purchase (e.g., free mints, promotional items), Coinflow will only pay the Stellar gas fees to execute the transaction on your contract. Your contract function does not need to handle any USDC transfer logic in this case.

1pub fn purchase_free_item(
2 e: &Env,
3 recipient: Address, // Customer wallet (receives the item)
4) -> u32 {
5 // No USDC handling needed - just deliver the item
6 Self::mint_item(e, &recipient)
7}

For gas-only purchases, pass subtotal: { cents: 0 } in your checkout request. The customer is only charged for the gas fees.

Gas Fee Handling

Coinflow automatically simulates your Stellar transaction to estimate gas fees. These fees are added to the customer’s total purchase price. The merchant does not need to handle gas fees or fund any wallets with XLM.

Whitelisting Your Contract

Before your contract can receive settlement, it must be whitelisted by Coinflow. Submit your contract address through the Coinflow Merchant Dashboard.

Your contract must be whitelisted on both sandbox and production environments separately. Start with sandbox for testing.

For more details on the whitelisting process, see How to Whitelist Your Contract.