Skip to main content

Swap

Swap lets a client exchange USDC and EURe directly on-chain using a short-lived quote signed by Monerium. The feature is currently in preview and available only in the sandbox environment on Arbitrum Sepolia.

Preview feature

Swap is currently in preview and available only in the sandbox environment on Arbitrum Sepolia. The API is subject to change before general availability. Check this page again before integrating or updating your implementation.

How it works

The client asks Monerium for a quote bound to a wallet, accepts that quote to get a signature and settlement calldata, approves the settlement contract to spend the sell token, then executes the signed swap on-chain.

  1. Quote: Request a price for exactly one sellAmount or buyAmount. The response includes an X-Quote-Token header.
  2. Accept: Send the quote token back to Monerium to receive a signed quote and complete settlement calldata.
  3. Approve: Approve the returned settlement contract to spend the sell token if allowance is too low.
  4. Execute: Send the returned calldata to the settlement contract before the quote expires.

Preview configuration

Use these values in sandbox while swap is in preview:

FieldValue
ChainArbitrum Sepolia
Chain namearbitrumsepolia
Chain ID421614
Supported pairUSDC and EURe

Token and settlement contract addresses are resolved by Monerium for the requested chain and returned by the API. Use the returned addresses rather than hard-coding them.

Amounts

The API accepts decimal strings of at least 1 token, such as 1 or 10.00. Display amounts remain decimal strings. Base-unit amounts are returned separately as integer strings and are authoritative for on-chain operations.

Get a quote

GET/swap/{chain}/{sellToken}/{buyToken}API Reference →

Pass the chain and token symbols in the path. Pass the wallet address and exactly one amount of at least 1 token in the query string. sellAmount means "sell this amount". buyAmount means "buy this amount".

const url = new URL(
'https://api.monerium.dev/swap/arbitrumsepolia/USDC/EURe',
);
url.search = new URLSearchParams({
sellAmount: '10.00',
walletAddress,
}).toString();

const response = await fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${access_token}`,
Accept: 'application/vnd.monerium.api-v2+json',
},
});

const quoteToken = response.headers.get('X-Quote-Token');
if (!quoteToken) throw new Error('Missing quote token');

const quote = await response.json();

The response includes:

FieldDescription
idQuote UUID used for reconciliation.
chainChain name used for settlement.
walletAddressWallet bound to the quote.
sellToken, buyTokenNormalized token symbols.
sellTokenAddress, buyTokenAddressToken contract addresses on the selected chain.
sellTokenDecimals, buyTokenDecimalsToken decimals on the selected chain.
sellAmount, buyAmountQuoted decimal token amounts.
sellAmountBaseUnits, buyAmountBaseUnitsQuoted amounts in token base units.
requiredAllowanceBaseUnitsMinimum sell-token allowance in base units.
sellAmountUsd, buyAmountUsdQuoted USD values.
price, priceImpactQuoted price and percentage price impact.
expiryUnix timestamp when the quote expires.

The X-Quote-Token header is opaque. Store it only long enough to accept this quote, and do not modify it.

Accept the quote

POST/swap/acceptAPI Reference →

Send the quote token in the X-Quote-Token header. The request has no JSON body. Monerium checks liquidity and token balances, then returns a signed quote.

A successful quote does not reserve liquidity or guarantee that acceptance will succeed. Treat /swap/accept as the authoritative check before asking the wallet to approve or execute the swap.

const response = await fetch('https://api.monerium.dev/swap/accept', {
method: 'POST',
headers: {
Authorization: `Bearer ${access_token}`,
Accept: 'application/vnd.monerium.api-v2+json',
'X-Quote-Token': quoteToken,
},
});

const acceptedQuote = await response.json();

acceptedQuote contains the quote fields plus:

FieldDescription
chainIdChain ID the quote was signed for.
settlementAddressContract that must receive the settlement transaction.
nonceSettlement nonce. It can only be used once.
signatureMonerium signature authorizing the swap.
calldataComplete ABI-encoded swap(...) call.

Execute on-chain

The settlement contract exposes:

function swap(
address walletAddress,
address sellToken,
address buyToken,
uint256 sellAmount,
uint256 buyAmount,
uint256 expiry,
uint256 nonce,
bytes16 quoteId,
bytes calldata signature
) external;

The caller must be walletAddress, must be connected to chainId, and must execute before expiry. The contract verifies Monerium's signature, marks the nonce as used, transfers sellAmount of sellToken from the wallet to the maker, and transfers buyAmount of buyToken from the maker to the wallet.

Submit the returned calldata unchanged to settlementAddress:

import { maxUint256, parseAbi } from 'viem';

const erc20Abi = parseAbi([
'function allowance(address owner, address spender) view returns (uint256)',
'function approve(address spender, uint256 amount) returns (bool)',
]);

const requiredAllowance = BigInt(
acceptedQuote.requiredAllowanceBaseUnits,
);

const allowance = await publicClient.readContract({
address: acceptedQuote.sellTokenAddress,
abi: erc20Abi,
functionName: 'allowance',
args: [walletAddress, acceptedQuote.settlementAddress],
});

if (allowance < requiredAllowance) {
const { request } = await publicClient.simulateContract({
account: walletAddress,
address: acceptedQuote.sellTokenAddress,
abi: erc20Abi,
functionName: 'approve',
args: [acceptedQuote.settlementAddress, maxUint256],
});

const approveHash = await walletClient.writeContract(request);
await publicClient.waitForTransactionReceipt({ hash: approveHash });
}

const swapHash = await walletClient.sendTransaction({
account: walletAddress,
to: acceptedQuote.settlementAddress,
data: acceptedQuote.calldata,
});
const receipt = await publicClient.waitForTransactionReceipt({ hash: swapHash });
Approval amount

Approving maxUint256 avoids repeated approval transactions. If your product prefers tighter allowances, approve requiredAllowance instead.

Monitor completion

The swap is complete when the settlement transaction is confirmed successfully. The settlement contract emits Swap(bytes16 quoteId), and the token contracts emit the corresponding Transfer events.

Use the transaction hash and quote ID for reconciliation in your client.