Send Universal Transaction
Overview
Universal transactions let you send native transactions from any Layer 1 chain—EVM or non-EVM, even Push Chain itself—without wrapping, bridging or extra tooling required.
Under the hood, the SDK automatically estimates gas, orchestrates signatures, and replays any EVM or non-EVM proofs, so you can focus on your app—not the network plumbing.
Sending Universal Transaction
pushChainClient.universal.sendTransaction({tx}): Promise<TransactionReceipt>
const txHash = await pushChainClient.universal.sendTransaction({
to: '0xa54E96d3fB93BD9f6cCEf87c2170aEdB1D47E1cF',
value: PushChain.utils.helpers.parseUnits('0.1', 18), // 0.1 PC in uPC
// value: BigInt('100000000000000000') is equivalent here
});
TheseArguments
are mandatory
Arguments | Type | Description |
---|---|---|
tx.to | string | The address of the recipient. |
tx.value | BigInt | The value to send in uPC. smallest unit of PC, like wei in ETH |
tx.data | string | The data to send. |
tx.gasLimit | BigInt | The gas limit for the transaction. |
tx.maxFeePerGas | BigInt | The maximum fee per gas for the transaction. |
tx.maxPriorityFeePerGas | BigInt | The maximum priority fee per gas for the transaction. |
Advanced Arguments
Arguments | Type | Default | Description |
---|---|---|---|
tx.deadline | BigInt | - | The deadline for the transaction. |
tx.progressHook | (progress: ProgressHookType) => void | - | A callback function to receive progress updates during transaction lifecycle, especially useful for tracking cross-chain transactions. |
ProgressHook Type and Response
Field | Type | Description |
---|---|---|
progress | Object | The progress of the transaction. |
progress.id | string | Unique identifier for the progress event. |
progress.title | string | Brief title of the progress event. |
progress.message | string | Detailed message describing the event. |
progress.level | INFO | SUCCESS | WARNING | ERROR | Severity level of the event. |
progress.timestamp | string | ISO-8601 timestamp when the event occurred (e.g. 2025-06-26T15:04:05.000Z ). |
ID | Title | Message | Level |
---|---|---|---|
SEND-TX-01 | Origin Chain Detected | Origin chain: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 | INFO |
SEND-TX-02-01 | Estimating Gas | Estimating and fetching gas limit, gas price for TX… | INFO |
SEND-TX-02-02 | Gas Estimated | Total execution cost (Gas cost + value): 1011250000000000000 UPC | SUCCESS |
SEND-TX-03-01 | Resolving UEA | Resolving Execution Account (UEA) – computing address, checking deployment status and balance | INFO |
SEND-TX-03-02 | UEA Resolved | UEA: 0x4f17B798A7d643d4F89cb2d8D42A72F84e83e566, Deployed: true | SUCCESS |
SEND_TX_04_01 | Awaiting Signature for Tx Execution | Universal Payload Hash: 0x1a579f18…fabac4309 | INFO |
SEND_TX_04_02 | Generated Universal Payload | Signature Completed | SUCCESS |
SEND-TX-05-01 | Locking Origin Chain Fee | Locking fee: 1000063864000000000 UPC on origin chain | INFO |
SEND-TX-05-02 | Awaiting Origin Chain Confirmations | Tx sent: 0xabc..234, waiting for 2 confirmations. | INFO |
SEND-TX-05-03 | Confirmations Received | Required confirmations received. | SUCCESS |
SEND-TX-06 | Broadcasting to Push Chain | Sending Tx to Push Chain… | INFO |
SEND-TX-99-01 | Push Chain TX Success | … | SUCCESS |
SEND-TX-99-02 | Push Chain TX Failed | … | ERROR |
Returns `TxResponse` <object>
{
blockHash: '0xd193f3d61a6d73c167d64ce97577882e4736346bc1460fcafafca9144afc083e',
blockNumber: 803963n,
from: '0xb59cdc85cacd15097ece4c77ed9d225014b4d56d',
gas: 21000n,
gasPrice: 1125000000n,
maxFeePerGas: 1325000000n,
maxPriorityFeePerGas: 125000000n,
hash: '0xa0a2a3a58bd7241785b9ff3470b8ba0bbbdf800b3ec8f2b806bb691595041537',
input: '0x',
nonce: 34,
to: '0xfae3594c68edfc2a61b7527164bdae80bc302108',
transactionIndex: 0,
value: 1n,
type: 'eip1559',
accessList: [],
chainId: 42101,
v: 0n,
r: '0x485939545430e60b5a1b6f4271bf1e1955f3045709a43ef616977f391c8601d1',
s: '0x4848e381fdc59955d9c63162caf15a0fb98d5c78e233dd10b177d7be2144d434',
typeHex: '0x2',
yParity: 0,
wait: [Function: wait]
}
Send Transaction with Contract Interaction
When calling a smart contract method via sendTransaction, supply the ABI-encoded function call as a hex string in the data field. You can choose ethers
or viem
or any of your favorite libraries to encode the function data. Or, use our utility function PushChain.utils.helpers.encodeTxData
to encode the function data.
// Define the ABI for the ERC20 transfer function
const erc20Abi = [
'function transfer(address to, uint256 amount) returns (bool)',
];
// Generate the encoded function data using viem
const data = PushChain.utils.helpers.encodeTxData({
abi: erc20Abi,
functionName: 'transfer',
// Transfer 10 tokens, converted to 18 decimal places
args: ['0xRecipientAddress', PushChain.utils.helpers.parseUnits('10', 18)],
});
// Send the transaction using Push Chain SDK
const txHash = await pushChainClient.universal.sendTransaction({
to: '0xTokenContractAddress', // The smart contract address on Push Chain
value: BigInt('0'), // No $PC being sent, just contract interaction
data: data, // The encoded function call
});
Live Playground
- Quickstart
- Ethers (v6)
- Viem
- Solana (Web3 JS)
- UI Kit
// Import necessary components from @pushchain/ui-kit import { PushUniversalWalletProvider, PushUniversalAccountButton, usePushWalletContext, usePushChainClient, PushUI, } from '@pushchain/ui-kit'; function App() { // Define Wallet Config const walletConfig = { network: PushUI.CONSTANTS.PUSH_NETWORK.TESTNET, }; function Component() { const [txnHash, setTxnHash] = useState<string | null>(null); const [isLoading, setIsLoading] = useState(false); const { connectionStatus } = usePushWalletContext(); const { pushChainClient } = usePushChainClient(); const handleSendTransaction = async () => { if (pushChainClient) { setIsLoading(true); try { const res = await pushChainClient.universal.sendTransaction({ to: '0xFaE3594C68EDFc2A61b7527164BDAe80bC302108', value: PushChain.utils.helpers.parseUnits('0.001', 18), // 0.001 PC in uPC data: '0x', }); setTxnHash(res.hash); } catch (err) { console.log(err); } finally { setIsLoading(false); } } }; return ( <div> <PushUniversalAccountButton /> {connectionStatus == PushUI.CONSTANTS.CONNECTION.STATUS.CONNECTED && <button disabled={isLoading} style={{ background: 'transparent', border: '1px solid', borderRadius: '10px', padding: '12px 18px', cursor: 'pointer', margin: '8px 0', }} onClick={handleSendTransaction} > Send Transaction </button> } {txnHash && ( <> <p>Txn Hash: {txnHash}</p> <a href={pushChainClient.explorer.getTransactionUrl(txnHash)} target="_blank" rel="noopener noreferrer" > View in Explorer </a> </> )} </div> ); } return ( <PushUniversalWalletProvider config={walletConfig}> <Component /> </PushUniversalWalletProvider> ); }
Live Playground: Interact with Smart Contract
- From Push Chain
- From Sepolia
- From Solana Devnet
Live Playground: (Advanced) Track the progress lifecycle of a transaction
Next Steps
- Sign arbitrary data with Sign Universal Message
- Surface live feedback in your UI by handling the
progressHook
events - Leverage pre-built utilities in Contract Helpers
- Integrate transaction flows into your frontend app using the UI Kit