|
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 | 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. |
| 8 | +However, "batching" can be used in two different contexts: |
8 | 9 |
|
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. |
| 10 | +1. [**Wagmi batching for contract reads**](#use-wagmi-usereadcontracts) - Wagmi does not support MetaMask's generic batching mechanism. |
| 11 | + Instead, it provides the [`useReadContracts`](https://wagmi.sh/react/api/hooks/useReadContracts) hook to perform multiple contract read operations in a single hook call. |
| 12 | + This is specialized for retrieving data from smart contracts and returns an array of results corresponding to each read call. |
14 | 13 |
|
15 |
| -Use cases include: |
| 14 | + :::note |
| 15 | + `useReadContracts` does not support batching JSON-RPC methods. |
| 16 | + ::: |
16 | 17 |
|
17 |
| -- **Batching multiple signatures** - Send multiple signing requests in one batch. |
| 18 | +2. [**Vanilla JavaScript batching with `metamask_batch`**](#use-vanilla-javascript-metamask_batch) - |
| 19 | + 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 (for example, signing messages or sending transactions). |
| 20 | + Despite being batched into one HTTP request, each call still requires individual user approval, and if any request is rejected, the entire batch fails. |
18 | 21 |
|
19 |
| -- **Switching networks** - Switch the EVM network, perform an action such as sending a transaction, |
20 |
| - and switch back, all in one batch. |
| 22 | +## Use Wagmi (`useReadContracts`) |
21 | 23 |
|
22 |
| -- **Mixed transactions and signatures** - Combine transaction sending and signing requests in one batch. |
| 24 | +When using Wagmi, you can perform multiple contract read operations in a single hook call using `useReadContracts`. |
| 25 | +This method is designed specifically for contract calls and batches them together internally, returning the results as an array. |
| 26 | +It is not a generic JSON-RPC batching tool but rather a specialized solution for reading from smart contracts. |
23 | 27 |
|
24 |
| -`metamask_batch` opens up additional possibilities for sophisticated transaction flows in dapps, |
25 |
| -enhancing the user experience and operational efficiency. |
| 28 | +For more information, see the [Wagmi documentation](https://wagmi.sh/react/api/hooks/useReadContracts). |
26 | 29 |
|
27 |
| -## Prerequisites |
| 30 | +The following is an example of batching read operations using `useReadContracts`: |
28 | 31 |
|
29 |
| -Set up MetaMask SDK in your JavaScript dapp. |
| 32 | +```js |
| 33 | +import { useReadContracts } from "wagmi"; |
30 | 34 |
|
31 |
| -## Use the `metamask_batch` method |
| 35 | +// Example contract definitions with their address and ABI |
| 36 | +const contractA = { |
| 37 | + address: "0xContractAddress1", |
| 38 | + abi: contractABI1, |
| 39 | +} as const; |
32 | 40 |
|
33 |
| -`metamask_batch` takes an array of JSON-RPC requests (`ChainRPC[]`) as its parameter. |
| 41 | +const contractB = { |
| 42 | + address: "0xContractAddress2", |
| 43 | + abi: contractABI2, |
| 44 | +} as const; |
34 | 45 |
|
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. |
| 46 | +function MyBatchReadComponent() { |
| 47 | + const { data, isError, isLoading } = useReadContracts({ |
| 48 | + contracts: [ |
| 49 | + { |
| 50 | + ...contractA, |
| 51 | + functionName: "getValueA", |
| 52 | + }, |
| 53 | + { |
| 54 | + ...contractA, |
| 55 | + functionName: "getValueB", |
| 56 | + }, |
| 57 | + { |
| 58 | + ...contractB, |
| 59 | + functionName: "getValueX", |
| 60 | + args: [42], |
| 61 | + }, |
| 62 | + { |
| 63 | + ...contractB, |
| 64 | + functionName: "getValueY", |
| 65 | + args: [42], |
| 66 | + }, |
| 67 | + ], |
| 68 | + }); |
| 69 | + |
| 70 | + if (isLoading) return <div>Loading...</div>; |
| 71 | + if (isError) return <div>Error fetching data.</div>; |
| 72 | + |
| 73 | + return ( |
| 74 | + <div> |
| 75 | + <p>getValueA: {data?.[0]?.toString()}</p> |
| 76 | + <p>getValueB: {data?.[1]?.toString()}</p> |
| 77 | + <p>getValueX: {data?.[2]?.toString()}</p> |
| 78 | + <p>getValueY: {data?.[3]?.toString()}</p> |
| 79 | + </div> |
| 80 | + ); |
| 81 | +} |
| 82 | +``` |
40 | 83 |
|
41 |
| -The method returns an array of results corresponding to each request. |
| 84 | +In this example, four contract read calls are batched together. |
| 85 | +The results are returned as an array in the same order as the calls, allowing you to process each result accordingly. |
42 | 86 |
|
43 |
| -### React / Next.js / React Native example |
| 87 | +:::tip |
| 88 | +For a better user experience, it's important to use reliable RPC providers instead of public nodes. |
| 89 | +We recommend using services like [MetaMask Developer](https://developer.metamask.io/) to ensure better reliability and performance. |
| 90 | +::: |
44 | 91 |
|
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: |
| 92 | +## Use Vanilla JavaScript (`metamask_batch`) |
48 | 93 |
|
49 |
| -```javascript title="index.js" |
50 |
| -import { metamask_batch } from "metamask-sdk" |
| 94 | +If you're not using Wagmi, you can directly use MetaMask SDK's `metamask_batch` method to group multiple JSON-RPC requests into a single HTTP call. |
51 | 95 |
|
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 |
| - } |
| 96 | +Use cases include: |
73 | 97 |
|
74 |
| - return <button onClick={handleBatchRequest}>Send Batch Request</button> |
75 |
| -} |
76 |
| -``` |
| 98 | +- **Batching multiple signatures** - Send multiple signing requests in one batch. |
| 99 | +- **Switching networks** - Switch the EVM network, perform an action such as sending a transaction, and switch back, all in one batch. |
| 100 | +- **Mixed transactions and signatures** - Combine transaction sending and signing requests in one batch. |
77 | 101 |
|
78 |
| -### Vue.js example |
| 102 | +:::note |
| 103 | +When using `metamask_batch`, keep in mind the following: |
79 | 104 |
|
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: |
| 105 | +- Even though the requests are batched, each individual request still requires user approval. |
| 106 | +- If any request in the batch is rejected, the entire batch will fail. |
| 107 | +::: |
83 | 108 |
|
84 |
| -```javascript title="App.vue" |
85 |
| -<script> |
86 |
| -import { metamask_batch } from "metamask-sdk"; |
| 109 | +The following is an example of batching JSON-RPC requests using `metamask_batch`: |
87 | 110 |
|
88 |
| -export default { |
89 |
| - methods: { |
90 |
| - async sendBatchRequest() { |
91 |
| - const batchRequests = [ |
92 |
| - { method: "personal_sign", params: ["message", "address"] }, |
| 111 | +```js |
| 112 | +import { MetaMaskSDK } from "@metamask/sdk"; |
| 113 | + |
| 114 | +const MMSDK = new MetaMaskSDK(); |
| 115 | +const provider = MMSDK.getProvider(); |
| 116 | + |
| 117 | +async function handleBatchRequests() { |
| 118 | + // Example batch: one personal_sign call and one eth_sendTransaction call. |
| 119 | + const requests = [ |
| 120 | + { method: "personal_sign", params: ["Hello from batch!", "0x1234..."] }, |
| 121 | + { |
| 122 | + method: "eth_sendTransaction", |
| 123 | + params: [ |
93 | 124 | {
|
94 |
| - method: "eth_sendTransaction", |
95 |
| - params: [ |
96 |
| - { |
97 |
| - /* Transaction parameters */ |
98 |
| - }, |
99 |
| - ], |
| 125 | + from: "0x1234...", |
| 126 | + to: "0xABCD...", |
| 127 | + // Additional transaction parameters. |
100 | 128 | },
|
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 |
| - } |
| 129 | + ], |
| 130 | + }, |
| 131 | + ]; |
| 132 | + |
| 133 | + try { |
| 134 | + const results = await provider.request({ |
| 135 | + method: "metamask_batch", |
| 136 | + params: [requests], |
| 137 | + }); |
| 138 | + console.log("Batch Results:", results); |
| 139 | + } catch (err) { |
| 140 | + console.error("Batch request failed:", err); |
110 | 141 | }
|
111 | 142 | }
|
112 |
| -</script> |
113 |
| -``` |
114 |
| - |
115 |
| -### Best practices |
116 | 143 |
|
117 |
| -Follow these best practices when using `metamask_batch`: |
118 |
| - |
119 |
| -- **Ensure each request in the batch is properly formatted** according to the JSON-RPC specifications. |
| 144 | +document.getElementById("batchBtn").addEventListener("click", handleBatchRequests); |
| 145 | +``` |
120 | 146 |
|
121 |
| -- **Handle errors appropriately**, especially when a batch request is partially approved. |
| 147 | +The following HTML displays a **Send Batch** button: |
122 | 148 |
|
123 |
| -- **Test batch operations** to ensure consistent behavior across different networks and accounts. |
| 149 | +```html |
| 150 | +<button id="batchBtn">Send Batch</button> |
| 151 | +``` |
124 | 152 |
|
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. |
| 153 | +:::tip Tips |
| 154 | +- For a better user experience, it's important to use reliable RPC providers instead of public nodes. |
| 155 | + We recommend using services like [MetaMask Developer](https://developer.metamask.io/) to ensure better reliability and performance. |
| 156 | +- Ensure that requests in a batch do not depend on one another's chain context, as mid-batch state changes can affect outcomes. |
| 157 | +::: |
0 commit comments