The application must sign the transactions received during the quote-fetching step using the user key stored in Privy.
import { Address, createWalletClient, custom, Hash } from "viem";
import { ConnectedWallet } from "@privy-io/react-auth";
// below interface corresponds to ChainOperationSwaggerDto on OneBalance Swagger documentation
import { ChainOperation } from '<your path to OneBalance interfaces>';
// below interface corresponds to QuoteSwaggerDto on OneBalance Swagger documentation
import { Quote } from '<your path to OneBalance interfaces>';
const signTypedDataWithPrivy =
(embeddedWallet: ConnectedWallet) =>
async (typedData: any): Promise<Hash> => {
const provider = await embeddedWallet.getEthereumProvider();
const walletClient = createWalletClient({
transport: custom(provider),
account: embeddedWallet.address as Address,
});
return walletClient.signTypedData(typedData);
};
const signOperation =
(embeddedWallet: ConnectedWallet) =>
(operation: ChainOperation): (() => Promise<ChainOperation>) => async () => {
const signature = await signTypedDataWithPrivy(embeddedWallet)(operation.typedDataToSign);
return {
...operation,
userOp: { ...operation.userOp, signature },
};
};
export const signQuote = async (
quote: Quote,
embeddedWallet: ConnectedWallet
) => {
const signWithEmbeddedWallet = signOperation(embeddedWallet);
const signedQuote = {
...quote,
};
signedQuote.originChainsOperations = await sequentialPromises(
quote.originChainsOperations.map(signWithEmbeddedWallet)
);
if (quote.destinationChainOperation) {
signedQuote.destinationChainOperation = await signWithEmbeddedWallet(
quote.destinationChainOperation
)();
}
return signedQuote;
};
// runs an array of lazy promises
const sequentialPromises = (
promises: (() => Promise<any>)[]
): Promise<any[]> => {
return promises.reduce<Promise<any[]>>(
(acc, curr) =>
acc.then((results) => curr().then((result) => [...results, result])),
Promise.resolve([])
);
};