Skip to content

Commit 211504a

Browse files
authored
Merge branch 'main' into imp-agt-scr-90-100
2 parents f0c2d79 + 50f48b0 commit 211504a

8 files changed

Lines changed: 181 additions & 125 deletions

File tree

gator-sidebar.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ const sidebar = {
221221
key: 'erc-7710-reference',
222222
items: ['reference/erc7710/bundler-client', 'reference/erc7710/wallet-client'],
223223
},
224+
'reference/x402',
224225
'reference/types',
225226
{
226227
type: 'doc',

smart-accounts-kit/get-started/smart-account-quickstart/eip7702.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ This quickstart demonstrates how to upgrade your <GlossaryTerm term="Externally
1212
functionality using an [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) transaction.
1313
This enables your EOA to leverage the benefits of <GlossaryTerm term="Account abstraction">account abstraction</GlossaryTerm>, such as batch transactions, gas sponsorship, and <GlossaryTerm term="Delegation">delegation</GlossaryTerm>.
1414

15+
:::note
16+
This guide is for embedded wallets. To upgrade a MetaMask account, you can [use MetaMask Connect to upgrade to a smart account](/tutorials/upgrade-eoa-to-smart-account).
17+
:::
18+
1519
## Prerequisites
1620

1721
- Install [Node.js](https://nodejs.org/en/blog/release/v18.18.0) v18 or later.
@@ -167,4 +171,3 @@ const userOperationHash = await bundlerClient.sendUserOperation({
167171

168172
- To grant specific permissions to other accounts from your smart account, [create a delegation](../../guides/delegation/execute-on-smart-accounts-behalf.md).
169173
- To quickly bootstrap a MetaMask Smart Accounts project, [use the CLI](../use-the-cli.md).
170-
- You can also [use MetaMask Connect to upgrade a MetaMask account to a smart account](/tutorials/upgrade-eoa-to-smart-account).

smart-accounts-kit/guides/x402/buyer/delegations.md

Lines changed: 20 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Pay for an x402-protected API access using delegation.
2+
description: Pay for x402-protected API access using delegation.
33
sidebar_label: Delegations
44
keywords: [x402, ERC-7710, delegation, smart account, facilitator, buyer, API]
55
---
@@ -11,10 +11,11 @@ import GlossaryTerm from '@theme/GlossaryTerm';
1111
# Pay for an x402 API with delegation
1212

1313
In this guide, you use a buyer account to access API data from an x402 server by creating
14-
an <GlossaryTerm term="Open root delegation">open delegation</GlossaryTerm> that authorizes
15-
token transfers on your behalf.
14+
a <GlossaryTerm term="Delegation">delegation</GlossaryTerm> that authorizes token transfers
15+
on your behalf.
1616

17-
You set up an `x402Erc7710Client` with a delegation provider, register it with the x402 client,
17+
You use [`createx402DelegationProvider`](../../../reference/x402.md#createx402delegationprovider)
18+
to set up an `x402Erc7710Client` with a delegation provider, register it with the x402 client,
1819
and use `wrapFetchWithPayment` to automatically handle payment when calling a protected API route.
1920

2021
## Prerequisites
@@ -80,62 +81,25 @@ export const buyerAccount = privateKeyToAccount('0x<BUYER_PRIVATE_KEY>')
8081

8182
### 3. Create an x402 ERC-7710 client
8283

83-
Create an `x402Erc7710Client` with a `delegationProvider` callback.
84-
The x402 client calls this function automatically when it needs to pay for a request, passing
85-
in the payment requirements from the server.
84+
Create an `x402Erc7710Client` using
85+
[`createx402DelegationProvider`](../../../reference/x402.md#createx402delegationprovider).
86+
The provider creates an <GlossaryTerm term="Open delegation">open</GlossaryTerm>
87+
<GlossaryTerm term="Root delegation">root delegation</GlossaryTerm>, signs it, and returns an ABI-encoded delegation chain
88+
when the x402 client needs to pay for a request.
8689

87-
Inside the provider, create an [open delegation](../../../concepts/delegation/overview.md#open-root-delegation)
88-
using [`createOpenDelegation`](../../../reference/delegation/index.md#createopendelegation).
89-
This example uses the [`erc20TransferAmount`](../../../guides/delegation/use-delegation-scopes/spending-limit.md#erc-20-transfer-scope)
90-
scope to allow USDC transfers up to the requested amount, and the
91-
[`timestamp`](../../../reference/delegation/caveats.md#timestamp) caveat to set a short expiry.
92-
93-
For ERC-7710, x402 requires the payload fields `delegationManager`, `permissionContext`, and `delegator`.
94-
Use [`encodeDelegations`](../../../reference/delegation/index.md#encodedelegations) to encode the delegation chain.
90+
The provider appends [`redeemer`](../../../reference/delegation/caveats.md#redeemer),
91+
[`allowedTargets`](../../../reference/delegation/caveats.md#allowedtargets), and
92+
[`timestamp`](../../../reference/delegation/caveats.md#timestamp)
93+
<GlossaryTerm term="Caveat">caveats</GlossaryTerm> if not already present.
9594

9695
```ts
97-
import { CaveatType, createOpenDelegation, ScopeType } from '@metamask/smart-accounts-kit'
98-
import { encodeDelegations } from '@metamask/smart-accounts-kit/utils'
96+
import { createx402DelegationProvider } from '@metamask/smart-accounts-kit/experimental'
9997
import { x402Erc7710Client } from '@metamask/x402'
100-
import { getAddress } from 'viem'
10198

10299
const erc7710Client = new x402Erc7710Client({
103-
delegationProvider: async requirements => {
104-
// Expires in 1 minute.
105-
const expiry = Math.floor(Date.now() / 1000) + 60
106-
107-
const delegation = createOpenDelegation({
108-
environment: buyerSmartAccount.environment,
109-
from: buyerSmartAccount.address,
110-
scope: {
111-
type: ScopeType.Erc20TransferAmount,
112-
tokenAddress: getAddress(requirements.asset),
113-
maxAmount: BigInt(requirements.amount),
114-
},
115-
caveats: [
116-
{
117-
type: CaveatType.Timestamp,
118-
afterThreshold: 0,
119-
beforeThreshold: expiry,
120-
},
121-
],
122-
})
123-
124-
const signature = await buyerSmartAccount.signDelegation({
125-
delegation,
126-
})
127-
128-
const signedDelegation = {
129-
...delegation,
130-
signature,
131-
}
132-
133-
return {
134-
delegationManager: buyerSmartAccount.environment.DelegationManager,
135-
permissionContext: encodeDelegations([signedDelegation]),
136-
delegator: buyerSmartAccount.address,
137-
}
138-
},
100+
delegationProvider: createx402DelegationProvider({
101+
account: buyerSmartAccount,
102+
}),
139103
})
140104
```
141105

@@ -157,8 +121,8 @@ const fetchWithPayment = wrapFetchWithPayment(fetch, httpClient)
157121
### 5. Make the paid request
158122

159123
Call the protected endpoint using `fetchWithPayment`.
160-
It handles the x402 payment flow, calling your `delegationProvider`
161-
to create an open redelegation when the server returns a `402` response.
124+
It handles the x402 payment flow, calling your delegation provider
125+
to create an <GlossaryTerm term="Open delegation">open delegation</GlossaryTerm> when the server returns a `402` response.
162126

163127
```ts
164128
const paidResponse = await fetchWithPayment('https://api.example.com/paid-endpoint', {

smart-accounts-kit/guides/x402/buyer/recurring-payments.md

Lines changed: 16 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -117,75 +117,28 @@ const grantedPermissions = await walletClient.requestExecutionPermissions([
117117

118118
### 5. Create an x402 ERC-7710 client
119119

120-
Create an `x402Erc7710Client` with a `delegationProvider` callback.
121-
The x402 client calls this function automatically when it needs to pay for a request, passing
122-
in the payment requirements from the server.
120+
Create an `x402Erc7710Client` using
121+
[`createx402DelegationProvider`](../../../reference/x402.md#createx402delegationprovider).
123122

124-
Inside the provider, create an <GlossaryTerm term="Open redelegation">open redelegation</GlossaryTerm>
125-
from the agent account so the facilitator can redeem the permission context for x402 settlement.
126-
This example uses the
127-
[`erc20TransferAmount`](../../../guides/delegation/use-delegation-scopes/spending-limit.md#erc-20-transfer-scope)
128-
scope to allow USDC transfers up to the amount requested in payment terms.
129-
130-
Use the Wallet Client's
131-
[`redelegatePermissionContextOpen`](../../../reference/erc7710/wallet-client.md#redelegatepermissioncontextopen)
132-
action to create a redelegated permission context.
133-
134-
<Tabs>
135-
<TabItem value="example.ts">
123+
The provider creates an <GlossaryTerm term="Open redelegation">open redelegation</GlossaryTerm>
124+
from the session account using the granted permission. The facilitator can then redeem the redelegated
125+
permission context for x402 settlement.
136126

137127
```ts
138-
import { ScopeType, CaveatType } from '@metamask/smart-accounts-kit'
128+
import { createx402DelegationProvider } from '@metamask/smart-accounts-kit/experimental'
139129
import { x402Erc7710Client } from '@metamask/x402'
140-
import { getAddress } from 'viem'
141-
import { environment, sessionAccountWalletClient } from './config'
142130

143131
const permission = grantedPermissions[0]
144132

145133
const erc7710Client = new x402Erc7710Client({
146-
delegationProvider: async requirements => {
147-
const { permissionContext: redelegatedPermissionContext } =
148-
await sessionAccountWalletClient.redelegatePermissionContextOpen({
149-
environment,
150-
permissionContext: permission.context,
151-
scope: {
152-
type: ScopeType.Erc20TransferAmount,
153-
tokenAddress: getAddress(requirements.asset),
154-
maxAmount: BigInt(requirements.amount),
155-
},
156-
})
157-
158-
return {
159-
delegationManager: permission.delegationManager,
160-
permissionContext: redelegatedPermissionContext,
161-
delegator: permission.from,
162-
}
163-
},
134+
delegationProvider: createx402DelegationProvider({
135+
account: sessionAccount,
136+
parentPermissionContext: permission.context,
137+
from: permission.from,
138+
}),
164139
})
165140
```
166141

167-
</TabItem>
168-
<TabItem value="config.ts">
169-
170-
```ts
171-
import { createWalletClient, http } from 'viem'
172-
import { base as chain } from 'viem/chains'
173-
import { getSmartAccountsEnvironment } from '@metamask/smart-accounts-kit'
174-
import { erc7710WalletActions } from '@metamask/smart-accounts-kit/actions'
175-
176-
export const environment = getSmartAccountsEnvironment(chain.id)
177-
178-
// Use sessionAccount from previous step.
179-
export const sessionAccountWalletClient = createWalletClient({
180-
account: sessionAccount,
181-
chain,
182-
transport: http(),
183-
}).extend(erc7710WalletActions())
184-
```
185-
186-
</TabItem>
187-
</Tabs>
188-
189142
### 6. Register the client
190143

191144
Register the ERC-7710 client with the x402 core client for all EVM networks,
@@ -204,16 +157,16 @@ const fetchWithPayment = wrapFetchWithPayment(fetch, httpClient)
204157
### 7. Make the paid request
205158

206159
Call the protected endpoint using `fetchWithPayment`.
207-
It handles the x402 payment flow, calling your `delegationProvider`
208-
to create an open redelegation when the server returns a `402` response.
160+
The x402 payment flow calls your delegation provider to create an open redelegation
161+
when the server returns a `402` response.
209162

210163
```ts
211164
const paidResponse = await fetchWithPayment('https://api.example.com/paid-endpoint', {
212165
method: 'GET',
213166
})
214167
```
215168

216-
Reuse the same weekly granted permission for additional protected routes and providers in your
217-
agent flow.
218-
Your agent can continue paying until the weekly cap is reached, then continue after the next
169+
You can reuse the same weekly granted permission for additional protected routes and providers
170+
in your agent flow.
171+
Your agent continues paying until the weekly cap is reached, then resumes after the next
219172
weekly period starts.

smart-accounts-kit/guides/x402/seller.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ through the MetaMask facilitator.
3030

3131
The following table lists the available MetaMask facilitator endpoints:
3232

33-
| Name | ID | URL |
34-
| ------------ | -------------- | ----------------------------------------------------------------------- |
35-
| Base | `eip155:8453` | `https://tx-sentinel-base-mainnet.api.cx.metamask.io/platform/v2/x402` |
36-
| Base Sepolia | `eip155:84532` | `https://tx-sentinel-base-sepolia.api.cx.metamask.io/platform/v2/x402` |
37-
| Monad | `eip155:143` | `https://tx-sentinel-monad-mainnet.api.cx.metamask.io/platform/v2/x402` |
33+
| Name | ID | URL |
34+
| ------------ | -------------- | --------------------------------------------------------------------------- |
35+
| Base | `eip155:8453` | `https://tx-sentinel-monad-mainnet.dev-api.cx.metamask.io/platform/v2/x402` |
36+
| Base Sepolia | `eip155:84532` | `https://tx-sentinel-base-sepolia.dev-api.cx.metamask.io/platform/v2/x402` |
37+
| Monad | `eip155:143` | `https://tx-sentinel-base-mainnet.dev-api.cx.metamask.io/platform/v2/x402` |
3838

3939
## Steps
4040

smart-accounts-kit/reference/delegation/index.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,18 @@ import { sepolia } from 'viem/chains'
584584
const environment = getSmartAccountsEnvironment(sepolia.id)
585585
```
586586

587+
## `generateSalt`
588+
589+
Generates a random 32-byte hex salt for creating delegations. This helps prevent hash collisions when creating identical delegations.
590+
591+
### Example
592+
593+
```ts
594+
import { generateSalt } from '@metamask/smart-accounts-kit/utils'
595+
596+
const salt = generateSalt()
597+
```
598+
587599
## `overrideDeployedEnvironment`
588600

589601
Overrides or adds the `SmartAccountsEnvironment` for a chain and supported version.

smart-accounts-kit/reference/types.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,39 @@ Describes a supported <GlossaryTerm term="Advanced Permissions">Advanced Permiss
228228
| `chainIds` | `number[]` | Yes | The chain IDs on which the permission type is supported. |
229229
| `ruleTypes` | `string[]` | Yes | The rule types supported for the permission type (for example, `"expiry"`). |
230230

231+
### `MaybeDeferred`
232+
233+
Represents a value that can be provided directly or derived at runtime from [`PaymentRequirements`](#paymentrequirements).
234+
235+
```ts
236+
type MaybeDeferred<TResult> =
237+
| TResult
238+
| ((requirements: PaymentRequirements) => Promise<TResult> | TResult)
239+
```
240+
241+
### `PaymentRequirements`
242+
243+
Represents the payment requirements returned by an x402 server. [`createx402DelegationProvider`](x402.md#createx402delegationprovider) uses these values to scope and construct the <GlossaryTerm term="Delegation">delegation</GlossaryTerm>.
244+
245+
| Name | Type | Required | Description |
246+
| ------------------- | ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------- |
247+
| `scheme` | `string` | Yes | The payment scheme identifier. |
248+
| `network` | `string` | Yes | The [CAIP](https://namespaces.chainagnostic.org/eip155/caip2) network identifier. For example, `eip155:8453`. |
249+
| `asset` | `string` | Yes | The token contract address for the payment asset. |
250+
| `amount` | `string` | Yes | The payment amount in the token's smallest unit. |
251+
| `payTo` | `string` | Yes | The recipient address for the payment. |
252+
| `maxTimeoutSeconds` | `number` | Yes | The maximum time in seconds before the payment expires. |
253+
| `extra` | `Record<string, unknown>` | No | Additional context for x402, such as the asset transfer method. |
254+
255+
### `RedeemersConfig`
256+
257+
Configuration for the redeemer constraint used in [`createx402DelegationProvider`](x402.md#createx402delegationprovider).
258+
259+
| Name | Type | Required | Description |
260+
| ------------------ | ---------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------- |
261+
| `requireRedeemers` | `boolean` | Yes | Whether at least one redeemer constraint must exist. |
262+
| `addresses` | [`MaybeDeferred`](#maybedeferred)`<Address[]>` | No | The addresses that are allowed to redeem the <GlossaryTerm term="Delegation">delegation</GlossaryTerm>. |
263+
231264
### `ValueLteBuilderConfig`
232265
233266
| Name | Type | Required | Description |

0 commit comments

Comments
 (0)