Skip to content

Example: Creating an Order

Define your route parameters

In this simplified example, we send funds to a single recipient on Ethereum, who will receive 10 USDC.

client.ts
// configure output parameters (for this example, sends funds around and back to the user)
const recipientAddr = account.address;
const tokenAddr = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
const tokenDecimals = 6;
const tokenSymbol = 'USDC';
const tokenAmount = '10';

Derive the viewer account

Before requesting a quote, we need to derive the viewer account from the facilitator group and export its public key. The viewer is used to observe the order execution.

client.ts
import { FacilitatorKeyType } from '@silentswap/sdk';
 
// derive viewer account from the facilitator group
const viewer = await group.viewer();
 
// export its public key
const {
    publicKeyBytes: pk65_viewer,
} = viewer.exportPublicKey('*', FacilitatorKeyType.SECP256K1);

Request a Quote

At this stage, we must commit to the facilitator accounts we will use for the order. We do this by exporting the public keys of the facilitator group using a predetermined selection of coin types, and including the viewer public key in the quote request.

client.ts
import BigNumber from 'bignumber.js';
import { caip19FungibleEvmToken } from '@silentswap/sdk';
 
// export public keys for the facilitator group. this example is for only 1 output
const groupPublicKeys = (await group.exportPublicKeys(1, [
    ...PublicKeyArgGroups.GENERIC,
]));
 
// request a quote
const [quoteError, quoteResponse] = await silentswap.quote({
    signer: viemSigner.address,
    viewer: pk65_viewer,
    outputs: [
        {
            method: DeliveryMethod.SNIP,
            recipient: recipientAddr,
            asset: caip19FungibleEvmToken(1, tokenAddr),
            value: BigNumber(tokenAmount).shiftedBy(tokenDecimals).toFixed(0) as `${bigint}`,
            facilitatorPublicKeys: groupPublicKeys[0],
        },
    ],
});
 
if (quoteError || !quoteResponse) {
    throw new Error(`Failed to get quote: ${quoteError?.type}: ${quoteError?.error}`);
}

Review and sign authorizations

Assuming we are happy with the quote, we must sign the authorizations for the order (including meta txs, proxy authorizations, and the order intent itself). This is done using the EvmSigner abstraction and selecting the appropriate signer for each document.

client.ts
import { quoteResponseToEip712Document } from '@silentswap/sdk';
 
// sign authorizations
const signedAuths = await Promise.all(quoteResponse.authorizations.map(async g_auth => ({
    ...g_auth,
    signature: await (async () => {
        // EIP-3009 deposit
        if ('eip3009_deposit' === g_auth.type) {
            return await viemSigner.signEip712TypedData(g_auth.eip712);
        }
 
        throw Error(`Authorization instruction type not implemented: ${g_auth.type}`);
    })(),
})));
 
// sign the order's EIP-712
const orderDoc = quoteResponseToEip712Document(quoteResponse);
const signedQuote = await viemSigner.signEip712TypedData(orderDoc);
 
// approve proxy authorizations
const facilitatorReplies = await group.approveProxyAuthorizations(quoteResponse.facilitators, {
    proxyPublicKey: silentswap.proxyPublicKey,
});

Place the order

Placing the order is a simple matter of sending a request to the SilentSwap service, including the quote, signed authorizations, and facilitator replies.

The OrderRequest can optionally include metadata with information about the source asset, source sender, and integrator ID for tracking purposes.

client.ts
// place the order
const [orderError, orderResponse] = await silentswap.order({
    quote: quoteResponse.quote,
    quoteId: quoteResponse.quoteId,
    authorizations: signedAuths,
    eip712Domain: orderDoc.domain,
    signature: signedQuote,
    facilitators: facilitatorReplies,
    metadata: {
        sourceAsset: {
            caip19: caip19FungibleEvmToken(1, tokenAddr),
            amount: BigNumber(tokenAmount).shiftedBy(tokenDecimals).toFixed(0) as `${bigint}`,
        },
        sourceSender: {
            contactId: `caip10:eip155:1:${account.address}`,
        },
        integratorId: process.env.INTEGRATOR_ID, // Optional: for tracking
    },
});
 
if (orderError || !orderResponse) {
    throw new Error(`Failed to place order: ${orderError?.type}: ${orderError?.error}`);
}
 
console.log(`Placed order ${orderResponse.response.orderId}`);

Optional Metadata

You can include optional metadata in the order request:

const [orderError, orderResponse] = await silentswap.order({
    quote: quoteResponse.quote,
    quoteId: quoteResponse.quoteId,
    authorizations: signedAuths,
    eip712Domain: orderDoc.domain,
    signature: signedQuote,
    facilitators: facilitatorReplies,
    metadata: {
        sourceAsset: {
            caip19: 'eip155:1/erc20:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
            amount: '1000000', // Amount in smallest unit
        },
        sourceSender: {
            contactId: 'caip10:eip155:1:0x...',
        },
        integratorId: 'my-integrator-id', // Optional: for tracking
    },
});