Skip to main content

What You Need

The Cashmere Developer SDK is currently in alpha.
A more comprehensive and production-ready version will be released in the coming weeks.
  • Access to a JSON-RPC endpoint for the origin chain (e.g., Ethereum).
  • A signer with USDC balance and the ability to send transactions.
  • Cashmere contract addresses from the Smart Contracts guide.
  • Node.js (for the TypeScript example) or your preferred language runtime.
All tooling in this quickstart is open—no API keys or proprietary SDKs required.

Step-by-Step (EVM)

  • 1. Fetch Fee
  • 2. Build Params
  • 3. Execute
const response = await fetch(
  'https://gas.cashmere.exchange/getEcdsaSig_native?' +
    new URLSearchParams({
      localDomain: '0',          // Ethereum
      destinationDomain: '3',    // Arbitrum
      isV2: 'true',              // transferV2
      isNative: 'false',
    })
);

if (!response.ok) throw new Error('Gas API error');
const quote = await response.json();
Decimals cheat sheet
Gas API quotes fee in 6-decimal USDC unless isNative=true. For native-fee routes use the chain’s native decimals when encoding gasDropAmount and forwarding value: EVM → 18 decimals, Solana (lamports) → 9, Sui → 9, Aptos → 8.
Need tighter maxFee bounds? Query Circle IRIS at https://iris-api.circle.com/v2/burn/USDC/fees/{sourceDomainId}/{destDomainId}. The response lists recommended minimumFee values for each finalityThreshold (e.g., 1,000 for Fast, 2,000 for Normal).

Step-by-Step (Solana)

  1. Request an Ed25519 signature from the Gas API. Pass version=2 when calling the v2 instruction.
  2. Derive the Solana Associated Token Account (ATA) for the destination wallet and convert both the ATA and owner to 32-byte hex (see the Recipient Encoding section in the Smart Contracts guide).
  3. Insert an Ed25519Program instruction ahead of the Cashmere program call inside the same VersionedTransaction and reuse the quote’s fee, deadline, and signature bytes when invoking transfer_v2.
  4. Include the Cashmere lookup table (865YCTTsymGpBjLMTvjd3T3RCGT8yvxnAHhyKZqRFfLi) so the transaction stays within the account limits, and fetch the config account to populate fee collectors.
import { Ed25519Program, PublicKey } from '@solana/web3.js';
import { getAssociatedTokenAddressSync } from '@solana/spl-token';

const quote = await fetchEd25519Quote({ localDomain: 5, destinationDomain, isNative, version: 2 });

const ed25519Ix = Ed25519Program.createInstructionWithPublicKey({
  publicKey: Buffer.from(quote.publicKey.slice(2), 'hex'),
  message: Buffer.from(quote.message.slice(2), 'hex'),
  signature: Buffer.from(quote.signature.slice(2), 'hex'),
});

const usdcMint = new PublicKey(process.env.SOLANA_USDC_MINT!);
const destinationWallet = new PublicKey(targetSolanaOwner);
const ata = getAssociatedTokenAddressSync(usdcMint, destinationWallet, true);
const recipientHex = toBytes32(ata);
const solanaOwnerHex = toBytes32(destinationWallet);
🔗 A full Anchor transaction (including PDA derivations and lookup-table usage) lives under Integration Examples → Solana Transfer (Anchor).

Step-by-Step (Sui)

  1. Request the Ed25519 quote with localDomain=8 (Sui) and your target destinationDomain.
  2. Mint or split USDC/SUI coins so prepare_deposit_for_burn_ticket receives usdc_coin containing the burn amount plus any USDC gas drop. When fee_is_native=true, split SUI gas to cover fee + gas_drop_amount.
  3. Call prepare_deposit_for_burn_ticket, forward the ticket to Circle’s deposit_for_burn_with_package_auth, then finish with post_deposit_for_burn.
const quote = await fetchEd25519Quote({ localDomain: 8, destinationDomain, isNative });
const signatureBytes = hexToByteArray(quote.signature);

tx.moveCall({
  target: `${modules.cashmereTransfer}::prepare_deposit_for_burn_ticket`,
  typeArguments: [modules.usdcType],
  arguments: [
    usdcCoin,
    nativeFeeCoin,
    tx.pure.u32(destinationDomain),
    tx.pure.address(recipientHex),
    tx.pure.address(solanaOwnerHex),
    tx.pure.u64(quote.fee),
    tx.pure.u64(quote.deadline),
    tx.pure.u64(gasDropAmount.toString()),
    tx.pure.bool(isNative),
    tx.pure.vector('u8', signatureBytes),
    tx.object(configId),
    tx.object(clockId),
  ],
});
🔗 Refer to Integration Examples → Sui Transfer (Transactions API) for the full script with mainnet object IDs.

Step-by-Step (Aptos)

  1. Fetch the Ed25519 quote with localDomain=9 and convert the signature hex into a byte array.
  2. Populate transfer_outer parameters: amounts in 6-decimal USDC, optional native fee in 8-decimal APT, and the 32-byte recipient/solana_owner fields.
  3. Build the entry-function payload, simulate if your wallet supports it, then sign and submit.
const quote = await fetchEd25519Quote({ localDomain: 9, destinationDomain, isNative });
const signatureBytes = hexToByteArray(quote.signature);

const payload = {
  function: `${process.env.APTOS_CASHMERE_MODULE}::transfer_outer`,
  typeArguments: [],
  functionArguments: [
    amount.toString(),
    nativeAmount.toString(),            // fee + gas drop when fee_is_native
    destinationDomain,
    recipientHex,
    solanaOwnerHex,
    quote.fee,
    quote.deadline,
    gasDropMicro.toString(),
    isNative,
    signatureBytes,
  ],
};
🔗 See Integration Examples → Aptos Transfer (ts-sdk) for a complete example that handles deadline refreshes and Pontem wallet quirks.

Monitor the Outcome

  • Use https://kapi.cashmere.exchange/transactionsmainnet to confirm settlement.
  • Subscribe to wss://gas.cashmere.exchange/subscribe for live fee updates.
const ws = new WebSocket('wss://gas.cashmere.exchange/subscribe');
ws.onmessage = (event) => console.log('Fee update:', JSON.parse(event.data));
curl "https://kapi.cashmere.exchange/transactionsmainnet?senders=0xYourAddress&limit=20"

Next Steps

  • Review the Backend APIs for detailed payload structures.
  • Explore the Smart Contracts guide for per-chain nuances.
  • Build notifications by polling /transactionsmainnet or streaming from your preferred indexer.