@seapay-ai/erc3009 0.1.0 → 0.1.1

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.
Files changed (83) hide show
  1. package/README.md +267 -48
  2. package/dist/api/index.d.ts +2 -0
  3. package/dist/api/index.d.ts.map +1 -0
  4. package/dist/api/index.js +1 -0
  5. package/dist/api/prepare.d.ts +47 -0
  6. package/dist/api/prepare.d.ts.map +1 -0
  7. package/dist/api/prepare.js +57 -0
  8. package/dist/core.d.ts +14 -0
  9. package/dist/core.d.ts.map +1 -0
  10. package/dist/core.js +13 -0
  11. package/dist/domain/index.d.ts +3 -0
  12. package/dist/domain/index.d.ts.map +1 -0
  13. package/dist/domain/index.js +2 -0
  14. package/dist/domain/normalize.d.ts +9 -0
  15. package/dist/domain/normalize.d.ts.map +1 -0
  16. package/dist/domain/normalize.js +25 -0
  17. package/dist/domain/resolveDomain.d.ts +15 -0
  18. package/dist/domain/resolveDomain.d.ts.map +1 -0
  19. package/dist/domain/resolveDomain.js +47 -0
  20. package/dist/erc3009/buildTypes.d.ts +6 -0
  21. package/dist/erc3009/buildTypes.d.ts.map +1 -0
  22. package/dist/erc3009/buildTypes.js +11 -0
  23. package/dist/erc3009/constants.d.ts +7 -0
  24. package/dist/erc3009/constants.d.ts.map +1 -0
  25. package/dist/erc3009/constants.js +6 -0
  26. package/dist/erc3009/index.d.ts +7 -0
  27. package/dist/erc3009/index.d.ts.map +1 -0
  28. package/dist/erc3009/index.js +6 -0
  29. package/dist/erc3009/message.d.ts +21 -0
  30. package/dist/erc3009/message.d.ts.map +1 -0
  31. package/dist/erc3009/message.js +29 -0
  32. package/dist/erc3009/sign.d.ts +7 -0
  33. package/dist/erc3009/sign.d.ts.map +1 -0
  34. package/dist/erc3009/sign.js +8 -0
  35. package/dist/erc3009/typedData.d.ts +15 -0
  36. package/dist/erc3009/typedData.d.ts.map +1 -0
  37. package/dist/erc3009/typedData.js +21 -0
  38. package/dist/erc3009/verify.d.ts +10 -0
  39. package/dist/erc3009/verify.d.ts.map +1 -0
  40. package/dist/erc3009/verify.js +17 -0
  41. package/dist/index.d.ts +23 -34
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +35 -65
  44. package/dist/registry/chains.d.ts +22 -0
  45. package/dist/registry/chains.d.ts.map +1 -0
  46. package/dist/registry/chains.js +104 -0
  47. package/dist/registry/index.d.ts +4 -0
  48. package/dist/registry/index.d.ts.map +1 -0
  49. package/dist/registry/index.js +6 -0
  50. package/dist/registry/registry.d.ts +38 -0
  51. package/dist/registry/registry.d.ts.map +1 -0
  52. package/dist/registry/registry.js +73 -0
  53. package/dist/registry/tokens/index.d.ts +11 -0
  54. package/dist/registry/tokens/index.d.ts.map +1 -0
  55. package/dist/registry/tokens/index.js +14 -0
  56. package/dist/registry/tokens/usdc.d.ts +27 -0
  57. package/dist/registry/tokens/usdc.d.ts.map +1 -0
  58. package/dist/registry/tokens/usdc.js +104 -0
  59. package/dist/types/domain.d.ts +24 -0
  60. package/dist/types/domain.d.ts.map +1 -0
  61. package/dist/types/domain.js +1 -0
  62. package/dist/types/erc3009.d.ts +38 -0
  63. package/dist/types/erc3009.d.ts.map +1 -0
  64. package/dist/types/erc3009.js +15 -0
  65. package/dist/types/index.d.ts +4 -0
  66. package/dist/types/index.d.ts.map +1 -0
  67. package/dist/types/index.js +3 -0
  68. package/dist/types/registry.d.ts +35 -0
  69. package/dist/types/registry.d.ts.map +1 -0
  70. package/dist/types/registry.js +1 -0
  71. package/dist/utils/hex.d.ts +13 -0
  72. package/dist/utils/hex.d.ts.map +1 -0
  73. package/dist/utils/hex.js +19 -0
  74. package/dist/utils/index.d.ts +4 -0
  75. package/dist/utils/index.d.ts.map +1 -0
  76. package/dist/utils/index.js +3 -0
  77. package/dist/utils/nonce.d.ts +5 -0
  78. package/dist/utils/nonce.d.ts.map +1 -0
  79. package/dist/utils/nonce.js +7 -0
  80. package/dist/utils/time.d.ts +13 -0
  81. package/dist/utils/time.d.ts.map +1 -0
  82. package/dist/utils/time.js +18 -0
  83. package/package.json +7 -8
package/README.md CHANGED
@@ -1,80 +1,299 @@
1
1
  # @seapay-ai/erc3009
2
2
 
3
- TypeScript utilities for ERC-3009 (Transfer With Authorization) EIP-712 signing.
3
+ Multi-chain ERC-3009 (TransferWithAuthorization) helper library for building, signing, and verifying EIP-712 typed data.
4
+
5
+ ## Features
6
+
7
+ - ✅ **Multi-chain support**: Base, Ethereum, Arbitrum, Optimism, Polygon (mainnet + testnets)
8
+ - ✅ **Token registry**: Pre-configured USDC addresses and domain parameters for all chains
9
+ - ✅ **Type-safe**: Full TypeScript support with strict types
10
+ - ✅ **Ergonomic API**: One-liner `prepare()` for common use cases
11
+ - ✅ **Override support**: Customize domain parameters for custom tokens
12
+ - ✅ **ethers.js v6**: Built on ethers v6 for signing and verification
4
13
 
5
14
  ## Installation
6
15
 
7
16
  ```bash
8
- npm install @seapay-ai/erc3009
9
- # or
10
17
  pnpm add @seapay-ai/erc3009
11
18
  # or
12
- yarn add @seapay-ai/erc3009
19
+ npm install @seapay-ai/erc3009
13
20
  ```
14
21
 
15
- ## Usage
16
-
17
- ### Basic Example
22
+ ## Quick Start
18
23
 
19
24
  ```typescript
25
+ import { prepare } from "@seapay-ai/erc3009";
20
26
  import { Wallet } from "ethers";
27
+
28
+ // One-call convenience API
29
+ const { typedData } = prepare({
30
+ chainId: 8453, // Base
31
+ token: "USDC",
32
+ from: wallet.address,
33
+ to: "0xRecipient...",
34
+ value: 1000000n, // 1 USDC (6 decimals)
35
+ ttlSeconds: 300, // 5 minutes
36
+ });
37
+
38
+ // Sign with ethers wallet
39
+ const signature = await wallet.signTypedData(
40
+ typedData.domain,
41
+ typedData.types,
42
+ typedData.message
43
+ );
44
+ ```
45
+
46
+ ## Usage Examples
47
+
48
+ ### 1. Ergonomic API (Recommended)
49
+
50
+ The `prepare()` function resolves the domain, builds the message, and returns everything needed:
51
+
52
+ ```typescript
53
+ import { prepare } from "@seapay-ai/erc3009";
54
+
55
+ const { domain, message, typedData } = prepare({
56
+ chainId: 8453, // Base mainnet
57
+ token: "USDC",
58
+ from: "0xSender...",
59
+ to: "0xRecipient...",
60
+ value: 1000000n, // 1 USDC
61
+ ttlSeconds: 300, // optional, default: 300
62
+ });
63
+
64
+ // Sign it
65
+ const sig = await wallet.signTypedData(
66
+ typedData.domain,
67
+ typedData.types,
68
+ typedData.message
69
+ );
70
+ ```
71
+
72
+ ### 2. Core Builders (Manual)
73
+
74
+ For more control, use the core builders:
75
+
76
+ ```typescript
21
77
  import {
78
+ resolveDomain,
79
+ buildMessage,
22
80
  buildTypedData,
23
- buildTypes,
24
- message_5_minutes,
25
- signTransferWithAuthorization,
26
- type EIP712Domain,
27
- type TransferWithAuthorization,
81
+ erc3009,
28
82
  } from "@seapay-ai/erc3009";
29
83
 
30
- // Create a wallet
31
- const wallet = new Wallet("0x...");
84
+ // 1. Resolve domain from registry
85
+ const domain = resolveDomain({
86
+ chainId: 8453,
87
+ token: "USDC",
88
+ });
32
89
 
33
- // Define the token domain (EIP-712 domain)
34
- const domain: EIP712Domain = {
35
- name: "USD Coin",
36
- version: "2",
37
- chainId: 84532, // Base Sepolia
38
- verifyingContract: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
39
- };
90
+ // 2. Build message
91
+ const message = buildMessage({
92
+ from: "0xSender...",
93
+ to: "0xRecipient...",
94
+ value: 1000000n,
95
+ validAfter: 0n,
96
+ validBefore: 1234567890n,
97
+ nonce: "0x...", // or use randomNonce()
98
+ });
40
99
 
41
- // Create a transfer authorization message
42
- const message = message_5_minutes(
43
- wallet.address, // from
44
- "0x...", // to
45
- BigInt("1000000") // value (1 USDC if 6 decimals)
46
- );
100
+ // 3. Build typed data
101
+ const typedData = buildTypedData({ domain, message });
47
102
 
48
- // Sign the authorization
49
- const signature = await signTransferWithAuthorization(wallet, domain, message);
103
+ // 4. Sign
104
+ const signature = await erc3009.sign(wallet, domain, message);
105
+ ```
50
106
 
51
- // Or build typed data manually
52
- const typedData = buildTypedData({ domain, message });
53
- const types = buildTypes();
54
- // Use with wallet.signTypedData(typedData.domain, types, typedData.message)
107
+ ### 3. Using the Registry
108
+
109
+ Query supported chains and tokens:
110
+
111
+ ```typescript
112
+ import { registry, getToken, CHAINS } from "@seapay-ai/erc3009";
113
+
114
+ // Get token config
115
+ const usdcBase = getToken("USDC", 8453);
116
+ // => { symbol: "USDC", chainId: 8453, verifyingContract: "0x...", ... }
117
+
118
+ // List all chains
119
+ const chains = registry.listChains();
120
+
121
+ // Check support
122
+ if (registry.isTokenSupported("USDC", 8453)) {
123
+ console.log("USDC is supported on Base");
124
+ }
125
+
126
+ // List tokens on a chain
127
+ const tokens = registry.listTokensOnChain(8453);
55
128
  ```
56
129
 
57
- ### API Reference
130
+ ### 4. Custom Tokens / Domain Overrides
131
+
132
+ For custom tokens not in the registry:
133
+
134
+ ```typescript
135
+ import { prepare } from "@seapay-ai/erc3009";
136
+
137
+ const { typedData } = prepare({
138
+ chainId: 8453,
139
+ token: "0xCustomTokenAddress",
140
+ // Override domain fields
141
+ name: "My Custom Token",
142
+ version: "1",
143
+ verifyingContract: "0xCustomTokenAddress",
144
+ from: "0xSender...",
145
+ to: "0xRecipient...",
146
+ value: 1000000n,
147
+ });
148
+ ```
58
149
 
59
- #### Types
150
+ ### 5. Signature Verification
151
+
152
+ ```typescript
153
+ import { verifySignature, recoverSigner } from "@seapay-ai/erc3009";
154
+
155
+ // Recover signer
156
+ const recovered = recoverSigner(domain, message, signature);
157
+ console.log("Signed by:", recovered);
158
+
159
+ // Verify signature
160
+ const isValid = verifySignature(domain, message, signature, expectedSigner);
161
+ ```
162
+
163
+ ## Supported Chains
164
+
165
+ | Chain | Chain ID | Testnet |
166
+ | ---------------- | -------- | ------- |
167
+ | Ethereum | 1 | - |
168
+ | Sepolia | 11155111 | ✅ |
169
+ | Base | 8453 | - |
170
+ | Base Sepolia | 84532 | ✅ |
171
+ | Arbitrum One | 42161 | - |
172
+ | Arbitrum Sepolia | 421614 | ✅ |
173
+ | Optimism | 10 | - |
174
+ | Optimism Sepolia | 11155420 | ✅ |
175
+ | Polygon | 137 | - |
176
+ | Polygon Amoy | 80002 | ✅ |
177
+
178
+ ## Supported Tokens
179
+
180
+ Currently supports **USDC** on all chains above. The registry includes:
181
+
182
+ - Proxy contract addresses
183
+ - EIP-712 domain parameters (name, version)
184
+ - Token decimals
185
+
186
+ ### ⚠️ Important: Base Network Domain Names
187
+
188
+ USDC has **different domain names** on Base networks:
189
+
190
+ | Network | Chain ID | Domain Name |
191
+ | ------------ | -------- | ------------ |
192
+ | Base Mainnet | 8453 | `"USD Coin"` |
193
+ | Base Sepolia | 84532 | `"USDC"` |
194
+
195
+ **This is critical for signature verification!** Always use the correct domain name:
196
+
197
+ ```typescript
198
+ // ✅ Correct - Base Mainnet
199
+ const { typedData } = prepare({
200
+ chainId: 8453,
201
+ token: "USDC", // Resolves to name: "USD Coin"
202
+ from: "0x...",
203
+ to: "0x...",
204
+ value: 1000000n,
205
+ });
206
+
207
+ // ✅ Correct - Base Sepolia
208
+ const { typedData } = prepare({
209
+ chainId: 84532,
210
+ token: "USDC", // Resolves to name: "USDC"
211
+ from: "0x...",
212
+ to: "0x...",
213
+ value: 1000000n,
214
+ });
215
+
216
+ // ❌ Wrong - Signature will fail!
217
+ const { typedData } = prepare({
218
+ chainId: 84532,
219
+ token: "USDC",
220
+ name: "USD Coin", // Override with wrong name
221
+ // ...
222
+ });
223
+ ```
224
+
225
+ The `prepare()` function automatically uses the correct domain name from the registry.
226
+
227
+ ## API Reference
228
+
229
+ ### Core Functions
230
+
231
+ - `prepare(params)` - One-call API to build everything
232
+ - `buildMessage(params)` - Build TransferWithAuthorization message
233
+ - `buildTypedData({ domain, message })` - Build EIP-712 typed data
234
+ - `resolveDomain({ chainId, token, ...overrides })` - Resolve EIP-712 domain
235
+ - `erc3009.sign(wallet, domain, message)` - Sign with ethers wallet
236
+ - `verifySignature(domain, message, sig, signer)` - Verify signature
237
+ - `recoverSigner(domain, message, sig)` - Recover signer address
238
+
239
+ ### Registry
240
+
241
+ - `registry.getToken(symbol, chainId)` - Get token config
242
+ - `registry.getChain(chainId)` - Get chain config
243
+ - `registry.listChains()` - List all supported chains
244
+ - `registry.listTokensOnChain(chainId)` - List tokens on a chain
245
+ - `registry.isTokenSupported(symbol, chainId)` - Check support
246
+
247
+ ### Utils
248
+
249
+ - `randomNonce()` - Generate random bytes32 nonce
250
+ - `nowSeconds()` - Current Unix timestamp
251
+ - `nowPlusSeconds(n)` - Unix timestamp N seconds from now
252
+ - `normalizeAddress(addr)` - Normalize to checksum address
253
+
254
+ ## TypeScript Types
255
+
256
+ ```typescript
257
+ import type {
258
+ TransferWithAuthorization,
259
+ EIP712Domain,
260
+ TokenConfig,
261
+ ChainConfig,
262
+ PrepareParams,
263
+ } from "@seapay-ai/erc3009";
264
+ ```
265
+
266
+ ## Advanced: Custom Registry
267
+
268
+ You can extend the registry by directly importing and modifying `TOKENS`:
269
+
270
+ ```typescript
271
+ import { TOKENS } from "@seapay-ai/erc3009";
272
+
273
+ // Add your custom token
274
+ TOKENS["MYTOKEN"] = {
275
+ 8453: {
276
+ symbol: "MYTOKEN",
277
+ chainId: 8453,
278
+ verifyingContract: "0x...",
279
+ name: "My Token",
280
+ version: "1",
281
+ decimals: 18,
282
+ },
283
+ };
284
+ ```
60
285
 
61
- - `TransferWithAuthorization`: The message structure for ERC-3009 transfers
62
- - `EIP712Domain`: The EIP-712 domain structure
286
+ ## Examples
63
287
 
64
- #### Functions
288
+ See the `/apps/erc3009-relay/src/signer-test.ts` in the monorepo for a complete working example.
65
289
 
66
- - `buildDomain(domain: EIP712Domain)`: Converts EIP712Domain to TypedDataDomain
67
- - `buildTypes()`: Returns the EIP-712 types for TransferWithAuthorization
68
- - `buildMessage(message: TransferWithAuthorization)`: Normalizes message values
69
- - `buildTypedData(params)`: Builds complete typed data for signing
70
- - `signTransferWithAuthorization(wallet, domain, message)`: Convenience function to sign
71
- - `message_5_minutes(from, to, value)`: Creates a message valid for 5 minutes
72
- - `USDC_Domain()`: Returns USDC domain for Base Sepolia (example)
290
+ ## Contributing
73
291
 
74
- ## Requirements
292
+ Contributions welcome! To add support for a new token:
75
293
 
76
- - Node.js 18+
77
- - ethers v6
294
+ 1. Add token config to `src/registry/tokens/{token}.ts`
295
+ 2. Export from `src/registry/tokens/index.ts`
296
+ 3. Add to `TOKENS` registry
78
297
 
79
298
  ## License
80
299
 
@@ -0,0 +1,2 @@
1
+ export * from "./prepare.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
@@ -0,0 +1 @@
1
+ export * from "./prepare.js";
@@ -0,0 +1,47 @@
1
+ import type { EIP712Domain, TransferWithAuthorization } from "../types/index.js";
2
+ import type { TypedData } from "../erc3009/typedData.js";
3
+ export type PrepareParams = {
4
+ chainId: number;
5
+ token: string;
6
+ name?: string;
7
+ version?: string;
8
+ verifyingContract?: string;
9
+ from: string;
10
+ to: string;
11
+ value: bigint | number | string;
12
+ ttlSeconds?: number;
13
+ nonce?: string;
14
+ validAfter?: bigint | number | string;
15
+ validBefore?: bigint | number | string;
16
+ };
17
+ export type PrepareResult = {
18
+ domain: EIP712Domain;
19
+ message: TransferWithAuthorization;
20
+ typedData: TypedData;
21
+ };
22
+ /**
23
+ * One-call convenience helper to prepare complete ERC-3009 typed data
24
+ *
25
+ * This resolves the domain from registry, builds the message with time window,
26
+ * and returns everything needed for signing.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const { domain, message, typedData } = prepare({
31
+ * chainId: 8453,
32
+ * token: "USDC",
33
+ * from: "0x...",
34
+ * to: "0x...",
35
+ * value: 1000000n, // 1 USDC (6 decimals)
36
+ * ttlSeconds: 300, // 5 minutes
37
+ * });
38
+ *
39
+ * const signature = await wallet.signTypedData(
40
+ * typedData.domain,
41
+ * typedData.types,
42
+ * typedData.message
43
+ * );
44
+ * ```
45
+ */
46
+ export declare function prepare(params: PrepareParams): PrepareResult;
47
+ //# sourceMappingURL=prepare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../src/api/prepare.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EAE1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAMzD,MAAM,MAAM,aAAa,GAAG;IAE1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,yBAAyB,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAgC5D"}
@@ -0,0 +1,57 @@
1
+ import { resolveDomain } from "../domain/resolveDomain.js";
2
+ import { buildMessageWithTTL } from "../erc3009/message.js";
3
+ import { buildTypedData } from "../erc3009/typedData.js";
4
+ import { randomNonce } from "../utils/nonce.js";
5
+ /**
6
+ * One-call convenience helper to prepare complete ERC-3009 typed data
7
+ *
8
+ * This resolves the domain from registry, builds the message with time window,
9
+ * and returns everything needed for signing.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const { domain, message, typedData } = prepare({
14
+ * chainId: 8453,
15
+ * token: "USDC",
16
+ * from: "0x...",
17
+ * to: "0x...",
18
+ * value: 1000000n, // 1 USDC (6 decimals)
19
+ * ttlSeconds: 300, // 5 minutes
20
+ * });
21
+ *
22
+ * const signature = await wallet.signTypedData(
23
+ * typedData.domain,
24
+ * typedData.types,
25
+ * typedData.message
26
+ * );
27
+ * ```
28
+ */
29
+ export function prepare(params) {
30
+ // Resolve domain
31
+ const domainParams = {
32
+ chainId: params.chainId,
33
+ token: params.token,
34
+ name: params.name,
35
+ version: params.version,
36
+ verifyingContract: params.verifyingContract,
37
+ };
38
+ const domain = resolveDomain(domainParams);
39
+ // Build message
40
+ const message = buildMessageWithTTL({
41
+ from: params.from,
42
+ to: params.to,
43
+ value: params.value,
44
+ ttlSeconds: params.ttlSeconds,
45
+ nonce: params.nonce ?? randomNonce(),
46
+ });
47
+ // Override time window if explicitly provided
48
+ if (params.validAfter !== undefined) {
49
+ message.validAfter = BigInt(params.validAfter);
50
+ }
51
+ if (params.validBefore !== undefined) {
52
+ message.validBefore = BigInt(params.validBefore);
53
+ }
54
+ // Build typed data
55
+ const typedData = buildTypedData({ domain, message });
56
+ return { domain, message, typedData };
57
+ }
package/dist/core.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Core ERC-3009 namespace with all builder functions
3
+ */
4
+ import { buildTypes, buildMessage, buildMessageWithTTL, buildTypedData, signTransferWithAuthorization, recoverSigner, verifySignature } from "./erc3009/index.js";
5
+ export declare const erc3009: {
6
+ readonly buildTypes: typeof buildTypes;
7
+ readonly buildMessage: typeof buildMessage;
8
+ readonly buildMessageWithTTL: typeof buildMessageWithTTL;
9
+ readonly buildTypedData: typeof buildTypedData;
10
+ readonly sign: typeof signTransferWithAuthorization;
11
+ readonly recoverSigner: typeof recoverSigner;
12
+ readonly verifySignature: typeof verifySignature;
13
+ };
14
+ //# sourceMappingURL=core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,6BAA6B,EAC7B,aAAa,EACb,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAE5B,eAAO,MAAM,OAAO;;;;;;;;CAQV,CAAC"}
package/dist/core.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Core ERC-3009 namespace with all builder functions
3
+ */
4
+ import { buildTypes, buildMessage, buildMessageWithTTL, buildTypedData, signTransferWithAuthorization, recoverSigner, verifySignature, } from "./erc3009/index.js";
5
+ export const erc3009 = {
6
+ buildTypes,
7
+ buildMessage,
8
+ buildMessageWithTTL,
9
+ buildTypedData,
10
+ sign: signTransferWithAuthorization,
11
+ recoverSigner,
12
+ verifySignature,
13
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./normalize.js";
2
+ export * from "./resolveDomain.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./normalize.js";
2
+ export * from "./resolveDomain.js";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Normalize address to checksum format
3
+ */
4
+ export declare function normalizeAddress(address: string): string;
5
+ /**
6
+ * Normalize chainId to number
7
+ */
8
+ export declare function normalizeChainId(chainId: number | bigint | string): number;
9
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/domain/normalize.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASxD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAI1E"}
@@ -0,0 +1,25 @@
1
+ import { getAddress } from "ethers";
2
+ /**
3
+ * Normalize address to checksum format
4
+ */
5
+ export function normalizeAddress(address) {
6
+ try {
7
+ return getAddress(address);
8
+ }
9
+ catch {
10
+ // If invalid address, return lowercase with 0x
11
+ return address.toLowerCase().startsWith("0x")
12
+ ? address.toLowerCase()
13
+ : `0x${address.toLowerCase()}`;
14
+ }
15
+ }
16
+ /**
17
+ * Normalize chainId to number
18
+ */
19
+ export function normalizeChainId(chainId) {
20
+ if (typeof chainId === "number")
21
+ return chainId;
22
+ if (typeof chainId === "bigint")
23
+ return Number(chainId);
24
+ return parseInt(String(chainId), 10);
25
+ }
@@ -0,0 +1,15 @@
1
+ import type { EIP712Domain, ResolveDomainParams } from "../types/domain.js";
2
+ /**
3
+ * Resolve EIP-712 domain from chain + token with override support
4
+ *
5
+ * Priority:
6
+ * 1. Explicit overrides (name, version, verifyingContract)
7
+ * 2. Registry lookup (by symbol or address)
8
+ * 3. Error if cannot resolve
9
+ */
10
+ export declare function resolveDomain(params: ResolveDomainParams): EIP712Domain;
11
+ /**
12
+ * Resolve domain from token config only (no overrides)
13
+ */
14
+ export declare function resolveDomainFromToken(symbol: string, chainId: number): EIP712Domain;
15
+ //# sourceMappingURL=resolveDomain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveDomain.d.ts","sourceRoot":"","sources":["../../src/domain/resolveDomain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAI5E;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,YAAY,CA8BvE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,YAAY,CAcd"}
@@ -0,0 +1,47 @@
1
+ import { getToken, getTokenByAddress } from "../registry/registry.js";
2
+ import { normalizeAddress, normalizeChainId } from "./normalize.js";
3
+ /**
4
+ * Resolve EIP-712 domain from chain + token with override support
5
+ *
6
+ * Priority:
7
+ * 1. Explicit overrides (name, version, verifyingContract)
8
+ * 2. Registry lookup (by symbol or address)
9
+ * 3. Error if cannot resolve
10
+ */
11
+ export function resolveDomain(params) {
12
+ const chainId = normalizeChainId(params.chainId);
13
+ // Try registry lookup
14
+ let config = getToken(params.token, chainId);
15
+ // If not found by symbol, try as address
16
+ if (!config && params.token.startsWith("0x")) {
17
+ config = getTokenByAddress(params.token, chainId);
18
+ }
19
+ // If still not found and no explicit verifyingContract, error
20
+ if (!config && !params.verifyingContract) {
21
+ throw new Error(`Token "${params.token}" not found in registry for chainId ${chainId}. ` +
22
+ `Provide explicit domain parameters or use a supported token.`);
23
+ }
24
+ // Build domain with overrides
25
+ const domain = {
26
+ name: params.name ?? config?.name ?? "USD Coin",
27
+ version: params.version ?? config?.version ?? "2",
28
+ chainId,
29
+ verifyingContract: normalizeAddress(params.verifyingContract ?? config?.verifyingContract ?? params.token),
30
+ };
31
+ return domain;
32
+ }
33
+ /**
34
+ * Resolve domain from token config only (no overrides)
35
+ */
36
+ export function resolveDomainFromToken(symbol, chainId) {
37
+ const config = getToken(symbol, chainId);
38
+ if (!config) {
39
+ throw new Error(`Token "${symbol}" not configured for chainId ${chainId}`);
40
+ }
41
+ return {
42
+ name: config.name,
43
+ version: config.version,
44
+ chainId: config.chainId,
45
+ verifyingContract: config.verifyingContract,
46
+ };
47
+ }
@@ -0,0 +1,6 @@
1
+ import type { TypedDataField } from "ethers";
2
+ /**
3
+ * Build EIP-712 types object for ERC-3009
4
+ */
5
+ export declare function buildTypes(): Record<string, TypedDataField[]>;
6
+ //# sourceMappingURL=buildTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildTypes.d.ts","sourceRoot":"","sources":["../../src/erc3009/buildTypes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAM7C;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAM7D"}
@@ -0,0 +1,11 @@
1
+ import { TRANSFER_WITH_AUTHORIZATION_TYPE, TRANSFER_WITH_AUTHORIZATION_FIELDS, } from "./constants.js";
2
+ /**
3
+ * Build EIP-712 types object for ERC-3009
4
+ */
5
+ export function buildTypes() {
6
+ return {
7
+ [TRANSFER_WITH_AUTHORIZATION_TYPE]: [
8
+ ...TRANSFER_WITH_AUTHORIZATION_FIELDS,
9
+ ],
10
+ };
11
+ }
@@ -0,0 +1,7 @@
1
+ import { TRANSFER_WITH_AUTHORIZATION_TYPE, TRANSFER_WITH_AUTHORIZATION_FIELDS } from "../types/erc3009.js";
2
+ export { TRANSFER_WITH_AUTHORIZATION_TYPE, TRANSFER_WITH_AUTHORIZATION_FIELDS };
3
+ /**
4
+ * EIP-712 primary type for ERC-3009
5
+ */
6
+ export declare const PRIMARY_TYPE = "TransferWithAuthorization";
7
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/erc3009/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,kCAAkC,EACnC,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,gCAAgC,EAAE,kCAAkC,EAAE,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,YAAY,8BAAmC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { TRANSFER_WITH_AUTHORIZATION_TYPE, TRANSFER_WITH_AUTHORIZATION_FIELDS, } from "../types/erc3009.js";
2
+ export { TRANSFER_WITH_AUTHORIZATION_TYPE, TRANSFER_WITH_AUTHORIZATION_FIELDS };
3
+ /**
4
+ * EIP-712 primary type for ERC-3009
5
+ */
6
+ export const PRIMARY_TYPE = TRANSFER_WITH_AUTHORIZATION_TYPE;
@@ -0,0 +1,7 @@
1
+ export * from "./constants.js";
2
+ export * from "./buildTypes.js";
3
+ export * from "./message.js";
4
+ export * from "./typedData.js";
5
+ export * from "./sign.js";
6
+ export * from "./verify.js";
7
+ //# sourceMappingURL=index.d.ts.map