Skip to main content

Send Multichain Transactions

Overview

Multichain transactions let you compose multiple universal transactions into a single ordered flow across different routes.

This allows you to submit a single user-signed transaction to Push Chain that coordinates execution across Push Chain, external chains, or both.

Prerequisite: Familiarize yourself with Send Universal Transaction before reading this page.

Mental Model

  1. Prepare each transaction step with prepareTransaction
  2. Execute all steps together with executeTransactions

Prepare Transaction

pushChainClient.universal.prepareTransaction({tx}): Promise<PreparedUniversalTx>

Prepares a transaction without executing it. Returns a PreparedUniversalTx object that you pass to executeTransactions.

const preparedTx = await pushChainClient.universal.prepareTransaction({
to: '0xContractAddress',
value: BigInt(0),
data: PushChain.utils.helpers.encodeTxData({
abi: MyABI,
functionName: 'myFunction',
args: [arg1, arg2],
}),
});
info

PreparedUniversalTx is an intermediate object that you pass to executeTransactions. Most apps do not need to manually inspect or modify its fields.

TheseArgumentsare mandatory

ArgumentsTypeDescription
tx.tostring | { address: string; chain: CHAIN }Target address on Push Chain (plain string), or { address, chain } for an external chain via CEA.
PushChain.CONSTANTS.CHAIN
PushChain.CONSTANTS.CHAIN.PUSH_TESTNETPushChain.CONSTANTS.CHAIN.PUSH_TESTNET_DONUTPushChain.CONSTANTS.CHAIN.ETHEREUM_SEPOLIAPushChain.CONSTANTS.CHAIN.BNB_TESTNETPushChain.CONSTANTS.CHAIN.BASE_SEPOLIAPushChain.CONSTANTS.CHAIN.ARBITRUM_SEPOLIAPushChain.CONSTANTS.CHAIN.SOLANA_DEVNET
tx.from{ chain: CHAIN }Optional. When set, originates from the CEA on that chain.
tx.valueBigIntNative value to send in the smallest unit of the execution context.
tx.datastring | Array<{ to: string; value: bigint; data: string }>ABI-encoded calldata, or an array of calls for multicall mode.
tx.funds{ amount: bigint; token?: MoveableToken }Move tokens from origin chain atomically with the call. Use PushChain.CONSTANTS.MOVEABLE.TOKEN.<CHAIN>.<TOKEN>.

prepareTransaction accepts the same transaction arguments as Send Universal Transaction.

Returns `PreparedUniversalTx` <object>
PropertyTypeDescription
route'UOA_TO_PUSH' | 'UOA_TO_CEA' | 'CEA_TO_PUSH' | 'CEA_TO_CEA'Detected routing mode for this transaction.
estimatedGasbigintEstimated gas units for execution.
noncebigintNonce to use for submission.
deadlinebigintSignature expiry deadline.
payloadstringEncoded payload ready for submission.
gatewayRequestobjectGateway request object (inbound or outbound).
Live Playground: Inspect PreparedUniversalTx
VIRTUAL NODE IDE
Copy playground link
Copy code

Execute Transactions

pushChainClient.universal.executeTransactions(txs: PreparedUniversalTx[]): Promise<CascadedTxResponse>

Executes an ordered array of prepared transactions as a multichain flow. This is submitted and handled as a single transaction. You sign once, and the SDK coordinates execution across Push Chain and supported external chains automatically.

Each prepared transaction becomes one ordered step in the multichain flow.

const step1 = await pushChainClient.universal.prepareTransaction({...}); // Push Chain
const step2 = await pushChainClient.universal.prepareTransaction({...}); // BNB

const result = await pushChainClient.universal.executeTransactions([step1, step2]);

TheseArgumentsare mandatory

ArgumentsTypeDescription
txsPreparedUniversalTx[]Ordered array of prepared transactions from prepareTransaction.

In the API response, each executed step is reported as a hop.

Returns `CascadedTxResponse` <object>
PropertyTypeDescription
initialTxHashstringHash of the user-signed Push Chain transaction that kicked off the cascade.
initialTxResponseUniversalTxResponseFull response object for the initial Push Chain transaction.
hopsCascadeHopInfo[]Ordered list of all hops with routing and status information.
hopCountnumberTotal number of hops in the cascade.
wait(opts?)Promise<CascadeCompletionResult>Alias for waitForAll. Waits for all hops to complete.
waitForAll(opts?)Promise<CascadeCompletionResult>Waits for all hops to complete across all chains.

CascadeHopInfo fields:

PropertyTypeDescription
hopIndexnumberPosition in the cascade (0-indexed).
routestringRouting mode for this hop (UOA_TO_PUSH, UOA_TO_CEA, etc.).
executionChainCHAINChain where this hop executes.
status'pending' | 'submitted' | 'confirmed' | 'failed'Current hop status.
txHashstringResolved transaction hash once available.
outboundDetailsobjectExternal chain tx details for outbound hops, including hash, explorer URL, recipient, and amount.

CascadeCompletionResult fields:

PropertyTypeDescription
successbooleanWhether all hops completed successfully.
hopsCascadeHopInfo[]Final state of all hops.
failedAtnumberIndex of first failed hop, if any.

waitForAll options:

OptionTypeDefaultDescription
pollingIntervalMsnumber5000Polling interval in milliseconds.
timeoutnumber600000Total timeout in milliseconds (10 min).
progressHook(event: CascadeProgressEvent) => void-Progress callback per hop. Reports hopIndex, route, chain, status, txHash, elapsed.
Live Playground: Execute Multiple Transactions in One Flow
VIRTUAL NODE IDE
Copy playground link
Copy code

More Examples

Cross-Chain AMM Swap: ETH → pSOL via Push Chain AMM

Pull ETH from an Ethereum Sepolia CEA into Push Chain, swap pETH → pSOL on the Push Chain AMM (Uniswap V3 fork), then bridge the pSOL out to the user's Solana Devnet CEA. All three hops execute under a single user signature.

Live Playground: ETH → pSOL Swap → Solana
VIRTUAL NODE IDE
Copy playground link
Copy code

Fund BNB CEA then Increment Counter on BNB Testnet

Increment a counter on Push Chain, then use the CEA on BNB Testnet to increment a counter there as well. Both hops are composed into a single signature, and the playground reads the counter values before and after to confirm the changes.

Live Playground: Increment on Push Chain → BNB via CEA
VIRTUAL NODE IDE
Copy playground link
Copy code

Batch Contract Calls: Push Chain + BNB + Solana in One Signature

Increment counters on Push Chain and BNB Testnet, then trigger a call on Solana Devnet. Three independent contract interactions across three chains, all composed into a single user signature.

Live Playground: Batch Cross-Chain Contract Calls
VIRTUAL NODE IDE
Copy playground link
Copy code

Key Considerations

  • Single signature: executeTransactions submits one transaction to Push Chain. You sign once, and the SDK coordinates the full multichain execution automatically.
  • No atomicity guarantee: If a downstream hop fails, earlier hops are already on-chain. Design contracts to handle partial execution.
  • Gas per hop: Each hop has its own estimated gas. Ensure gas is properly funded.
  • Tracking: Use cascade.wait({ progressHook }) to receive live status updates per hop as they propagate across chains.

Next Steps