-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SDK - Reworked advanced section for the 'recommended path' (#1865)
* reworked advanced section for the 'recommended path' * edits * minor fixes --------- Co-authored-by: Alexandra Tran <[email protected]>
- Loading branch information
1 parent
05faf12
commit 9298341
Showing
5 changed files
with
244 additions
and
163 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,132 +1,157 @@ | ||
--- | ||
description: Batch multiple JSON-RPC requests. | ||
description: Batch multiple JSON-RPC requests using MetaMask SDK or Wagmi. | ||
--- | ||
|
||
# Batch requests | ||
|
||
You can batch multiple JSON-RPC requests in your JavaScript dapp. | ||
MetaMask SDK provides mechanisms to send multiple JSON-RPC requests in a single call. | ||
However, "batching" can be used in two different contexts: | ||
|
||
The SDK's `metamask_batch` method enables you to batch multiple JSON-RPC requests in a single call, | ||
providing a streamlined approach for dapps to interact with EVM networks, and enabling complex | ||
sequences of actions. | ||
This method enhances performance, usability, and efficiency by reducing the number of network calls | ||
made to MetaMask. | ||
1. [**Wagmi batching for contract reads**](#use-wagmi-usereadcontracts) - 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. | ||
|
||
Use cases include: | ||
:::note | ||
`useReadContracts` does not support batching JSON-RPC methods. | ||
::: | ||
|
||
- **Batching multiple signatures** - Send multiple signing requests in one batch. | ||
2. [**Vanilla JavaScript batching with `metamask_batch`**](#use-vanilla-javascript-metamask_batch) - | ||
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). | ||
Despite being batched into one HTTP request, each call still requires individual user approval, and if any request is rejected, the entire batch fails. | ||
|
||
- **Switching networks** - Switch the EVM network, perform an action such as sending a transaction, | ||
and switch back, all in one batch. | ||
## Use Wagmi (`useReadContracts`) | ||
|
||
- **Mixed transactions and signatures** - Combine transaction sending and signing requests in one batch. | ||
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. | ||
|
||
`metamask_batch` opens up additional possibilities for sophisticated transaction flows in dapps, | ||
enhancing the user experience and operational efficiency. | ||
For more information, see the [Wagmi documentation](https://wagmi.sh/react/api/hooks/useReadContracts). | ||
|
||
## Prerequisites | ||
The following is an example of batching read operations using `useReadContracts`: | ||
|
||
Set up MetaMask SDK in your JavaScript dapp. | ||
```js | ||
import { useReadContracts } from "wagmi"; | ||
|
||
## Use the `metamask_batch` method | ||
// Example contract definitions with their address and ABI | ||
const contractA = { | ||
address: "0xContractAddress1", | ||
abi: contractABI1, | ||
} as const; | ||
|
||
`metamask_batch` takes an array of JSON-RPC requests (`ChainRPC[]`) as its parameter. | ||
const contractB = { | ||
address: "0xContractAddress2", | ||
abi: contractABI2, | ||
} as const; | ||
|
||
Each request in the batch is independent. | ||
The user receives a prompt for each action within the batch, allowing them to approve or reject | ||
individual requests. | ||
If any request is rejected, the entire batch fails and an error is returned, ensuring integrity in | ||
transactional operations. | ||
function MyBatchReadComponent() { | ||
const { data, isError, isLoading } = useReadContracts({ | ||
contracts: [ | ||
{ | ||
...contractA, | ||
functionName: "getValueA", | ||
}, | ||
{ | ||
...contractA, | ||
functionName: "getValueB", | ||
}, | ||
{ | ||
...contractB, | ||
functionName: "getValueX", | ||
args: [42], | ||
}, | ||
{ | ||
...contractB, | ||
functionName: "getValueY", | ||
args: [42], | ||
}, | ||
], | ||
}); | ||
|
||
if (isLoading) return <div>Loading...</div>; | ||
if (isError) return <div>Error fetching data.</div>; | ||
|
||
return ( | ||
<div> | ||
<p>getValueA: {data?.[0]?.toString()}</p> | ||
<p>getValueB: {data?.[1]?.toString()}</p> | ||
<p>getValueX: {data?.[2]?.toString()}</p> | ||
<p>getValueY: {data?.[3]?.toString()}</p> | ||
</div> | ||
); | ||
} | ||
``` | ||
The method returns an array of results corresponding to each request. | ||
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. | ||
### React / Next.js / React Native example | ||
:::tip | ||
For a better user experience, it's important to use reliable RPC providers instead of public nodes. | ||
We recommend using services like [MetaMask Developer](https://developer.metamask.io/) to ensure better reliability and performance. | ||
::: | ||
The following is an example of using `metamask_batch` to batch | ||
[`personal_sign`](/wallet/reference/json-rpc-methods/personal_sign) and | ||
[`eth_sendTransaction`](/wallet/reference/json-rpc-methods/eth_sendtransaction) in React, Next.js, or React Native/Expo: | ||
## Use Vanilla JavaScript (`metamask_batch`) | ||
```javascript title="index.js" | ||
import { metamask_batch } from "metamask-sdk" | ||
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. | ||
function MyComponent() { | ||
const handleBatchRequest = async () => { | ||
const batchRequests = [ | ||
{ method: "personal_sign", params: ["message", "address"] }, | ||
{ | ||
method: "eth_sendTransaction", | ||
params: [ | ||
{ | ||
/* Transaction parameters */ | ||
}, | ||
], | ||
}, | ||
] | ||
|
||
try { | ||
const results = await metamask_batch(batchRequests) | ||
console.log(results) // Process results. | ||
} catch (error) { | ||
console.error("Batch request failed", error) | ||
} | ||
} | ||
Use cases include: | ||
return <button onClick={handleBatchRequest}>Send Batch Request</button> | ||
} | ||
``` | ||
- **Batching multiple signatures** - Send multiple signing requests in one batch. | ||
- **Switching networks** - Switch the EVM network, perform an action such as sending a transaction, and switch back, all in one batch. | ||
- **Mixed transactions and signatures** - Combine transaction sending and signing requests in one batch. | ||
### Vue.js example | ||
:::note | ||
When using `metamask_batch`, keep in mind the following: | ||
The following is an example of using `metamask_batch` to batch | ||
[`personal_sign`](/wallet/reference/json-rpc-methods/personal_sign) and | ||
[`eth_sendTransaction`](/wallet/reference/json-rpc-methods/eth_sendtransaction) in Vue.js: | ||
- Even though the requests are batched, each individual request still requires user approval. | ||
- If any request in the batch is rejected, the entire batch will fail. | ||
::: | ||
```javascript title="App.vue" | ||
<script> | ||
import { metamask_batch } from "metamask-sdk"; | ||
The following is an example of batching JSON-RPC requests using `metamask_batch`: | ||
export default { | ||
methods: { | ||
async sendBatchRequest() { | ||
const batchRequests = [ | ||
{ method: "personal_sign", params: ["message", "address"] }, | ||
```js | ||
import { MetaMaskSDK } from "@metamask/sdk"; | ||
|
||
const MMSDK = new MetaMaskSDK(); | ||
const provider = MMSDK.getProvider(); | ||
|
||
async function handleBatchRequests() { | ||
// Example batch: one personal_sign call and one eth_sendTransaction call. | ||
const requests = [ | ||
{ method: "personal_sign", params: ["Hello from batch!", "0x1234..."] }, | ||
{ | ||
method: "eth_sendTransaction", | ||
params: [ | ||
{ | ||
method: "eth_sendTransaction", | ||
params: [ | ||
{ | ||
/* Transaction parameters */ | ||
}, | ||
], | ||
from: "0x1234...", | ||
to: "0xABCD...", | ||
// Additional transaction parameters. | ||
}, | ||
]; | ||
|
||
try { | ||
const results = await metamask_batch(batchRequests); | ||
console.log(results); | ||
} catch (error) { | ||
console.error("Error in batch request", error); | ||
} | ||
} | ||
], | ||
}, | ||
]; | ||
|
||
try { | ||
const results = await provider.request({ | ||
method: "metamask_batch", | ||
params: [requests], | ||
}); | ||
console.log("Batch Results:", results); | ||
} catch (err) { | ||
console.error("Batch request failed:", err); | ||
} | ||
} | ||
</script> | ||
``` | ||
|
||
### Best practices | ||
|
||
Follow these best practices when using `metamask_batch`: | ||
|
||
- **Ensure each request in the batch is properly formatted** according to the JSON-RPC specifications. | ||
document.getElementById("batchBtn").addEventListener("click", handleBatchRequests); | ||
``` | ||
- **Handle errors appropriately**, especially when a batch request is partially approved. | ||
The following HTML displays a **Send Batch** button: | ||
- **Test batch operations** to ensure consistent behavior across different networks and accounts. | ||
```html | ||
<button id="batchBtn">Send Batch</button> | ||
``` | ||
- **Be aware of the dependencies between chained requests.** | ||
Avoid creating a dependency where the outcome of one request directly influences the context or | ||
validity of a subsequent request within the same batch. | ||
For example, avoid chaining a [`wallet_switchEthereumChain`](/wallet/reference/json-rpc-methods/wallet_switchethereumchain) | ||
request with [`eth_signTypedData_v4`](/wallet/reference/json-rpc-methods/eth_signtypeddata_v4), because | ||
`eth_signTypedData_v4` relies on the current chain ID, which would be altered by `wallet_switchEthereumChain`. | ||
This approach ensures that each request in the batch operates independently and maintains its | ||
integrity, regardless of changes introduced by preceding requests in the batch. | ||
:::tip Tips | ||
- For a better user experience, it's important to use reliable RPC providers instead of public nodes. | ||
We recommend using services like [MetaMask Developer](https://developer.metamask.io/) to ensure better reliability and performance. | ||
- Ensure that requests in a batch do not depend on one another's chain context, as mid-batch state changes can affect outcomes. | ||
::: |
Oops, something went wrong.