Step 6: Signing transactions with Privy

The application must sign the transactions received during the quote-fetching step using the user key stored in Privy.

To accomplish this, the app utilizes the PrivyProvider. Here’s an example:

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([])
  );
};

For more detailed implementation, refer to the sample application here.

Last updated