wayleave 0.4.0 → 0.4.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.
- package/package.json +1 -1
- package/x402.d.ts +7 -0
- package/x402.js +55 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wayleave",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Charge AI agents for passage across your app. Verify agent signatures (Web Bot Auth / Ed25519), classify every request, and return 402 with a price on routes you choose. Humans browse free.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
package/x402.d.ts
CHANGED
|
@@ -16,6 +16,13 @@ export interface CoinbaseFacilitatorOptions {
|
|
|
16
16
|
asset?: string;
|
|
17
17
|
/** Asset decimals. 6 for USDC. */
|
|
18
18
|
decimals?: number;
|
|
19
|
+
/**
|
|
20
|
+
* The EIP-712 domain the payer signed against, as the token contract
|
|
21
|
+
* reports it. Defaults are known for `base` and `base-sepolia`; supply it
|
|
22
|
+
* for any other network. Required by the facilitator — without it a payment
|
|
23
|
+
* is read, the payer identified, and the signature never checked.
|
|
24
|
+
*/
|
|
25
|
+
extra?: { name: string; version: string };
|
|
19
26
|
/**
|
|
20
27
|
* true (default) submits the payment on-chain. false only verifies it,
|
|
21
28
|
* which is useful for a dry run but pays nobody and never grants access.
|
package/x402.js
CHANGED
|
@@ -56,6 +56,37 @@ export function toAtomicUnits(usd, decimals = DEFAULT_DECIMALS) {
|
|
|
56
56
|
return (whole + frac.padEnd(decimals, '0')).replace(/^0+(?=\d)/, '');
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* The settlement asset per network, and the EIP-712 domain its contract
|
|
61
|
+
* enforces.
|
|
62
|
+
*
|
|
63
|
+
* Both are REQUIRED by the facilitator and neither can be guessed:
|
|
64
|
+
*
|
|
65
|
+
* - Omit `asset` and CDP rejects the call outright ("x402V1PaymentRequirements
|
|
66
|
+
* requires 'asset'"). Until 0.4.1 this module omitted it whenever the
|
|
67
|
+
* caller did not pass one, which was the default. No default configuration
|
|
68
|
+
* could settle a payment.
|
|
69
|
+
* - Omit `extra` and CDP identifies the payer and then refuses with "missing
|
|
70
|
+
* EIP-712 domain parameters". The agent signs an EIP-3009 authorization
|
|
71
|
+
* against the token's own domain, and the facilitator has to be told which
|
|
72
|
+
* domain to check the signature against.
|
|
73
|
+
*
|
|
74
|
+
* The name genuinely differs per deployment -- Base mainnet USDC calls itself
|
|
75
|
+
* "USD Coin", the Sepolia test token calls itself "USDC" -- so one hardcoded
|
|
76
|
+
* value is wrong on the other chain. These were read from each contract and
|
|
77
|
+
* checked against its own DOMAIN_SEPARATOR.
|
|
78
|
+
*/
|
|
79
|
+
const KNOWN_ASSETS = {
|
|
80
|
+
'base': {
|
|
81
|
+
asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
82
|
+
extra: { name: 'USD Coin', version: '2' }, decimals: 6,
|
|
83
|
+
},
|
|
84
|
+
'base-sepolia': {
|
|
85
|
+
asset: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
86
|
+
extra: { name: 'USDC', version: '2' }, decimals: 6,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
59
90
|
/**
|
|
60
91
|
* Build a `verifyPayment(proof, ctx)` for the Coinbase x402 facilitator.
|
|
61
92
|
*
|
|
@@ -74,7 +105,7 @@ export function toAtomicUnits(usd, decimals = DEFAULT_DECIMALS) {
|
|
|
74
105
|
*/
|
|
75
106
|
export function coinbaseFacilitator({
|
|
76
107
|
apiKeyId, apiKeySecret, receivingAddress,
|
|
77
|
-
network = 'base', asset = null, decimals =
|
|
108
|
+
network = 'base', asset = null, decimals = null, extra = null,
|
|
78
109
|
settle = true, baseUrl = DEFAULT_BASE, onError = () => {}, fetch: f = fetch,
|
|
79
110
|
} = {}) {
|
|
80
111
|
if (!apiKeyId || !apiKeySecret)
|
|
@@ -82,6 +113,24 @@ export function coinbaseFacilitator({
|
|
|
82
113
|
if (!receivingAddress)
|
|
83
114
|
throw new Error('coinbaseFacilitator requires receivingAddress — the address YOU get paid at');
|
|
84
115
|
|
|
116
|
+
const known = KNOWN_ASSETS[network];
|
|
117
|
+
const resolvedAsset = asset ?? known?.asset ?? null;
|
|
118
|
+
const resolvedExtra = extra ?? known?.extra ?? null;
|
|
119
|
+
const resolvedDecimals = decimals ?? known?.decimals ?? DEFAULT_DECIMALS;
|
|
120
|
+
|
|
121
|
+
// Fail here rather than on the first payment. A facilitator that cannot
|
|
122
|
+
// possibly settle should not be constructible: the alternative is a service
|
|
123
|
+
// that looks configured, passes its own tests, and denies every real payment
|
|
124
|
+
// with a 400 from someone else's API.
|
|
125
|
+
if (!resolvedAsset)
|
|
126
|
+
throw new Error(
|
|
127
|
+
`coinbaseFacilitator: no settlement asset known for network "${network}" — ` +
|
|
128
|
+
'pass asset: "0x..." (the token contract payment settles in)');
|
|
129
|
+
if (!resolvedExtra?.name || !resolvedExtra?.version)
|
|
130
|
+
throw new Error(
|
|
131
|
+
`coinbaseFacilitator: no EIP-712 domain known for network "${network}" — ` +
|
|
132
|
+
'pass extra: { name, version } as the token contract reports them');
|
|
133
|
+
|
|
85
134
|
const base = baseUrl.replace(/\/$/, '');
|
|
86
135
|
|
|
87
136
|
return async function verifyPayment(proof, ctx) {
|
|
@@ -104,13 +153,16 @@ export function coinbaseFacilitator({
|
|
|
104
153
|
// matches. Under the exact scheme the transfer MUST equal this and
|
|
105
154
|
// MUST land at payTo, so a wrong amount or wrong address cannot come
|
|
106
155
|
// back valid. That is stronger than trusting a number the payer sent.
|
|
107
|
-
maxAmountRequired: toAtomicUnits(ctx.price,
|
|
156
|
+
maxAmountRequired: toAtomicUnits(ctx.price, resolvedDecimals),
|
|
108
157
|
resource: ctx.resource ?? ctx.path ?? '',
|
|
109
158
|
description: '',
|
|
110
159
|
mimeType: 'application/json',
|
|
111
160
|
payTo: receivingAddress,
|
|
112
161
|
maxTimeoutSeconds: 60,
|
|
113
|
-
|
|
162
|
+
asset: resolvedAsset,
|
|
163
|
+
// The domain the payer signed against. Without it the facilitator can
|
|
164
|
+
// read the payload and still not check the signature.
|
|
165
|
+
extra: resolvedExtra,
|
|
114
166
|
};
|
|
115
167
|
} catch (err) {
|
|
116
168
|
return deny(`cannot build payment requirements: ${err.message}`);
|