|
1 | 1 | --- |
2 | | -description: Batch multiple JSON-RPC requests. |
| 2 | +description: Batch multiple JSON-RPC requests using MetaMask SDK or Wagmi. |
3 | 3 | --- |
4 | 4 |
|
5 | | -# Batch requests |
| 5 | +# Batch Requests |
6 | 6 |
|
7 | | -You can batch multiple JSON-RPC requests in your JavaScript dapp. |
| 7 | +MetaMask SDK provides mechanisms to send multiple JSON-RPC requests in a single call. However, it's important to note that the term "batching" is used in two different contexts here: |
8 | 8 |
|
9 | | -The SDK's `metamask_batch` method enables you to batch multiple JSON-RPC requests in a single call, |
10 | | -providing a streamlined approach for dapps to interact with EVM networks, and enabling complex |
11 | | -sequences of actions. |
12 | | -This method enhances performance, usability, and efficiency by reducing the number of network calls |
13 | | -made to MetaMask. |
| 9 | +1. **Wagmi Batching for Contract Reads:** |
| 10 | + Wagmi does not support MetaMask’s generic batching mechanism. Instead, it provides the [`useReadContracts`](https://wagmi.sh/react/api/hooks/useReadContracts) hook to perform multiple contract read operations in a single hook call. This is specialized for retrieving data from smart contracts and returns an array of results corresponding to each read call. |
14 | 11 |
|
15 | | -Use cases include: |
| 12 | +2. **Vanilla JavaScript Batching with `metamask_batch`:** |
| 13 | + This approach uses MetaMask SDK’s `metamask_batch` method to group any JSON-RPC requests together, whether they are contract calls or other JSON-RPC methods (e.g., signing messages, sending transactions). Despite being batched into one HTTP request, each call still requires individual user approval, and if any request is rejected, the entire batch fails. |
16 | 14 |
|
17 | | -- **Batching multiple signatures** - Send multiple signing requests in one batch. |
| 15 | +## Wagmi (Read Operations with `useReadContracts`) |
18 | 16 |
|
19 | | -- **Switching networks** - Switch the EVM network, perform an action such as sending a transaction, |
20 | | - and switch back, all in one batch. |
| 17 | +When using Wagmi, you can perform multiple contract read operations in a single hook call using `useReadContracts`. This method is designed specifically for contract calls and batches them together internally, returning the results as an array. It is not a generic JSON-RPC batching tool but rather a specialized solution for reading from smart contracts. |
21 | 18 |
|
22 | | -- **Mixed transactions and signatures** - Combine transaction sending and signing requests in one batch. |
| 19 | +For more information, see the [Wagmi documentation](https://wagmi.sh/react/api/hooks/useReadContracts). |
| 20 | + |
| 21 | +Below is an example: |
23 | 22 |
|
24 | | -`metamask_batch` opens up additional possibilities for sophisticated transaction flows in dapps, |
25 | | -enhancing the user experience and operational efficiency. |
| 23 | +```js |
| 24 | +import { useReadContracts } from 'wagmi'; |
26 | 25 |
|
27 | | -## Prerequisites |
| 26 | +// Example contract definitions with their address and ABI |
| 27 | +const contractA = { |
| 28 | + address: '0xContractAddress1', |
| 29 | + abi: contractABI1, |
| 30 | +} as const; |
28 | 31 |
|
29 | | -Set up MetaMask SDK in your JavaScript dapp. |
| 32 | +const contractB = { |
| 33 | + address: '0xContractAddress2', |
| 34 | + abi: contractABI2, |
| 35 | +} as const; |
30 | 36 |
|
31 | | -## Use the `metamask_batch` method |
| 37 | +function MyBatchReadComponent() { |
| 38 | + const { data, isError, isLoading } = useReadContracts({ |
| 39 | + contracts: [ |
| 40 | + { |
| 41 | + ...contractA, |
| 42 | + functionName: 'getValueA', |
| 43 | + }, |
| 44 | + { |
| 45 | + ...contractA, |
| 46 | + functionName: 'getValueB', |
| 47 | + }, |
| 48 | + { |
| 49 | + ...contractB, |
| 50 | + functionName: 'getValueX', |
| 51 | + args: [42], |
| 52 | + }, |
| 53 | + { |
| 54 | + ...contractB, |
| 55 | + functionName: 'getValueY', |
| 56 | + args: [42], |
| 57 | + }, |
| 58 | + ], |
| 59 | + }); |
| 60 | + |
| 61 | + if (isLoading) return <div>Loading...</div>; |
| 62 | + if (isError) return <div>Error fetching data.</div>; |
| 63 | + |
| 64 | + return ( |
| 65 | + <div> |
| 66 | + <p>getValueA: {data?.[0]?.toString()}</p> |
| 67 | + <p>getValueB: {data?.[1]?.toString()}</p> |
| 68 | + <p>getValueX: {data?.[2]?.toString()}</p> |
| 69 | + <p>getValueY: {data?.[3]?.toString()}</p> |
| 70 | + </div> |
| 71 | + ); |
| 72 | +} |
| 73 | +``` |
32 | 74 |
|
33 | | -`metamask_batch` takes an array of JSON-RPC requests (`ChainRPC[]`) as its parameter. |
| 75 | +In this example, four contract read calls are batched together. The results are returned as an array in the same order as the calls, allowing you to process each result accordingly. |
34 | 76 |
|
35 | | -Each request in the batch is independent. |
36 | | -The user receives a prompt for each action within the batch, allowing them to approve or reject |
37 | | -individual requests. |
38 | | -If any request is rejected, the entire batch fails and an error is returned, ensuring integrity in |
39 | | -transactional operations. |
| 77 | +:::tip |
| 78 | +For a better user experience, it's important to use reliable RPC providers instead of public nodes. |
| 79 | +We recommend using services like [MetaMask Developer](https://developer.metamask.io/) to ensure better reliability and performance. |
| 80 | +::: |
40 | 81 |
|
41 | | -The method returns an array of results corresponding to each request. |
42 | 82 |
|
43 | | -### React / Next.js / React Native example |
| 83 | +## Vanilla JavaScript (Using `metamask_batch`) |
44 | 84 |
|
45 | | -The following is an example of using `metamask_batch` to batch |
46 | | -[`personal_sign`](/wallet/reference/json-rpc-methods/personal_sign) and |
47 | | -[`eth_sendTransaction`](/wallet/reference/json-rpc-methods/eth_sendtransaction) in React, Next.js, or React Native/Expo: |
| 85 | +If you’re **not** using Wagmi, you can directly utilize MetaMask SDK’s `metamask_batch` method to group multiple JSON-RPC requests into a single HTTP call. |
48 | 86 |
|
49 | | -```javascript title="index.js" |
50 | | -import { metamask_batch } from "metamask-sdk" |
| 87 | +Use cases include: |
51 | 88 |
|
52 | | -function MyComponent() { |
53 | | - const handleBatchRequest = async () => { |
54 | | - const batchRequests = [ |
55 | | - { method: "personal_sign", params: ["message", "address"] }, |
56 | | - { |
57 | | - method: "eth_sendTransaction", |
58 | | - params: [ |
59 | | - { |
60 | | - /* Transaction parameters */ |
61 | | - }, |
62 | | - ], |
63 | | - }, |
64 | | - ] |
65 | | - |
66 | | - try { |
67 | | - const results = await metamask_batch(batchRequests) |
68 | | - console.log(results) // Process results. |
69 | | - } catch (error) { |
70 | | - console.error("Batch request failed", error) |
71 | | - } |
72 | | - } |
| 89 | +- **Batching multiple signatures** - Send multiple signing requests in one batch. |
| 90 | +- **Switching networks** - Switch the EVM network, perform an action such as sending a transaction, and switch back, all in one batch. |
| 91 | +- **Mixed transactions and signatures** - Combine transaction sending and signing requests in one batch. |
73 | 92 |
|
74 | | - return <button onClick={handleBatchRequest}>Send Batch Request</button> |
75 | | -} |
76 | | -``` |
| 93 | +However, keep in mind: |
77 | 94 |
|
78 | | -### Vue.js example |
| 95 | +- **Individual Approvals:** Even though the requests are batched, each individual request still requires user approval. |
| 96 | +- **Batch Failure:** If any request in the batch is rejected, the entire batch will fail. |
79 | 97 |
|
80 | | -The following is an example of using `metamask_batch` to batch |
81 | | -[`personal_sign`](/wallet/reference/json-rpc-methods/personal_sign) and |
82 | | -[`eth_sendTransaction`](/wallet/reference/json-rpc-methods/eth_sendtransaction) in Vue.js: |
| 98 | +```js |
| 99 | +import { MetaMaskSDK } from "@metamask/sdk"; |
83 | 100 |
|
84 | | -```javascript title="App.vue" |
85 | | -<script> |
86 | | -import { metamask_batch } from "metamask-sdk"; |
| 101 | +const MMSDK = new MetaMaskSDK(); |
| 102 | +const provider = MMSDK.getProvider(); |
87 | 103 |
|
88 | | -export default { |
89 | | - methods: { |
90 | | - async sendBatchRequest() { |
91 | | - const batchRequests = [ |
92 | | - { method: "personal_sign", params: ["message", "address"] }, |
| 104 | +async function handleBatchRequests() { |
| 105 | + // Example batch: one personal_sign call and one eth_sendTransaction call. |
| 106 | + const requests = [ |
| 107 | + { method: "personal_sign", params: ["Hello from batch!", "0x1234..."] }, |
| 108 | + { |
| 109 | + method: "eth_sendTransaction", |
| 110 | + params: [ |
93 | 111 | { |
94 | | - method: "eth_sendTransaction", |
95 | | - params: [ |
96 | | - { |
97 | | - /* Transaction parameters */ |
98 | | - }, |
99 | | - ], |
| 112 | + from: "0x1234...", |
| 113 | + to: "0xABCD...", |
| 114 | + // additional transaction parameters |
100 | 115 | }, |
101 | | - ]; |
102 | | - |
103 | | - try { |
104 | | - const results = await metamask_batch(batchRequests); |
105 | | - console.log(results); |
106 | | - } catch (error) { |
107 | | - console.error("Error in batch request", error); |
108 | | - } |
109 | | - } |
| 116 | + ], |
| 117 | + }, |
| 118 | + ]; |
| 119 | + |
| 120 | + try { |
| 121 | + const results = await provider.request({ |
| 122 | + method: "metamask_batch", |
| 123 | + params: [requests], |
| 124 | + }); |
| 125 | + console.log("Batch Results:", results); |
| 126 | + } catch (err) { |
| 127 | + console.error("Batch request failed:", err); |
110 | 128 | } |
111 | 129 | } |
112 | | -</script> |
| 130 | + |
| 131 | +document.getElementById("batchBtn").addEventListener("click", handleBatchRequests); |
113 | 132 | ``` |
114 | 133 |
|
115 | | -### Best practices |
| 134 | +Include the following HTML in your document: |
116 | 135 |
|
117 | | -Follow these best practices when using `metamask_batch`: |
| 136 | +```html |
| 137 | +<button id="batchBtn">Send Batch</button> |
| 138 | +``` |
| 139 | +
|
| 140 | +--- |
118 | 141 |
|
119 | | -- **Ensure each request in the batch is properly formatted** according to the JSON-RPC specifications. |
| 142 | +### Important Distinctions and Notes |
120 | 143 |
|
121 | | -- **Handle errors appropriately**, especially when a batch request is partially approved. |
| 144 | +- **Different Batching Purposes:** |
| 145 | + - **Wagmi's `useReadContracts`:** |
| 146 | + - Specifically designed for reading data from smart contracts. |
| 147 | + - Batches multiple contract read operations and returns results in a structured array. |
| 148 | + - Does not support general JSON-RPC methods (e.g., signing messages or sending transactions). |
| 149 | + |
| 150 | + - **Vanilla JavaScript's `metamask_batch`:** |
| 151 | + - A generic JSON-RPC batching method provided by MetaMask SDK. |
| 152 | + - Can batch any type of JSON-RPC requests (reads, writes, signing, etc.). |
| 153 | + - Each batched request still requires individual user approval. |
122 | 154 |
|
123 | | -- **Test batch operations** to ensure consistent behavior across different networks and accounts. |
| 155 | +- **User Experience:** |
| 156 | + For a better user experience, especially when making multiple contract read calls, it is recommended to use reliable RPC providers rather than public nodes. We suggest using services like [MetaMask Developer](https://developer.metamask.io/) to ensure enhanced reliability and performance. |
124 | 157 |
|
125 | | -- **Be aware of the dependencies between chained requests.** |
126 | | - Avoid creating a dependency where the outcome of one request directly influences the context or |
127 | | - validity of a subsequent request within the same batch. |
128 | | - For example, avoid chaining a [`wallet_switchEthereumChain`](/wallet/reference/json-rpc-methods/wallet_switchethereumchain) |
129 | | - request with [`eth_signTypedData_v4`](/wallet/reference/json-rpc-methods/eth_signtypeddata_v4), because |
130 | | - `eth_signTypedData_v4` relies on the current chain ID, which would be altered by `wallet_switchEthereumChain`. |
131 | | - This approach ensures that each request in the batch operates independently and maintains its |
132 | | - integrity, regardless of changes introduced by preceding requests in the batch. |
| 158 | +- **Chain Context:** |
| 159 | + Ensure that requests in a batch do not depend on one another’s chain context, as mid-batch state changes can affect outcomes. |
0 commit comments