Appearance
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.
For embedded wallets on both EVM networks and Solana, Privy's default transaction confirmation modals are highly-customizable, allowing you to contextualize onchain actions within the broader experience of your product.
Sending a transaction
To request a transaction from a user use Privy's sendTransaction
or sendSolanaTransaction
method:
tsx
import {usePrivy} from '@privy-io/react-auth';
...
const {sendTransaction} = usePrivy();
When invoked, this method will request your user's wallet to send the specified transaction to the blockchain. The method returns a Promise
for a transaction receipt once it has been confirmed by the network.
Sending a transaction takes the following parameters:
Parameter | Type | Description |
---|---|---|
requestData | UnsignedTransactionRequest | Required. The transaction request to be sent. |
uiConfig | SendTransactionModalUIOptions | Optional. Options to customize the transaction prompt shown to the user. Defaults to the values outlined below. |
fundWalletConfig | FundWalletConfig | Optional. 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 sentSendTransactionModalUIOptions
to customize the transaction prompt shown to the user.
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.
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
fortype: 2
transactions (EIP-1559), orgasPrice
fortype: 0
or1
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.
Field | Type | Description |
---|---|---|
to | string | Destination address of the transaction. Must be hexadecimal formatted. |
nonce | number | Nonce for this transaction. Defaults to the current transaction count for the wallet. |
chainId | number | Chain ID for the network that this transaction should be sent on. Defaults to the current chain of the wallet. |
data | string | Data to send to the receiving address, especially when calling smart contracts. Must be hexadecimal formatted. |
value | Quantity | Amount (in wei) to transfer from sender to receiver. |
type | number | EIP-2718 type of this transaction. |
gasLimit | Quantity | Max. units of gas that can be used by this transaction. |
gasPrice | Quantity | Price (in wei) per unit of gas for this transaction. This should only be set for non-EIP-1559 transactions. |
maxFeePerGas | Quantity | Maximum 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. |
maxPriorityFeePerGas | Quantity | Maximum 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. This interface is identical across both EVM networks and Solana.
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.
Field | Type | Description |
---|---|---|
showWalletUIs | boolean | (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. |
header | string | Header text for the transaction screen. Defaults to 'Review transaction' or 'Send <token symbol>' if the transaction is a native token transfer. |
description | string | Description text for the transaction. |
buttonText | string | Text to show on the transaction confirmation button. Defaults to 'Submit'. |
successHeader | string | Header text for the transaction success screen. Defaults to 'Transaction complete!' |
successDescription | string | Description text for the transaction success screen. Defaults to 'You're all set.' |
transactionInfo | Object | Information to show in the transaction details accordion. The fields for this object are outlined below. |
transactionInfo.title | Quantity | Title for the transaction details accordion. |
transactionInfo.action | number | Short description of the action taken by the user. Should be <4 words (e.g. 'Send NFT'). Shown within the transaction details accordion. |
transactionInfo.contractInfo | Object | Additional information to show in the transaction details accordion, when the transaction is a smart contract interaction. |
transactionInfo.contractInfo.name | string | Name of the smart contract being called (e.g. 'Uniswap' or 'Seaport'). |
transactionInfo.contractInfo.url | string | URL to show for the smart contract. |
transactionInfo.contractInfo.imgUrl | string | URL 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 to Privy's send transaction method, 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);
Getting the receipt
Once a transaction is sent, Privy's methods will return a Promise
for a transaction receipt object with details about the sent transaction. See a breakdown of this object's parameters below.
Field | Type | Description |
---|---|---|
to | string | Receiving address of the transaction. May either be an externally-owned account or a smart contract. |
from | string | Sending address of the transaction. |
type | number | EIP-2718 type of this transaction. |
status? | number | 1 if the transaction was successful and 0 if the transaction reverted. Only available for transactions sent after the Byzantium Hard Fork. |
blockHash | string | Hash of the block this transaction was included in. |
transactionHash | string | Hash of this transaction. You may use this value to inspect the transaction on a Block Explorer for your respective network. |
blockNumber | number | Height/number of the block this transaction was included in. |
gasUsed | string | Amount of gas consumed by this transaction. Formatted as a hexadecimal string. |
cumulativeGasUsed | string | Amount of gas consumed by this transaction and every preceding transaction that was mined in the same block. |
effectiveGasPrice | string | Effective gas price the transaction charged the sending address. |
contractAddress | string | If 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 . |
logs | Array<TransactionLog> | List of all TransactionLog s emitted by this transaction. |
logsBloom | string | Bloom filter of all addresses and topics included in any log in this transaction. |
confirmations | number | Number of blocks that have been mined since this transaction, including the block that contains this transaction. |
transactionIndex | number | The index of this transaction in the list of transactions that were included in the transaction's block. |
root? | string | Intermediate state root of the transaction receipt. Only used by transactions sent before the Byzantium Hard Fork. |
byzantium | boolean | Returns 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>
);
}