How to execute a payout quote on EVM, Solana, and Stellar: approve, delegate, or sign
Funding a payout from your own wallet needs one on-chain authorization. What EVM approve, Solana delegation, and Stellar signing look like, step by step.
To execute a payout quote from your own wallet, authorize the exact quoted amount on-chain, then create the payout before the quote expires. On EVM chains you call approve on the token contract, on Solana you sign a token delegation, and on Stellar you sign a payment transaction. A BlindPay managed wallet skips the authorization.
Same quote, three chain-native ways to say yes. This guide puts them side by side, with the endpoints, the fields, and the timing traps inside a 5-minute quote window.
Key takeaways
- Every payout quote expires 5 minutes after creation. The authorization has to confirm inside that window.
- EVM: call
approvewith thecontractpayload from the quote, thenPOST /payouts/evm. - Solana:
POST /prepare-delegate-solana, sign and submit, thenPOST /payouts/evm. - Stellar:
POST /payouts/stellar/authorize, sign and submit, thenPOST /payouts/stellarwith the signed transaction. - Quotes and authorizations are single-use. Authorize again for every payout.
Why does a payout from your own wallet need an authorization?
Because BlindPay never holds keys to your wallet. For payout flows from customer-controlled wallets, BlindPay operates as a non-custodial payment processor: you authorize the exact amount and BlindPay executes that single transaction. If a payout can't be delivered after the stablecoins are collected, BlindPay refunds them to the quote's refund wallet, or to the sending wallet when none is set. On Pix and other non-USD local rails that refund is automatic, while USD payouts and payouts whose review times out are refunded after an operator review.
The authorization is how you grant "this amount, this once." Each chain has its own primitive for it. What happens on-chain in a stablecoin payment shows where that step sits in the full flow.
If the funds sit in a BlindPay managed wallet instead, there's nothing to sign. You create the quote and call POST /payouts/evm with the managed wallet's address, for every supported chain, Solana included (payout with managed wallet). Managed wallets are in beta and custodial.
How do the three chains compare?
| Step | EVM (Ethereum, Base, Polygon, Arbitrum) | Solana | Stellar |
|---|---|---|---|
| Primitive | ERC-20 allowance (approve) | Token delegation | Signed payment transaction (XDR) |
| What BlindPay returns | contract object inside the quote | Serialized transaction from prepare-delegate-solana | Unsigned transaction from payouts/stellar/authorize |
| Who submits on-chain | You | You | You |
| Payout endpoint | POST /payouts/evm | POST /payouts/evm | POST /payouts/stellar |
| Extra field on the payout call | None | None | signed_transaction |
| Reusable? | No, single-use | No, one delegation per quote | No, single-use |
The quote request is the same everywhere: bank_account_id, currency_type, cover_fees, request_amount in minor units, plus the network and token you send from (payout quotes). The chain only changes what happens between the quote and the payout. If you're still choosing the chain, which network to off-ramp from compares finality and fees.
How do you execute a quote on an EVM chain?
Approve, wait, pay. The quote response for an EVM network carries a contract object with everything the approval needs (payout with EVM):
contract field | What it is |
|---|---|
address | The ERC-20 token contract for the chosen token and network |
abi | The ERC-20 ABI, ready for your Ethereum library |
functionName | Always approve |
blindpayContractAddress | The spender to approve: BlindPay's receiving address on that network |
amount | The decimal-adjusted amount to approve, as a string |
network | { name, chainId } for the quoted network |
With ethers.js, the call looks like this:
The ERC-20 standard defines approve as allowing a spender to withdraw from your account up to the approved value (EIP-20). Once the approval confirms, create the payout with quote_id and sender_wallet_address. You pay gas on the approval, which who pays gas fees covers in detail.
How do you execute a quote on Solana?
Delegate, sign, pay. Solana payouts need a token delegation before the payout executes (payout with Solana):
POST /v1/instances/{instance_id}/prepare-delegate-solanawithowner_address,token_address, andamount. It returns{ "success": true, "transaction": "..." }, a base64 serialized transaction.- Deserialize it as a
VersionedTransaction, sign it with the sender's wallet (a browser wallet or a server-side keypair), send it, and wait for confirmation. POST /v1/instances/{instance_id}/payouts/evmwithquote_idand the Solanasender_wallet_address. Yes, the EVM path. The name is historical.
Solana's token program says account owners can delegate authority over some or all of their balance with the Approve instruction, and delegates may transfer or burn up to the amount delegated (Solana Program Library). Each BlindPay delegation covers only the amount tied to that quote, so repeat all three steps for every payout.
How do you execute a quote on Stellar?
Authorize, sign, pay with the signature. Stellar has no allowance mechanism, so you sign a real payment to BlindPay's treasury address (payout with Stellar):
POST /v1/instances/{instance_id}/payouts/stellar/authorizewithquote_idandsender_wallet_address. It returns an unsigned transaction intransaction_hash. This call does not consume the quote or create any record.- Rebuild it with
TransactionBuilder.fromXDR, sign with the sender's key, and submit it to the network. POST /v1/instances/{instance_id}/payouts/stellarwithquote_id,signed_transaction, andsender_wallet_address. BlindPay re-validates the signed transaction against the quote, destination and amount, before dispatching the payout.
Stellar encodes transactions in XDR, a compact binary format that SDKs convert to and from base64 (Stellar docs). BlindPay's Stellar mainnet treasury address is GCOSSQDM2SWMHRP7CDBOLL2V45NHCRLUWUCEHPPBA2ABCOOLPOLZKIHE, useful when you reconcile on an explorer.
Illustrative example: does the authorization fit in a 5-minute quote?
A treasury script pays 1,250.00 USDC from an external wallet. request_amount is 125000 in minor units. The approval amount is decimal-adjusted on-chain: BlindPay's own Solana example delegates "50000000" for a 50-dollar quote, which is 50 x 1,000,000, so a token with six decimals needs 1,250 x 1,000,000 = 1,250,000,000 base units here. Read contract.amount from the quote instead of computing it.
Now the clock. The step timings below are illustrative.
| Step | Illustrative time | Clock used |
|---|---|---|
| Create quote | 1 s | 1 s |
| Build and sign the authorization | 3 s | 4 s |
| Wait for on-chain confirmation | 30 s | 34 s |
| Create the payout | 1 s | 35 s |
| Quote window | 300 s | 265 s to spare |
Plenty of room when it's a script. The real risk is a human: a wallet pop-up left open while someone gets coffee. If 300 seconds pass before the payout call, the quote is dead and the old authorization was sized for it. Re-quote and authorize again. Handling expired quotes in TypeScript and Python has the retry loop, and stablecoin API idempotency keys covers safe retries on the payout call. For reading the quote's two rates, see how to read an FX quote.
What to do next
Pick the chain your treasury already uses, open the matching tutorial in the BlindPay docs, and run one 50-dollar payout end to end on a development instance with USDB. Start with payout with EVM if you're unsure.
FAQ
More payments articles
See all payments articlesHow to run batch payouts with live quotes: one quote per payout, expiry, and rate drift
How to pay 100+ recipients from USDC with live quotes: quote and execute per payout, size the funding, handle expiry and retries, and track the batch.
USDC on the wrong chain? How to rebalance across networks before a payout
Your USDC sits on one network and the payout needs another. How cross-chain USDC transfers work, which routes exist, the cost, and how long they take.
How much does pre-funding cost? A working capital formula for cross-border payout teams
Price pre-funded payout balances in basis points: the balance formula, five cost lines, an illustrative worked example, and a sensitivity table to copy.