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.
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.
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.
// place the order
const [orderError, orderResponse] = await silentswap.order({
quote: quoteResponse.quote,
quoteId: quoteResponse.quoteId,
authorizations: signedAuths,
eip712Domain: orderDoc.domain,
signature: signedQuote,
facilitators: facilitatorReplies,
});
if (orderError || !orderResponse) {
throw new Error(`Failed to place order: ${orderError?.type}: ${orderError?.error}`);
}
console.log(`Placed order ${orderResponse.response.orderId}`);