Skip to main content
Cross-border payments require burning a source currency, applying an exchange rate, and minting the destination currency to the receiver, coordinating multiple actors (bank, sender, FX provider) across each step. This solution shows how to orchestrate that flow on Solana with DFNS wallets handling key management and transaction signing.

Get the code

dfns/dfns-solutions: cross-border-payments-solana
The system involves three main actors:

Bank

Deploys stablecoins and the payment program, mints tokens, and executes settlements

FX Provider

Quotes the exchange rate and records the converted amount on-chain

Receiver

Receives funds in the destination currency (e.g., tSGD)
Setup: The Bank deploys two SPL token stablecoins (tEUR and tSGD) and the cross-border payment Anchor program. Payment flow:
  1. The Bank initiates a payment, specifying the receiver and amount in tEUR
  2. The FX Provider sets the conversion rate (how much tSGD the receiver gets)
  3. The Bank executes the payment. tEUR is burned from the sender and tSGD is minted to the receiver
The execution is atomic: the burn and mint happen in the same Solana transaction. If either fails, nothing happens.

Prerequisites

  1. Clone the cross-border-payments-solana solution
  2. Create a DFNS organization if you don’t have one already, and note the organization ID
  3. Create a service account for API access (see the service account guide)
  4. Create 2 wallets: Bank and Receiver on Solana Devnet
  5. Fund the Bank wallet with devnet SOL for transaction fees (solana airdrop 2 <BANK_WALLET_ADDRESS> --url devnet)
  6. Make sure you have installed Node.js v18+, Rust, and Cargo
  7. Install Solana CLI and Anchor (v0.32+). The included setup.sh script can install these

Project Structure

Configuration

1

Clone and install

2

Set up environment variables

Copy the example environment file and fill in your values:
dfns/.env
3

Build and test

Build the Anchor program and run the test suite against a local validator:
4 tests cover the full flow: initialization, FX rate setting, atomic execution, and duplicate prevention. No DFNS credentials or devnet access required.

Deploy

1

Deploy stablecoins

Deploy two SPL token mints that represent the source and target currencies. The bank’s DFNS wallet becomes the mint authority.
Each command prints the mint address. Copy both into your dfns/.env as SOURCE_MINT and TARGET_MINT.
2

Deploy the program

Upload the compiled Anchor program to Solana Devnet. The DFNS wallet is used as the payer and upgrade authority.
The upgrade authority stays in the DFNS KMS, meaning future upgrades also go through DFNS.
3

Mint tokens to the sender

This mints 1,000 tokens (amounts use 6 decimals: 1000000000 = 1,000.000000 tokens).

End-to-End Payment Flow

1

Initialize a payment

Create a payment record on-chain. This stores the sender, receiver, and input amount in a PDA.
  • 1: payment ID (unique per sender)
  • 500000: amount in base units (0.5 tokens)
2

Set the FX rate

The FX provider locks in the conversion rate. In this demo, any signer can call set_fx_rate. A production system should restrict this to authorized accounts.For example, converting 0.5 tEUR at a rate of 1.6x gives 0.8 tSGD:
  • 800000: the exact output amount in target token base units
3

Execute the payment

Trigger the atomic swap. The program burns the source tokens from the sender and mints the target tokens to the receiver:
The script automatically creates the receiver’s token account if it doesn’t exist yet.
4

Verify balances

  • Sender: should show reduced tEUR balance
  • Receiver: should show new tSGD balance

Interactive UI

The solution includes a web UI for running the full payment flow:
Open http://localhost:3000. The UI provides:
  • A three-step form to initialize a payment, set the FX rate, and execute the swap
  • A flow visualization showing the current payment status (PendingFX → FXRateSet → Completed)
  • Live balances for sender and receiver (source tokens, target tokens, SOL)
  • Solana Explorer links for every transaction

CLI Reference

All amounts are in base units (6 decimals). To send 100 tokens, pass 100000000.

Settle to fiat with Payouts

If your cross-border flow ends in fiat bank deposits rather than on-chain tokens, use Payouts to convert stablecoins (USDC, USDT, EURC) to local currency across 94 countries and 63 currencies. Payouts supports Solana. See the usage guide or developer guide.
Last modified on July 8, 2026