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.
// 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.
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.
The quote request can optionally include a pro field — your integrator/pro ID — for volume tracking and custom fees. The same ID should also be sent on the order as metadata.integratorId (see Optional Metadata below).
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,
pro: process.env.INTEGRATOR_ID, // Optional: integrator/pro ID for volume tracking and custom fees
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.
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.
// 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 — same ID as `pro` on the quote request
},
});
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 — same ID as the `pro` field on the quote request
},
});