Skip to content

Transactions ​

Privy allows your app to easily request transactions from users embedded wallet. By default, Privy will display a UI preview of the transaction to get approval from the user.

These UIs are highly-customizable via params, allowing you to contextualize onchain actions within the broader experience of your product. You can also fully disable Privy's UIs in favor of your own. Learn more about customizing wallet UIs here.

Sending a transaction ​

To request a transaction from a user use the sendTransaction method returned by the usePrivy hook:

tsx
const {sendTransaction} = usePrivy();

When invoked, sendTransaction will make an eth_sendTransaction request to your user's wallet to send the specified transaction to the blockchain. The method returns a Promise for a TransactionReceipt object once it has been confirmed by the network.

sendTransaction takes the following parameters:

ParameterTypeDescription
requestDataUnsignedTransactionRequestRequired. The transaction request to be sent.
uiConfigSendTransactionModalUIOptionsOptional. Options to customize the transaction prompt shown to the user. Defaults to the values outlined below
fundWalletConfigFundWalletConfigOptional. Options to customize the fiat on-ramp flow for the wallet, if your app has Privy's fiat on-ramp enabled.

In particular, you should use:

  • UnsignedTransactionRequest to prepare the transaction to be sent
  • SendTransactionModalUIOptions to customize the transaction prompt shown to the user.

INFO

Need to interact with a smart contract? Calling a smart contract method is a special case of a transaction.

Building the transaction ​

To prepare the transaction for the user's embedded wallet, set your desired transaction details in the UnsignedTransactionRequest object.

The possible fields for this object are listed below. All of the fields are optional. If fields relating to gas consumption are left unspecified (e.g. gasPrice, maxFeePerGas), Privy will compute a real-time estimate for gas.

TIP

If you choose to manually configure any parameters related to gas fees, please make sure to pass in an explicit value for all of the following parameters: type (EIP-1559 or not), gasLimit, and

  • maxFeePerGas/maxPriorityFeePerGas for type: 2 transactions (EIP-1559), or
  • gasPrice for type: 0 or 1 transactions (legacy or EIP-2930).

If you only pass a subset of the parameters above, Privy will estimate the rest according to our defaults, which may result in unpredictable behavior for transactions.

FieldTypeDescription
tostringDestination address of the transaction. Must be hexadecimal formatted.
noncenumberNonce for this transaction. Defaults to the current transaction count for the wallet.
chainIdnumberChain ID for the network that this transaction should be sent on. Defaults to the current chain of the wallet.
datastringData to send to the receiving address, especially when calling smart contracts. Must be hexadecimal formatted.
valueQuantityAmount (in wei) to transfer from sender to receiver.
typenumberEIP-2718 type of this transaction.
gasLimitQuantityMax. units of gas that can be used by this transaction.
gasPriceQuantityPrice (in wei) per unit of gas for this transaction. This should only be set for non-EIP-1559 transactions.
maxFeePerGasQuantityMaximum price (in wei) per unit of gas to be paid total for this transaction. This includes the base fee and the priority fee. This should only be set for EIP-1559 transactions.
maxPriorityFeePerGasQuantityMaximum price (in wei) per unit of gas to be paid in addition to the base fee, to increase the transaction's priority. This includes the base fee and the priority fee. This should only be set for EIP-1559 transactions.

Customizing the prompt ​

To customize the transaction prompt for the user's embedded wallet, set your desired customizations in the SendTransactionModalUIOptions object.

The possible fields for this object are listed below. All of the fields are optional. If a default is not explicitly listed, Privy will omit that element from the UI if you do not set a value for that parameter. We recommend that you experiment with a number of prompt customizations to arrive at the best option for your users.

FieldTypeDescription
showWalletUIsboolean(Optional) Whether to overwrite the configured wallet UI for the transaction prompt. Defaults to undefined, which will respect the server-side or SDK configured option.
headerstringHeader text for the transaction screen. Defaults to 'Review transaction' or 'Send <token symbol>' if the transaction is a native token transfer.
descriptionstringDescription text for the transaction.
buttonTextstringText to show on the transaction confirmation button. Defaults to 'Submit'.
successHeaderstringHeader text for the transaction success screen. Defaults to 'Transaction complete!'
successDescriptionstringDescription text for the transaction success screen. Defaults to 'You're all set.'
transactionInfoObjectInformation to show in the transaction details accordion. The fields for this object are outlined below.
transactionInfo.titleQuantityTitle for the transaction details accordion.
transactionInfo.actionnumberShort description of the action taken by the user. Should be <4 words (e.g. 'Send NFT'). Shown within the transaction details accordion.
transactionInfo.contractInfoObjectAdditional information to show in the transaction details accordion, when the transaction is a smart contract interaction.
transactionInfo.contractInfo.namestringName of the smart contract being called (e.g. 'Uniswap' or 'Seaport').
transactionInfo.contractInfo.urlstringURL to show for the smart contract.
transactionInfo.contractInfo.imgUrlstringURL of a hosted image to show in the transaction prompt.
transactionInfo.contractInfo.imgSize'sm' | 'lg'Size of hosted image to show, if transactionInfo.contractInfo.imgUrl is set.

Customizing price display ​

By default, Privy's transaction prompt will show prices in both the native token (e.g. ETH) and in USD. If you'd like to customize Privy's transaction prompt to show prices only in the native token and not in USD, update the config.embeddedWallets.priceDisplay property of your PrivyProvider component like so:

tsx
<PrivyProvider
  appId="insert-your-privy-app-id"
  config={{
    embeddedWallets: {
      priceDisplay: {

        primary: 'native-token', // Defaults to 'fiat-currency'
        secondary: null, // Defaults to 'native-token'
      },
    },
  }}
>
  {children}
</PrivyProvider>

Setting funding options ​

This section only applies to apps that have funding enabled.

If a user attempts to send a transaction with the embedded wallet and does not has sufficient funds to complete the transaction, Privy will automatically display an "Add funds" button in the transaction prompt for the user.

When a user clicks the "Add funds" button, they will be taken through a funding flow with your selected method, where they can top up their wallet with the assets they need.

You can customize the funding flow for a given transaction by passing in a FundWalletConfig object as a third, optional parameter to sendTransaction, like so:

tsx
// Configure the onramp to purchase 0.02 ETH if out of funds
const fundWalletConfig = {amount: '0.02'};

await sendTransaction(insertYourTransaction, insertYourUIConfig, fundWalletConfig);

The chain ID from fundWalletConfig will be overridden by the transaction's configured chain.

Getting the receipt ​

Once invoked, sendTransaction will return a Promise for a TransactionReceipt object with details about the sent transaction. See a breakdown of this object's parameters below.

FieldTypeDescription
tostringReceiving address of the transaction. May either be an externally-owned account or a smart contract.
fromstringSending address of the transaction.
typenumberEIP-2718 type of this transaction.
status?number1 if the transaction was successful and 0 if the transaction reverted. Only available for transactions sent after the Byzantium Hard Fork.
blockHashstringHash of the block this transaction was included in.
transactionHashstringHash of this transaction. You may use this value to inspect the transaction on a Block Explorer for your respective network.
blockNumbernumberHeight/number of the block this transaction was included in.
gasUsedstringAmount of gas consumed by this transaction. Formatted as a hexadecimal string.
cumulativeGasUsedstringAmount of gas consumed by this transaction and every preceding transaction that was mined in the same block.
effectiveGasPricestringEffective gas price the transaction charged the sending address.
contractAddressstringIf the transaction deploys a smart contract, this is the address of the deployed contract. This should only happen if the receiving address (to) for this transaction is null.
logsArray<TransactionLog>List of all TransactionLogs emitted by this transaction.
logsBloomstringBloom filter of all addresses and topics included in any log in this transaction.
confirmationsnumberNumber of blocks that have been mined since this transaction, including the block that contains this transaction.
transactionIndexnumberThe index of this transaction in the list of transactions that were included in the transaction's block.
root?stringIntermediate state root of the transaction receipt. Only used by transactions sent before the Byzantium Hard Fork.
byzantiumbooleanReturns true if the transaction block was mined after the Byzantium Hard Fork.

Example ​

Below is an example of customizing the transaction prompt:

tsx
import {usePrivy} from '@privy-io/react-auth';
import type {UnsignedTransactionRequest, SendTransactionModalUIConfig} from '@privy-io/react-auth';

function SendTransactionButton() {
  const {sendTransaction} = usePrivy();

  const requestData: UnsignedTransactionRequest = {
    to: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
    chainId: 1,
    value: '0x3B9ACA00',
  };

  const uiConfig: SendTransactionModalUIConfig = {
    header: 'Sample header text',
    description: 'Sample description text',
    buttonText: 'Sample button text',
  };

  return (
    <button
      onClick={async () => {
        const txReceipt = await sendTransaction(unsignedTx, uiConfig);
        // The returned `txReceipt` has the type `TransactionReceipt`
      }}
    >
      Send ETH
    </button>
  );
}