@bankofai/x402-evm 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -0
- package/dist/cjs/auth-capture/client/index.d.ts +44 -0
- package/dist/cjs/auth-capture/client/index.js +298 -0
- package/dist/cjs/auth-capture/client/index.js.map +1 -0
- package/dist/cjs/batch-settlement/client/file-storage.d.ts +47 -0
- package/dist/cjs/batch-settlement/client/file-storage.js +116 -0
- package/dist/cjs/batch-settlement/client/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/client/index.d.ts +111 -0
- package/dist/cjs/batch-settlement/client/index.js +1565 -0
- package/dist/cjs/batch-settlement/client/index.js.map +1 -0
- package/dist/cjs/batch-settlement/facilitator/index.d.ts +72 -0
- package/dist/cjs/batch-settlement/facilitator/index.js +2102 -0
- package/dist/cjs/batch-settlement/facilitator/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/file-storage.d.ts +53 -0
- package/dist/cjs/batch-settlement/server/file-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/server/index.d.ts +491 -0
- package/dist/cjs/batch-settlement/server/index.js +1978 -0
- package/dist/cjs/batch-settlement/server/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/redis-storage.d.ts +87 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js.map +1 -0
- package/dist/cjs/client/agent-wallet.d.ts +69 -0
- package/dist/cjs/client/agent-wallet.js +84 -0
- package/dist/cjs/client/agent-wallet.js.map +1 -0
- package/dist/cjs/exact/client/index.d.ts +63 -0
- package/dist/cjs/exact/client/index.js +739 -0
- package/dist/cjs/exact/client/index.js.map +1 -0
- package/dist/cjs/exact/facilitator/index.d.ts +141 -0
- package/dist/cjs/exact/facilitator/index.js +1989 -0
- package/dist/cjs/exact/facilitator/index.js.map +1 -0
- package/dist/cjs/exact/server/index.d.ts +118 -0
- package/dist/cjs/exact/server/index.js +326 -0
- package/dist/cjs/exact/server/index.js.map +1 -0
- package/dist/cjs/exact/v1/client/index.d.ts +38 -0
- package/dist/cjs/exact/v1/client/index.js +193 -0
- package/dist/cjs/exact/v1/client/index.js.map +1 -0
- package/dist/cjs/exact/v1/facilitator/index.d.ts +84 -0
- package/dist/cjs/exact/v1/facilitator/index.js +739 -0
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -0
- package/dist/cjs/facilitator/agent-wallet.d.ts +109 -0
- package/dist/cjs/facilitator/agent-wallet.js +105 -0
- package/dist/cjs/facilitator/agent-wallet.js.map +1 -0
- package/dist/cjs/index.d.ts +338 -0
- package/dist/cjs/index.js +2860 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/permit2-DK5A8alk.d.ts +729 -0
- package/dist/cjs/permit2-DhJRUcgY.d.ts +729 -0
- package/dist/cjs/rpc-DULZzRne.d.ts +13 -0
- package/dist/cjs/scheme-7ehldYoO.d.ts +307 -0
- package/dist/cjs/scheme-BjBJzHF7.d.ts +307 -0
- package/dist/cjs/scheme-DWgpkDgz.d.ts +47 -0
- package/dist/cjs/signer-BFelv8DL.d.ts +170 -0
- package/dist/cjs/storage-6W5MO46W.d.ts +50 -0
- package/dist/cjs/storage-CHNote8s.d.ts +81 -0
- package/dist/cjs/storage-DjCv5IPh.d.ts +81 -0
- package/dist/cjs/types-CKd3Xoi1.d.ts +180 -0
- package/dist/cjs/types-DIt9uAUy.d.ts +180 -0
- package/dist/cjs/upto/client/index.d.ts +34 -0
- package/dist/cjs/upto/client/index.js +509 -0
- package/dist/cjs/upto/client/index.js.map +1 -0
- package/dist/cjs/upto/facilitator/index.d.ts +54 -0
- package/dist/cjs/upto/facilitator/index.js +1313 -0
- package/dist/cjs/upto/facilitator/index.js.map +1 -0
- package/dist/cjs/upto/server/index.d.ts +69 -0
- package/dist/cjs/upto/server/index.js +296 -0
- package/dist/cjs/upto/server/index.js.map +1 -0
- package/dist/cjs/v1/index.d.ts +40 -0
- package/dist/cjs/v1/index.js +199 -0
- package/dist/cjs/v1/index.js.map +1 -0
- package/dist/esm/auth-capture/client/index.d.mts +44 -0
- package/dist/esm/auth-capture/client/index.mjs +8 -0
- package/dist/esm/auth-capture/client/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/client/file-storage.d.mts +47 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs +63 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/client/index.d.mts +111 -0
- package/dist/esm/batch-settlement/client/index.mjs +58 -0
- package/dist/esm/batch-settlement/client/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/facilitator/index.d.mts +72 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs +1252 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/file-storage.d.mts +53 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs +128 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/index.d.mts +491 -0
- package/dist/esm/batch-settlement/server/index.mjs +1640 -0
- package/dist/esm/batch-settlement/server/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/redis-storage.d.mts +87 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs +156 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs.map +1 -0
- package/dist/esm/chunk-2EUQTNJO.mjs +38 -0
- package/dist/esm/chunk-2EUQTNJO.mjs.map +1 -0
- package/dist/esm/chunk-3WZF6722.mjs +36 -0
- package/dist/esm/chunk-3WZF6722.mjs.map +1 -0
- package/dist/esm/chunk-E4Z7PNXC.mjs +275 -0
- package/dist/esm/chunk-E4Z7PNXC.mjs.map +1 -0
- package/dist/esm/chunk-GQVMVP4N.mjs +911 -0
- package/dist/esm/chunk-GQVMVP4N.mjs.map +1 -0
- package/dist/esm/chunk-H2EYJIZL.mjs +489 -0
- package/dist/esm/chunk-H2EYJIZL.mjs.map +1 -0
- package/dist/esm/chunk-H3KPLYGI.mjs +152 -0
- package/dist/esm/chunk-H3KPLYGI.mjs.map +1 -0
- package/dist/esm/chunk-HYABYUBD.mjs +432 -0
- package/dist/esm/chunk-HYABYUBD.mjs.map +1 -0
- package/dist/esm/chunk-I2DVUHM5.mjs +123 -0
- package/dist/esm/chunk-I2DVUHM5.mjs.map +1 -0
- package/dist/esm/chunk-JK7SLLF7.mjs +34 -0
- package/dist/esm/chunk-JK7SLLF7.mjs.map +1 -0
- package/dist/esm/chunk-JNT7C46S.mjs +352 -0
- package/dist/esm/chunk-JNT7C46S.mjs.map +1 -0
- package/dist/esm/chunk-MACPBXCT.mjs +415 -0
- package/dist/esm/chunk-MACPBXCT.mjs.map +1 -0
- package/dist/esm/chunk-P3QOX3QZ.mjs +113 -0
- package/dist/esm/chunk-P3QOX3QZ.mjs.map +1 -0
- package/dist/esm/chunk-QVATVA3J.mjs +47 -0
- package/dist/esm/chunk-QVATVA3J.mjs.map +1 -0
- package/dist/esm/chunk-SHJFA25H.mjs +159 -0
- package/dist/esm/chunk-SHJFA25H.mjs.map +1 -0
- package/dist/esm/chunk-TW7Z65AO.mjs +34 -0
- package/dist/esm/chunk-TW7Z65AO.mjs.map +1 -0
- package/dist/esm/chunk-U4HCGTLU.mjs +35 -0
- package/dist/esm/chunk-U4HCGTLU.mjs.map +1 -0
- package/dist/esm/chunk-VS3RYAYE.mjs +80 -0
- package/dist/esm/chunk-VS3RYAYE.mjs.map +1 -0
- package/dist/esm/chunk-W6ON4LG2.mjs +39 -0
- package/dist/esm/chunk-W6ON4LG2.mjs.map +1 -0
- package/dist/esm/chunk-XG2JLZVJ.mjs +627 -0
- package/dist/esm/chunk-XG2JLZVJ.mjs.map +1 -0
- package/dist/esm/chunk-ZCJRY5LQ.mjs +162 -0
- package/dist/esm/chunk-ZCJRY5LQ.mjs.map +1 -0
- package/dist/esm/client/agent-wallet.d.mts +69 -0
- package/dist/esm/client/agent-wallet.mjs +36 -0
- package/dist/esm/client/agent-wallet.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +63 -0
- package/dist/esm/exact/client/index.mjs +25 -0
- package/dist/esm/exact/client/index.mjs.map +1 -0
- package/dist/esm/exact/facilitator/index.d.mts +141 -0
- package/dist/esm/exact/facilitator/index.mjs +694 -0
- package/dist/esm/exact/facilitator/index.mjs.map +1 -0
- package/dist/esm/exact/server/index.d.mts +118 -0
- package/dist/esm/exact/server/index.mjs +153 -0
- package/dist/esm/exact/server/index.mjs.map +1 -0
- package/dist/esm/exact/v1/client/index.d.mts +38 -0
- package/dist/esm/exact/v1/client/index.mjs +12 -0
- package/dist/esm/exact/v1/client/index.mjs.map +1 -0
- package/dist/esm/exact/v1/facilitator/index.d.mts +84 -0
- package/dist/esm/exact/v1/facilitator/index.mjs +12 -0
- package/dist/esm/exact/v1/facilitator/index.mjs.map +1 -0
- package/dist/esm/facilitator/agent-wallet.d.mts +109 -0
- package/dist/esm/facilitator/agent-wallet.mjs +74 -0
- package/dist/esm/facilitator/agent-wallet.mjs.map +1 -0
- package/dist/esm/index.d.mts +338 -0
- package/dist/esm/index.mjs +144 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/permit2-DhJRUcgY.d.mts +729 -0
- package/dist/esm/rpc-DULZzRne.d.mts +13 -0
- package/dist/esm/scheme-CkNhpXrG.d.mts +307 -0
- package/dist/esm/scheme-D8ZbykGV.d.mts +47 -0
- package/dist/esm/signer-BFelv8DL.d.mts +170 -0
- package/dist/esm/storage-6W5MO46W.d.mts +50 -0
- package/dist/esm/storage-BEzTEiUr.d.mts +81 -0
- package/dist/esm/types-DIt9uAUy.d.mts +180 -0
- package/dist/esm/upto/client/index.d.mts +34 -0
- package/dist/esm/upto/client/index.mjs +22 -0
- package/dist/esm/upto/client/index.mjs.map +1 -0
- package/dist/esm/upto/facilitator/index.d.mts +54 -0
- package/dist/esm/upto/facilitator/index.mjs +507 -0
- package/dist/esm/upto/facilitator/index.mjs.map +1 -0
- package/dist/esm/upto/server/index.d.mts +69 -0
- package/dist/esm/upto/server/index.mjs +124 -0
- package/dist/esm/upto/server/index.mjs.map +1 -0
- package/dist/esm/v1/index.d.mts +40 -0
- package/dist/esm/v1/index.mjs +18 -0
- package/dist/esm/v1/index.mjs.map +1 -0
- package/package.json +250 -0
package/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# `@bankofai/x402-evm` [](https://www.npmjs.com/package/@bankofai/x402-evm)
|
|
2
|
+
|
|
3
|
+
EVM (Ethereum Virtual Machine) implementation of the x402 payment protocol using the **Exact** payment scheme with EIP-3009 TransferWithAuthorization.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @bankofai/x402-evm
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
This package provides three main components for handling x402 payments on EVM-compatible blockchains:
|
|
14
|
+
|
|
15
|
+
- **Client** - For applications that need to make payments (have wallets/signers)
|
|
16
|
+
- **Facilitator** - For payment processors that verify and execute on-chain transactions
|
|
17
|
+
- **Service** - For resource servers that accept payments and build payment requirements
|
|
18
|
+
|
|
19
|
+
## Package Exports
|
|
20
|
+
|
|
21
|
+
### Main Package (`@bankofai/x402-evm`)
|
|
22
|
+
|
|
23
|
+
**V2 Protocol Support** - Modern x402 protocol with CAIP-2 network identifiers
|
|
24
|
+
|
|
25
|
+
**Client:**
|
|
26
|
+
- `ExactEvmClient` - V2 client implementation using EIP-3009
|
|
27
|
+
- `toClientEvmSigner(account)` - Converts viem accounts to x402 signers
|
|
28
|
+
- `ClientEvmSigner` - TypeScript type for client signers
|
|
29
|
+
|
|
30
|
+
**Facilitator:**
|
|
31
|
+
- `ExactEvmFacilitator` - V2 facilitator for payment verification and settlement
|
|
32
|
+
- `toFacilitatorEvmSigner(wallet)` - Converts viem wallets to facilitator signers
|
|
33
|
+
- `FacilitatorEvmSigner` - TypeScript type for facilitator signers
|
|
34
|
+
|
|
35
|
+
**Service:**
|
|
36
|
+
- `ExactEvmServer` - V2 service for building payment requirements
|
|
37
|
+
|
|
38
|
+
### V1 Package (`@bankofai/x402-evm/v1`)
|
|
39
|
+
|
|
40
|
+
**V1 Protocol Support** - Legacy x402 protocol with simple network names
|
|
41
|
+
|
|
42
|
+
**Exports:**
|
|
43
|
+
- `ExactEvmClientV1` - V1 client implementation
|
|
44
|
+
- `ExactEvmFacilitatorV1` - V1 facilitator implementation
|
|
45
|
+
- `NETWORKS` - Array of all supported V1 network names
|
|
46
|
+
|
|
47
|
+
**Supported V1 Networks:**
|
|
48
|
+
```typescript
|
|
49
|
+
[
|
|
50
|
+
"abstract", "abstract-testnet",
|
|
51
|
+
"base-sepolia", "base",
|
|
52
|
+
"avalanche-fuji", "avalanche",
|
|
53
|
+
"iotex", "sei", "sei-testnet",
|
|
54
|
+
"polygon", "polygon-amoy",
|
|
55
|
+
"peaq", "story", "educhain",
|
|
56
|
+
"skale-base-sepolia"
|
|
57
|
+
]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Version Differences
|
|
61
|
+
|
|
62
|
+
### V2 (Main Package)
|
|
63
|
+
- Network format: CAIP-2 (`eip155:8453`)
|
|
64
|
+
- Wildcard support: Yes (`eip155:*`)
|
|
65
|
+
- Payload structure: Partial (core wraps with metadata)
|
|
66
|
+
- Extensions: Full support
|
|
67
|
+
- Validity window: 1 hour (default)
|
|
68
|
+
|
|
69
|
+
### V1 (V1 Package)
|
|
70
|
+
- Network format: Simple names (`base-sepolia`)
|
|
71
|
+
- Wildcard support: No (fixed list)
|
|
72
|
+
- Payload structure: Complete
|
|
73
|
+
- Extensions: Limited
|
|
74
|
+
- Validity window: 10 minutes with buffer
|
|
75
|
+
|
|
76
|
+
## Usage Patterns
|
|
77
|
+
|
|
78
|
+
### 1. Direct Registration (Full Control)
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { x402Client } from "@bankofai/x402-core/client";
|
|
82
|
+
import { ExactEvmClient } from "@bankofai/x402-evm";
|
|
83
|
+
import { ExactEvmClientV1 } from "@bankofai/x402-evm/v1";
|
|
84
|
+
|
|
85
|
+
const client = new x402Client()
|
|
86
|
+
.register("eip155:*", new ExactEvmClient(signer))
|
|
87
|
+
.registerSchemeV1("base-sepolia", new ExactEvmClientV1(signer))
|
|
88
|
+
.registerSchemeV1("base", new ExactEvmClientV1(signer));
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Extension RPC Configuration (Optional)
|
|
92
|
+
|
|
93
|
+
`ExactEvmClient` only requires signer support for `address` + `signTypedData`.
|
|
94
|
+
Permit2 extension enrichment (EIP-2612 / ERC-20 approval gas sponsoring) can
|
|
95
|
+
optionally use explicit RPC config when signer read/fee helpers are unavailable.
|
|
96
|
+
|
|
97
|
+
No chain-default RPC fallback is applied by the SDK.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// Per-network explicit registration
|
|
101
|
+
const client = new x402Client()
|
|
102
|
+
.register("eip155:137", new ExactEvmClient(signer, { rpcUrl: polygonRpcUrl }))
|
|
103
|
+
.register("eip155:8453", new ExactEvmClient(signer, { rpcUrl: baseRpcUrl }));
|
|
104
|
+
|
|
105
|
+
// Wildcard registration with chain-id keyed config map
|
|
106
|
+
const wildcardClient = new x402Client().register(
|
|
107
|
+
"eip155:*",
|
|
108
|
+
new ExactEvmClient(signer, {
|
|
109
|
+
137: { rpcUrl: polygonRpcUrl },
|
|
110
|
+
8453: { rpcUrl: baseRpcUrl },
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 2. Using Config (Flexible)
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { x402Client } from "@bankofai/x402-core/client";
|
|
119
|
+
import { ExactEvmClient } from "@bankofai/x402-evm";
|
|
120
|
+
|
|
121
|
+
const client = x402Client.fromConfig({
|
|
122
|
+
schemes: [
|
|
123
|
+
{ network: "eip155:*", client: new ExactEvmClient(signer) },
|
|
124
|
+
{ network: "base-sepolia", client: new ExactEvmClientV1(signer), x402Version: 1 }
|
|
125
|
+
],
|
|
126
|
+
policies: [myCustomPolicy]
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Supported Networks
|
|
131
|
+
|
|
132
|
+
**V2 Networks** (via CAIP-2):
|
|
133
|
+
- `eip155:1` - Ethereum Mainnet
|
|
134
|
+
- `eip155:8453` - Base Mainnet
|
|
135
|
+
- `eip155:84532` - Base Sepolia
|
|
136
|
+
- `eip155:*` - Wildcard (matches all EVM chains)
|
|
137
|
+
- Any `eip155:<chainId>` network
|
|
138
|
+
|
|
139
|
+
**V1 Networks** (simple names):
|
|
140
|
+
See `NETWORKS` constant in `@bankofai/x402-evm/v1`
|
|
141
|
+
|
|
142
|
+
## Asset Support
|
|
143
|
+
|
|
144
|
+
Supports two asset transfer methods:
|
|
145
|
+
- **EIP-3009**: Tokens with native `transferWithAuthorization()` (e.g., USDC, EURC) — simplest, truly gasless
|
|
146
|
+
- **Permit2**: Any ERC-20 token — universal fallback, requires one-time approval
|
|
147
|
+
|
|
148
|
+
For the current list of chains with default assets configured, see [Default Assets for Dollar-String Pricing](../../../../docs/core-concepts/network-and-token-support.mdx#default-assets-for-dollar-string-pricing) in the x402 docs. To add default asset support for a new chain, see [Adding Support for New Networks](../../../../docs/core-concepts/network-and-token-support.mdx#adding-support-for-new-networks).
|
|
149
|
+
|
|
150
|
+
## Development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Build
|
|
154
|
+
npm run build
|
|
155
|
+
|
|
156
|
+
# Test
|
|
157
|
+
npm run test
|
|
158
|
+
|
|
159
|
+
# Integration tests
|
|
160
|
+
npm run test:integration
|
|
161
|
+
|
|
162
|
+
# Lint & Format
|
|
163
|
+
npm run lint
|
|
164
|
+
npm run format
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Related Packages
|
|
168
|
+
|
|
169
|
+
- `@bankofai/x402-core` - Core protocol types and client
|
|
170
|
+
- `@bankofai/x402-fetch` - HTTP wrapper with automatic payment handling
|
|
171
|
+
- `@bankofai/x402-svm` - Solana/SVM implementation
|
|
172
|
+
- `@bankofai/x402-stellar` - Stellar implementation
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { SchemeNetworkClient, PaymentRequirements, PaymentPayloadContext, PaymentPayloadResult } from '@bankofai/x402-core/types';
|
|
2
|
+
import { C as ClientEvmSigner } from '../../signer-BFelv8DL.js';
|
|
3
|
+
import 'viem';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* AuthCapture Scheme - Client
|
|
7
|
+
* Builds payment payloads for auth-capture payments.
|
|
8
|
+
*
|
|
9
|
+
* Implements x402's SchemeNetworkClient interface so it can be registered
|
|
10
|
+
* on an x402Client via client.register('eip155:84532', new AuthCaptureEvmScheme(signer)).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Client-side implementation of the auth-capture scheme: derives the canonical
|
|
15
|
+
* payer-agnostic PaymentInfo hash, signs an ERC-3009 ReceiveWithAuthorization
|
|
16
|
+
* (default) or a Permit2 PermitTransferFrom against it, and returns a wire
|
|
17
|
+
* payload the facilitator can settle. Implements `SchemeNetworkClient`.
|
|
18
|
+
*/
|
|
19
|
+
declare class AuthCaptureEvmScheme implements SchemeNetworkClient {
|
|
20
|
+
private readonly signer;
|
|
21
|
+
readonly scheme: "auth-capture";
|
|
22
|
+
/**
|
|
23
|
+
* Construct a client-side auth-capture scheme bound to a specific signer.
|
|
24
|
+
*
|
|
25
|
+
* @param signer - Client-side signer that exposes `address` and `signTypedData`.
|
|
26
|
+
*/
|
|
27
|
+
constructor(signer: ClientEvmSigner);
|
|
28
|
+
/**
|
|
29
|
+
* Build and sign an auth-capture payment payload for the given requirements.
|
|
30
|
+
* Validates all spec-mandated `extra` fields and the asset-transfer method
|
|
31
|
+
* (default `eip3009`, alternative `permit2`), reconstructs the on-chain
|
|
32
|
+
* PaymentInfo struct, computes its payer-agnostic hash, and returns the
|
|
33
|
+
* signed wire payload.
|
|
34
|
+
*
|
|
35
|
+
* @param x402Version - Wire protocol version; only `2` is supported.
|
|
36
|
+
* @param requirements - Resource server's payment requirements (includes scheme `extra`).
|
|
37
|
+
* @param _ - Unused FacilitatorContext (interface compatibility).
|
|
38
|
+
* @returns The signed wire payload tagged with the x402 protocol version.
|
|
39
|
+
* @throws If `x402Version !== 2` or any required `extra` field is missing.
|
|
40
|
+
*/
|
|
41
|
+
createPaymentPayload(x402Version: number, requirements: PaymentRequirements, _?: PaymentPayloadContext): Promise<PaymentPayloadResult>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { AuthCaptureEvmScheme };
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/auth-capture/client/index.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
AuthCaptureEvmScheme: () => AuthCaptureEvmScheme
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(client_exports);
|
|
26
|
+
|
|
27
|
+
// src/auth-capture/client/scheme.ts
|
|
28
|
+
var import_viem2 = require("viem");
|
|
29
|
+
|
|
30
|
+
// src/auth-capture/constants.ts
|
|
31
|
+
var AUTH_CAPTURE_SCHEME = "auth-capture";
|
|
32
|
+
var AUTH_CAPTURE_ESCROW_ADDRESS = "0xBdEA0D1bcC5966192B070Fdf62aB4EF5b4420cff";
|
|
33
|
+
var EIP3009_TOKEN_COLLECTOR_ADDRESS = "0x0E3dF9510de65469C4518D7843919c0b8C7A7757";
|
|
34
|
+
var PERMIT2_TOKEN_COLLECTOR_ADDRESS = "0x992476B9Ee81d52a5BdA0622C333938D0Af0aB26";
|
|
35
|
+
var RECEIVE_AUTHORIZATION_TYPES = {
|
|
36
|
+
ReceiveWithAuthorization: [
|
|
37
|
+
{ name: "from", type: "address" },
|
|
38
|
+
{ name: "to", type: "address" },
|
|
39
|
+
{ name: "value", type: "uint256" },
|
|
40
|
+
{ name: "validAfter", type: "uint256" },
|
|
41
|
+
{ name: "validBefore", type: "uint256" },
|
|
42
|
+
{ name: "nonce", type: "bytes32" }
|
|
43
|
+
]
|
|
44
|
+
};
|
|
45
|
+
var PERMIT2_TRANSFER_FROM_TYPES = {
|
|
46
|
+
PermitTransferFrom: [
|
|
47
|
+
{ name: "permitted", type: "TokenPermissions" },
|
|
48
|
+
{ name: "spender", type: "address" },
|
|
49
|
+
{ name: "nonce", type: "uint256" },
|
|
50
|
+
{ name: "deadline", type: "uint256" }
|
|
51
|
+
],
|
|
52
|
+
TokenPermissions: [
|
|
53
|
+
{ name: "token", type: "address" },
|
|
54
|
+
{ name: "amount", type: "uint256" }
|
|
55
|
+
]
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/auth-capture/nonce.ts
|
|
59
|
+
var import_viem = require("viem");
|
|
60
|
+
|
|
61
|
+
// src/constants.ts
|
|
62
|
+
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
63
|
+
|
|
64
|
+
// src/auth-capture/nonce.ts
|
|
65
|
+
var PAYMENT_INFO_TYPEHASH = (0, import_viem.keccak256)(
|
|
66
|
+
new TextEncoder().encode(
|
|
67
|
+
"PaymentInfo(address operator,address payer,address receiver,address token,uint120 maxAmount,uint48 preApprovalExpiry,uint48 authorizationExpiry,uint48 refundExpiry,uint16 minFeeBps,uint16 maxFeeBps,address feeReceiver,uint256 salt)"
|
|
68
|
+
)
|
|
69
|
+
);
|
|
70
|
+
function computePayerAgnosticPaymentInfoHash(chainId, paymentInfo) {
|
|
71
|
+
const paymentInfoEncoded = (0, import_viem.encodeAbiParameters)(
|
|
72
|
+
[
|
|
73
|
+
{ name: "typehash", type: "bytes32" },
|
|
74
|
+
{ name: "operator", type: "address" },
|
|
75
|
+
{ name: "payer", type: "address" },
|
|
76
|
+
{ name: "receiver", type: "address" },
|
|
77
|
+
{ name: "token", type: "address" },
|
|
78
|
+
{ name: "maxAmount", type: "uint120" },
|
|
79
|
+
{ name: "preApprovalExpiry", type: "uint48" },
|
|
80
|
+
{ name: "authorizationExpiry", type: "uint48" },
|
|
81
|
+
{ name: "refundExpiry", type: "uint48" },
|
|
82
|
+
{ name: "minFeeBps", type: "uint16" },
|
|
83
|
+
{ name: "maxFeeBps", type: "uint16" },
|
|
84
|
+
{ name: "feeReceiver", type: "address" },
|
|
85
|
+
{ name: "salt", type: "uint256" }
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
PAYMENT_INFO_TYPEHASH,
|
|
89
|
+
paymentInfo.operator,
|
|
90
|
+
import_viem.zeroAddress,
|
|
91
|
+
paymentInfo.receiver,
|
|
92
|
+
paymentInfo.token,
|
|
93
|
+
BigInt(paymentInfo.maxAmount),
|
|
94
|
+
paymentInfo.preApprovalExpiry,
|
|
95
|
+
paymentInfo.authorizationExpiry,
|
|
96
|
+
paymentInfo.refundExpiry,
|
|
97
|
+
paymentInfo.minFeeBps,
|
|
98
|
+
paymentInfo.maxFeeBps,
|
|
99
|
+
paymentInfo.feeReceiver,
|
|
100
|
+
BigInt(paymentInfo.salt)
|
|
101
|
+
]
|
|
102
|
+
);
|
|
103
|
+
const paymentInfoHash = (0, import_viem.keccak256)(paymentInfoEncoded);
|
|
104
|
+
const outerEncoded = (0, import_viem.encodeAbiParameters)(
|
|
105
|
+
[
|
|
106
|
+
{ name: "chainId", type: "uint256" },
|
|
107
|
+
{ name: "escrow", type: "address" },
|
|
108
|
+
{ name: "paymentInfoHash", type: "bytes32" }
|
|
109
|
+
],
|
|
110
|
+
[BigInt(chainId), AUTH_CAPTURE_ESCROW_ADDRESS, paymentInfoHash]
|
|
111
|
+
);
|
|
112
|
+
return (0, import_viem.keccak256)(outerEncoded);
|
|
113
|
+
}
|
|
114
|
+
async function signERC3009(signer, authorization, extra, tokenAddress, chainId) {
|
|
115
|
+
const domain = {
|
|
116
|
+
name: extra.name,
|
|
117
|
+
version: extra.version,
|
|
118
|
+
chainId,
|
|
119
|
+
verifyingContract: (0, import_viem.getAddress)(tokenAddress)
|
|
120
|
+
};
|
|
121
|
+
const message = {
|
|
122
|
+
from: (0, import_viem.getAddress)(authorization.from),
|
|
123
|
+
to: (0, import_viem.getAddress)(authorization.to),
|
|
124
|
+
value: BigInt(authorization.value),
|
|
125
|
+
validAfter: BigInt(authorization.validAfter),
|
|
126
|
+
validBefore: BigInt(authorization.validBefore),
|
|
127
|
+
nonce: authorization.nonce
|
|
128
|
+
};
|
|
129
|
+
return signer.signTypedData({
|
|
130
|
+
domain,
|
|
131
|
+
types: RECEIVE_AUTHORIZATION_TYPES,
|
|
132
|
+
primaryType: "ReceiveWithAuthorization",
|
|
133
|
+
message
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
async function signPermit2(signer, permit, chainId) {
|
|
137
|
+
const domain = {
|
|
138
|
+
name: "Permit2",
|
|
139
|
+
chainId,
|
|
140
|
+
verifyingContract: PERMIT2_ADDRESS
|
|
141
|
+
};
|
|
142
|
+
const message = {
|
|
143
|
+
permitted: {
|
|
144
|
+
token: (0, import_viem.getAddress)(permit.permitted.token),
|
|
145
|
+
amount: BigInt(permit.permitted.amount)
|
|
146
|
+
},
|
|
147
|
+
spender: (0, import_viem.getAddress)(permit.spender),
|
|
148
|
+
nonce: BigInt(permit.nonce),
|
|
149
|
+
deadline: BigInt(permit.deadline)
|
|
150
|
+
};
|
|
151
|
+
return signer.signTypedData({
|
|
152
|
+
domain,
|
|
153
|
+
types: PERMIT2_TRANSFER_FROM_TYPES,
|
|
154
|
+
primaryType: "PermitTransferFrom",
|
|
155
|
+
message
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function generateSalt() {
|
|
159
|
+
const bytes = new Uint8Array(32);
|
|
160
|
+
crypto.getRandomValues(bytes);
|
|
161
|
+
return (0, import_viem.toHex)(bytes);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/auth-capture/utils.ts
|
|
165
|
+
function parseChainId(network) {
|
|
166
|
+
const parts = network.split(":");
|
|
167
|
+
if (parts.length !== 2 || parts[0] !== "eip155") {
|
|
168
|
+
throw new Error(`Invalid network format: ${network}. Expected 'eip155:<chainId>'`);
|
|
169
|
+
}
|
|
170
|
+
const chainId = parseInt(parts[1], 10);
|
|
171
|
+
if (isNaN(chainId)) {
|
|
172
|
+
throw new Error(`Invalid chainId in network: ${network}`);
|
|
173
|
+
}
|
|
174
|
+
return chainId;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/auth-capture/client/scheme.ts
|
|
178
|
+
var AuthCaptureEvmScheme = class {
|
|
179
|
+
/**
|
|
180
|
+
* Construct a client-side auth-capture scheme bound to a specific signer.
|
|
181
|
+
*
|
|
182
|
+
* @param signer - Client-side signer that exposes `address` and `signTypedData`.
|
|
183
|
+
*/
|
|
184
|
+
constructor(signer) {
|
|
185
|
+
this.signer = signer;
|
|
186
|
+
this.scheme = AUTH_CAPTURE_SCHEME;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Build and sign an auth-capture payment payload for the given requirements.
|
|
190
|
+
* Validates all spec-mandated `extra` fields and the asset-transfer method
|
|
191
|
+
* (default `eip3009`, alternative `permit2`), reconstructs the on-chain
|
|
192
|
+
* PaymentInfo struct, computes its payer-agnostic hash, and returns the
|
|
193
|
+
* signed wire payload.
|
|
194
|
+
*
|
|
195
|
+
* @param x402Version - Wire protocol version; only `2` is supported.
|
|
196
|
+
* @param requirements - Resource server's payment requirements (includes scheme `extra`).
|
|
197
|
+
* @param _ - Unused FacilitatorContext (interface compatibility).
|
|
198
|
+
* @returns The signed wire payload tagged with the x402 protocol version.
|
|
199
|
+
* @throws If `x402Version !== 2` or any required `extra` field is missing.
|
|
200
|
+
*/
|
|
201
|
+
async createPaymentPayload(x402Version, requirements, _) {
|
|
202
|
+
if (x402Version !== 2) {
|
|
203
|
+
throw new Error(`Unsupported x402Version: ${x402Version}. Only version 2 is supported.`);
|
|
204
|
+
}
|
|
205
|
+
const extra = requirements.extra;
|
|
206
|
+
if (!extra.name) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`EIP-712 domain parameter 'name' is required in payment requirements for asset ${requirements.asset}`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
if (!extra.version) {
|
|
212
|
+
throw new Error(
|
|
213
|
+
`EIP-712 domain parameter 'version' is required in payment requirements for asset ${requirements.asset}`
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
if (!extra.captureAuthorizer) {
|
|
217
|
+
throw new Error(`'captureAuthorizer' is required in payment requirements extra`);
|
|
218
|
+
}
|
|
219
|
+
if (!extra.feeRecipient) {
|
|
220
|
+
throw new Error(`'feeRecipient' is required in payment requirements extra`);
|
|
221
|
+
}
|
|
222
|
+
if (typeof extra.captureDeadline !== "number") {
|
|
223
|
+
throw new Error(`'captureDeadline' is required in payment requirements extra`);
|
|
224
|
+
}
|
|
225
|
+
if (typeof extra.refundDeadline !== "number") {
|
|
226
|
+
throw new Error(`'refundDeadline' is required in payment requirements extra`);
|
|
227
|
+
}
|
|
228
|
+
if (typeof extra.minFeeBps !== "number") {
|
|
229
|
+
throw new Error(`'minFeeBps' is required in payment requirements extra`);
|
|
230
|
+
}
|
|
231
|
+
if (typeof extra.maxFeeBps !== "number") {
|
|
232
|
+
throw new Error(`'maxFeeBps' is required in payment requirements extra`);
|
|
233
|
+
}
|
|
234
|
+
if (typeof requirements.maxTimeoutSeconds !== "number") {
|
|
235
|
+
throw new Error(
|
|
236
|
+
`'maxTimeoutSeconds' is required in PaymentRequirements (used to derive preApprovalExpiry)`
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
const chainId = parseChainId(requirements.network);
|
|
240
|
+
const maxAmount = requirements.amount;
|
|
241
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
242
|
+
const preApprovalExpiry = nowSeconds + requirements.maxTimeoutSeconds;
|
|
243
|
+
const salt = generateSalt();
|
|
244
|
+
const assetTransferMethod = extra.assetTransferMethod ?? "eip3009";
|
|
245
|
+
const paymentInfo = {
|
|
246
|
+
operator: extra.captureAuthorizer,
|
|
247
|
+
payer: this.signer.address,
|
|
248
|
+
receiver: requirements.payTo,
|
|
249
|
+
token: requirements.asset,
|
|
250
|
+
maxAmount,
|
|
251
|
+
preApprovalExpiry,
|
|
252
|
+
authorizationExpiry: extra.captureDeadline,
|
|
253
|
+
refundExpiry: extra.refundDeadline,
|
|
254
|
+
minFeeBps: extra.minFeeBps,
|
|
255
|
+
maxFeeBps: extra.maxFeeBps,
|
|
256
|
+
feeReceiver: extra.feeRecipient,
|
|
257
|
+
salt
|
|
258
|
+
};
|
|
259
|
+
const nonce = computePayerAgnosticPaymentInfoHash(chainId, paymentInfo);
|
|
260
|
+
if (assetTransferMethod === "permit2") {
|
|
261
|
+
const permit2Authorization = {
|
|
262
|
+
from: this.signer.address,
|
|
263
|
+
permitted: {
|
|
264
|
+
token: requirements.asset,
|
|
265
|
+
amount: maxAmount
|
|
266
|
+
},
|
|
267
|
+
spender: PERMIT2_TOKEN_COLLECTOR_ADDRESS,
|
|
268
|
+
nonce: (0, import_viem2.hexToBigInt)(nonce).toString(),
|
|
269
|
+
deadline: String(preApprovalExpiry)
|
|
270
|
+
};
|
|
271
|
+
const signature2 = await signPermit2(this.signer, permit2Authorization, chainId);
|
|
272
|
+
const payload2 = { permit2Authorization, signature: signature2, salt };
|
|
273
|
+
return { x402Version, payload: payload2 };
|
|
274
|
+
}
|
|
275
|
+
const authorization = {
|
|
276
|
+
from: this.signer.address,
|
|
277
|
+
to: EIP3009_TOKEN_COLLECTOR_ADDRESS,
|
|
278
|
+
value: maxAmount,
|
|
279
|
+
validAfter: "0",
|
|
280
|
+
validBefore: String(preApprovalExpiry),
|
|
281
|
+
nonce
|
|
282
|
+
};
|
|
283
|
+
const signature = await signERC3009(
|
|
284
|
+
this.signer,
|
|
285
|
+
authorization,
|
|
286
|
+
extra,
|
|
287
|
+
requirements.asset,
|
|
288
|
+
chainId
|
|
289
|
+
);
|
|
290
|
+
const payload = { authorization, signature, salt };
|
|
291
|
+
return { x402Version, payload };
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
295
|
+
0 && (module.exports = {
|
|
296
|
+
AuthCaptureEvmScheme
|
|
297
|
+
});
|
|
298
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/auth-capture/client/index.ts","../../../../src/auth-capture/client/scheme.ts","../../../../src/auth-capture/constants.ts","../../../../src/auth-capture/nonce.ts","../../../../src/constants.ts","../../../../src/auth-capture/utils.ts"],"sourcesContent":["export { AuthCaptureEvmScheme } from \"./scheme\";\n","/**\n * AuthCapture Scheme - Client\n * Builds payment payloads for auth-capture payments.\n *\n * Implements x402's SchemeNetworkClient interface so it can be registered\n * on an x402Client via client.register('eip155:84532', new AuthCaptureEvmScheme(signer)).\n */\n\nimport type {\n PaymentPayloadContext,\n PaymentPayloadResult,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@bankofai/x402-core/types\";\nimport type { ClientEvmSigner } from \"../../signer\";\nimport { hexToBigInt } from \"viem\";\nimport {\n AUTH_CAPTURE_SCHEME,\n EIP3009_TOKEN_COLLECTOR_ADDRESS,\n PERMIT2_TOKEN_COLLECTOR_ADDRESS,\n} from \"../constants\";\nimport {\n computePayerAgnosticPaymentInfoHash,\n generateSalt,\n signERC3009,\n signPermit2,\n} from \"../nonce\";\nimport type { AuthCaptureExtra, Eip3009Payload, PaymentInfoStruct, Permit2Payload } from \"../types\";\nimport { parseChainId } from \"../utils\";\n\n/**\n * Client-side implementation of the auth-capture scheme: derives the canonical\n * payer-agnostic PaymentInfo hash, signs an ERC-3009 ReceiveWithAuthorization\n * (default) or a Permit2 PermitTransferFrom against it, and returns a wire\n * payload the facilitator can settle. Implements `SchemeNetworkClient`.\n */\nexport class AuthCaptureEvmScheme implements SchemeNetworkClient {\n readonly scheme = AUTH_CAPTURE_SCHEME;\n\n /**\n * Construct a client-side auth-capture scheme bound to a specific signer.\n *\n * @param signer - Client-side signer that exposes `address` and `signTypedData`.\n */\n constructor(private readonly signer: ClientEvmSigner) {}\n\n /**\n * Build and sign an auth-capture payment payload for the given requirements.\n * Validates all spec-mandated `extra` fields and the asset-transfer method\n * (default `eip3009`, alternative `permit2`), reconstructs the on-chain\n * PaymentInfo struct, computes its payer-agnostic hash, and returns the\n * signed wire payload.\n *\n * @param x402Version - Wire protocol version; only `2` is supported.\n * @param requirements - Resource server's payment requirements (includes scheme `extra`).\n * @param _ - Unused FacilitatorContext (interface compatibility).\n * @returns The signed wire payload tagged with the x402 protocol version.\n * @throws If `x402Version !== 2` or any required `extra` field is missing.\n */\n async createPaymentPayload(\n x402Version: number,\n requirements: PaymentRequirements,\n _?: PaymentPayloadContext,\n ): Promise<PaymentPayloadResult> {\n if (x402Version !== 2) {\n throw new Error(`Unsupported x402Version: ${x402Version}. Only version 2 is supported.`);\n }\n\n const extra = requirements.extra as unknown as AuthCaptureExtra;\n\n // Validate required EIP-712 token-domain parameters\n if (!extra.name) {\n throw new Error(\n `EIP-712 domain parameter 'name' is required in payment requirements for asset ${requirements.asset}`,\n );\n }\n if (!extra.version) {\n throw new Error(\n `EIP-712 domain parameter 'version' is required in payment requirements for asset ${requirements.asset}`,\n );\n }\n if (!extra.captureAuthorizer) {\n throw new Error(`'captureAuthorizer' is required in payment requirements extra`);\n }\n if (!extra.feeRecipient) {\n throw new Error(`'feeRecipient' is required in payment requirements extra`);\n }\n if (typeof extra.captureDeadline !== \"number\") {\n throw new Error(`'captureDeadline' is required in payment requirements extra`);\n }\n if (typeof extra.refundDeadline !== \"number\") {\n throw new Error(`'refundDeadline' is required in payment requirements extra`);\n }\n if (typeof extra.minFeeBps !== \"number\") {\n throw new Error(`'minFeeBps' is required in payment requirements extra`);\n }\n if (typeof extra.maxFeeBps !== \"number\") {\n throw new Error(`'maxFeeBps' is required in payment requirements extra`);\n }\n if (typeof requirements.maxTimeoutSeconds !== \"number\") {\n throw new Error(\n `'maxTimeoutSeconds' is required in PaymentRequirements (used to derive preApprovalExpiry)`,\n );\n }\n\n const chainId = parseChainId(requirements.network);\n const maxAmount = requirements.amount;\n const nowSeconds = Math.floor(Date.now() / 1000);\n const preApprovalExpiry = nowSeconds + requirements.maxTimeoutSeconds;\n const salt = generateSalt();\n const assetTransferMethod = extra.assetTransferMethod ?? \"eip3009\";\n\n // Build the canonical PaymentInfo struct (Solidity field names — do not rename).\n const paymentInfo: PaymentInfoStruct = {\n operator: extra.captureAuthorizer,\n payer: this.signer.address,\n receiver: requirements.payTo as `0x${string}`,\n token: requirements.asset as `0x${string}`,\n maxAmount,\n preApprovalExpiry,\n authorizationExpiry: extra.captureDeadline,\n refundExpiry: extra.refundDeadline,\n minFeeBps: extra.minFeeBps,\n maxFeeBps: extra.maxFeeBps,\n feeReceiver: extra.feeRecipient,\n salt,\n };\n\n // Payer-agnostic PaymentInfo hash — used as ERC-3009 nonce or Permit2 nonce.\n const nonce = computePayerAgnosticPaymentInfoHash(chainId, paymentInfo);\n\n if (assetTransferMethod === \"permit2\") {\n const permit2Authorization: Permit2Payload[\"permit2Authorization\"] = {\n from: this.signer.address,\n permitted: {\n token: requirements.asset as `0x${string}`,\n amount: maxAmount,\n },\n spender: PERMIT2_TOKEN_COLLECTOR_ADDRESS,\n nonce: hexToBigInt(nonce).toString(),\n deadline: String(preApprovalExpiry),\n };\n const signature = await signPermit2(this.signer, permit2Authorization, chainId);\n const payload: Permit2Payload = { permit2Authorization, signature, salt };\n return { x402Version, payload: payload as unknown as Record<string, unknown> };\n }\n\n // Default: EIP-3009 ReceiveWithAuthorization to the canonical EIP-3009 token collector.\n const authorization: Eip3009Payload[\"authorization\"] = {\n from: this.signer.address,\n to: EIP3009_TOKEN_COLLECTOR_ADDRESS,\n value: maxAmount,\n validAfter: \"0\",\n validBefore: String(preApprovalExpiry),\n nonce,\n };\n const signature = await signERC3009(\n this.signer,\n authorization,\n extra,\n requirements.asset as `0x${string}`,\n chainId,\n );\n const payload: Eip3009Payload = { authorization, signature, salt };\n return { x402Version, payload: payload as unknown as Record<string, unknown> };\n }\n}\n","// Scheme identifier for the auth-capture payment scheme.\nexport const AUTH_CAPTURE_SCHEME = \"auth-capture\" as const;\n\n// Canonical AuthCaptureEscrow + token collector deployments from\n// base/commerce-payments (https://github.com/base/commerce-payments). These are\n// the audited, live addresses listed in the upstream README and are the source\n// of truth for this scheme. They are universal constants, not configurable per\n// merchant.\nexport const AUTH_CAPTURE_ESCROW_ADDRESS =\n \"0xBdEA0D1bcC5966192B070Fdf62aB4EF5b4420cff\" as const satisfies `0x${string}`;\nexport const EIP3009_TOKEN_COLLECTOR_ADDRESS =\n \"0x0E3dF9510de65469C4518D7843919c0b8C7A7757\" as const satisfies `0x${string}`;\nexport const PERMIT2_TOKEN_COLLECTOR_ADDRESS =\n \"0x992476B9Ee81d52a5BdA0622C333938D0Af0aB26\" as const satisfies `0x${string}`;\n\n// ERC-3009 ReceiveWithAuthorization EIP-712 types\nexport const RECEIVE_AUTHORIZATION_TYPES = {\n ReceiveWithAuthorization: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n} as const;\n\n// Uniswap Permit2 PermitTransferFrom EIP-712 types\nexport const PERMIT2_TRANSFER_FROM_TYPES = {\n PermitTransferFrom: [\n { name: \"permitted\", type: \"TokenPermissions\" },\n { name: \"spender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n TokenPermissions: [\n { name: \"token\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n} as const;\n","/**\n * Nonce computation, salt generation, and signing helpers.\n */\n\nimport { encodeAbiParameters, getAddress, keccak256, toHex, zeroAddress } from \"viem\";\nimport type { ClientEvmSigner } from \"../signer\";\nimport { PERMIT2_ADDRESS } from \"../constants\";\nimport {\n AUTH_CAPTURE_ESCROW_ADDRESS,\n PERMIT2_TRANSFER_FROM_TYPES,\n RECEIVE_AUTHORIZATION_TYPES,\n} from \"./constants\";\nimport type { AuthCaptureExtra, Eip3009Payload, PaymentInfoStruct, Permit2Payload } from \"./types\";\n\n/**\n * PaymentInfo typehash — must match AuthCaptureEscrow.PAYMENT_INFO_TYPEHASH.\n */\nconst PAYMENT_INFO_TYPEHASH = keccak256(\n new TextEncoder().encode(\n \"PaymentInfo(address operator,address payer,address receiver,address token,uint120 maxAmount,uint48 preApprovalExpiry,uint48 authorizationExpiry,uint48 refundExpiry,uint16 minFeeBps,uint16 maxFeeBps,address feeReceiver,uint256 salt)\",\n ),\n);\n\n/**\n * Compute the payer-agnostic PaymentInfo hash that auth-capture uses as both\n * the ERC-3009 nonce (`bytes32`) and the Permit2 nonce (`uint256`, via the\n * same 32 bytes interpreted as an integer). The payer field is zeroed before\n * hashing so the facilitator can reconstruct the same hash on the verify side\n * without knowing payer identity in advance.\n *\n * Freshness comes from `paymentInfo.salt`; generate a new salt per signing\n * call via `generateSalt`. Identical extras + same salt would collide across\n * payers.\n *\n * @param chainId - EVM chain id; binds the hash to a specific chain.\n * @param paymentInfo - The reconstructed PaymentInfo struct (canonical Solidity field names).\n * @returns The 32-byte hash to use as the nonce on the wire.\n */\nexport function computePayerAgnosticPaymentInfoHash(\n chainId: number,\n paymentInfo: PaymentInfoStruct,\n): `0x${string}` {\n const paymentInfoEncoded = encodeAbiParameters(\n [\n { name: \"typehash\", type: \"bytes32\" },\n { name: \"operator\", type: \"address\" },\n { name: \"payer\", type: \"address\" },\n { name: \"receiver\", type: \"address\" },\n { name: \"token\", type: \"address\" },\n { name: \"maxAmount\", type: \"uint120\" },\n { name: \"preApprovalExpiry\", type: \"uint48\" },\n { name: \"authorizationExpiry\", type: \"uint48\" },\n { name: \"refundExpiry\", type: \"uint48\" },\n { name: \"minFeeBps\", type: \"uint16\" },\n { name: \"maxFeeBps\", type: \"uint16\" },\n { name: \"feeReceiver\", type: \"address\" },\n { name: \"salt\", type: \"uint256\" },\n ],\n [\n PAYMENT_INFO_TYPEHASH,\n paymentInfo.operator,\n zeroAddress,\n paymentInfo.receiver,\n paymentInfo.token,\n BigInt(paymentInfo.maxAmount),\n paymentInfo.preApprovalExpiry,\n paymentInfo.authorizationExpiry,\n paymentInfo.refundExpiry,\n paymentInfo.minFeeBps,\n paymentInfo.maxFeeBps,\n paymentInfo.feeReceiver,\n BigInt(paymentInfo.salt),\n ],\n );\n const paymentInfoHash = keccak256(paymentInfoEncoded);\n\n const outerEncoded = encodeAbiParameters(\n [\n { name: \"chainId\", type: \"uint256\" },\n { name: \"escrow\", type: \"address\" },\n { name: \"paymentInfoHash\", type: \"bytes32\" },\n ],\n [BigInt(chainId), AUTH_CAPTURE_ESCROW_ADDRESS, paymentInfoHash],\n );\n\n return keccak256(outerEncoded);\n}\n\n/**\n * Sign an ERC-3009 `ReceiveWithAuthorization` over the supplied authorization\n * fields. The EIP-712 domain is bound to the **token contract** (not the\n * escrow), so the token's `name` and `version` come from `extra` because they\n * vary per asset (e.g. `\"USDC\"` on Sepolia vs `\"USD Coin\"` on mainnet).\n *\n * @param signer - Client signer with `signTypedData`.\n * @param authorization - The ERC-3009 authorization to sign.\n * @param extra - Carries the token EIP-712 domain `name` + `version`.\n * @param tokenAddress - Address of the token contract (verifyingContract in the domain).\n * @param chainId - EVM chain id (chainId in the domain).\n * @returns The 65-byte ECDSA signature (or EIP-1271 / EIP-6492 envelope, depending on the signer).\n */\nexport async function signERC3009(\n signer: ClientEvmSigner,\n authorization: Eip3009Payload[\"authorization\"],\n extra: AuthCaptureExtra,\n tokenAddress: `0x${string}`,\n chainId: number,\n): Promise<`0x${string}`> {\n const domain = {\n name: extra.name,\n version: extra.version,\n chainId,\n verifyingContract: getAddress(tokenAddress),\n };\n\n const message = {\n from: getAddress(authorization.from),\n to: getAddress(authorization.to),\n value: BigInt(authorization.value),\n validAfter: BigInt(authorization.validAfter),\n validBefore: BigInt(authorization.validBefore),\n nonce: authorization.nonce,\n };\n\n return signer.signTypedData({\n domain,\n types: RECEIVE_AUTHORIZATION_TYPES,\n primaryType: \"ReceiveWithAuthorization\",\n message,\n });\n}\n\n/**\n * Sign a Permit2 `PermitTransferFrom` over the supplied permit fields. Domain\n * is bound to the canonical Permit2 contract. No witness struct is needed —\n * the deterministic nonce (the payer-agnostic PaymentInfo hash, packed into\n * uint256) cryptographically binds all payment parameters including receiver,\n * amount, and deadlines.\n *\n * @param signer - Client signer with `signTypedData`.\n * @param permit - The Permit2 PermitTransferFrom message to sign.\n * @param chainId - EVM chain id (chainId in the Permit2 domain).\n * @returns The 65-byte ECDSA signature (or EIP-1271 / EIP-6492 envelope, depending on the signer).\n */\nexport async function signPermit2(\n signer: ClientEvmSigner,\n permit: Permit2Payload[\"permit2Authorization\"],\n chainId: number,\n): Promise<`0x${string}`> {\n const domain = {\n name: \"Permit2\",\n chainId,\n verifyingContract: PERMIT2_ADDRESS,\n };\n\n const message = {\n permitted: {\n token: getAddress(permit.permitted.token),\n amount: BigInt(permit.permitted.amount),\n },\n spender: getAddress(permit.spender),\n nonce: BigInt(permit.nonce),\n deadline: BigInt(permit.deadline),\n };\n\n return signer.signTypedData({\n domain,\n types: PERMIT2_TRANSFER_FROM_TYPES,\n primaryType: \"PermitTransferFrom\",\n message,\n });\n}\n\n/**\n * Generate a fresh cryptographically-random 32-byte salt. MUST be called once\n * per signing request — never reuse across requests. Freshness is required\n * because the nonce derivation zeroes the payer field; identical extras with\n * the same salt would collide across payers.\n *\n * @returns A new 32-byte salt as a `0x`-prefixed hex string.\n */\nexport function generateSalt(): `0x${string}` {\n const bytes = new Uint8Array(32);\n crypto.getRandomValues(bytes);\n return toHex(bytes);\n}\n","// EIP-3009 TransferWithAuthorization types for EIP-712 signing\nexport const authorizationTypes = {\n TransferWithAuthorization: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n} as const;\n\n/**\n * Permit2 EIP-712 types for signing PermitWitnessTransferFrom (exact scheme).\n * Must match the exact format expected by the Permit2 contract.\n * Note: Types must be in ALPHABETICAL order after the primary type (TokenPermissions < Witness).\n */\nexport const permit2WitnessTypes = {\n PermitWitnessTransferFrom: [\n { name: \"permitted\", type: \"TokenPermissions\" },\n { name: \"spender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n { name: \"witness\", type: \"Witness\" },\n ],\n TokenPermissions: [\n { name: \"token\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n Witness: [\n { name: \"to\", type: \"address\" },\n { name: \"validAfter\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * Permit2 EIP-712 types for signing PermitWitnessTransferFrom (upto scheme).\n * The upto witness includes a `facilitator` field that the exact witness does not.\n * This ensures only the authorized facilitator can settle the payment.\n * Must match: Witness(address to,address facilitator,uint256 validAfter)\n */\nexport const uptoPermit2WitnessTypes = {\n PermitWitnessTransferFrom: [\n { name: \"permitted\", type: \"TokenPermissions\" },\n { name: \"spender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n { name: \"witness\", type: \"Witness\" },\n ],\n TokenPermissions: [\n { name: \"token\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n Witness: [\n { name: \"to\", type: \"address\" },\n { name: \"facilitator\", type: \"address\" },\n { name: \"validAfter\", type: \"uint256\" },\n ],\n} as const;\n\n// EIP3009 ABI for transferWithAuthorization function\nexport const eip3009ABI = [\n {\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n name: \"transferWithAuthorization\",\n outputs: [],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n {\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"signature\", type: \"bytes\" },\n ],\n name: \"transferWithAuthorization\",\n outputs: [],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n {\n inputs: [{ name: \"account\", type: \"address\" }],\n name: \"balanceOf\",\n outputs: [{ name: \"\", type: \"uint256\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [],\n name: \"version\",\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [],\n name: \"name\",\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [\n { name: \"authorizer\", type: \"address\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n name: \"authorizationState\",\n outputs: [{ name: \"\", type: \"bool\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n] as const;\n\n/**\n * EIP-2612 Permit EIP-712 types for signing token.permit().\n */\nexport const eip2612PermitTypes = {\n Permit: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * EIP-2612 nonces ABI for querying current nonce.\n */\nexport const eip2612NoncesAbi = [\n {\n type: \"function\",\n name: \"nonces\",\n inputs: [{ name: \"owner\", type: \"address\" }],\n outputs: [{ type: \"uint256\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/** ERC-20 approve(address,uint256) ABI for encoding/decoding approval calldata. */\nexport const erc20ApproveAbi = [\n {\n type: \"function\",\n name: \"approve\",\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ type: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n] as const;\n\n/** ERC-20 allowance(address,address) ABI for checking spender approval. */\nexport const erc20AllowanceAbi = [\n {\n type: \"function\",\n name: \"allowance\",\n inputs: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n ],\n outputs: [{ type: \"uint256\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/** Gas limit for a standard ERC-20 approve() transaction. */\nexport const ERC20_APPROVE_GAS_LIMIT = 70_000n;\n\n/** Fallback max fee per gas (1 gwei) when fee estimation fails. */\nexport const DEFAULT_MAX_FEE_PER_GAS = 1_000_000_000n;\n\n/** Fallback max priority fee per gas (0.1 gwei) when fee estimation fails. */\nexport const DEFAULT_MAX_PRIORITY_FEE_PER_GAS = 100_000_000n;\n\n/**\n * Canonical Permit2 contract address.\n * Same address on all EVM chains via CREATE2 deployment.\n *\n * @see https://github.com/Uniswap/permit2\n */\nexport const PERMIT2_ADDRESS = \"0x000000000022D473030F116dDEE9F6B43aC78BA3\" as const;\n\n/**\n * x402ExactPermit2Proxy contract address.\n * Vanity address: 0x4020...0001 for easy recognition.\n * This address is deterministic based on:\n * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C)\n * - Vanity-mined salt for prefix 0x4020 and suffix 0001\n * - Contract bytecode + constructor args (PERMIT2_ADDRESS)\n */\nexport const x402ExactPermit2ProxyAddress = \"0x402085c248EeA27D92E8b30b2C58ed07f9E20001\" as const;\n\n/**\n * x402UptoPermit2Proxy contract address.\n * Vanity address: 0x4020...0002 for easy recognition.\n * This address is deterministic based on:\n * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C)\n * - Vanity-mined salt for prefix 0x4020 and suffix 0002\n * - Contract bytecode + constructor args (PERMIT2_ADDRESS)\n */\nexport const x402UptoPermit2ProxyAddress = \"0x4020A4f3b7b90ccA423B9fabCc0CE57C6C240002\" as const;\n\n/**\n * ABI components for the exact Permit2 witness tuple: Witness(address to, uint256 validAfter).\n */\nconst permit2WitnessABIComponents = [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n] as const;\n\n/**\n * ABI components for the upto Permit2 witness tuple:\n * Witness(address to, address facilitator, uint256 validAfter).\n */\nconst uptoPermit2WitnessABIComponents = [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"facilitator\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n] as const;\n\n/**\n * x402UptoPermit2Proxy ABI — settle/settleWithPermit for the upto payment scheme.\n * Key differences from exact: settle() takes a `uint256 amount` parameter, and the\n * Witness struct includes an `address facilitator` field.\n */\nexport const x402UptoPermit2ProxyABI = [\n {\n type: \"function\",\n name: \"PERMIT2\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\", internalType: \"contract ISignatureTransfer\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPEHASH\",\n inputs: [],\n outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPE_STRING\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"settle\",\n inputs: [\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402UptoPermit2Proxy.Witness\",\n components: uptoPermit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"settleWithPermit\",\n inputs: [\n {\n name: \"permit2612\",\n type: \"tuple\",\n internalType: \"struct x402UptoPermit2Proxy.EIP2612Permit\",\n components: [\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"r\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"s\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"v\", type: \"uint8\", internalType: \"uint8\" },\n ],\n },\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402UptoPermit2Proxy.Witness\",\n components: uptoPermit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n { type: \"event\", name: \"Settled\", inputs: [], anonymous: false },\n { type: \"event\", name: \"SettledWithPermit\", inputs: [], anonymous: false },\n { type: \"error\", name: \"AmountExceedsPermitted\", inputs: [] },\n { type: \"error\", name: \"InvalidDestination\", inputs: [] },\n { type: \"error\", name: \"InvalidOwner\", inputs: [] },\n { type: \"error\", name: \"InvalidPermit2Address\", inputs: [] },\n { type: \"error\", name: \"PaymentTooEarly\", inputs: [] },\n { type: \"error\", name: \"Permit2612AmountMismatch\", inputs: [] },\n { type: \"error\", name: \"ReentrancyGuardReentrantCall\", inputs: [] },\n { type: \"error\", name: \"UnauthorizedFacilitator\", inputs: [] },\n] as const;\n\n/**\n * x402ExactPermit2Proxy ABI - settle function for exact payment scheme.\n */\nexport const x402ExactPermit2ProxyABI = [\n {\n type: \"function\",\n name: \"PERMIT2\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\", internalType: \"contract ISignatureTransfer\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPEHASH\",\n inputs: [],\n outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPE_STRING\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"settle\",\n inputs: [\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402ExactPermit2Proxy.Witness\",\n components: permit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"settleWithPermit\",\n inputs: [\n {\n name: \"permit2612\",\n type: \"tuple\",\n internalType: \"struct x402ExactPermit2Proxy.EIP2612Permit\",\n components: [\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"r\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"s\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"v\", type: \"uint8\", internalType: \"uint8\" },\n ],\n },\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402ExactPermit2Proxy.Witness\",\n components: permit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n { type: \"event\", name: \"Settled\", inputs: [], anonymous: false },\n { type: \"event\", name: \"SettledWithPermit\", inputs: [], anonymous: false },\n { type: \"error\", name: \"InvalidAmount\", inputs: [] },\n { type: \"error\", name: \"InvalidDestination\", inputs: [] },\n { type: \"error\", name: \"InvalidOwner\", inputs: [] },\n { type: \"error\", name: \"InvalidPermit2Address\", inputs: [] },\n { type: \"error\", name: \"PaymentTooEarly\", inputs: [] },\n { type: \"error\", name: \"Permit2612AmountMismatch\", inputs: [] },\n { type: \"error\", name: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","/**\n * Parse chainId from CAIP-2 network identifier\n *\n * @param network - CAIP-2 network identifier (e.g., 'eip155:84532')\n * @returns The chain ID as a number\n */\nexport function parseChainId(network: string): number {\n const parts = network.split(\":\");\n if (parts.length !== 2 || parts[0] !== \"eip155\") {\n throw new Error(`Invalid network format: ${network}. Expected 'eip155:<chainId>'`);\n }\n const chainId = parseInt(parts[1], 10);\n if (isNaN(chainId)) {\n throw new Error(`Invalid chainId in network: ${network}`);\n }\n return chainId;\n}\n"],"mappings":"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","names":["import_viem","signature","payload"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { F as FileChannelStorageOptions } from '../../types-DIt9uAUy.js';
|
|
2
|
+
import { C as ClientChannelStorage, B as BatchSettlementClientContext } from '../../storage-6W5MO46W.js';
|
|
3
|
+
import 'viem';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Node.js file-backed {@link ClientChannelStorage} for the batched client scheme.
|
|
7
|
+
* Each channel's context is persisted as `{root}/client/{channelId}.json` so that channel
|
|
8
|
+
* records survive process restarts.
|
|
9
|
+
*/
|
|
10
|
+
declare class FileClientChannelStorage implements ClientChannelStorage {
|
|
11
|
+
private readonly root;
|
|
12
|
+
/**
|
|
13
|
+
* Creates file-backed client channel storage under the given root directory.
|
|
14
|
+
*
|
|
15
|
+
* @param options - Configuration including the storage root directory.
|
|
16
|
+
*/
|
|
17
|
+
constructor(options: FileChannelStorageOptions);
|
|
18
|
+
/**
|
|
19
|
+
* Loads the stored client context for a channel, if present.
|
|
20
|
+
*
|
|
21
|
+
* @param key - Channel storage key (typically a lowercased channelId).
|
|
22
|
+
* @returns Parsed context or `undefined` when the file is missing.
|
|
23
|
+
*/
|
|
24
|
+
get(key: string): Promise<BatchSettlementClientContext | undefined>;
|
|
25
|
+
/**
|
|
26
|
+
* Persists the client context for a channel.
|
|
27
|
+
*
|
|
28
|
+
* @param key - Channel storage key.
|
|
29
|
+
* @param context - Context record to write.
|
|
30
|
+
*/
|
|
31
|
+
set(key: string, context: BatchSettlementClientContext): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Removes the persisted context file for a channel, if it exists.
|
|
34
|
+
*
|
|
35
|
+
* @param key - Channel storage key.
|
|
36
|
+
*/
|
|
37
|
+
delete(key: string): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Absolute path to the JSON file for a channel.
|
|
40
|
+
*
|
|
41
|
+
* @param key - Channel storage key.
|
|
42
|
+
* @returns Filesystem path under `{root}/client/...`.
|
|
43
|
+
*/
|
|
44
|
+
private filePath;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { FileChannelStorageOptions, FileClientChannelStorage };
|