@x402r/evm 0.0.2 → 0.0.3
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 +20 -16
- package/dist/cjs/escrow/client/index.cjs +227 -0
- package/dist/cjs/escrow/client/index.cjs.map +1 -0
- package/dist/cjs/escrow/client/index.d.cts +23 -0
- package/dist/cjs/escrow/client/index.d.ts +23 -0
- package/dist/cjs/escrow/client/index.js +223 -0
- package/dist/cjs/escrow/client/index.js.map +1 -0
- package/dist/cjs/escrow/facilitator/index.cjs +359 -0
- package/dist/cjs/escrow/facilitator/index.cjs.map +1 -0
- package/dist/cjs/escrow/facilitator/index.d.cts +53 -0
- package/dist/{escrow → cjs/escrow}/facilitator/index.d.ts +17 -13
- package/dist/cjs/escrow/facilitator/index.js +358 -0
- package/dist/cjs/escrow/facilitator/index.js.map +1 -0
- package/dist/cjs/escrow/server/index.cjs +222 -0
- package/dist/cjs/escrow/server/index.cjs.map +1 -0
- package/dist/cjs/escrow/server/index.d.cts +78 -0
- package/dist/{escrow → cjs/escrow}/server/index.d.ts +15 -9
- package/dist/cjs/escrow/server/index.js +217 -0
- package/dist/cjs/escrow/server/index.js.map +1 -0
- package/dist/{shared/types.d.ts → cjs/escrow/types/index.d.ts} +7 -6
- package/dist/cjs/escrow/types/index.js +40 -0
- package/dist/cjs/escrow/types/index.js.map +1 -0
- package/dist/cjs/index.cjs +215 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +22 -0
- package/dist/cjs/index.d.ts +54 -0
- package/dist/cjs/index.js +223 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/scheme-CNrmuyp3.d.ts +22 -0
- package/dist/esm/chunk-DLIBGHEY.mjs +85 -0
- package/dist/esm/chunk-DLIBGHEY.mjs.map +1 -0
- package/dist/esm/chunk-IYUU7AJZ.mjs +187 -0
- package/dist/esm/chunk-IYUU7AJZ.mjs.map +1 -0
- package/dist/esm/chunk-JBHVAJN3.mjs +13 -0
- package/dist/esm/chunk-JBHVAJN3.mjs.map +1 -0
- package/dist/esm/chunk-NSSMTXJJ.mjs +8 -0
- package/dist/esm/chunk-NSSMTXJJ.mjs.map +1 -0
- package/dist/esm/escrow/client/index.d.mts +23 -0
- package/dist/esm/escrow/client/index.mjs +20 -0
- package/dist/esm/escrow/client/index.mjs.map +1 -0
- package/dist/esm/escrow/facilitator/index.d.mts +53 -0
- package/dist/esm/escrow/facilitator/index.mjs +230 -0
- package/dist/esm/escrow/facilitator/index.mjs.map +1 -0
- package/dist/esm/escrow/server/index.d.mts +78 -0
- package/dist/esm/escrow/server/index.mjs +191 -0
- package/dist/esm/escrow/server/index.mjs.map +1 -0
- package/dist/esm/index.d.mts +54 -0
- package/dist/esm/index.mjs +15 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/scheme-CNrmuyp3.d.mts +22 -0
- package/package.json +42 -16
- package/src/escrow/client/index.ts +3 -161
- package/src/escrow/client/register.ts +33 -0
- package/src/escrow/client/scheme.ts +107 -0
- package/src/escrow/facilitator/index.ts +3 -388
- package/src/escrow/facilitator/register.ts +33 -0
- package/src/escrow/facilitator/scheme.ts +289 -0
- package/src/escrow/index.ts +3 -0
- package/src/escrow/server/index.ts +3 -261
- package/src/escrow/server/register.ts +34 -0
- package/src/escrow/server/scheme.ts +226 -0
- package/src/escrow/shared/constants.ts +65 -0
- package/src/escrow/shared/nonce.ts +175 -0
- package/src/escrow/shared/types.ts +69 -0
- package/src/escrow/shared/utils.ts +16 -0
- package/dist/escrow/client/index.d.ts +0 -40
- package/dist/escrow/client/index.d.ts.map +0 -1
- package/dist/escrow/client/index.js +0 -104
- package/dist/escrow/client/index.js.map +0 -1
- package/dist/escrow/facilitator/index.d.ts.map +0 -1
- package/dist/escrow/facilitator/index.js +0 -300
- package/dist/escrow/facilitator/index.js.map +0 -1
- package/dist/escrow/server/index.d.ts.map +0 -1
- package/dist/escrow/server/index.js +0 -214
- package/dist/escrow/server/index.js.map +0 -1
- package/dist/shared/constants.d.ts +0 -112
- package/dist/shared/constants.d.ts.map +0 -1
- package/dist/shared/constants.js +0 -51
- package/dist/shared/constants.js.map +0 -1
- package/dist/shared/nonce.d.ts +0 -41
- package/dist/shared/nonce.d.ts.map +0 -1
- package/dist/shared/nonce.js +0 -154
- package/dist/shared/nonce.js.map +0 -1
- package/dist/shared/types.d.ts.map +0 -1
- package/dist/shared/types.js +0 -21
- package/dist/shared/types.js.map +0 -1
- package/src/shared/constants.ts +0 -58
- package/src/shared/nonce.ts +0 -203
- package/src/shared/types.ts +0 -69
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { SchemeNetworkServer, MoneyParser, Price, Network, AssetAmount, PaymentRequirements } from '@x402/core/types';
|
|
2
|
+
import { x402ResourceServer } from '@x402/core/server';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Escrow Scheme - Server
|
|
6
|
+
* Handles price parsing and requirement enhancement for resource servers.
|
|
7
|
+
*
|
|
8
|
+
* Implements x402's SchemeNetworkServer interface so it can be registered
|
|
9
|
+
* on an x402ResourceServer via server.register('eip155:84532', new EscrowServerScheme()).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Server scheme - handles price parsing and requirement enhancement.
|
|
14
|
+
* Implements x402's SchemeNetworkServer interface.
|
|
15
|
+
*/
|
|
16
|
+
declare class EscrowServerScheme implements SchemeNetworkServer {
|
|
17
|
+
readonly scheme = "escrow";
|
|
18
|
+
private moneyParsers;
|
|
19
|
+
/**
|
|
20
|
+
* Register a custom money parser in the parser chain.
|
|
21
|
+
* Multiple parsers can be registered — they will be tried in registration order.
|
|
22
|
+
* Each parser receives a decimal amount (e.g., 1.50 for $1.50).
|
|
23
|
+
* If a parser returns null, the next parser in the chain will be tried.
|
|
24
|
+
* The default parser (USDC) is always the final fallback.
|
|
25
|
+
*
|
|
26
|
+
* @param parser - Custom function to convert amount to AssetAmount (or null to skip)
|
|
27
|
+
* @returns The server instance for chaining
|
|
28
|
+
*/
|
|
29
|
+
registerMoneyParser(parser: MoneyParser): EscrowServerScheme;
|
|
30
|
+
/**
|
|
31
|
+
* Parse a price into an x402 AssetAmount.
|
|
32
|
+
*
|
|
33
|
+
* Accepts x402's Price type:
|
|
34
|
+
* - string: "$0.01", "0.01", "10000"
|
|
35
|
+
* - number: 0.01
|
|
36
|
+
* - AssetAmount: { asset: "0x...", amount: "10000" }
|
|
37
|
+
*/
|
|
38
|
+
parsePrice(price: Price, network: Network): Promise<AssetAmount>;
|
|
39
|
+
/**
|
|
40
|
+
* Parse Money (string | number) to a decimal number.
|
|
41
|
+
*/
|
|
42
|
+
private parseMoneyToDecimal;
|
|
43
|
+
/**
|
|
44
|
+
* Default money conversion — converts decimal amount to the default stablecoin on the network.
|
|
45
|
+
*/
|
|
46
|
+
private defaultMoneyConversion;
|
|
47
|
+
/**
|
|
48
|
+
* Enhance payment requirements with facilitator's extra fields.
|
|
49
|
+
*
|
|
50
|
+
* Merges supportedKind.extra (from facilitator's /supported endpoint) into
|
|
51
|
+
* the requirements, so escrow addresses flow from facilitator → merchant
|
|
52
|
+
* requirements automatically.
|
|
53
|
+
*/
|
|
54
|
+
enhancePaymentRequirements(requirements: PaymentRequirements, supportedKind: {
|
|
55
|
+
x402Version: number;
|
|
56
|
+
scheme: string;
|
|
57
|
+
network: Network;
|
|
58
|
+
extra?: Record<string, unknown>;
|
|
59
|
+
}, _facilitatorExtensions: string[]): Promise<PaymentRequirements>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface EvmResourceServerConfig {
|
|
63
|
+
networks?: Network | Network[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Register escrow server scheme with x402ResourceServer
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const server = new x402ResourceServer(facilitatorConfig);
|
|
71
|
+
* registerEscrowEvmScheme(server);
|
|
72
|
+
* // or with specific networks:
|
|
73
|
+
* registerEscrowEvmScheme(server, { networks: "eip155:84532" });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
declare function registerEscrowEvmScheme(server: x402ResourceServer, config?: EvmResourceServerConfig): x402ResourceServer;
|
|
77
|
+
|
|
78
|
+
export { EscrowServerScheme, type EvmResourceServerConfig, registerEscrowEvmScheme };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__publicField
|
|
3
|
+
} from "../../chunk-NSSMTXJJ.mjs";
|
|
4
|
+
|
|
5
|
+
// src/escrow/server/scheme.ts
|
|
6
|
+
var ASSET_INFO = {
|
|
7
|
+
// Base Sepolia
|
|
8
|
+
"eip155:84532": {
|
|
9
|
+
address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
10
|
+
name: "USDC",
|
|
11
|
+
version: "2",
|
|
12
|
+
decimals: 6
|
|
13
|
+
},
|
|
14
|
+
// Base mainnet
|
|
15
|
+
"eip155:8453": {
|
|
16
|
+
address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
17
|
+
name: "USD Coin",
|
|
18
|
+
version: "2",
|
|
19
|
+
decimals: 6
|
|
20
|
+
},
|
|
21
|
+
// Ethereum Sepolia
|
|
22
|
+
"eip155:11155111": {
|
|
23
|
+
address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
24
|
+
name: "USDC",
|
|
25
|
+
version: "2",
|
|
26
|
+
decimals: 6
|
|
27
|
+
},
|
|
28
|
+
// Ethereum mainnet
|
|
29
|
+
"eip155:1": {
|
|
30
|
+
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
31
|
+
name: "USD Coin",
|
|
32
|
+
version: "2",
|
|
33
|
+
decimals: 6
|
|
34
|
+
},
|
|
35
|
+
// Polygon
|
|
36
|
+
"eip155:137": {
|
|
37
|
+
address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
38
|
+
name: "USD Coin",
|
|
39
|
+
version: "2",
|
|
40
|
+
decimals: 6
|
|
41
|
+
},
|
|
42
|
+
// Arbitrum
|
|
43
|
+
"eip155:42161": {
|
|
44
|
+
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
45
|
+
name: "USD Coin",
|
|
46
|
+
version: "2",
|
|
47
|
+
decimals: 6
|
|
48
|
+
},
|
|
49
|
+
// Celo
|
|
50
|
+
"eip155:42220": {
|
|
51
|
+
address: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
|
|
52
|
+
name: "USD Coin",
|
|
53
|
+
version: "2",
|
|
54
|
+
decimals: 6
|
|
55
|
+
},
|
|
56
|
+
// Monad
|
|
57
|
+
"eip155:143": {
|
|
58
|
+
address: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
|
|
59
|
+
name: "USDC",
|
|
60
|
+
version: "2",
|
|
61
|
+
decimals: 6
|
|
62
|
+
},
|
|
63
|
+
// Avalanche
|
|
64
|
+
"eip155:43114": {
|
|
65
|
+
address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
|
66
|
+
name: "USD Coin",
|
|
67
|
+
version: "2",
|
|
68
|
+
decimals: 6
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
function convertToTokenAmount(decimalAmount, decimals) {
|
|
72
|
+
const amount = parseFloat(decimalAmount);
|
|
73
|
+
if (isNaN(amount)) {
|
|
74
|
+
throw new Error(`Invalid amount: ${decimalAmount}`);
|
|
75
|
+
}
|
|
76
|
+
const [intPart, decPart = ""] = String(amount).split(".");
|
|
77
|
+
const paddedDec = decPart.padEnd(decimals, "0").slice(0, decimals);
|
|
78
|
+
const tokenAmount = (intPart + paddedDec).replace(/^0+/, "") || "0";
|
|
79
|
+
return tokenAmount;
|
|
80
|
+
}
|
|
81
|
+
var EscrowServerScheme = class {
|
|
82
|
+
constructor() {
|
|
83
|
+
__publicField(this, "scheme", "escrow");
|
|
84
|
+
__publicField(this, "moneyParsers", []);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Register a custom money parser in the parser chain.
|
|
88
|
+
* Multiple parsers can be registered — they will be tried in registration order.
|
|
89
|
+
* Each parser receives a decimal amount (e.g., 1.50 for $1.50).
|
|
90
|
+
* If a parser returns null, the next parser in the chain will be tried.
|
|
91
|
+
* The default parser (USDC) is always the final fallback.
|
|
92
|
+
*
|
|
93
|
+
* @param parser - Custom function to convert amount to AssetAmount (or null to skip)
|
|
94
|
+
* @returns The server instance for chaining
|
|
95
|
+
*/
|
|
96
|
+
registerMoneyParser(parser) {
|
|
97
|
+
this.moneyParsers.push(parser);
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Parse a price into an x402 AssetAmount.
|
|
102
|
+
*
|
|
103
|
+
* Accepts x402's Price type:
|
|
104
|
+
* - string: "$0.01", "0.01", "10000"
|
|
105
|
+
* - number: 0.01
|
|
106
|
+
* - AssetAmount: { asset: "0x...", amount: "10000" }
|
|
107
|
+
*/
|
|
108
|
+
async parsePrice(price, network) {
|
|
109
|
+
if (typeof price === "object" && price !== null && "amount" in price) {
|
|
110
|
+
if (!price.asset) {
|
|
111
|
+
throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
amount: price.amount,
|
|
115
|
+
asset: price.asset,
|
|
116
|
+
extra: price.extra || {}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const numericAmount = this.parseMoneyToDecimal(price);
|
|
120
|
+
for (const parser of this.moneyParsers) {
|
|
121
|
+
const result = await parser(numericAmount, network);
|
|
122
|
+
if (result !== null) {
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return this.defaultMoneyConversion(numericAmount, network);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Parse Money (string | number) to a decimal number.
|
|
130
|
+
*/
|
|
131
|
+
parseMoneyToDecimal(money) {
|
|
132
|
+
if (typeof money === "number") {
|
|
133
|
+
return money;
|
|
134
|
+
}
|
|
135
|
+
const cleaned = String(money).replace(/[$,]/g, "").trim();
|
|
136
|
+
const amount = parseFloat(cleaned);
|
|
137
|
+
if (isNaN(amount)) {
|
|
138
|
+
throw new Error(`Cannot parse price: ${money}`);
|
|
139
|
+
}
|
|
140
|
+
return amount;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Default money conversion — converts decimal amount to the default stablecoin on the network.
|
|
144
|
+
*/
|
|
145
|
+
defaultMoneyConversion(amount, network) {
|
|
146
|
+
const assetInfo = ASSET_INFO[network];
|
|
147
|
+
if (!assetInfo) {
|
|
148
|
+
throw new Error(`No USDC address configured for network: ${network}`);
|
|
149
|
+
}
|
|
150
|
+
const tokenAmount = convertToTokenAmount(String(amount), assetInfo.decimals);
|
|
151
|
+
return {
|
|
152
|
+
asset: assetInfo.address,
|
|
153
|
+
amount: tokenAmount,
|
|
154
|
+
extra: {
|
|
155
|
+
name: assetInfo.name,
|
|
156
|
+
version: assetInfo.version
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Enhance payment requirements with facilitator's extra fields.
|
|
162
|
+
*
|
|
163
|
+
* Merges supportedKind.extra (from facilitator's /supported endpoint) into
|
|
164
|
+
* the requirements, so escrow addresses flow from facilitator → merchant
|
|
165
|
+
* requirements automatically.
|
|
166
|
+
*/
|
|
167
|
+
async enhancePaymentRequirements(requirements, supportedKind, _facilitatorExtensions) {
|
|
168
|
+
return {
|
|
169
|
+
...requirements,
|
|
170
|
+
extra: {
|
|
171
|
+
...supportedKind.extra,
|
|
172
|
+
...requirements.extra
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/escrow/server/register.ts
|
|
179
|
+
function registerEscrowEvmScheme(server, config = {}) {
|
|
180
|
+
const scheme = new EscrowServerScheme();
|
|
181
|
+
const networks = config.networks ? Array.isArray(config.networks) ? config.networks : [config.networks] : ["eip155:*"];
|
|
182
|
+
for (const network of networks) {
|
|
183
|
+
server.register(network, scheme);
|
|
184
|
+
}
|
|
185
|
+
return server;
|
|
186
|
+
}
|
|
187
|
+
export {
|
|
188
|
+
EscrowServerScheme,
|
|
189
|
+
registerEscrowEvmScheme
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/escrow/server/scheme.ts","../../../../src/escrow/server/register.ts"],"sourcesContent":["/**\n * Escrow Scheme - Server\n * Handles price parsing and requirement enhancement for resource servers.\n *\n * Implements x402's SchemeNetworkServer interface so it can be registered\n * on an x402ResourceServer via server.register('eip155:84532', new EscrowServerScheme()).\n */\n\nimport type {\n AssetAmount,\n MoneyParser,\n Network,\n PaymentRequirements,\n Price,\n SchemeNetworkServer,\n} from '@x402/core/types'\n\n/**\n * Asset info including EIP-712 domain parameters per network\n */\nconst ASSET_INFO: Record<\n string,\n { address: string; name: string; version: string; decimals: number }\n> = {\n // Base Sepolia\n 'eip155:84532': {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n name: 'USDC',\n version: '2',\n decimals: 6,\n },\n // Base mainnet\n 'eip155:8453': {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n name: 'USD Coin',\n version: '2',\n decimals: 6,\n },\n // Ethereum Sepolia\n 'eip155:11155111': {\n address: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n name: 'USDC',\n version: '2',\n decimals: 6,\n },\n // Ethereum mainnet\n 'eip155:1': {\n address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n name: 'USD Coin',\n version: '2',\n decimals: 6,\n },\n // Polygon\n 'eip155:137': {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n name: 'USD Coin',\n version: '2',\n decimals: 6,\n },\n // Arbitrum\n 'eip155:42161': {\n address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n name: 'USD Coin',\n version: '2',\n decimals: 6,\n },\n // Celo\n 'eip155:42220': {\n address: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',\n name: 'USD Coin',\n version: '2',\n decimals: 6,\n },\n // Monad\n 'eip155:143': {\n address: '0x754704Bc059F8C67012fEd69BC8A327a5aafb603',\n name: 'USDC',\n version: '2',\n decimals: 6,\n },\n // Avalanche\n 'eip155:43114': {\n address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n name: 'USD Coin',\n version: '2',\n decimals: 6,\n },\n}\n\n/**\n * Convert decimal amount to token units using string-based conversion\n * (e.g., 0.10 -> 100000 for 6-decimal tokens)\n * Avoids floating-point precision issues from BigInt(Math.round(...))\n */\nfunction convertToTokenAmount(decimalAmount: string, decimals: number): string {\n const amount = parseFloat(decimalAmount)\n if (isNaN(amount)) {\n throw new Error(`Invalid amount: ${decimalAmount}`)\n }\n const [intPart, decPart = ''] = String(amount).split('.')\n const paddedDec = decPart.padEnd(decimals, '0').slice(0, decimals)\n const tokenAmount = (intPart + paddedDec).replace(/^0+/, '') || '0'\n return tokenAmount\n}\n\n/**\n * Server scheme - handles price parsing and requirement enhancement.\n * Implements x402's SchemeNetworkServer interface.\n */\nexport class EscrowServerScheme implements SchemeNetworkServer {\n readonly scheme = 'escrow'\n private moneyParsers: MoneyParser[] = []\n\n /**\n * Register a custom money parser in the parser chain.\n * Multiple parsers can be registered — they will be tried in registration order.\n * Each parser receives a decimal amount (e.g., 1.50 for $1.50).\n * If a parser returns null, the next parser in the chain will be tried.\n * The default parser (USDC) is always the final fallback.\n *\n * @param parser - Custom function to convert amount to AssetAmount (or null to skip)\n * @returns The server instance for chaining\n */\n registerMoneyParser(parser: MoneyParser): EscrowServerScheme {\n this.moneyParsers.push(parser)\n return this\n }\n\n /**\n * Parse a price into an x402 AssetAmount.\n *\n * Accepts x402's Price type:\n * - string: \"$0.01\", \"0.01\", \"10000\"\n * - number: 0.01\n * - AssetAmount: { asset: \"0x...\", amount: \"10000\" }\n */\n async parsePrice(price: Price, network: Network): Promise<AssetAmount> {\n // If already an AssetAmount, pass through with validation\n if (typeof price === 'object' && price !== null && 'amount' in price) {\n if (!price.asset) {\n throw new Error(`Asset address must be specified for AssetAmount on network ${network}`)\n }\n return {\n amount: price.amount,\n asset: price.asset,\n extra: price.extra || {},\n }\n }\n\n // Parse Money to decimal number\n const numericAmount = this.parseMoneyToDecimal(price)\n\n // Try each custom money parser in order\n for (const parser of this.moneyParsers) {\n const result = await parser(numericAmount, network)\n if (result !== null) {\n return result\n }\n }\n\n // All custom parsers returned null (or none registered), use default conversion\n return this.defaultMoneyConversion(numericAmount, network)\n }\n\n /**\n * Parse Money (string | number) to a decimal number.\n */\n private parseMoneyToDecimal(money: string | number): number {\n if (typeof money === 'number') {\n return money\n }\n const cleaned = String(money).replace(/[$,]/g, '').trim()\n const amount = parseFloat(cleaned)\n if (isNaN(amount)) {\n throw new Error(`Cannot parse price: ${money}`)\n }\n return amount\n }\n\n /**\n * Default money conversion — converts decimal amount to the default stablecoin on the network.\n */\n private defaultMoneyConversion(amount: number, network: Network): AssetAmount {\n const assetInfo = ASSET_INFO[network]\n if (!assetInfo) {\n throw new Error(`No USDC address configured for network: ${network}`)\n }\n\n const tokenAmount = convertToTokenAmount(String(amount), assetInfo.decimals)\n\n return {\n asset: assetInfo.address,\n amount: tokenAmount,\n extra: {\n name: assetInfo.name,\n version: assetInfo.version,\n },\n }\n }\n\n /**\n * Enhance payment requirements with facilitator's extra fields.\n *\n * Merges supportedKind.extra (from facilitator's /supported endpoint) into\n * the requirements, so escrow addresses flow from facilitator → merchant\n * requirements automatically.\n */\n async enhancePaymentRequirements(\n requirements: PaymentRequirements,\n supportedKind: {\n x402Version: number\n scheme: string\n network: Network\n extra?: Record<string, unknown>\n },\n _facilitatorExtensions: string[],\n ): Promise<PaymentRequirements> {\n return {\n ...requirements,\n extra: {\n ...supportedKind.extra,\n ...requirements.extra,\n },\n }\n }\n}\n","import type { Network } from '@x402/core/types'\nimport { x402ResourceServer } from '@x402/core/server'\nimport { EscrowServerScheme } from './scheme'\n\nexport interface EvmResourceServerConfig {\n networks?: Network | Network[]\n}\n\n/**\n * Register escrow server scheme with x402ResourceServer\n *\n * @example\n * ```typescript\n * const server = new x402ResourceServer(facilitatorConfig);\n * registerEscrowEvmScheme(server);\n * // or with specific networks:\n * registerEscrowEvmScheme(server, { networks: \"eip155:84532\" });\n * ```\n */\nexport function registerEscrowEvmScheme(\n server: x402ResourceServer,\n config: EvmResourceServerConfig = {},\n): x402ResourceServer {\n const scheme = new EscrowServerScheme()\n const networks = config.networks\n ? Array.isArray(config.networks)\n ? config.networks\n : [config.networks]\n : ['eip155:*' as Network]\n for (const network of networks) {\n server.register(network, scheme)\n }\n return server\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export { E as EscrowEvmScheme } from './scheme-CNrmuyp3.mjs';
|
|
2
|
+
import '@x402/core/types';
|
|
3
|
+
import '@x402/evm';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Type guard for EscrowPayload
|
|
7
|
+
*/
|
|
8
|
+
declare function isEscrowPayload(value: unknown): value is EscrowPayload;
|
|
9
|
+
/**
|
|
10
|
+
* Type guard for EscrowExtra
|
|
11
|
+
*/
|
|
12
|
+
declare function isEscrowExtra(value: unknown): value is EscrowExtra;
|
|
13
|
+
interface EscrowExtra {
|
|
14
|
+
escrowAddress: `0x${string}`;
|
|
15
|
+
operatorAddress: `0x${string}`;
|
|
16
|
+
tokenCollector: `0x${string}`;
|
|
17
|
+
authorizeAddress?: `0x${string}`;
|
|
18
|
+
minDeposit?: string;
|
|
19
|
+
maxDeposit?: string;
|
|
20
|
+
preApprovalExpirySeconds?: number;
|
|
21
|
+
authorizationExpirySeconds?: number;
|
|
22
|
+
refundExpirySeconds?: number;
|
|
23
|
+
minFeeBps?: number;
|
|
24
|
+
maxFeeBps?: number;
|
|
25
|
+
feeReceiver?: `0x${string}`;
|
|
26
|
+
name: string;
|
|
27
|
+
version: string;
|
|
28
|
+
}
|
|
29
|
+
interface EscrowPayload {
|
|
30
|
+
authorization: {
|
|
31
|
+
from: `0x${string}`;
|
|
32
|
+
to: `0x${string}`;
|
|
33
|
+
value: string;
|
|
34
|
+
validAfter: string;
|
|
35
|
+
validBefore: string;
|
|
36
|
+
nonce: `0x${string}`;
|
|
37
|
+
};
|
|
38
|
+
signature: `0x${string}`;
|
|
39
|
+
paymentInfo: {
|
|
40
|
+
operator: `0x${string}`;
|
|
41
|
+
receiver: `0x${string}`;
|
|
42
|
+
token: `0x${string}`;
|
|
43
|
+
maxAmount: string;
|
|
44
|
+
preApprovalExpiry: number;
|
|
45
|
+
authorizationExpiry: number;
|
|
46
|
+
refundExpiry: number;
|
|
47
|
+
minFeeBps: number;
|
|
48
|
+
maxFeeBps: number;
|
|
49
|
+
feeReceiver: `0x${string}`;
|
|
50
|
+
salt: `0x${string}`;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { type EscrowExtra, type EscrowPayload, isEscrowExtra, isEscrowPayload };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EscrowEvmScheme
|
|
3
|
+
} from "./chunk-DLIBGHEY.mjs";
|
|
4
|
+
import {
|
|
5
|
+
isEscrowExtra,
|
|
6
|
+
isEscrowPayload
|
|
7
|
+
} from "./chunk-JBHVAJN3.mjs";
|
|
8
|
+
import "./chunk-IYUU7AJZ.mjs";
|
|
9
|
+
import "./chunk-NSSMTXJJ.mjs";
|
|
10
|
+
export {
|
|
11
|
+
EscrowEvmScheme,
|
|
12
|
+
isEscrowExtra,
|
|
13
|
+
isEscrowPayload
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SchemeNetworkClient, PaymentRequirements, PaymentPayloadContext, PaymentPayloadResult } from '@x402/core/types';
|
|
2
|
+
import { ClientEvmSigner } from '@x402/evm';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Escrow Scheme - Client
|
|
6
|
+
* Creates payment payloads for escrow payments.
|
|
7
|
+
*
|
|
8
|
+
* Implements x402's SchemeNetworkClient interface so it can be registered
|
|
9
|
+
* on an x402Client via client.register('eip155:84532', new EscrowEvmScheme(signer)).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Escrow Client Scheme - implements x402's SchemeNetworkClient
|
|
14
|
+
*/
|
|
15
|
+
declare class EscrowEvmScheme implements SchemeNetworkClient {
|
|
16
|
+
private readonly signer;
|
|
17
|
+
readonly scheme = "escrow";
|
|
18
|
+
constructor(signer: ClientEvmSigner);
|
|
19
|
+
createPaymentPayload(x402Version: number, requirements: PaymentRequirements, _context?: PaymentPayloadContext): Promise<PaymentPayloadResult>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { EscrowEvmScheme as E };
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@x402r/evm",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"type": "module",
|
|
3
|
+
"version": "0.0.3",
|
|
5
4
|
"description": "Escrow payment scheme for x402 using Base Commerce Payments",
|
|
6
5
|
"license": "MIT",
|
|
7
6
|
"author": "x402r",
|
|
@@ -11,21 +10,45 @@
|
|
|
11
10
|
"directory": "packages/evm"
|
|
12
11
|
},
|
|
13
12
|
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/esm/index.d.mts",
|
|
16
|
+
"default": "./dist/esm/index.mjs"
|
|
17
|
+
},
|
|
18
|
+
"require": {
|
|
19
|
+
"types": "./dist/cjs/index.d.ts",
|
|
20
|
+
"default": "./dist/cjs/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
14
23
|
"./escrow/client": {
|
|
15
|
-
"
|
|
16
|
-
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/esm/escrow/client/index.d.mts",
|
|
26
|
+
"default": "./dist/esm/escrow/client/index.mjs"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/cjs/escrow/client/index.d.ts",
|
|
30
|
+
"default": "./dist/cjs/escrow/client/index.js"
|
|
31
|
+
}
|
|
17
32
|
},
|
|
18
33
|
"./escrow/server": {
|
|
19
|
-
"
|
|
20
|
-
|
|
34
|
+
"import": {
|
|
35
|
+
"types": "./dist/esm/escrow/server/index.d.mts",
|
|
36
|
+
"default": "./dist/esm/escrow/server/index.mjs"
|
|
37
|
+
},
|
|
38
|
+
"require": {
|
|
39
|
+
"types": "./dist/cjs/escrow/server/index.d.ts",
|
|
40
|
+
"default": "./dist/cjs/escrow/server/index.js"
|
|
41
|
+
}
|
|
21
42
|
},
|
|
22
43
|
"./escrow/facilitator": {
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
44
|
+
"import": {
|
|
45
|
+
"types": "./dist/esm/escrow/facilitator/index.d.mts",
|
|
46
|
+
"default": "./dist/esm/escrow/facilitator/index.mjs"
|
|
47
|
+
},
|
|
48
|
+
"require": {
|
|
49
|
+
"types": "./dist/cjs/escrow/facilitator/index.d.ts",
|
|
50
|
+
"default": "./dist/cjs/escrow/facilitator/index.js"
|
|
51
|
+
}
|
|
29
52
|
}
|
|
30
53
|
},
|
|
31
54
|
"publishConfig": {
|
|
@@ -37,21 +60,24 @@
|
|
|
37
60
|
"README.md"
|
|
38
61
|
],
|
|
39
62
|
"scripts": {
|
|
40
|
-
"build": "
|
|
63
|
+
"build": "tsup",
|
|
41
64
|
"clean": "rm -rf dist",
|
|
42
65
|
"test": "vitest run",
|
|
43
66
|
"test:watch": "vitest",
|
|
44
67
|
"typecheck": "tsc --noEmit",
|
|
45
|
-
"lint": "eslint
|
|
46
|
-
"
|
|
68
|
+
"lint": "eslint . --fix",
|
|
69
|
+
"lint:check": "eslint .",
|
|
70
|
+
"format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"",
|
|
71
|
+
"format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\""
|
|
47
72
|
},
|
|
48
73
|
"peerDependencies": {
|
|
49
|
-
"@x402/core": "^2.
|
|
74
|
+
"@x402/core": "^2.4.0",
|
|
50
75
|
"@x402/evm": "^2.0.0",
|
|
51
76
|
"viem": "^2.0.0"
|
|
52
77
|
},
|
|
53
78
|
"devDependencies": {
|
|
54
79
|
"@types/node": "^22.0.0",
|
|
80
|
+
"tsup": "^8.4.0",
|
|
55
81
|
"typescript": "^5.7.0",
|
|
56
82
|
"vitest": "^4.0.18"
|
|
57
83
|
}
|
|
@@ -1,161 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
* Implements x402's SchemeNetworkClient interface so it can be registered
|
|
6
|
-
* on an x402Client via client.register('eip155:84532', new EscrowEvmScheme(signer)).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type {
|
|
10
|
-
Network,
|
|
11
|
-
PaymentPayload,
|
|
12
|
-
PaymentRequirements,
|
|
13
|
-
SchemeNetworkClient,
|
|
14
|
-
} from "@x402/core/types";
|
|
15
|
-
import type { ClientEvmSigner } from "@x402/evm";
|
|
16
|
-
import { x402Client } from "@x402/core/client";
|
|
17
|
-
import {
|
|
18
|
-
computeEscrowNonce,
|
|
19
|
-
signERC3009,
|
|
20
|
-
generateSalt,
|
|
21
|
-
} from "../../shared/nonce.js";
|
|
22
|
-
import { MAX_UINT48 } from "../../shared/constants.js";
|
|
23
|
-
import type { EscrowExtra } from "../../shared/types.js";
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Parse chainId from CAIP-2 network identifier
|
|
27
|
-
*/
|
|
28
|
-
function parseChainId(network: string): number {
|
|
29
|
-
const parts = network.split(":");
|
|
30
|
-
if (parts.length !== 2 || parts[0] !== "eip155") {
|
|
31
|
-
throw new Error(
|
|
32
|
-
`Invalid network format: ${network}. Expected 'eip155:<chainId>'`,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
const chainId = parseInt(parts[1], 10);
|
|
36
|
-
if (isNaN(chainId)) {
|
|
37
|
-
throw new Error(`Invalid chainId in network: ${network}`);
|
|
38
|
-
}
|
|
39
|
-
return chainId;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Escrow Client Scheme - implements x402's SchemeNetworkClient
|
|
44
|
-
*/
|
|
45
|
-
export class EscrowEvmScheme implements SchemeNetworkClient {
|
|
46
|
-
readonly scheme = "escrow";
|
|
47
|
-
|
|
48
|
-
constructor(private readonly signer: ClientEvmSigner) {}
|
|
49
|
-
|
|
50
|
-
async createPaymentPayload(
|
|
51
|
-
x402Version: number,
|
|
52
|
-
requirements: PaymentRequirements,
|
|
53
|
-
): Promise<Pick<PaymentPayload, "x402Version" | "payload">> {
|
|
54
|
-
if (x402Version !== 2) {
|
|
55
|
-
throw new Error(
|
|
56
|
-
`Unsupported x402Version: ${x402Version}. Only version 2 is supported.`,
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const extra = requirements.extra as unknown as EscrowExtra;
|
|
61
|
-
|
|
62
|
-
// Validate required EIP-712 domain parameters (M3, M10)
|
|
63
|
-
if (!extra.name) {
|
|
64
|
-
throw new Error(
|
|
65
|
-
`EIP-712 domain parameter 'name' is required in payment requirements for asset ${requirements.asset}`,
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
if (!extra.version) {
|
|
69
|
-
throw new Error(
|
|
70
|
-
`EIP-712 domain parameter 'version' is required in payment requirements for asset ${requirements.asset}`,
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const {
|
|
75
|
-
escrowAddress,
|
|
76
|
-
operatorAddress,
|
|
77
|
-
tokenCollector,
|
|
78
|
-
minFeeBps = 0,
|
|
79
|
-
maxFeeBps = 0,
|
|
80
|
-
feeReceiver,
|
|
81
|
-
preApprovalExpirySeconds,
|
|
82
|
-
refundExpirySeconds,
|
|
83
|
-
authorizationExpirySeconds,
|
|
84
|
-
} = extra;
|
|
85
|
-
|
|
86
|
-
const chainId = parseChainId(requirements.network);
|
|
87
|
-
const maxAmount = requirements.amount;
|
|
88
|
-
|
|
89
|
-
const paymentInfo = {
|
|
90
|
-
operator: operatorAddress,
|
|
91
|
-
receiver: requirements.payTo as `0x${string}`,
|
|
92
|
-
token: requirements.asset as `0x${string}`,
|
|
93
|
-
maxAmount,
|
|
94
|
-
preApprovalExpiry: preApprovalExpirySeconds ?? MAX_UINT48,
|
|
95
|
-
authorizationExpiry: authorizationExpirySeconds ?? MAX_UINT48,
|
|
96
|
-
refundExpiry: refundExpirySeconds ?? MAX_UINT48,
|
|
97
|
-
minFeeBps,
|
|
98
|
-
maxFeeBps,
|
|
99
|
-
feeReceiver: feeReceiver ?? operatorAddress,
|
|
100
|
-
salt: generateSalt(),
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const nonce = computeEscrowNonce(chainId, escrowAddress, paymentInfo);
|
|
104
|
-
|
|
105
|
-
// ERC-3009 authorization - validBefore MUST match what contract passes to receiveWithAuthorization
|
|
106
|
-
// The contract uses paymentInfo.preApprovalExpiry as validBefore
|
|
107
|
-
const authorization = {
|
|
108
|
-
from: this.signer.address,
|
|
109
|
-
to: tokenCollector,
|
|
110
|
-
value: maxAmount,
|
|
111
|
-
validAfter: "0",
|
|
112
|
-
validBefore: String(paymentInfo.preApprovalExpiry),
|
|
113
|
-
nonce,
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const signature = await signERC3009(
|
|
117
|
-
this.signer,
|
|
118
|
-
authorization,
|
|
119
|
-
extra,
|
|
120
|
-
requirements.asset as `0x${string}`,
|
|
121
|
-
chainId,
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
x402Version,
|
|
126
|
-
payload: { authorization, signature, paymentInfo },
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Register escrow client scheme with x402Client
|
|
133
|
-
*
|
|
134
|
-
* @example
|
|
135
|
-
* ```typescript
|
|
136
|
-
* const client = new x402Client();
|
|
137
|
-
* registerEscrowScheme(client, { signer, networks: "eip155:84532" });
|
|
138
|
-
* ```
|
|
139
|
-
*/
|
|
140
|
-
export function registerEscrowScheme(
|
|
141
|
-
client: x402Client,
|
|
142
|
-
config: { signer: ClientEvmSigner; networks: Network | Network[] },
|
|
143
|
-
): x402Client {
|
|
144
|
-
const scheme = new EscrowEvmScheme(config.signer);
|
|
145
|
-
const networks = Array.isArray(config.networks)
|
|
146
|
-
? config.networks
|
|
147
|
-
: [config.networks];
|
|
148
|
-
for (const network of networks) {
|
|
149
|
-
client.register(network, scheme);
|
|
150
|
-
}
|
|
151
|
-
return client;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* @deprecated Use `new EscrowEvmScheme(signer)` directly
|
|
156
|
-
*/
|
|
157
|
-
export const EscrowScheme = {
|
|
158
|
-
scheme: "escrow" as const,
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
export type { EscrowExtra, EscrowPayload } from "../../shared/types.js";
|
|
1
|
+
export { EscrowEvmScheme } from './scheme'
|
|
2
|
+
export { registerEscrowEvmScheme } from './register'
|
|
3
|
+
export type { EvmClientConfig } from './register'
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Network } from '@x402/core/types'
|
|
2
|
+
import type { ClientEvmSigner } from '@x402/evm'
|
|
3
|
+
import { x402Client } from '@x402/core/client'
|
|
4
|
+
import { EscrowEvmScheme } from './scheme'
|
|
5
|
+
|
|
6
|
+
export interface EvmClientConfig {
|
|
7
|
+
signer: ClientEvmSigner
|
|
8
|
+
networks?: Network | Network[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Register escrow client scheme with x402Client
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const client = new x402Client();
|
|
17
|
+
* registerEscrowEvmScheme(client, { signer });
|
|
18
|
+
* // or with specific networks:
|
|
19
|
+
* registerEscrowEvmScheme(client, { signer, networks: "eip155:84532" });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function registerEscrowEvmScheme(client: x402Client, config: EvmClientConfig): x402Client {
|
|
23
|
+
const scheme = new EscrowEvmScheme(config.signer)
|
|
24
|
+
const networks = config.networks
|
|
25
|
+
? Array.isArray(config.networks)
|
|
26
|
+
? config.networks
|
|
27
|
+
: [config.networks]
|
|
28
|
+
: ['eip155:*' as Network]
|
|
29
|
+
for (const network of networks) {
|
|
30
|
+
client.register(network, scheme)
|
|
31
|
+
}
|
|
32
|
+
return client
|
|
33
|
+
}
|