diff --git a/.gitignore b/.gitignore index fe97056833b..8e188e9452d 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ .env.development.local .env.test.local .env.production.local +.prettierignore npm-debug.log* .vercel diff --git a/services/get-started/pricing/credit-cost.mdx b/services/get-started/pricing/credit-cost.mdx index dda4b0a267a..efc25450390 100644 --- a/services/get-started/pricing/credit-cost.mdx +++ b/services/get-started/pricing/credit-cost.mdx @@ -46,22 +46,18 @@ a specific network, then use the default Ethereum method's credit cost. - ### Trace methods - ### Filter methods ### Debug methods - - ### Subscription events You can subscribe and unsubscribe to events using [`eth_subscribe`](../../reference/ethereum/json-rpc-methods/subscription-methods/eth_subscribe.mdx) and [`eth_unsubscribe`](../../reference/ethereum/json-rpc-methods/subscription-methods/eth_unsubscribe.mdx). @@ -75,7 +71,6 @@ are charged at approximately one second intervals. - ## Polygon @@ -95,3 +90,11 @@ All Solana methods are charged at 160 credits per request. ## Gas API + +## Bundler API + +:::info +The Bundler API methods are currently only available on Ethereum Mainnet and Sepolia. +::: + + diff --git a/services/reference/_partials/bundler/_eth_estimateuseroperationgas-description.mdx b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-description.mdx new file mode 100644 index 00000000000..9703aced87d --- /dev/null +++ b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-description.mdx @@ -0,0 +1,13 @@ +import CreditCost from '@site/src/components/CreditCost/CreditCostPrice.js' + +Simulates the user operation and estimates the appropriate gas limits. Returns an error if the operation +is unsuccessful. + +:::tip +- You can use `stateOverrides` to estimate the gas cost even if the sender has no funds. + However, if the operation is sent onchain when the sender has no balance, it will revert during + the call phase due to lack of funds. + +- You can include a dummy signature for the `signature` field to estimate the gas cost. For example: + `0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c` +::: diff --git a/services/reference/_partials/bundler/_eth_estimateuseroperationgas-example.mdx b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-example.mdx new file mode 100644 index 00000000000..7411f170544 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-example.mdx @@ -0,0 +1 @@ +Replace `` with an API key from your [MetaMask Developer dashboard](https://developer.metamask.io/). \ No newline at end of file diff --git a/services/reference/_partials/bundler/_eth_estimateuseroperationgas-parameters.mdx b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-parameters.mdx new file mode 100644 index 00000000000..9a691028187 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-parameters.mdx @@ -0,0 +1,79 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +- `userOperation`: The user operation object containing the following fields: + + - `sender`: (string) - The address of the account making the operation. + - `nonce`: (string) - Unique identifier for the request from this sender. This includes the key and sequence number. + - `factory`: (string) [_optional_] - The factory contract address that will deploy the smart account if it doesn't exist yet. + - `factoryData`: (string) [_optional_] - The data passed to the factory contract to deploy the smart account. + - `callData`: (string) [_optional_] - The data to pass to the sender during the main execution call. + - `callGasLimit`: (string) - The amount of gas to allocate the main execution call. + - `verificationGasLimit`: (string) - The amount of gas to allocate for the verification step. + - `preVerificationGas`: (string) - The amount of gas to pay for to compensate the bundler for pre-verification execution and `calldata`. + - `maxFeePerGas`: (string) - Maximum fee per gas, in wei, the sender is willing to pay per gas. + - `maxPriorityFeePerGas`: (string) - Maximum fee, in wei, the sender is willing to pay per gas above the base fee. + - `paymaster`: (string) [_optional_] - Address of paymaster sponsoring the transaction, or `null` if none. + - `paymasterVerificationGasLimit`: (string) [_optional_] - The amount of gas to allocate for the verification step of the paymaster, or `null` if no paymaster. + - `paymasterPostOpGasLimit`: (string) [_optional_] - The amount of gas to allocate for the post-operation step of the paymaster, or `null` if no paymaster. + - `paymasterData`: (string) [_optional_] - The data to pass to the paymaster during the verification step, or `null` if no paymaster. + - `signature`: (string) - The signature data. For gas estimation, this can be a dummy signature. + - `eip7702Auth`: (object) [_optional_] - The EIP-7702 authorization data. This can be a dummy authorization + for estimations: + - `address`: (string) - The contract address for the authorization. + - `chainId`: (string) - The chain ID. + - `nonce`: (string) - The nonce. + - `r`: (string) - The r component of the signature. + - `s`: (string) - The s component of the signature. + - `v`: (string) - The v component of the signature. + - `yParity`: (string) - The y-parity value. + +- `entryPoint`: (string) - The EntryPoint contract address (`0x0000000071727De22E5E9d8BAf0edAc6f37da032`). + +- `stateOverrides`: (object) [_optional_] - State overrides to apply for the simulation. Each key is an address, and each value is an object that can contain: + - `balance`: (string) [_optional_] - The balance to set for the address. + - `nonce`: (string) [_optional_] - The nonce to set for the address. + - `code`: (string) [_optional_] - The code to set for the address. + - `state`: (object) [_optional_] - Complete state to set, where each key is a 32-byte hex storage slot and each value is a 32-byte hex value. + - `stateDiff`: (object) [_optional_] - State differences to apply, where each key is a 32-byte hex storage slot and each value is a 32-byte hex value. + + + + +- `userOperation`: The user operation object containing the following fields: + + - `sender`: (string) - The address of the account making the operation. + - `nonce`: (string) - Unique identifier for the request from this sender. + - `initCode`: (string) - The initialization code for the smart account if it doesn't exist yet. + - `callData`: (string) [_optional_] - The data to pass to the sender during the main execution call. + - `callGasLimit`: (string) - The amount of gas to allocate the main execution call. + - `verificationGasLimit`: (string) - The amount of gas to allocate for the verification step. + - `preVerificationGas`: (string) - The amount of gas to pay for to compensate the bundler for pre-verification execution and `calldata`. + - `maxFeePerGas`: (string) - Maximum fee per gas, in wei, the sender is willing to pay per gas. + - `maxPriorityFeePerGas`: (string) - Maximum fee, in wei, the sender is willing to pay per gas above the base fee. + - `paymasterAndData`: (string) - The address of the paymaster contract and the data that will be passed to it. + - `signature`: (string) - The signature data. For gas estimation, this can be a dummy signature. + - `eip7702Auth`: (object) [_optional_] - The EIP-7702 authorization data. This can be a dummy authorization + for estimations: + - `address`: (string) - The contract address for the authorization. + - `chainId`: (string) - The chain ID. + - `nonce`: (string) - The nonce. + - `r`: (string) - The r component of the signature. + - `s`: (string) - The s component of the signature. + - `v`: (string) - The v component of the signature. + - `yParity`: (string) - The y-parity value. + +- `entryPoint`: (string) - The EntryPoint contract address (`0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789`). + +- `stateOverrides`: (object) [_optional_] - State overrides to apply for the simulation. Each key is an address, and each value is an object that can contain: + - `balance`: (string) [_optional_] - The balance to set for the address. + - `nonce`: (string) [_optional_] - The nonce to set for the address. + - `code`: (string) [_optional_] - The code to set for the address. + - `state`: (object) [_optional_] - Complete state to set, where each key is a 32-byte hex storage slot and each value is a 32-byte hex value. + - `stateDiff`: (object) [_optional_] - State differences to apply, where each key is a 32-byte hex storage slot and each value is a 32-byte hex value. + + + diff --git a/services/reference/_partials/bundler/_eth_estimateuseroperationgas-request.mdx b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-request.mdx new file mode 100644 index 00000000000..510e4dc1079 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-request.mdx @@ -0,0 +1,82 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + + ```bash + curl https://mainnet.infura.io/v3/ \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "eth_estimateUserOperationGas", + "params": [ + { + "sender": "0x5a6b47F4131bf1feAFA56A05573314BcF44C9149", + "nonce": "0x845adb2c711129d4f3966735ed98a9f09fc4ce5700000000000000000000", + "factory": "0xd703aaE79538628d27099B8c4f621bE4CCd142d5", + "factoryData": "0xc5265d5d000000000000000000000000aac5d4240af87249b3f71bc8e4a2cae074a3e419", + "callData": "0xe9ae5c5300000000000000000000000000000000000000000000000000000000000000000000000000", + "callGasLimit": "0x0", + "verificationGasLimit": "0x0", + "preVerificationGas": "0x0", + "maxFeePerGas": "0x7a5cf70d5", + "maxPriorityFeePerGas": "0x3b9aca00", + "paymaster": null, + "paymasterVerificationGasLimit": null, + "paymasterPostOpGasLimit": null, + "paymasterData": null, + "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c" + }, + "0x0000000071727De22E5E9d8BAf0edAc6f37da032" + ], + "id": 1 + }' + ``` + + + + + ```bash + curl https://mainnet.infura.io/v3/ \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "eth_estimateUserOperationGas", + "params": [ + { + "sender": "0xa203fDb8bC335F86016F635b85389B62B189E417", + "nonce": "0x35bf2a054f92f3730b87582ef223c8d663f9eb01158154750000000000000000", + "factory": "0xd703aaE79538628d27099B8c4f621bE4CCd142d5", + "callData": "0xb61d27f6000000000000000000000000530fff22987e137e7c8d2adcc4c15eb45b4fa752", + "callGasLimit": "0x0", + "verificationGasLimit": "0x0", + "preVerificationGas": "0x0", + "maxPriorityFeePerGas": "0x12a05f200", + "maxFeePerGas": "0x5b08082fa", + "paymaster": null, + "paymasterVerificationGasLimit": null, + "paymasterPostOpGasLimit": null, + "paymasterData": null, + "signature": "0xa6cc6589c8bd561cfd68d7b6b0757ef6f208e7438782939938498eee7d703260137856c840c491b3d415956265e81bf5c2184a725be2abfc365f7536b6af525e1c" + }, + "0x0000000071727De22E5E9d8BAf0edAc6f37da032", + { + "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3": { + "balance": "0xde0b6b3a7640000" + }, + "0xebe8efa441b9302a0d7eaecc277c09d20d684540": { + "stateDiff": { + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80": "0x21" + } + } + } + ], + "id": 1 + }' + ``` + + + \ No newline at end of file diff --git a/services/reference/_partials/bundler/_eth_estimateuseroperationgas-response.mdx b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-response.mdx new file mode 100644 index 00000000000..0567dbde663 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-response.mdx @@ -0,0 +1,22 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + + ```JSON + { + "jsonrpc": "2.0", + "id": 1, + "result": { + "preVerificationGas": "0xd3e3", + "verificationGasLimit": "0x60b01", + "callGasLimit": "0x13880", + "paymasterVerificationGasLimit": "0x0", + "paymasterPostOpGasLimit": "0x0" + } + } + ``` + + + \ No newline at end of file diff --git a/services/reference/_partials/bundler/_eth_estimateuseroperationgas-returns.mdx b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-returns.mdx new file mode 100644 index 00000000000..0f24bed514e --- /dev/null +++ b/services/reference/_partials/bundler/_eth_estimateuseroperationgas-returns.mdx @@ -0,0 +1,30 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +**Type:** `Object` + +An object containing the estimated gas values for the user operation. + + + + +- `preVerificationGas`: (string) - The amount of gas to pay for to compensate the bundler for + pre-verification execution and `calldata`. +- `verificationGasLimit`: (string) - The amount of gas to allocate for the verification step. +- `callGasLimit`: (string) - The amount of gas to allocate the main execution call. +- `paymasterVerificationGasLimit`: (string) - The amount of gas to allocate for the verification step + of the paymaster, or `null` if no paymaster. +- `paymasterPostOpGasLimit`: (string) - The amount of gas to allocate for the post-operation step of + the paymaster, or `null` if no paymaster. + + + + +- `preVerificationGas`: (string) - The amount of gas to pay for to compensate the bundler for + pre-verification execution and `calldata`. +- `verificationGas`: (string) - The amount of gas used for verification (legacy field from v0.6). +- `verificationGasLimit`: (string) - The amount of gas to allocate for the verification step. +- `callGasLimit`: (string) - The amount of gas to allocate the main execution call. + + + diff --git a/services/reference/_partials/bundler/_eth_getuseroperationbyhash-description.mdx b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-description.mdx new file mode 100644 index 00000000000..454b1480390 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-description.mdx @@ -0,0 +1,4 @@ +import CreditCost from '@site/src/components/CreditCost/CreditCostPrice.js' + +Fetches user operation details by providing its hash. If the user operation is not available, it +will return `null`. diff --git a/services/reference/_partials/bundler/_eth_getuseroperationbyhash-example.mdx b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-example.mdx new file mode 100644 index 00000000000..061467dfe81 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-example.mdx @@ -0,0 +1 @@ +Replace `` with an API key from your [MetaMask Developer dashboard](https://developer.metamask.io/). diff --git a/services/reference/_partials/bundler/_eth_getuseroperationbyhash-parameters.mdx b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-parameters.mdx new file mode 100644 index 00000000000..528680be2b2 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-parameters.mdx @@ -0,0 +1 @@ +- `userOpHash`: (string) - The 32-byte hash of the user operation to retrieve. diff --git a/services/reference/_partials/bundler/_eth_getuseroperationbyhash-request.mdx b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-request.mdx new file mode 100644 index 00000000000..0fa6415f653 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-request.mdx @@ -0,0 +1,20 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```bash +curl https://mainnet.infura.io/v3/ \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "eth_getUserOperationByHash", + "params": ["0xa5a579c6fd86c2d8a4d27f5bb22796614d3a31bbccaba8f3019ec001e001b95f"], + "id": 1 + }' +``` + + + diff --git a/services/reference/_partials/bundler/_eth_getuseroperationbyhash-response.mdx b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-response.mdx new file mode 100644 index 00000000000..65b704badf9 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-response.mdx @@ -0,0 +1,34 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```JSON +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "userOperation": { + "sender": "0x8C6bdb488F664EB98E12cB2671fE2389Cc227D33", + "nonce": "0x18554d9a95404c5e8ac591f8608a18f80000000000000000", + "initCode": "0xaee9762ce625e0a8f7b184670fb57c37bfe1d0f1296601cd000000000000000000000000417f5a41305ddc99d18b5e176521b468b2a31b86000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014c982ab3499d854fca39ff8326b27d3b8a9463c5d000000000000000000000000", + "callData": "0x519454470000000000000000000000008eb187a55b701f8990539bf219b7921d5d3bdadd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001647c7efe6b0000000000000000000000000000000000000000000000000000000000000080bfa0715290784075e564f966fffd9898ace1d7814f833780f62e59b0791357460000000000000000000000008c6bdb488f664eb98e12cb2671fe2389cc227d3300000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000007677265676f7279000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001b1ec8da9a52488e3f60b7b7af36c2e64f1873e03a047c2c2e9061bbef4d0a9d8f1332b32afb163075273cd462140c2a24b2c9e1276adfaae0b4cb84ef78b95e8a0000000000000000000000000000000000000000000000000000000065a32e4f00000000000000000000000000000000000000000000000000000000", + "callGasLimit": "0x39b2d", + "verificationGasLimit": "0x6fb14", + "preVerificationGas": "0xc6a0", + "maxFeePerGas": "0x974038caf", + "maxPriorityFeePerGas": "0x974038c95", + "paymasterAndData": "0xe3dc822d77f8ca7ac74c30b0dffea9fcdcaaa3210000000000000000000000000000000000000000000000000000000065a3229b00000000000000000000000000000000000000000000000000000000000000009c3e8f934f2ec99974fddae7d38107a6d899c236c1b127e97d3c074cea5bb328023e295bb95254be40c47b82633676f8716c43c81aca3f2e49c2944afd1326371b", + "signature": "0x000000003ea0a3434dfd35a9eb05c4605466a7e05a5c3fc8aaba066c83bf4b43300dfd930e2203725eafa2702f860e5b6c18b4402ffb86b0d9b9c1719f1692254039810b1b" + }, + "entryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", + "transactionHash": "0x57465d20d634421008a167cfcfcde94847dba9d6b5d3652b071d4b84e5ce74ff", + "blockHash": "0xeaeec1eff4095bdcae44d86574cf1bf08b14b26be571b7c2290f32f9f250c103", + "blockNumber": "0x31de70e" + } +} +``` + + + diff --git a/services/reference/_partials/bundler/_eth_getuseroperationbyhash-returns.mdx b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-returns.mdx new file mode 100644 index 00000000000..610fb4d10c4 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationbyhash-returns.mdx @@ -0,0 +1,20 @@ +An object containing the user operation information and transaction details, or `null` if the user +operation is not available. When available, the response object contains: + +- `userOperation`: (object) - The user operation object containing: + - `sender`: (string) - The address of the account that initiated the user operation. + - `nonce`: (string) - The nonce used for the user operation. + - `initCode`: (string) - The initialization code for account creation. + - `callData`: (string) - The data to pass to the sender during the main execution call. + - `callGasLimit`: (string) - The amount of gas allocated for the main execution call. + - `verificationGasLimit`: (string) - The amount of gas allocated for the verification step. + - `preVerificationGas`: (string) - The amount of gas to compensate the bundler for pre-verification execution. + - `maxFeePerGas`: (string) - Maximum fee per gas, in wei, the sender is willing to pay per gas. + - `maxPriorityFeePerGas`: (string) - Maximum fee, in wei, the sender is willing to pay per gas above + the base fee. + - `paymasterAndData`: (string) - The paymaster address and data. + - `signature`: (string) - The signature data for the user operation. +- `entryPoint`: (string) - The EntryPoint contract address used. +- `transactionHash`: (string) - The hash of the transaction that included this user operation. +- `blockHash`: (string) - The hash of the block containing the transaction. +- `blockNumber`: (string) - The number of the block containing the transaction. diff --git a/services/reference/_partials/bundler/_eth_getuseroperationreceipt-description.mdx b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-description.mdx new file mode 100644 index 00000000000..cf1c7bcf16f --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-description.mdx @@ -0,0 +1,4 @@ +import CreditCost from '@site/src/components/CreditCost/CreditCostPrice.js' + +Fetches the receipt of a user operation by providing its hash. If the receipt is not available, it +will return `null`. diff --git a/services/reference/_partials/bundler/_eth_getuseroperationreceipt-example.mdx b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-example.mdx new file mode 100644 index 00000000000..061467dfe81 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-example.mdx @@ -0,0 +1 @@ +Replace `` with an API key from your [MetaMask Developer dashboard](https://developer.metamask.io/). diff --git a/services/reference/_partials/bundler/_eth_getuseroperationreceipt-parameters.mdx b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-parameters.mdx new file mode 100644 index 00000000000..dc088102182 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-parameters.mdx @@ -0,0 +1 @@ +- `userOpHash`: (string) - The 32-byte hash of the user operation for which to retrieve the receipt. diff --git a/services/reference/_partials/bundler/_eth_getuseroperationreceipt-request.mdx b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-request.mdx new file mode 100644 index 00000000000..308423c40a1 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-request.mdx @@ -0,0 +1,20 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```bash +curl https://mainnet.infura.io/v3/ \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "eth_getUserOperationReceipt", + "params": ["0xa5a579c6fd86c2d8a4d27f5bb22796614d3a31bbccaba8f3019ec001e001b95f"], + "id": 1 + }' +``` + + + diff --git a/services/reference/_partials/bundler/_eth_getuseroperationreceipt-response.mdx b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-response.mdx new file mode 100644 index 00000000000..11c02b329e6 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-response.mdx @@ -0,0 +1,44 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```JSON +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "entryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", + "userOpHash": "0xa5a579c6fd86c2d8a4d27f5bb22796614d3a31bbccaba8f3019ec001e001b95f", + "sender": "0x8C6bdb488F664EB98E12cB2671fE2389Cc227D33", + "nonce": "0x18554d9a95404c5e8ac591f8608a18f80000000000000000", + "actualGasUsed": "0x7f550", + "actualGasCost": "0x4b3b147f788710", + "success": true, + "logs": [ + // ... + ], + "receipt": { + "transactionHash": "0x57465d20d634421008a167cfcfcde94847dba9d6b5d3652b071d4b84e5ce74ff", + "transactionIndex": "0x20", + "blockHash": "0xeaeec1eff4095bdcae44d86574cf1bf08b14b26be571b7c2290f32f9f250c103", + "blockNumber": "0x31de70e", + "from": "0x43370996A3Aff7B66B3AC7676dD973d01Ecec039", + "to": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", + "cumulativeGasUsed": "0x4724c3", + "gasUsed": "0x7ff5a", + "address": null, + "logs": [ + // ... + ], + "logsBloom": "0x010004000800020000000040000000000000040000000000000010000004000000080000001000000212841100000000041080000000000020000240000000000800000022001000400000080000028000040000000000200001000010000000000000000a0000000000000000800800000000004110004080800110282000000000000002000000000000000000000000000200000400000000000000240040200002000000000000400000000002000140000000000000000002200000004000000002000000000021000000000000000000000000800080108020000020000000080000000000000000000000000000000000000000000108000000102000", + "status": "0x1", + "effectiveGasPrice": "0x89b098f46" + } + } +} +``` + + + diff --git a/services/reference/_partials/bundler/_eth_getuseroperationreceipt-returns.mdx b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-returns.mdx new file mode 100644 index 00000000000..7445c2870b0 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_getuseroperationreceipt-returns.mdx @@ -0,0 +1,25 @@ +An object containing the user operation receipt information, or `null` if the receipt is not available. +When available, the receipt object contains: + +- `entryPoint`: (string) - The EntryPoint contract address. +- `userOpHash`: (string) - The hash of the user operation. +- `sender`: (string) - The address of the account that initiated the user operation. +- `nonce`: (string) - The nonce used for the user operation. +- `actualGasUsed`: (string) - The actual amount of gas used during execution. +- `actualGasCost`: (string) - The actual cost of gas in wei. +- `success`: (boolean) - Whether the user operation was successful. +- `logs`: (array) - Array of log entries generated during execution. +- `receipt`: (object) - The underlying transaction receipt containing: + - `transactionHash`: (string) - The hash of the transaction. + - `transactionIndex`: (string) - The index of the transaction in the block. + - `blockHash`: (string) - The hash of the block containing the transaction. + - `blockNumber`: (string) - The number of the block containing the transaction. + - `from`: (string) - The address that initiated the transaction. + - `to`: (string) - The address that received the transaction. + - `cumulativeGasUsed`: (string) - The total gas used by all transactions in the block up to this one. + - `gasUsed`: (string) - The amount of gas used by this transaction. + - `address`: (string) - The contract address created, if any. + - `logs`: (array) - Array of log entries for this transaction. + - `logsBloom`: (string) - The bloom filter for the logs. + - `status`: (string) - The status of the transaction (`0x1` for success, `0x0` for failure). + - `effectiveGasPrice`: (string) - The effective gas price used for the transaction. diff --git a/services/reference/_partials/bundler/_eth_senduseroperation-description.mdx b/services/reference/_partials/bundler/_eth_senduseroperation-description.mdx new file mode 100644 index 00000000000..acb3a8fb2f5 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_senduseroperation-description.mdx @@ -0,0 +1,4 @@ +import CreditCost from '@site/src/components/CreditCost/CreditCostPrice.js' + +Submits a user operation to be included onchain and returns the user operation hash if successful (or queued). +If the operation is not successful, it will return an error. diff --git a/services/reference/_partials/bundler/_eth_senduseroperation-example.mdx b/services/reference/_partials/bundler/_eth_senduseroperation-example.mdx new file mode 100644 index 00000000000..7411f170544 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_senduseroperation-example.mdx @@ -0,0 +1 @@ +Replace `` with an API key from your [MetaMask Developer dashboard](https://developer.metamask.io/). \ No newline at end of file diff --git a/services/reference/_partials/bundler/_eth_senduseroperation-parameters.mdx b/services/reference/_partials/bundler/_eth_senduseroperation-parameters.mdx new file mode 100644 index 00000000000..6e3c0dd8f2d --- /dev/null +++ b/services/reference/_partials/bundler/_eth_senduseroperation-parameters.mdx @@ -0,0 +1,63 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +- `userOperation`: The user operation object containing the following fields: + + - `sender`: (string) - The address of the account making the operation. + - `nonce`: (string) - Nonce for the request from this sender. This includes the key and sequence number. + - `factory`: (string) [_optional_] - The factory contract address that will deploy the smart account if it doesn't exist yet. + - `factoryData`: (string) [_optional_] - The data passed to the factory contract to deploy the smart account. + - `callData`: (string) [_optional_] - The data to pass to the sender during the main execution call. + - `callGasLimit`: (string) - The amount of gas to allocate the main execution call. + - `verificationGasLimit`: (string) - The amount of gas to allocate for the verification step. + - `preVerificationGas`: (string) - The amount of gas to pay for to compensate the bundler for pre-verification execution and `calldata`. + - `maxFeePerGas` : (string) - Maximum fee per gas, in wei, the sender is willing to pay per gas. + - `maxPriorityFeePerGas`: (string) - Maximum fee, in wei, the sender is willing to pay per gas above the base fee. + - `paymaster`: (string) [_optional_] - Address of paymaster sponsoring the transaction, or `null` if none. + - `paymasterVerificationGasLimit`: (string) [_optional_] - The amount of gas to allocate for the verification step of the paymaster, or `null` if no paymaster. + - `paymasterPostOpGasLimit`: (string) [_optional_] - The amount of gas to allocate for the post-operation step of the paymaster, or `null` if no paymaster. + - `paymasterData`: (string) [_optional_] - The data to pass to the paymaster during the verification step, or `null` if no paymaster. + - `signature`: (string) - The signature data. + - `eip7702Auth`: (object) [_optional_] - The EIP-7702 authorization data: + - `address`: (string) - The contract address for the authorization. + - `chainId`: (string) - The chain ID. + - `nonce`: (string) - The nonce. + - `r`: (string) - The r component of the signature. + - `s`: (string) - The s component of the signature. + - `v`: (string) - The v component of the signature. + - `yParity`: (string) - The y-parity value. + +- `entryPoint`: (string) - The EntryPoint contract address (`0x0000000071727De22E5E9d8BAf0edAc6f37da032`). + + + + +- `userOperation`: The user operation object containing the following fields: + + - `sender`: (string) - The address of the account making the operation. + - `nonce`: (string) - Nonce for the request from this sender. + - `initCode`: (string) - The initialization code for the smart account if it doesn't exist yet. + - `callData`: (string) [_optional_] - The data to pass to the sender during the main execution call. + - `callGasLimit`: (string) - The amount of gas to allocate the main execution call. + - `verificationGasLimit`: (string) - The amount of gas to allocate for the verification step. + - `preVerificationGas`: (string) - The amount of gas to pay for to compensate the bundler for pre-verification execution and `calldata`. + - `maxFeePerGas` : (string) - Maximum fee per gas, in wei, the sender is willing to pay per gas. + - `maxPriorityFeePerGas`: (string) - Maximum fee, in wei, the sender is willing to pay per gas above the base fee. + - `paymasterAndData`: (string) - The address of the paymaster contract and the data that will be passed to it. + - `signature`: (string) - The signature data. + - `eip7702Auth`: (object) [_optional_] - The EIP-7702 authorization data: + - `address`: (string) - The contract address for the authorization. + - `chainId`: (string) - The chain ID. + - `nonce`: (string) - The nonce. + - `r`: (string) - The r component of the signature. + - `s`: (string) - The s component of the signature. + - `v`: (string) - The v component of the signature. + - `yParity`: (string) - The y-parity value. + +- `entryPoint`: (string) - The EntryPoint contract address (`0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789`). + + + diff --git a/services/reference/_partials/bundler/_eth_senduseroperation-request.mdx b/services/reference/_partials/bundler/_eth_senduseroperation-request.mdx new file mode 100644 index 00000000000..4c60081a15b --- /dev/null +++ b/services/reference/_partials/bundler/_eth_senduseroperation-request.mdx @@ -0,0 +1,39 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```bash +curl https://mainnet.infura.io/v3/ \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "eth_sendUserOperation", + "params": [ + { + "sender": "0x5a6b47F4131bf1feAFA56A05573314BcF44C9149", + "nonce": "0x845ADB2C711129D4F3966735ED98A9F09FC4CE5700000000000000000000", + "factory": "0xd703aaE79538628d27099B8c4f621bE4CCd142d5", + "factoryData": "0xc5265d5d000000000000000000000000aac5d4240af87249b3f71bc8e4a2cae074a3e419", + "callData": "0xe9ae5c5300000000000000000000000000000000000000000000000000000000000000000000000000", + "callGasLimit": "0x13880", + "verificationGasLimit": "0x60B01", + "preVerificationGas": "0xD3E3", + "maxPriorityFeePerGas": "0x3B9ACA00", + "maxFeePerGas": "0x7A5CF70D5", + "paymaster": "0x", + "paymasterVerificationGasLimit": "0x0", + "paymasterPostOpGasLimit": "0x0", + "paymasterData": null, + "signature": "0xa6cc6589c8bd561cfd68d7b6b0757ef6f208e7438782939938498eee7d703260137856c840c491b3d415956265e81bf5c2184a725be2abfc365f7536b6af525e1c" + }, + "0x0000000071727De22E5E9d8BAf0edAc6f37da032" + ], + "id": 1 + }' +``` + + + \ No newline at end of file diff --git a/services/reference/_partials/bundler/_eth_senduseroperation-response.mdx b/services/reference/_partials/bundler/_eth_senduseroperation-response.mdx new file mode 100644 index 00000000000..1545dda6edc --- /dev/null +++ b/services/reference/_partials/bundler/_eth_senduseroperation-response.mdx @@ -0,0 +1,16 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```JSON +{ + "jsonrpc": "2.0", + "id": 1, + "result": "0x4c31ae84205a9c862dd8d0822f427fb516448451850ee6f65351951f6a2b2154" +} +``` + + + \ No newline at end of file diff --git a/services/reference/_partials/bundler/_eth_senduseroperation-returns.mdx b/services/reference/_partials/bundler/_eth_senduseroperation-returns.mdx new file mode 100644 index 00000000000..7d3b27e489f --- /dev/null +++ b/services/reference/_partials/bundler/_eth_senduseroperation-returns.mdx @@ -0,0 +1,2 @@ +The 32-byte hash of the user operation (`userOpHash`). This hash uniquely identifies the user operation +and can be used to track its status. \ No newline at end of file diff --git a/services/reference/_partials/bundler/_eth_supportedentrypoints-description.mdx b/services/reference/_partials/bundler/_eth_supportedentrypoints-description.mdx new file mode 100644 index 00000000000..3d974b4ce6e --- /dev/null +++ b/services/reference/_partials/bundler/_eth_supportedentrypoints-description.mdx @@ -0,0 +1,4 @@ +import CreditCost from '@site/src/components/CreditCost/CreditCostPrice.js' + +Fetches the EntryPoint addresses supported by the bundler. The first address is the one preferred by the +bundler to use. diff --git a/services/reference/_partials/bundler/_eth_supportedentrypoints-example.mdx b/services/reference/_partials/bundler/_eth_supportedentrypoints-example.mdx new file mode 100644 index 00000000000..061467dfe81 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_supportedentrypoints-example.mdx @@ -0,0 +1 @@ +Replace `` with an API key from your [MetaMask Developer dashboard](https://developer.metamask.io/). diff --git a/services/reference/_partials/bundler/_eth_supportedentrypoints-parameters.mdx b/services/reference/_partials/bundler/_eth_supportedentrypoints-parameters.mdx new file mode 100644 index 00000000000..ed30b68824b --- /dev/null +++ b/services/reference/_partials/bundler/_eth_supportedentrypoints-parameters.mdx @@ -0,0 +1 @@ +None. diff --git a/services/reference/_partials/bundler/_eth_supportedentrypoints-request.mdx b/services/reference/_partials/bundler/_eth_supportedentrypoints-request.mdx new file mode 100644 index 00000000000..aea285e3179 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_supportedentrypoints-request.mdx @@ -0,0 +1,20 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```bash +curl https://mainnet.infura.io/v3/ \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "eth_supportedEntryPoints", + "params": [], + "id": 1 + }' +``` + + + diff --git a/services/reference/_partials/bundler/_eth_supportedentrypoints-response.mdx b/services/reference/_partials/bundler/_eth_supportedentrypoints-response.mdx new file mode 100644 index 00000000000..9f8104deb81 --- /dev/null +++ b/services/reference/_partials/bundler/_eth_supportedentrypoints-response.mdx @@ -0,0 +1,16 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```JSON +{ + "jsonrpc": "2.0", + "id": 1, + "result": ["0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"] +} +``` + + + diff --git a/services/reference/_partials/bundler/_eth_supportedentrypoints-returns.mdx b/services/reference/_partials/bundler/_eth_supportedentrypoints-returns.mdx new file mode 100644 index 00000000000..b212a20bcfb --- /dev/null +++ b/services/reference/_partials/bundler/_eth_supportedentrypoints-returns.mdx @@ -0,0 +1,2 @@ +An array of supported EntryPoint addresses. The first address in the array is the preferred EntryPoint +that the bundler recommends using. diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-description.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-description.mdx new file mode 100644 index 00000000000..52c1c6d2c50 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-description.mdx @@ -0,0 +1,3 @@ +import CreditCost from '@site/src/components/CreditCost/CreditCostPrice.js' + +Returns the gas prices that must be used for the user operation you are bundling with Pimlico bundlers. diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-example.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-example.mdx new file mode 100644 index 00000000000..061467dfe81 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-example.mdx @@ -0,0 +1 @@ +Replace `` with an API key from your [MetaMask Developer dashboard](https://developer.metamask.io/). diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-parameters.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-parameters.mdx new file mode 100644 index 00000000000..ed30b68824b --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-parameters.mdx @@ -0,0 +1 @@ +None. diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-request.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-request.mdx new file mode 100644 index 00000000000..4dc90c4b37e --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-request.mdx @@ -0,0 +1,20 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```bash +curl https://mainnet.infura.io/v3/ \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "pimlico_getUserOperationGasPrice", + "params": [], + "id": 1 + }' +``` + + + diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-response.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-response.mdx new file mode 100644 index 00000000000..1ddeaae613f --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-response.mdx @@ -0,0 +1,29 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```JSON +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "slow": { + "maxFeePerGas": "0x829b42b5", + "maxPriorityFeePerGas": "0x829b42b5" + }, + "standard": { + "maxFeePerGas": "0x88d36a75", + "maxPriorityFeePerGas": "0x88d36a75" + }, + "fast": { + "maxFeePerGas": "0x8f0b9234", + "maxPriorityFeePerGas": "0x8f0b9234" + } + } +} +``` + + + diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-returns.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-returns.mdx new file mode 100644 index 00000000000..79f6932dc19 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-returns.mdx @@ -0,0 +1,11 @@ +An object containing gas price recommendations for different priority levels: + +- `slow`: (object) - Lower gas prices for non-urgent transactions: + - `maxFeePerGas`: (string) - Maximum fee per gas for slow priority. + - `maxPriorityFeePerGas`: (string) - Maximum priority fee per gas for slow priority. +- `standard`: (object) - Standard gas prices for normal transactions: + - `maxFeePerGas`: (string) - Maximum fee per gas for standard priority. + - `maxPriorityFeePerGas`: (string) - Maximum priority fee per gas for standard priority. +- `fast`: (object) - Higher gas prices for urgent transactions: + - `maxFeePerGas`: (string) - Maximum fee per gas for fast priority. + - `maxPriorityFeePerGas`: (string) - Maximum priority fee per gas for fast priority. diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-description.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-description.mdx new file mode 100644 index 00000000000..07074dacc8d --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-description.mdx @@ -0,0 +1,10 @@ +import CreditCost from '@site/src/components/CreditCost/CreditCostPrice.js' + +Returns the user operation status and, optionally, the transaction hash that +the bundler is using to bundle the user operation onchain. + +:::info +The transaction hash returned when the result is `submitted` can change if the bundler resubmits the +user operation inside a different transaction. For this reason, when showing the pending transaction hash to +the user, it is recommended to keep calling this method in case the transaction hash changes. +::: diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-example.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-example.mdx new file mode 100644 index 00000000000..061467dfe81 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-example.mdx @@ -0,0 +1 @@ +Replace `` with an API key from your [MetaMask Developer dashboard](https://developer.metamask.io/). diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-parameters.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-parameters.mdx new file mode 100644 index 00000000000..81c016b2223 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-parameters.mdx @@ -0,0 +1 @@ +- `userOpHash`: (string) - The 32-byte hash of the user operation to check the status for. diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-request.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-request.mdx new file mode 100644 index 00000000000..bc66e5c2457 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-request.mdx @@ -0,0 +1,20 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```bash +curl https://mainnet.infura.io/v3/ \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "pimlico_getUserOperationStatus", + "params": ["0x9bd004b8240da8eba3a02190a72be8a70ade8ef4c581b6e59789643c5e642ac3"], + "id": 1 + }' +``` + + + diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-response.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-response.mdx new file mode 100644 index 00000000000..d1515926499 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-response.mdx @@ -0,0 +1,47 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + +```JSON +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "status": "not_found", + "transactionHash": null + } +} +``` + + + + +```JSON +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "status": "submitted", + "transactionHash": "0x9bd004b8240da8eba3a02190a72be8a70ade8ef4c581b6e59789643c5e642ac3" + } +} +``` + + + + +```JSON +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "status": "included", + "transactionHash": "0x9bd004b8240da8eba3a02190a72be8a70ade8ef4c581b6e59789643c5e642ac3" + } +} +``` + + + diff --git a/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-returns.mdx b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-returns.mdx new file mode 100644 index 00000000000..60a36e4a6b7 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-returns.mdx @@ -0,0 +1,16 @@ +An object containing the status information: + +- `status`: (string) - The current status of the user operation. Possible values: + + | Result | Response includes transaction hash | Description | + | :------- | :-------------------------------- | :---------- | + | `not_found` | false | The operation hash is not known to the bundler or has been rejected during validation and has never entered the mempool. | + | `not_submitted` | false | The operation hash is known to the bundler but is sitting in the mempool and has not been bundled into a transaction yet. | + | `submitted` | true | The operation hash is known to the bundler, has been bundled into a transaction which is currently pending in the mempool. | + | `rejected` | false | The operation hash has entered the mempool but as it was being bundled into a bundle transaction the re-simulation failed and it was never submitted. | + | `included` | true | The operation hash is known to the bundler and has been included onchain. | + | `failed` | true | The operation hash is known to the bundler and the transaction bundling it has been included onchain but the bundle transaction reverted. | + | `queued` | false | The operation hash is known to the bundler but is waiting in a queue before being sent to the mempool due to its nonce being too high. | + +- `transactionHash`: (string) - The transaction hash bundling the user operation, or `null` if + not applicable for the current status. diff --git a/services/reference/_partials/bundler/_pimlico_simulateassetchanges-description.mdx b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-description.mdx new file mode 100644 index 00000000000..77b2869992e --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-description.mdx @@ -0,0 +1,9 @@ +import CreditCost from '@site/src/components/CreditCost/CreditCostPrice.js' + +Simulates a user operation to predict the asset changes it will cause. Shows all balance changes +and shows all balance changes including native currency, ERC-20, ERC-1155, and ERC-721 tokens. + +:::info +This method does not support v0.6 user operations. +::: + diff --git a/services/reference/_partials/bundler/_pimlico_simulateassetchanges-errors.mdx b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-errors.mdx new file mode 100644 index 00000000000..fa52af5c0c3 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-errors.mdx @@ -0,0 +1,7 @@ +Common error responses when simulation fails: + +| Error Code | Description | +| :------------------------| :------------------------------------------------- | +| `AA23` | User operation reverted during simulation. | +| `UserOperationReverted` | User operation execution failed during simulation. | +| `SimulateValidation` | Validation failed for the user operation. | \ No newline at end of file diff --git a/services/reference/_partials/bundler/_pimlico_simulateassetchanges-example.mdx b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-example.mdx new file mode 100644 index 00000000000..061467dfe81 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-example.mdx @@ -0,0 +1 @@ +Replace `` with an API key from your [MetaMask Developer dashboard](https://developer.metamask.io/). diff --git a/services/reference/_partials/bundler/_pimlico_simulateassetchanges-parameters.mdx b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-parameters.mdx new file mode 100644 index 00000000000..e5aedbbd61c --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-parameters.mdx @@ -0,0 +1,16 @@ +- `userOperation`: (object) - The user operation object with the same format as `eth_estimateUserOperationGas`: + - `sender`: (string) - The address of the account making the operation. + - `nonce`: (string) - The account nonce. + - `callData`: (string) - The data to pass to the sender during the main execution call. + - `callGasLimit`: (string) [_optional_] - The amount of gas to allocate the main execution call. + - `verificationGasLimit`: (string) [_optional_] - The amount of gas to allocate for the verification step. + - `preVerificationGas`: (string) [_optional_] - The amount of gas to pay for to compensate the bundler. + - `maxFeePerGas`: (string) [_optional_] - Maximum fee per gas, in wei, the sender is willing to pay per gas. + - `maxPriorityFeePerGas`: (string) [_optional_] - Maximum priority fee per gas above the base fee. + - `paymasterVerificationGasLimit`: (string) [_optional_] - Gas for paymaster verification step. + - `paymasterPostOpGasLimit`: (string) [_optional_] - Gas for paymaster post-operation step. + - `signature`: (string) - Must be a valid dummy signature for simulation. + +- `entryPoint`: (string) - The EntryPoint contract address. + +- `blockNumber`: (string) [_optional_] - Hex encoded block number to run the simulation at (defaults to `latest`). diff --git a/services/reference/_partials/bundler/_pimlico_simulateassetchanges-request.mdx b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-request.mdx new file mode 100644 index 00000000000..401dcc394c2 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-request.mdx @@ -0,0 +1,35 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + + ```bash + curl https://mainnet.infura.io/v3/ \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "pimlico_simulateAssetChanges", + "id": 4337, + "params": [ + { + "sender": "0x5a6b47F4131bf1feAFA56A05573314BcF44C9149", + "nonce": "0x1", + "callData": "0x9faf00f4d9c8df66a69fd6242d468aa8a31a439d14fc6c7af3868a06ed392233bc7e39475df25ad2b52bd5e19e1d438277207a415cb4d4ce8ad192464c55ddf1a9559ff900000000000000000000000073da77f0f2daaa88b908413495d3d0e37458212e00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000039946fd82c9c86c9a61bceed86fbdd284590bdd90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "callGasLimit": "0x0", + "verificationGasLimit": "0x0", + "preVerificationGas": "0x0", + "maxFeePerGas": "0x7a5cf70d5", + "maxPriorityFeePerGas": "0x3b9aca00", + "paymasterVerificationGasLimit": "0x0", + "paymasterPostOpGasLimit": "0x0", + "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c" + }, + "0x0000000071727De22E5E9d8BAf0edAc6f37da032" + ] + }' + ``` + + + diff --git a/services/reference/_partials/bundler/_pimlico_simulateassetchanges-response.mdx b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-response.mdx new file mode 100644 index 00000000000..03f2596ca76 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-response.mdx @@ -0,0 +1,165 @@ +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + + + + + ```JSON + { + "jsonrpc": "2.0", + "id": 4337, + "result": { + "assetChanges": [ + { + "token": { + "tokenType": "NATIVE" + }, + "value": { + "diff": "-1000000000000000000", + "pre": "5000000000000000000", + "post": "4000000000000000000" + } + } + ] + } + } + ``` + + + + + ```JSON + { + "jsonrpc": "2.0", + "id": 4337, + "result": { + "assetChanges": [ + { + "token": { + "tokenType": "ERC-20", + "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "decimals": 6, + "name": "USD Coin", + "symbol": "USDC" + }, + "value": { + "diff": "-1000000", + "pre": "100000000", + "post": "99000000" + } + } + ] + } + } + ``` + + + + + ```JSON + { + "jsonrpc": "2.0", + "id": 4337, + "result": { + "assetChanges": [ + { + "token": { + "tokenType": "ERC-721", + "address": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", + "tokenId": 1234, + "name": "Bored Ape Yacht Club", + "symbol": "BAYC" + }, + "value": { + "diff": "1", + "pre": "0", + "post": "1" + } + } + ] + } + } + ``` + + + + + ```JSON + { + "jsonrpc": "2.0", + "id": 4337, + "result": { + "assetChanges": [ + { + "token": { + "tokenType": "ERC-1155", + "address": "0x76BE3b62873462d2142405439777e971754E8E77", + "tokenId": 5678, + "name": "OpenSea Shared Storefront", + "symbol": "OPENSTORE" + }, + "value": { + "diff": "10", + "pre": "5", + "post": "15" + } + } + ] + } + } + ``` + + + + + ```JSON + { + "jsonrpc": "2.0", + "id": 4337, + "result": { + "assetChanges": [ + { + "token": { + "tokenType": "ERC-20", + "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "decimals": 6, + "name": "USD Coin", + "symbol": "USDC" + }, + "value": { + "diff": "-1000000", + "pre": "100000000", + "post": "99000000" + } + }, + { + "token": { + "tokenType": "ERC-20", + "address": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + "decimals": 8, + "name": "Wrapped BTC", + "symbol": "WBTC" + }, + "value": { + "diff": "1196", + "pre": "0", + "post": "1196" + } + }, + { + "token": { + "tokenType": "NATIVE" + }, + "value": { + "diff": "-1000000000000000000", + "pre": "5000000000000000000", + "post": "4000000000000000000" + } + } + ] + } + } + ``` + + + diff --git a/services/reference/_partials/bundler/_pimlico_simulateassetchanges-returns.mdx b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-returns.mdx new file mode 100644 index 00000000000..ff27148c951 --- /dev/null +++ b/services/reference/_partials/bundler/_pimlico_simulateassetchanges-returns.mdx @@ -0,0 +1,10 @@ +An object containing asset changes that would occur from executing the user operation: + +`assetChanges`: (array) - Array of asset change objects, each containing: + +- `token`: (object) - Token information (varies by token type). Token metadata fields (`name` and `symbol`) + are included when available but may be undefined as they are optional in token standards. +- `value`: (object) - Balance change information: + - `diff`: (string) - The balance difference. + - `pre`: (string) - Balance before the operation. + - `post`: (string) - Balance after the operation. diff --git a/services/reference/ethereum/json-rpc-methods/bundler/eth_estimateuseroperationgas.mdx b/services/reference/ethereum/json-rpc-methods/bundler/eth_estimateuseroperationgas.mdx new file mode 100644 index 00000000000..0af2180c553 --- /dev/null +++ b/services/reference/ethereum/json-rpc-methods/bundler/eth_estimateuseroperationgas.mdx @@ -0,0 +1,44 @@ +--- +title: eth_estimateUserOperationGas +sidebar_label: eth_estimateUserOperationGas +description: Simulate and estimate gas limits for a user operation before submission. +--- + +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +import Description from "/services/reference/_partials/bundler/_eth_estimateuseroperationgas-description.mdx" + +# `eth_estimateUserOperationGas` + + + +## Parameters + +import Params from "/services/reference/_partials/bundler/_eth_estimateuseroperationgas-parameters.mdx" + + + +## Returns + +import Returns from "/services/reference/_partials/bundler/_eth_estimateuseroperationgas-returns.mdx" + + + +## Example + +import Example from "/services/reference/_partials/bundler/_eth_estimateuseroperationgas-example.mdx" + + + +### Request + +import Request from "/services/reference/_partials/bundler/_eth_estimateuseroperationgas-request.mdx" + + + +### Response + +import Response from "/services/reference/_partials/bundler/_eth_estimateuseroperationgas-response.mdx" + + diff --git a/services/reference/ethereum/json-rpc-methods/bundler/eth_getuseroperationbyhash.mdx b/services/reference/ethereum/json-rpc-methods/bundler/eth_getuseroperationbyhash.mdx new file mode 100644 index 00000000000..adce4cbe6e3 --- /dev/null +++ b/services/reference/ethereum/json-rpc-methods/bundler/eth_getuseroperationbyhash.mdx @@ -0,0 +1,44 @@ +--- +title: eth_getUserOperationByHash +sidebar_label: eth_getUserOperationByHash +description: Fetch user operation details by its hash. +--- + +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +import Description from "/services/reference/_partials/bundler/_eth_getuseroperationbyhash-description.mdx" + +# `eth_getUserOperationByHash` + + + +## Parameters + +import Params from "/services/reference/_partials/bundler/_eth_getuseroperationbyhash-parameters.mdx" + + + +## Returns + +import Returns from "/services/reference/_partials/bundler/_eth_getuseroperationbyhash-returns.mdx" + + + +## Example + +import Example from "/services/reference/_partials/bundler/_eth_getuseroperationbyhash-example.mdx" + + + +### Request + +import Request from "/services/reference/_partials/bundler/_eth_getuseroperationbyhash-request.mdx" + + + +### Response + +import Response from "/services/reference/_partials/bundler/_eth_getuseroperationbyhash-response.mdx" + + diff --git a/services/reference/ethereum/json-rpc-methods/bundler/eth_getuseroperationreceipt.mdx b/services/reference/ethereum/json-rpc-methods/bundler/eth_getuseroperationreceipt.mdx new file mode 100644 index 00000000000..a9426e1d552 --- /dev/null +++ b/services/reference/ethereum/json-rpc-methods/bundler/eth_getuseroperationreceipt.mdx @@ -0,0 +1,44 @@ +--- +title: eth_getUserOperationReceipt +sidebar_label: eth_getUserOperationReceipt +description: Fetch the receipt of a user operation by its hash. +--- + +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +import Description from "/services/reference/_partials/bundler/_eth_getuseroperationreceipt-description.mdx" + +# `eth_getUserOperationReceipt` + + + +## Parameters + +import Params from "/services/reference/_partials/bundler/_eth_getuseroperationreceipt-parameters.mdx" + + + +## Returns + +import Returns from "/services/reference/_partials/bundler/_eth_getuseroperationreceipt-returns.mdx" + + + +## Example + +import Example from "/services/reference/_partials/bundler/_eth_getuseroperationreceipt-example.mdx" + + + +### Request + +import Request from "/services/reference/_partials/bundler/_eth_getuseroperationreceipt-request.mdx" + + + +### Response + +import Response from "/services/reference/_partials/bundler/_eth_getuseroperationreceipt-response.mdx" + + diff --git a/services/reference/ethereum/json-rpc-methods/bundler/eth_senduseroperation.mdx b/services/reference/ethereum/json-rpc-methods/bundler/eth_senduseroperation.mdx new file mode 100644 index 00000000000..7b2c4cdb4c1 --- /dev/null +++ b/services/reference/ethereum/json-rpc-methods/bundler/eth_senduseroperation.mdx @@ -0,0 +1,44 @@ +--- +title: eth_sendUserOperation +sidebar_label: eth_sendUserOperation +description: Submit a user operation to the mempool for bundling and execution. +--- + +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +import Description from "/services/reference/_partials/bundler/_eth_senduseroperation-description.mdx" + +# `eth_sendUserOperation` + + + +## Parameters + +import Params from "/services/reference/_partials/bundler/_eth_senduseroperation-parameters.mdx" + + + +## Returns + +import Returns from "/services/reference/_partials/bundler/_eth_senduseroperation-returns.mdx" + + + +## Example + +import Example from "/services/reference/_partials/bundler/_eth_senduseroperation-example.mdx" + + + +### Request + +import Request from "/services/reference/_partials/bundler/_eth_senduseroperation-request.mdx" + + + +### Response + +import Response from "/services/reference/_partials/bundler/_eth_senduseroperation-response.mdx" + + diff --git a/services/reference/ethereum/json-rpc-methods/bundler/eth_supportedentrypoints.mdx b/services/reference/ethereum/json-rpc-methods/bundler/eth_supportedentrypoints.mdx new file mode 100644 index 00000000000..fc88a6fc9e3 --- /dev/null +++ b/services/reference/ethereum/json-rpc-methods/bundler/eth_supportedentrypoints.mdx @@ -0,0 +1,44 @@ +--- +title: eth_supportedEntryPoints +sidebar_label: eth_supportedEntryPoints +description: Get the list of EntryPoint addresses supported by the bundler. +--- + +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +import Description from "/services/reference/_partials/bundler/_eth_supportedentrypoints-description.mdx" + +# `eth_supportedEntryPoints` + + + +## Parameters + +import Params from "/services/reference/_partials/bundler/_eth_supportedentrypoints-parameters.mdx" + + + +## Returns + +import Returns from "/services/reference/_partials/bundler/_eth_supportedentrypoints-returns.mdx" + + + +## Example + +import Example from "/services/reference/_partials/bundler/_eth_supportedentrypoints-example.mdx" + + + +### Request + +import Request from "/services/reference/_partials/bundler/_eth_supportedentrypoints-request.mdx" + + + +### Response + +import Response from "/services/reference/_partials/bundler/_eth_supportedentrypoints-response.mdx" + + diff --git a/services/reference/ethereum/json-rpc-methods/bundler/index.md b/services/reference/ethereum/json-rpc-methods/bundler/index.md new file mode 100644 index 00000000000..05b1677b091 --- /dev/null +++ b/services/reference/ethereum/json-rpc-methods/bundler/index.md @@ -0,0 +1,36 @@ +--- +title: Ethereum bundler methods +sidebar_label: Bundler methods +description: Ethereum bundler methods +--- + +Infura provides seamless integration with the Pimlico account abstraction bundler infrastructure, enabling +developers to access ERC‑4337 smart account features. +Infura transparently routes supported smart account methods to the Pimlico backend, allowing +teams to construct, validate, simulate, and submit user operations without needing to directly call +Pimlico endpoints or manage bundler infrastructure. + +:::info +Refer to the [official Pimlico documentation](https://docs.pimlico.io/references/bundler) +for more about the bundler methods and +[EntryPoint errors](https://docs.pimlico.io/references/bundler/entrypoint-errors#entrypoint-errors). +::: + +The following bundler methods are supported on Ethereum Mainnet and Sepolia: + +- [`eth_sendUserOperation`](./eth_senduseroperation): Submits a user operation to be included onchain. +- [`eth_estimateUserOperationGas`](./eth_estimateuseroperationgas): Simulates the user operation and estimates the appropriate gas limits. +- [`eth_getUserOperationReceipt`](./eth_getuseroperationreceipt): Fetches the receipt of a user operation. +- [`eth_getUserOperationByHash`](./eth_getuseroperationbyhash): Fetches the user operation by hash. +- [`eth_supportedEntryPoints`](./eth_supportedentrypoints): Fetches the EntryPoint addresses supported by the bundler. +- [`pimlico_getUserOperationGasPrice`](./pimlico_getuseroperationgasprice): Returns the gas prices that must be used for the user operation. +- [`pimlico_getUserOperationStatus`](./pimlico_getuseroperationstatus): Returns the user operation status. +- [`pimlico_simulateAssetChanges`](./pimlico_simulateassetchanges): Simulates a user operation to predict the asset changes it will cause. + +## Method EntryPoints + +The bundler supports calling multiple EntryPoint versions (v0.6 and v0.7/v0.8) through the same set of +RPC methods (for example, `eth_sendUserOperation` and `eth_estimateUserOperationGas`, etc.), allowing +it to handle both older and modern smart account schemes. + +When you submit a user operation via standard methods, the bundler reads the payload and identifies the appropriate EntryPoint version based on which fields are present. \ No newline at end of file diff --git a/services/reference/ethereum/json-rpc-methods/bundler/pimlico_getuseroperationgasprice.mdx b/services/reference/ethereum/json-rpc-methods/bundler/pimlico_getuseroperationgasprice.mdx new file mode 100644 index 00000000000..70897d7e524 --- /dev/null +++ b/services/reference/ethereum/json-rpc-methods/bundler/pimlico_getuseroperationgasprice.mdx @@ -0,0 +1,44 @@ +--- +title: pimlico_getUserOperationGasPrice +sidebar_label: pimlico_getUserOperationGasPrice +description: Get recommended gas prices for user operations on Pimlico bundlers. +--- + +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +import Description from "/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-description.mdx" + +# `pimlico_getUserOperationGasPrice` + + + +## Parameters + +import Params from "/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-parameters.mdx" + + + +## Returns + +import Returns from "/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-returns.mdx" + + + +## Example + +import Example from "/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-example.mdx" + + + +### Request + +import Request from "/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-request.mdx" + + + +### Response + +import Response from "/services/reference/_partials/bundler/_pimlico_getuseroperationgasprice-response.mdx" + + diff --git a/services/reference/ethereum/json-rpc-methods/bundler/pimlico_getuseroperationstatus.mdx b/services/reference/ethereum/json-rpc-methods/bundler/pimlico_getuseroperationstatus.mdx new file mode 100644 index 00000000000..24c4e50da7e --- /dev/null +++ b/services/reference/ethereum/json-rpc-methods/bundler/pimlico_getuseroperationstatus.mdx @@ -0,0 +1,44 @@ +--- +title: pimlico_getUserOperationStatus +sidebar_label: pimlico_getUserOperationStatus +description: Get the current status of a user operation by its hash. +--- + +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +import Description from "/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-description.mdx" + +# `pimlico_getUserOperationStatus` + + + +## Parameters + +import Params from "/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-parameters.mdx" + + + +## Returns + +import Returns from "/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-returns.mdx" + + + +## Example + +import Example from "/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-example.mdx" + + + +### Request + +import Request from "/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-request.mdx" + + + +### Response + +import Response from "/services/reference/_partials/bundler/_pimlico_getuseroperationstatus-response.mdx" + + diff --git a/services/reference/ethereum/json-rpc-methods/bundler/pimlico_simulateassetchanges.mdx b/services/reference/ethereum/json-rpc-methods/bundler/pimlico_simulateassetchanges.mdx new file mode 100644 index 00000000000..019d0050b4c --- /dev/null +++ b/services/reference/ethereum/json-rpc-methods/bundler/pimlico_simulateassetchanges.mdx @@ -0,0 +1,50 @@ +--- +title: pimlico_simulateAssetChanges +sidebar_label: pimlico_simulateAssetChanges +description: Simulate a user operation and return predicted asset changes. +--- + +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +import Description from "/services/reference/_partials/bundler/_pimlico_simulateassetchanges-description.mdx" + +# `pimlico_simulateAssetChanges` + + + +## Parameters + +import Params from "/services/reference/_partials/bundler/_pimlico_simulateassetchanges-parameters.mdx" + + + +## Returns + +import Returns from "/services/reference/_partials/bundler/_pimlico_simulateassetchanges-returns.mdx" + + + +## Example + +import Example from "/services/reference/_partials/bundler/_pimlico_simulateassetchanges-example.mdx" + + + +### Request + +import Request from "/services/reference/_partials/bundler/_pimlico_simulateassetchanges-request.mdx" + + + +### Response + +import Response from "/services/reference/_partials/bundler/_pimlico_simulateassetchanges-response.mdx" + + + +## Errors + +import Errors from "/services/reference/_partials/bundler/_pimlico_simulateassetchanges-errors.mdx" + + diff --git a/src/lib/data.js b/src/lib/data.js index cabdc235bcb..41e800b6563 100644 --- a/src/lib/data.js +++ b/src/lib/data.js @@ -351,4 +351,14 @@ export const API_COSTS = { busyThreshold: 80, suggestedGasFees: 80, }, + bundler: { + eth_estimateUserOperationGas: 80, + eth_getUserOperationByHash: 80, + eth_getUserOperationReceipt: 80, + eth_sendUserOperation: 80, + eth_supportedEntryPoints: 80, + pimlico_getUserOperationGasPrice: 80, + pimlico_getUserOperationStatus: 80, + pimlico_simulateAssetChanges: 80, + }, } diff --git a/src/theme/Tabs/styles.module.scss b/src/theme/Tabs/styles.module.scss index d5e3c1c98c5..24d1888b052 100644 --- a/src/theme/Tabs/styles.module.scss +++ b/src/theme/Tabs/styles.module.scss @@ -36,6 +36,38 @@ p { padding: 1.6rem; } + + // Required for tabs that include bullet lists (e.g., bundler method parameters) + // Without this, L1 bullets are not visible and spacing is inconsistent + ul, + ol { + margin: 1.6rem 0 1.6rem 2rem; + + li { + margin-bottom: 1rem; + + // Handle list items that contain paragraphs (L1 bullets from markdown parsing) + p { + padding: 0; // Remove padding for paragraphs inside list items + margin: 0; // Remove margin to prevent double spacing + } + } + } + + ul { + list-style-type: disc; + list-style-position: outside; + } + + ul ul { + list-style-type: circle; + margin-left: 1.6rem; + margin-top: 1rem; + } + + ul ul ul { + list-style-type: square; + } } .flaskOnly::after {