Skip to content

Commit 43de9d2

Browse files
Batching transactions with Viem (#389)
* Batching transactions with Viem * Simplify function
1 parent 222a902 commit 43de9d2

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

docs/building-on-etherlink/transactions.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,101 @@ async function sendTransaction() {
363363
sendTransaction();
364364
```
365365

366+
## Batching transactions
367+
368+
Because the sequencer orders transactions in the order that it receives them, you cannot expect transactions that you submit to run sequentially, even if you submit them quickly.
369+
To ensure that your transactions run in the same block or sequence, you can submit them in a batch by signing them all first and submitting them at the same time.
370+
371+
The following example uses the [`viem`](https://viem.sh/) SDK to create five transactions that send XTZ to an account and submit them in a batch.
372+
It configures the Viem client to send transactions as a batch, signs multiple transactions, and submits them all at once so Viem uses [Batch JSON-RPC](https://viem.sh/docs/clients/transports/http#batch-json-rpc) to send them as a batch.
373+
374+
Note that the code submits the transaction to the relay endpoint, not the usual RPC endpoint, because the public RPC node has a load balancer that splits transactions into single RPC requests.
375+
However, the relay endpoint accepts transactions only via the `eth_sendRawTransaction` endpoint, so the code uses the `sendRawTransaction` method to send transactions to this endpoint.
376+
Other EVM clients may not use this endpoint to send transactions and therefore cannot use the relay endpoint.
377+
In this case, you can set up your own Etherlink EVM node and send batched transactions to it.
378+
379+
```javascript
380+
import { createWalletClient, createPublicClient, http, parseEther } from 'viem'; // "viem": "^2.27"
381+
import { privateKeyToAccount } from 'viem/accounts';
382+
383+
const etherlinkShadownet = {
384+
"id": 127823,
385+
"name": "Etherlink Shadownet",
386+
"nativeCurrency": {
387+
"decimals": 18,
388+
"name": "Tez",
389+
"symbol": "XTZ"
390+
},
391+
"rpcUrls": {
392+
"default": {
393+
"http": [
394+
"https://node.shadownet.etherlink.com"
395+
]
396+
}
397+
},
398+
"blockExplorers": {
399+
"default": {
400+
"name": "Etherlink Shadownet",
401+
"url": "https://shadownet.explorer.etherlink.com"
402+
}
403+
},
404+
"testnet": true
405+
}
406+
407+
async function main() {
408+
const client = createWalletClient({
409+
chain: etherlinkShadownet,
410+
transport: http()
411+
});
412+
413+
const publicClient = createPublicClient({
414+
chain: etherlinkShadownet,
415+
transport: http()
416+
});
417+
418+
// Relay supports eth_blockNumber & eth_sendRawTransaction only
419+
const publicRelayClient = createPublicClient({
420+
transport: http('https://relay.shadownet.etherlink.com', { batch: true }),
421+
});
422+
423+
// Add the sender's private key
424+
const account = privateKeyToAccount('');
425+
426+
const startingNonce = await publicClient.getTransactionCount({ address: account.address });
427+
428+
const signedTransactions = [];
429+
430+
// Create an array of signed transactions
431+
for (let i = 0; i < 5; i++) {
432+
const requestData = {
433+
account,
434+
to: '0x45Ff91b4bF16aC9907CF4A11436f9Ce61BE0650d',
435+
value: parseEther('0.001'),
436+
nonce: startingNonce + i
437+
};
438+
439+
const request = await client.prepareTransactionRequest(requestData);
440+
const signedTx = await client.signTransaction(request);
441+
signedTransactions.push(signedTx);
442+
}
443+
444+
// Batch send raw transactions
445+
const transactionHashes = await Promise.all(
446+
signedTransactions.map((serializedTransaction) =>
447+
publicRelayClient.sendRawTransaction({ serializedTransaction })
448+
)
449+
);
450+
451+
console.log('Signed transactions:', JSON.stringify(signedTransactions, null, 2));
452+
console.log('Transaction hashes:', transactionHashes);
453+
}
454+
455+
main().catch((error) => {
456+
console.error('Unhandled error:', error);
457+
process.exit(1);
458+
});
459+
```
460+
366461
## Getting event logs
367462

368463
Etherlink does not support listening for smart contract events with endpoints such as `eth_newFilter` and `eth_getFilterChanges`.

0 commit comments

Comments
 (0)