Repository: ithacaxyz/porto
Pull request #274: docs(rpc-server): use snippets
Author: login: onbjerg
Created: 2025-05-22T17:05:15Z | Merged: 2025-05-23T11:00:39Z

Builds on top of #265 and #272 

Replaces repeating sections with snippets


Diff:
diff --git a/apps/docs/pages/rpc-server/snippets/fees.mdx b/apps/docs/pages/rpc-server/snippets/fees.mdx
new file mode 100644
index 000000000..3375a0874
--- /dev/null
+++ b/apps/docs/pages/rpc-server/snippets/fees.mdx
@@ -0,0 +1,5 @@
+## Fees
+
+Execution of bundles are paid for by the fee payer, which defaults to the EOA. This can be overriden using `feePayer`.
+
+Fees are paid in `feeToken`, which is specified in the capabilities of `wallet_prepareCalls`. The fee token must be supported on the target chain. The list of supported tokens on each network can be found in the response of [`wallet_getCapabilities`](/rpc-server/wallet_getCapabilities).
diff --git a/apps/docs/pages/rpc-server/snippets/keys.mdx b/apps/docs/pages/rpc-server/snippets/keys.mdx
new file mode 100644
index 000000000..573287b6c
--- /dev/null
+++ b/apps/docs/pages/rpc-server/snippets/keys.mdx
@@ -0,0 +1,31 @@
+## Keys
+
+There exists three different key roles:
+
+- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
+- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
+- **Session keys** are like normal keys, except they also have an expiry.
+
+Setting permissions on an admin key is not allowed and will return an error.
+
+### Public key encoding
+
+The encoding of a key pair's public key depends on the key type:
+
+| Key Type         | Encoding Format       | Description                                                                    |
+| ---------------- | --------------------- | ------------------------------------------------------------------------------ |
+| secp256k1        | `abi.encode(address)` | Stores only the Ethereum address derived from the public key (truncated hash). |
+| webAuthn          | `abi.encode(x, y)`    | Stores both x and y coordinates of the public key on the elliptic curve.       |
+| secp256r1 (P256) | `abi.encode(x, y) `   | Stores both x and y coordinates for the secp256r1 curve.                       |
+
+## Signature encoding
+
+The signature is encoded as follows: `abi.encodePacked(bytes(innerSignature), bytes32(keyHash), bool(prehash))`, where the key hash is `keccak(bytes32(keyType, publicKey))`.
+
+The inner signature depends on the key type:
+
+| Key Type | Signature |
+| -------- | --------- |
+| secp256r1 (p256) | `(r, s)` |
+| webauthn | `(r, s)` |
+| secp256k1 | `(r, s)` or `(r, vs)` |
diff --git a/apps/docs/pages/rpc-server/snippets/selectors.mdx b/apps/docs/pages/rpc-server/snippets/selectors.mdx
new file mode 100644
index 000000000..7d0c04bd8
--- /dev/null
+++ b/apps/docs/pages/rpc-server/snippets/selectors.mdx
@@ -0,0 +1,3 @@
+## Selectors
+
+Selectors for call permissions can either be a 4-byte selector, e.g. `0x12345678`, or a Solidity-style selector, like `transfer(address,uint256)`.
diff --git a/apps/docs/pages/rpc-server/wallet_prepareCalls.md b/apps/docs/pages/rpc-server/wallet_prepareCalls.mdx
similarity index 76%
rename from apps/docs/pages/rpc-server/wallet_prepareCalls.md
rename to apps/docs/pages/rpc-server/wallet_prepareCalls.mdx
index f52260f00..d9f66bb19 100644
--- a/apps/docs/pages/rpc-server/wallet_prepareCalls.md
+++ b/apps/docs/pages/rpc-server/wallet_prepareCalls.mdx
@@ -1,3 +1,7 @@
+import Keys from './snippets/keys.mdx'
+import Fees from './snippets/fees.mdx'
+import Selectors from './snippets/selectors.mdx'
+
 # `wallet_prepareCalls`
 
 Prepares a call bundle. The calls are simulated and a quote for executing the bundle by the server is provided. The quote lives for a certain amount of time, after which it expires.
@@ -21,45 +25,9 @@ Only certain types of calls are allowed in preops:
 
 Preops have their own signatures, and they must be signed with a key that is already attached to the account. The `from` and `key` fields can be omitted when building a preop (`preop: true`).
 
-## Fees
-
-Execution of bundles are paid for by the fee payer, which defaults to the EOA. This can be overriden using `feePayer`.
-
-Fees are paid in `feeToken`, which is specified in the capabilities of `wallet_prepareCalls`. The fee token must be supported on the target chain. The list of supported tokens on each network can be found in the response of [`wallet_getCapabilities`](/rpc-server/wallet_getCapabilities).
-
-## Keys
-
-There exists three different key roles:
-
-- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
-- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
-- **Session keys** are like normal keys, except they also have an expiry.
-
-Setting permissions on an admin key does nothing.
-
-### Public key encoding
-
-The encoding of a key pair's public key depends on the key type:
-
-| Key Type         | Encoding Format       | Description                                                                    |
-| ---------------- | --------------------- | ------------------------------------------------------------------------------ |
-| secp256k1        | `abi.encode(address)` | Stores only the Ethereum address derived from the public key (truncated hash). |
-| webAuthn          | `abi.encode(x, y)`    | Stores both x and y coordinates of the public key on the elliptic curve.       |
-| secp256r1 (P256) | `abi.encode(x, y)`   | Stores both x and y coordinates for the secp256r1 curve.                       |
-
-## Signature encoding
-
-The signature is encoded as follows: `abi.encodePacked(bytes(innerSignature), bytes32(keyHash), bool(prehash))`, where the key hash is `keccak(bytes32(keyType, publicKey))`.
-
-The inner signature depends on the key type:
-
-| Key Type | Signature |
-| -------- | --------- |
-| secp256r1 (p256) | `(r, s)` |
-| webauthn | `(r, s)` |
-| secp256k1 | `(r, s)` or `(r, vs)` |
-
-## Selectors
+<Fees />
+<Keys />
+<Selectors />
 
 Selectors for call permissions can either be a 4-byte selector, e.g. `0x12345678`, or a Solidity-style selector, like `transfer(address,uint256)`.
 
@@ -178,7 +146,7 @@ type Response = {
       entrypoint: `0x${string}`,
       // The RPC servers signature over the quote.
       signature: {
-        y_parity: boolean,
+        y_parity: bool,
         r: `0x${string}`,
         s: `0x${string}`,
       },
diff --git a/apps/docs/pages/rpc-server/wallet_prepareCreateAccount.md b/apps/docs/pages/rpc-server/wallet_prepareCreateAccount.mdx
similarity index 67%
rename from apps/docs/pages/rpc-server/wallet_prepareCreateAccount.md
rename to apps/docs/pages/rpc-server/wallet_prepareCreateAccount.mdx
index 629b82be9..afee0ab3b 100644
--- a/apps/docs/pages/rpc-server/wallet_prepareCreateAccount.md
+++ b/apps/docs/pages/rpc-server/wallet_prepareCreateAccount.mdx
@@ -1,3 +1,6 @@
+import Keys from './snippets/keys.mdx'
+import Selectors from './snippets/selectors.mdx'
+
 # `wallet_prepareCreateAccount`
 
 Prepares an account creation.
@@ -6,29 +9,8 @@ Accounts created using the RPC server use [PREP](https://blog.biconomy.io/prep-d
 
 The account is not fully created until `wallet_createAccount` is called.
 
-## Keys
-
-There exist three different key roles:
-
-- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
-- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
-- **Session keys** are like normal keys, except they also have an expiry.
-
-Setting permissions on an admin key does nothing.
-
-### Public key encoding
-
-The encoding of a key pairs public key depends on the key type:
-
-| Key Type         | Encoding Format       | Description                                                                    |
-| ---------------- | --------------------- | ------------------------------------------------------------------------------ |
-| secp256k1        | `abi.encode(address)` | Stores only the Ethereum address derived from the public key (truncated hash). |
-| webAuth          | `abi.encode(x, y)`    | Stores both x and y coordinates of the public key on the elliptic curve.       |
-| secp256r1 (P256) | `abi.encode(x, y)`   | Stores both x and y coordinates for the secp256r1 curve.                       |
-
-## Selectors
-
-Selectors for call permissions can either be a 4-byte selector, e.g. `0x12345678`, or a Solidity-style selector, like `transfer(address,uint256)`.
+<Keys />
+<Selectors />
 
 ## Request
 
diff --git a/apps/docs/pages/rpc-server/wallet_prepareUpgradeAccount.md b/apps/docs/pages/rpc-server/wallet_prepareUpgradeAccount.mdx
similarity index 74%
rename from apps/docs/pages/rpc-server/wallet_prepareUpgradeAccount.md
rename to apps/docs/pages/rpc-server/wallet_prepareUpgradeAccount.mdx
index a45ab2a85..b85ca2ffe 100644
--- a/apps/docs/pages/rpc-server/wallet_prepareUpgradeAccount.md
+++ b/apps/docs/pages/rpc-server/wallet_prepareUpgradeAccount.mdx
@@ -1,3 +1,5 @@
+import Keys from './snippets/keys.mdx'
+
 # `wallet_prepareUpgradeAccount`
 
 Prepares an account for upgrade by generating initialization data and an EIP-7702 authorization item.
@@ -10,37 +12,7 @@ The returned EIP-7702 authorization item must be signed by the EOA root key.
 This method is intended to be used in conjunction with [`wallet_upgradeAccount`](/rpc-server/wallet_upgradeAccount).
 :::
 
-## Keys
-
-There exists three different key roles:
-
-- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
-- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
-- **Session keys** are like normal keys, except they also have an expiry.
-
-Setting permissions on an admin key does nothing.
-
-### Public key encoding
-
-The encoding of a key pair's public key depends on the key type:
-
-| Key Type         | Encoding Format       | Description                                                                    |
-| ---------------- | --------------------- | ------------------------------------------------------------------------------ |
-| secp256k1        | `abi.encode(address)` | Stores only the Ethereum address derived from the public key (truncated hash). |
-| webAuthn          | `abi.encode(x, y)`    | Stores both x and y coordinates of the public key on the elliptic curve.       |
-| secp256r1 (P256) | `abi.encode(x, y)`   | Stores both x and y coordinates for the secp256r1 curve.                       |
-
-## Signature encoding
-
-The signature is encoded as follows: `abi.encodePacked(bytes(innerSignature), bytes32(keyHash), bool(prehash))`, where the key hash is `keccak(bytes32(keyType, publicKey))`.
-
-The inner signature depends on the key type:
-
-| Key Type | Signature |
-| -------- | --------- |
-| secp256r1 (p256) | `(r, s)` |
-| webauthn | `(r, s)` |
-| secp256k1 | `(r, s)` or `(r, vs)` |
+<Keys />
 
 ## Request
 
@@ -124,7 +96,7 @@ type Response = {
       entrypoint: `0x${string}`,
       // The RPC servers signature over the quote.
       signature: {
-        y_parity: boolean,
+        y_parity: bool,
         r: `0x${string}`,
         s: `0x${string}`,
       },
diff --git a/apps/docs/pages/rpc-server/wallet_sendPreparedCalls.md b/apps/docs/pages/rpc-server/wallet_sendPreparedCalls.md
deleted file mode 100644
index 79821b804..000000000
--- a/apps/docs/pages/rpc-server/wallet_sendPreparedCalls.md
+++ /dev/null
@@ -1,120 +0,0 @@
-# `wallet_sendPreparedCalls`
-
-Sends a prepared call bundle.
-
-:::tip
-This method is intended to be used in conjunction with [`wallet_prepareCalls`](/rpc-server/wallet_prepareCalls).
-:::
-
-## Fees
-
-Execution of bundles are paid for by the fee payer, which defaults to the EOA. This can be overridden using `feePayer`.
-
-Fees are paid in `feeToken`, which is specified in the capabilities of `wallet_prepareCalls`. The fee token must be supported on the target chain. The list of supported tokens on each network can be found in the response of [`wallet_getCapabilities`](/rpc-server/wallet_getCapabilities).
-
-## Keys
-
-There are three different key roles:
-
-- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
-- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
-- **Session keys** are like normal keys, except they also have an expiry.
-
-Setting permissions on an admin key does nothing.
-
-### Public key encoding
-
-The encoding of a key pair's public key depends on the key type:
-
-| Key Type         | Encoding Format       | Description                                                                    |
-| ---------------- | --------------------- | ------------------------------------------------------------------------------ |
-| secp256k1        | `abi.encode(address)` | Stores only the Ethereum address derived from the public key (truncated hash). |
-| webAuthn          | `abi.encode(x, y)`    | Stores both x and y coordinates of the public key on the elliptic curve.       |
-| secp256r1 (P256) | `abi.encode(x, y)`   | Stores both x and y coordinates for the secp256r1 curve.                       |
-
-## Signature encoding
-
-The signature is encoded as follows: `abi.encodePacked(bytes(innerSignature), bytes32(keyHash), bool(prehash))`, where the key hash is `keccak(bytes32(keyType, publicKey))`.
-
-The inner signature depends on the key type:
-
-| Key Type | Signature |
-| -------- | --------- |
-| secp256r1 (p256) | `(r, s)` |
-| webauthn | `(r, s)` |
-| secp256k1 | `(r, s)` or `(r, vs)` |
-
-## Selectors
-
-Selectors for call permissions can either be a 4-byte selector, e.g. `0x12345678`, or a Solidity-style selector, like `transfer(address,uint256)`.
-
-## Request
-
-```ts
-type Request = {
-  method: 'wallet_sendPreparedCalls',
-  params: [{
-    capabilities?: {
-      // This will be passed to `feePayer` if specified for additional on-chain verification.
-      feeSignature?: `0x${string}`,
-    },
-    context: {
-      quote: {
-        chainId: `0x${string}`,
-        op: {
-          eoa: `0x${string}`,
-          executionData: `0x${string}`,
-          nonce: `0x${string}`,
-          payer: `0x${string}`,
-          paymentToken: `0x${string}`,
-          prePaymentMaxAmount: `0x${string}`,
-          totalPaymentMaxAmount: `0x${string}`,
-          combinedGas: `0x${string}`,
-          encodedPreOps: `0x${string}`[],
-          initData: `0x${string}`,
-          prePaymentAmount: `0x${string}`,
-          totalPaymentAmount: `0x${string}`,
-          paymentRecipient: `0x${string}`,
-          signature: `0x${string}`,
-          paymentSignature: `0x${string}`,
-          supportedDelegationImplementation: `0x${string}`,
-        },
-        txGas: `0x${string}`,
-        nativeFeeEstimate: {
-          maxFeePerGas: number,
-          maxPriorityFeePerGas: number,
-        },
-        // UNIX timestamp the quote expires at.
-        ttl: number,
-        authorizationAddress?: `0x${string}`,
-        entrypoint: `0x${string}`,
-        // The RPC servers signature over the quote.
-        signature: {
-          y_parity: boolean,
-          r: `0x${string}`,
-          s: `0x${string}`,
-        },
-        // The hash of the quote.
-        hash: `0x${string}`,
-      },
-    },
-    // The key that signed the bundle. See "Keys".
-    key: {
-      type: 'p256' | 'webauthnp256' | 'secp256k1',
-      publicKey: `0x${string}`,
-      // Whether the bundle digest will be prehashed by the key.
-      prehash: boolean,
-    },
-    signature: `0x${string}`,
-  }],
-}
-```
-
-## Response
-
-```ts
-type Response = {
-  // The bundle ID
-  id: `0x${string}`
-}
-```
diff --git a/apps/docs/pages/rpc-server/wallet_sendPreparedCalls.mdx b/apps/docs/pages/rpc-server/wallet_sendPreparedCalls.mdx
new file mode 100644
index 000000000..93c17b47a
--- /dev/null
+++ b/apps/docs/pages/rpc-server/wallet_sendPreparedCalls.mdx
@@ -0,0 +1,86 @@
+import Fees from './snippets/fees.mdx'
+import Keys from './snippets/keys.mdx'
+import Selectors from './snippets/selectors.mdx'
+
+# `wallet_sendPreparedCalls`
+
+Sends a prepared call bundle.
+
+:::tip
+This method is intended to be used in conjunction with [`wallet_prepareCalls`](/rpc-server/wallet_prepareCalls).
+:::
+
+<Fees />
+<Keys />
+<Selectors />
+
+## Request
+
+```ts
+type Request = {
+  method: 'wallet_sendPreparedCalls',
+  params: [{
+    capabilities?: {
+      // This will be passed to `feePayer` if specified for additional on-chain verification.
+      feeSignature?: `0x${string}`,
+    },
+    context: {
+      quote: {
+        chainId: `0x${string}`,
+        op: {
+          eoa: `0x${string}`,
+          executionData: `0x${string}`,
+          nonce: `0x${string}`,
+          payer: `0x${string}`,
+          paymentToken: `0x${string}`,
+          prePaymentMaxAmount: `0x${string}`,
+          totalPaymentMaxAmount: `0x${string}`,
+          combinedGas: `0x${string}`,
+          encodedPreOps: `0x${string}`[],
+          initData: `0x${string}`,
+          prePaymentAmount: `0x${string}`,
+          totalPaymentAmount: `0x${string}`,
+          paymentRecipient: `0x${string}`,
+          signature: `0x${string}`,
+          paymentSignature: `0x${string}`,
+          supportedDelegationImplementation: `0x${string}`,
+        },
+        txGas: `0x${string}`,
+        nativeFeeEstimate: {
+          maxFeePerGas: number,
+          maxPriorityFeePerGas: number,
+        },
+        // UNIX timestamp the quote expires at.
+        ttl: number,
+        authorizationAddress?: `0x${string}`,
+        entrypoint: `0x${string}`,
+        // The RPC servers signature over the quote.
+        signature: {
+          y_parity: boolean,
+          r: `0x${string}`,
+          s: `0x${string}`,
+        },
+        // The hash of the quote.
+        hash: `0x${string}`,
+      },
+    },
+    // The key that signed the bundle. See "Keys".
+    key: {
+      type: 'p256' | 'webauthnp256' | 'secp256k1',
+      publicKey: `0x${string}`,
+      // Whether the bundle digest will be prehashed by the key.
+      prehash: boolean,
+    },
+    signature: `0x${string}`,
+  }],
+}
+```
+
+## Response
+
+```ts
+type Response = {
+  // The bundle ID
+  id: `0x${string}`
+}
+```


Reviews:
user: login: graphite-app[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T18:27:50Z
user: login: graphite-app[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T10:13:09Z
user: login: jenpaff
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T10:43:22Z
user: login: jenpaff
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T10:45:42Z
user: login: onbjerg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T11:00:34Z

Review comments:
diff_hunk: @@ -0,0 +1,31 @@
+## Keys
+
+There exists three different key roles:
+
+- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
+- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
+- **Session keys** are like normal keys, except they also have an expiry.
+
+Setting permissions on an admin key is not allowed and will return an error.
path: apps/docs/pages/rpc-server/snippets/keys.mdx
user: login: graphite-app[bot]
body: There's a discrepancy in how admin key permission setting is described. The original files (e.g., in `wallet_prepareCalls.mdx` line 38) stated "Setting permissions on an admin key does nothing," but the new text in the snippet says it "is not allowed and will return an error." 

These statements describe different behaviors - one suggests silent failure while the other indicates explicit error handling. This inconsistency could cause confusion for developers implementing against this API.

Could you verify which behavior is correct and update all instances to maintain consistency across the documentation?
```suggestion
+Setting permissions on an admin key does nothing.
```
  

*Spotted by [Diamond](https://app.graphite.dev/diamond/?org=ithacaxyz&ref=ai-review-comment)*<i class='graphite__hidden'><br /><br />Is this helpful? React 👍 or 👎 to let us know.</i>
created_at: 2025-05-22T18:27:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -21,45 +25,9 @@ Only certain types of calls are allowed in preops:
 
 Preops have their own signatures, and they must be signed with a key that is already attached to the account. The `from` and `key` fields can be omitted when building a preop (`preop: true`).
 
-## Fees
-
-Execution of bundles are paid for by the fee payer, which defaults to the EOA. This can be overriden using `feePayer`.
-
-Fees are paid in `feeToken`, which is specified in the capabilities of `wallet_prepareCalls`. The fee token must be supported on the target chain. The list of supported tokens on each network can be found in the response of [`wallet_getCapabilities`](/rpc-server/wallet_getCapabilities).
-
-## Keys
-
-There exists three different key roles:
-
-- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
-- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
-- **Session keys** are like normal keys, except they also have an expiry.
-
-Setting permissions on an admin key does nothing.
-
-### Public key encoding
-
-The encoding of a key pair's public key depends on the key type:
-
-| Key Type         | Encoding Format       | Description                                                                    |
-| ---------------- | --------------------- | ------------------------------------------------------------------------------ |
-| secp256k1        | `abi.encode(address)` | Stores only the Ethereum address derived from the public key (truncated hash). |
-| webAuthn          | `abi.encode(x, y)`    | Stores both x and y coordinates of the public key on the elliptic curve.       |
-| secp256r1 (P256) | `abi.encode(x, y) `   | Stores both x and y coordinates for the secp256r1 curve.                       |
-
-## Signature encoding
-
-The signature is encoded as follows: `abi.encodePacked(bytes(innerSignature), bytes32(keyHash), bool(prehash))`, where the key hash is `keccak(bytes32(keyType, publicKey))`.
-
-The inner signature depends on the key type:
-
-| Key Type | Signature |
-| -------- | --------- |
-| secp256r1 (p256) | `(r, s)` |
-| webauthn | `(r, s)` |
-| secp256k1 | `(r, s)` or `(r, vs)` |
-
-## Selectors
+<Fees />
+<Keys />
+<Selectors />
 
 Selectors for call permissions can either be a 4-byte selector, e.g. `0x12345678`, or a Solidity-style selector, like `transfer(address,uint256)`.
path: apps/docs/pages/rpc-server/wallet_prepareCalls.mdx
user: login: graphite-app[bot]
body: The line 32 duplicates the content already imported from the `Selectors` snippet. Since you're already including the `<Selectors />` component on line 30, this repeated text should be removed to avoid duplication. The imported snippet already contains the exact same explanation about selector formats.
```suggestion


```
  

*Spotted by [Diamond](https://app.graphite.dev/diamond/?org=ithacaxyz&ref=ai-review-comment)*<i class='graphite__hidden'><br /><br />Is this helpful? React 👍 or 👎 to let us know.</i>
created_at: 2025-05-22T18:27:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,31 @@
+## Keys
+
+There exists three different key roles:
+
+- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
+- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
+- **Session keys** are like normal keys, except they also have an expiry.
+
+Setting permissions on an admin key is not allowed and will return an error.
+
+### Public key encoding
+
+The encoding of a key pair's public key depends on the key type:
+
+| Key Type         | Encoding Format       | Description                                                                    |
+| ---------------- | --------------------- | ------------------------------------------------------------------------------ |
+| secp256k1        | `abi.encode(address)` | Stores only the Ethereum address derived from the public key (truncated hash). |
+| webAuthn          | `abi.encode(x, y)`    | Stores both x and y coordinates of the public key on the elliptic curve.       |
+| secp256r1 (P256) | `abi.encode(x, y) `   | Stores both x and y coordinates for the secp256r1 curve.                       |
path: apps/docs/pages/rpc-server/snippets/keys.mdx
user: login: graphite-app[bot]
body: There's an extra space in the table cell formatting for the secp256r1 entry: `abi.encode(x, y) `. For consistency with the other table entries, this trailing space should be removed.
```suggestion
| secp256r1 (P256) | `abi.encode(x, y)`   | Stores both x and y coordinates for the secp256r1 curve.                       |
```
  

*Spotted by [Diamond](https://app.graphite.dev/diamond/?org=ithacaxyz&ref=ai-review-comment)*<i class='graphite__hidden'><br /><br />Is this helpful? React 👍 or 👎 to let us know.</i>
created_at: 2025-05-23T10:13:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,31 @@
+## Keys
+
+There exists three different key roles:
+
+- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
+- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
+- **Session keys** are like normal keys, except they also have an expiry.
path: apps/docs/pages/rpc-server/snippets/keys.mdx
user: login: jenpaff
body: and can be restricted to a function selector 
created_at: 2025-05-23T10:43:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,31 @@
+## Keys
+
+There exists three different key roles:
+
+- **Admin keys** are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
+- **Normal keys** can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
+- **Session keys** are like normal keys, except they also have an expiry.
path: apps/docs/pages/rpc-server/snippets/keys.mdx
user: login: onbjerg
body: thats described under normal keys
created_at: 2025-05-23T11:00:34Z
author_association: CONTRIBUTOR

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-05-22T17:05:18Z
body: ###  ⚠️  No Changeset found

Latest commit: 69bd94b890013a166a83cfe73930774f2bfb2f7d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/ithacaxyz/porto/new/onbjerg/docs-snippets?filename=.changeset/slimy-numbers-applaud.md&value=---%0A%22docs%22%3A%20patch%0A---%0A%0Adocs(rpc-server)%3A%20use%20snippets%0A)


author_association: NONE
user: login: vercel[bot]
created_at: 2025-05-22T17:05:19Z
body: [vc]: #8x9oiBGqCKkoqCRno3FngVNjlHkBtxx+9+w1ox+L3dU=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJ3YWdtaS5wb3J0byIsInJvb3REaXJlY3RvcnkiOiJhcHBzL3dhZ21pIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2l0aGFjYXh5ei93YWdtaS5wb3J0by9CYTFOSGVKUVFic2k5M1MzN0ZtQ0dvV3h1aW9tIiwicHJldmlld1VybCI6IndhZ21pcG9ydG8tZ2l0LW9uYmplcmctZG9jcy1zbmlwcGV0cy1pdGhhY2F4eXoudmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJ3YWdtaXBvcnRvLWdpdC1vbmJqZXJnLWRvY3Mtc25pcHBldHMtaXRoYWNheHl6LnZlcmNlbC5hcHAifX0seyJuYW1lIjoiZGlhbG9nLnBvcnRvIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvZGlhbG9nIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2l0aGFjYXh5ei9kaWFsb2cucG9ydG8vNXR3aGpjTW9WN1luVEVzaVc4cnVhZDY3ZFF5RCIsInByZXZpZXdVcmwiOiJkaWFsb2dwb3J0by1naXQtb25iamVyZy1kb2NzLXNuaXBwZXRzLWl0aGFjYXh5ei52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImRpYWxvZ3BvcnRvLWdpdC1vbmJqZXJnLWRvY3Mtc25pcHBldHMtaXRoYWNheHl6LnZlcmNlbC5hcHAifX0seyJuYW1lIjoibWFuYWdlLnBvcnRvIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvbWFuYWdlciIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9pdGhhY2F4eXovbWFuYWdlLnBvcnRvL0QxTmRGNmRvZWUzZDl2a001RVl0N1VIaFF3dzIiLCJwcmV2aWV3VXJsIjoibWFuYWdlcG9ydG8tZ2l0LW9uYmplcmctZG9jcy1zbmlwcGV0cy1pdGhhY2F4eXoudmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJtYW5hZ2Vwb3J0by1naXQtb25iamVyZy1kb2NzLXNuaXBwZXRzLWl0aGFjYXh5ei52ZXJjZWwuYXBwIn19LHsibmFtZSI6ImlkLnBvcnRvIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvcHJveHkiLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vaXRoYWNheHl6L2lkLnBvcnRvLzVYeTV1ZG5TeW5TbXVRdW9yZnFNeDJzV3pjNE4iLCJwcmV2aWV3VXJsIjoiaWRwb3J0by1naXQtb25iamVyZy1kb2NzLXNuaXBwZXRzLWl0aGFjYXh5ei52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImlkcG9ydG8tZ2l0LW9uYmplcmctZG9jcy1zbmlwcGV0cy1pdGhhY2F4eXoudmVyY2VsLmFwcCJ9fSx7Im5hbWUiOiJwbGF5Z3JvdW5kLnBvcnRvIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvcGxheWdyb3VuZCIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9pdGhhY2F4eXovcGxheWdyb3VuZC5wb3J0by9GMUF4V3N6aXQ0d3RWVWRMZkFuQmVBRHI1UktkIiwicHJldmlld1VybCI6InBsYXlncm91bmRwb3J0by1naXQtb25iamVyZy1kb2NzLXNuaXBwZXRzLWl0aGFjYXh5ei52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6InBsYXlncm91bmRwb3J0by1naXQtb25iamVyZy1kb2NzLXNuaXBwZXRzLWl0aGFjYXh5ei52ZXJjZWwuYXBwIn19LHsibmFtZSI6ImRvY3MucG9ydG8iLCJyb290RGlyZWN0b3J5IjoiYXBwcy9kb2NzIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2l0aGFjYXh5ei9kb2NzLnBvcnRvLzZBbmY4TFhaZTRCV0xpbnVheXA4RVBOUmZLMXoiLCJwcmV2aWV3VXJsIjoiZG9jc3BvcnRvLWdpdC1vbmJqZXJnLWRvY3Mtc25pcHBldHMtaXRoYWNheHl6LnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiZG9jc3BvcnRvLWdpdC1vbmJqZXJnLWRvY3Mtc25pcHBldHMtaXRoYWNheHl6LnZlcmNlbC5hcHAifX1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **dialog.porto** | ✅ Ready ([Inspect](https://vercel.com/ithacaxyz/dialog.porto/5twhjcMoV7YnTEsiW8ruad67dQyD)) | [Visit Preview](https://dialogporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/dialogporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app?via=pr-comment-feedback-link) | May 23, 2025 10:16am |
| **docs.porto** | ✅ Ready ([Inspect](https://vercel.com/ithacaxyz/docs.porto/6Anf8LXZe4BWLinuayp8EPNRfK1z)) | [Visit Preview](https://docsporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/docsporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app?via=pr-comment-feedback-link) | May 23, 2025 10:16am |
| **id.porto** | ✅ Ready ([Inspect](https://vercel.com/ithacaxyz/id.porto/5Xy5udnSynSmuQuorfqMx2sWzc4N)) | [Visit Preview](https://idporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/idporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app?via=pr-comment-feedback-link) | May 23, 2025 10:16am |
| **manage.porto** | ✅ Ready ([Inspect](https://vercel.com/ithacaxyz/manage.porto/D1NdF6doee3d9vkM5EYt7UHhQww2)) | [Visit Preview](https://manageporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/manageporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app?via=pr-comment-feedback-link) | May 23, 2025 10:16am |
| **playground.porto** | ✅ Ready ([Inspect](https://vercel.com/ithacaxyz/playground.porto/F1AxWszit4wtVUdLfAnBeADr5RKd)) | [Visit Preview](https://playgroundporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/playgroundporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app?via=pr-comment-feedback-link) | May 23, 2025 10:16am |
| **wagmi.porto** | ✅ Ready ([Inspect](https://vercel.com/ithacaxyz/wagmi.porto/Ba1NHeJQQbsi93S37FmCGoWxuiom)) | [Visit Preview](https://wagmiporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/wagmiporto-git-onbjerg-docs-snippets-ithacaxyz.vercel.app?via=pr-comment-feedback-link) | May 23, 2025 10:16am |







author_association: NONE