kawasekit 0.0.1 → 0.1.0-alpha.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/LICENSE +201 -0
- package/README.md +260 -1
- package/dist/chunk-3S34WBAW.js +856 -0
- package/dist/chunk-3S34WBAW.js.map +1 -0
- package/dist/chunk-6M7UN23J.js +546 -0
- package/dist/chunk-6M7UN23J.js.map +1 -0
- package/dist/chunk-7D4SUZUM.js +35 -0
- package/dist/chunk-7D4SUZUM.js.map +1 -0
- package/dist/chunk-GGPXRIXM.js +81 -0
- package/dist/chunk-GGPXRIXM.js.map +1 -0
- package/dist/chunk-LEHWRDVS.js +19 -0
- package/dist/chunk-LEHWRDVS.js.map +1 -0
- package/dist/chunk-SA7LMQFG.js +44 -0
- package/dist/chunk-SA7LMQFG.js.map +1 -0
- package/dist/chunk-V5PUKFPL.js +304 -0
- package/dist/chunk-V5PUKFPL.js.map +1 -0
- package/dist/cli/index.cjs +1604 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +990 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index-BT-LhXV1.d.ts +558 -0
- package/dist/index-Bf78wMqn.d.cts +498 -0
- package/dist/index-CzX09uRS.d.cts +558 -0
- package/dist/index-WQ_Hq4_Z.d.ts +498 -0
- package/dist/index-jF4BGOIb.d.cts +173 -0
- package/dist/index-jF4BGOIb.d.ts +173 -0
- package/dist/index.cjs +1888 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +786 -0
- package/dist/index.d.ts +786 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/observability/index.cjs +22 -0
- package/dist/observability/index.cjs.map +1 -0
- package/dist/observability/index.d.cts +3 -0
- package/dist/observability/index.d.ts +3 -0
- package/dist/observability/index.js +4 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/otlp/index.cjs +118 -0
- package/dist/observability/otlp/index.cjs.map +1 -0
- package/dist/observability/otlp/index.d.cts +98 -0
- package/dist/observability/otlp/index.d.ts +98 -0
- package/dist/observability/otlp/index.js +106 -0
- package/dist/observability/otlp/index.js.map +1 -0
- package/dist/observability/prometheus/index.cjs +133 -0
- package/dist/observability/prometheus/index.cjs.map +1 -0
- package/dist/observability/prometheus/index.d.cts +94 -0
- package/dist/observability/prometheus/index.d.ts +94 -0
- package/dist/observability/prometheus/index.js +117 -0
- package/dist/observability/prometheus/index.js.map +1 -0
- package/dist/server-C3XkkTIP.d.cts +113 -0
- package/dist/server-t1qVFVnJ.d.ts +113 -0
- package/dist/session/index.cjs +338 -0
- package/dist/session/index.cjs.map +1 -0
- package/dist/session/index.d.cts +7 -0
- package/dist/session/index.d.ts +7 -0
- package/dist/session/index.js +5 -0
- package/dist/session/index.js.map +1 -0
- package/dist/x402/hono/index.cjs +274 -0
- package/dist/x402/hono/index.cjs.map +1 -0
- package/dist/x402/hono/index.d.cts +92 -0
- package/dist/x402/hono/index.d.ts +92 -0
- package/dist/x402/hono/index.js +29 -0
- package/dist/x402/hono/index.js.map +1 -0
- package/dist/x402/index.cjs +1421 -0
- package/dist/x402/index.cjs.map +1 -0
- package/dist/x402/index.d.cts +613 -0
- package/dist/x402/index.d.ts +613 -0
- package/dist/x402/index.js +7 -0
- package/dist/x402/index.js.map +1 -0
- package/package.json +162 -8
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
import { X402InvalidPayloadError, X402_VERSION, chainIdToX402Network, X402_HEADER_PAYMENT_SIGNATURE, encodePaymentSignatureHeader, X402_HEADER_PAYMENT_RESPONSE, decodePaymentResponseHeader, x402NetworkToChainId, JPYC_V2_ADDRESS, JPYC_EIP712_DOMAIN_HINT, X402_HEADER_PAYMENT_REQUIRED, decodePaymentRequiredHeader, jpycAbi } from './chunk-6M7UN23J.js';
|
|
2
|
+
import { getChain, isSupportedChainId } from './chunk-SA7LMQFG.js';
|
|
3
|
+
import { invokeHookSafely } from './chunk-LEHWRDVS.js';
|
|
4
|
+
import { parseSignature, getAddress, recoverTypedDataAddress, isAddress } from 'viem';
|
|
5
|
+
|
|
6
|
+
var transferWithAuthorizationTypes = {
|
|
7
|
+
TransferWithAuthorization: [
|
|
8
|
+
{ name: "from", type: "address" },
|
|
9
|
+
{ name: "to", type: "address" },
|
|
10
|
+
{ name: "value", type: "uint256" },
|
|
11
|
+
{ name: "validAfter", type: "uint256" },
|
|
12
|
+
{ name: "validBefore", type: "uint256" },
|
|
13
|
+
{ name: "nonce", type: "bytes32" }
|
|
14
|
+
]
|
|
15
|
+
};
|
|
16
|
+
var receiveWithAuthorizationTypes = {
|
|
17
|
+
ReceiveWithAuthorization: [
|
|
18
|
+
{ name: "from", type: "address" },
|
|
19
|
+
{ name: "to", type: "address" },
|
|
20
|
+
{ name: "value", type: "uint256" },
|
|
21
|
+
{ name: "validAfter", type: "uint256" },
|
|
22
|
+
{ name: "validBefore", type: "uint256" },
|
|
23
|
+
{ name: "nonce", type: "bytes32" }
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
var cancelAuthorizationTypes = {
|
|
27
|
+
CancelAuthorization: [
|
|
28
|
+
{ name: "authorizer", type: "address" },
|
|
29
|
+
{ name: "nonce", type: "bytes32" }
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
function generateAuthorizationNonce() {
|
|
33
|
+
const bytes = new Uint8Array(32);
|
|
34
|
+
crypto.getRandomValues(bytes);
|
|
35
|
+
return `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
36
|
+
}
|
|
37
|
+
function authorizationDeadlineFromNow(seconds, nowSec) {
|
|
38
|
+
const now = nowSec ?? BigInt(Math.floor(Date.now() / 1e3));
|
|
39
|
+
return now + BigInt(seconds);
|
|
40
|
+
}
|
|
41
|
+
function requireSignTypedData(account) {
|
|
42
|
+
if (!account.signTypedData) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`Account ${account.address} cannot sign typed data \u2014 pass a LocalAccount or a JsonRpcAccount bound to a WalletClient.`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return account.signTypedData.bind(account);
|
|
48
|
+
}
|
|
49
|
+
function assertSignerMatches(account, expectedFrom, role) {
|
|
50
|
+
if (getAddress(account.address) !== getAddress(expectedFrom)) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`EIP-3009 ${role} signature must come from \`${role === "cancel" ? "authorizer" : "from"}\`: account is ${account.address}, message says ${expectedFrom}.`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function signTransferWithAuthorization(account, domain, message) {
|
|
57
|
+
assertSignerMatches(account, message.from, "transfer");
|
|
58
|
+
const sign = requireSignTypedData(account);
|
|
59
|
+
const signature = await sign({
|
|
60
|
+
domain,
|
|
61
|
+
types: transferWithAuthorizationTypes,
|
|
62
|
+
primaryType: "TransferWithAuthorization",
|
|
63
|
+
message
|
|
64
|
+
});
|
|
65
|
+
return splitAuthorization(signature, domain, message);
|
|
66
|
+
}
|
|
67
|
+
async function signReceiveWithAuthorization(account, domain, message) {
|
|
68
|
+
assertSignerMatches(account, message.from, "receive");
|
|
69
|
+
const sign = requireSignTypedData(account);
|
|
70
|
+
const signature = await sign({
|
|
71
|
+
domain,
|
|
72
|
+
types: receiveWithAuthorizationTypes,
|
|
73
|
+
primaryType: "ReceiveWithAuthorization",
|
|
74
|
+
message
|
|
75
|
+
});
|
|
76
|
+
return splitAuthorization(signature, domain, message);
|
|
77
|
+
}
|
|
78
|
+
async function signCancelAuthorization(account, domain, message) {
|
|
79
|
+
assertSignerMatches(account, message.authorizer, "cancel");
|
|
80
|
+
const sign = requireSignTypedData(account);
|
|
81
|
+
const signature = await sign({
|
|
82
|
+
domain,
|
|
83
|
+
types: cancelAuthorizationTypes,
|
|
84
|
+
primaryType: "CancelAuthorization",
|
|
85
|
+
message
|
|
86
|
+
});
|
|
87
|
+
return splitAuthorization(signature, domain, message);
|
|
88
|
+
}
|
|
89
|
+
function splitAuthorization(signature, domain, message) {
|
|
90
|
+
const parsed = parseSignature(signature);
|
|
91
|
+
const v = parsed.v !== void 0 ? Number(parsed.v) : (parsed.yParity ?? 0) + 27;
|
|
92
|
+
return {
|
|
93
|
+
signature,
|
|
94
|
+
v,
|
|
95
|
+
r: parsed.r,
|
|
96
|
+
s: parsed.s,
|
|
97
|
+
domain,
|
|
98
|
+
message
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
var X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS = 300;
|
|
102
|
+
var UINT256_MAX = (1n << 256n) - 1n;
|
|
103
|
+
var UINT256_DECIMAL = /^(0|[1-9][0-9]*)$/;
|
|
104
|
+
function parseUintString(value, field) {
|
|
105
|
+
if (!UINT256_DECIMAL.test(value)) {
|
|
106
|
+
throw new X402InvalidPayloadError(
|
|
107
|
+
"PaymentRequirements",
|
|
108
|
+
`\`${field}\` must be a non-negative decimal string, got ${JSON.stringify(value)}`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
const parsed = BigInt(value);
|
|
112
|
+
if (parsed > UINT256_MAX) {
|
|
113
|
+
throw new X402InvalidPayloadError(
|
|
114
|
+
"PaymentRequirements",
|
|
115
|
+
`\`${field}\` exceeds uint256, got ${value}`
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return parsed;
|
|
119
|
+
}
|
|
120
|
+
function assertAddress(value, field) {
|
|
121
|
+
if (!isAddress(value, { strict: false })) {
|
|
122
|
+
throw new X402InvalidPayloadError(
|
|
123
|
+
"PaymentRequirements",
|
|
124
|
+
`\`${field}\` is not a valid address: ${value}`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
return value;
|
|
128
|
+
}
|
|
129
|
+
function resolveDomain(requirements, override) {
|
|
130
|
+
if (override) {
|
|
131
|
+
return override;
|
|
132
|
+
}
|
|
133
|
+
const extra = requirements.extra;
|
|
134
|
+
if (typeof extra.name === "string" && typeof extra.version === "string") {
|
|
135
|
+
return { name: extra.name, version: extra.version };
|
|
136
|
+
}
|
|
137
|
+
if (getAddress(requirements.asset) === getAddress(JPYC_V2_ADDRESS)) {
|
|
138
|
+
return JPYC_EIP712_DOMAIN_HINT;
|
|
139
|
+
}
|
|
140
|
+
throw new X402InvalidPayloadError(
|
|
141
|
+
"PaymentRequirements",
|
|
142
|
+
"`extra.name` and `extra.version` are required for exact-EVM signing on a non-JPYC asset"
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
function validateRequirements(requirements) {
|
|
146
|
+
if (requirements.scheme !== "exact") {
|
|
147
|
+
throw new X402InvalidPayloadError(
|
|
148
|
+
"PaymentRequirements",
|
|
149
|
+
`unsupported scheme: ${requirements.scheme}`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
const chainId = x402NetworkToChainId(requirements.network);
|
|
153
|
+
if (!isSupportedChainId(chainId)) {
|
|
154
|
+
throw new X402InvalidPayloadError(
|
|
155
|
+
"PaymentRequirements",
|
|
156
|
+
`unsupported network: ${requirements.network}`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
const value = parseUintString(requirements.amount, "amount");
|
|
160
|
+
if (value === 0n) {
|
|
161
|
+
throw new X402InvalidPayloadError("PaymentRequirements", "`amount` must be positive");
|
|
162
|
+
}
|
|
163
|
+
if (requirements.maxTimeoutSeconds <= 0) {
|
|
164
|
+
throw new X402InvalidPayloadError(
|
|
165
|
+
"PaymentRequirements",
|
|
166
|
+
`\`maxTimeoutSeconds\` must be positive, got ${requirements.maxTimeoutSeconds}`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
const asset = assertAddress(requirements.asset, "asset");
|
|
170
|
+
const payTo = assertAddress(requirements.payTo, "payTo");
|
|
171
|
+
return { chainId, value, asset, payTo };
|
|
172
|
+
}
|
|
173
|
+
function createX402PaymentSigner(params) {
|
|
174
|
+
const { account, network } = params;
|
|
175
|
+
const defaultLifetimeSeconds = params.defaultLifetimeSeconds ?? X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS;
|
|
176
|
+
if (defaultLifetimeSeconds <= 0) {
|
|
177
|
+
throw new X402InvalidPayloadError(
|
|
178
|
+
"X402PaymentSignerConfig",
|
|
179
|
+
`\`defaultLifetimeSeconds\` must be positive, got ${defaultLifetimeSeconds}`
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
const domainOverride = params.domainOverride;
|
|
183
|
+
return {
|
|
184
|
+
address: account.address,
|
|
185
|
+
async sign(signParams) {
|
|
186
|
+
const { paymentRequirements } = signParams;
|
|
187
|
+
const { chainId, value, asset, payTo } = validateRequirements(paymentRequirements);
|
|
188
|
+
const chain = getChain(chainId);
|
|
189
|
+
if (network === "mainnet" && chain.isTestnet) {
|
|
190
|
+
throw new X402InvalidPayloadError(
|
|
191
|
+
"PaymentRequirements",
|
|
192
|
+
`signer was configured for network="mainnet" but requirements.network="${paymentRequirements.network}" (chainId ${chainId}) is a testnet`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
if (network === "testnet" && !chain.isTestnet) {
|
|
196
|
+
throw new X402InvalidPayloadError(
|
|
197
|
+
"PaymentRequirements",
|
|
198
|
+
`signer was configured for network="testnet" but requirements.network="${paymentRequirements.network}" (chainId ${chainId}) is a mainnet \u2014 refusing to sign payment for real funds`
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
const domain = resolveDomain(paymentRequirements, domainOverride);
|
|
202
|
+
const lifetime = Math.min(defaultLifetimeSeconds, paymentRequirements.maxTimeoutSeconds);
|
|
203
|
+
const validAfter = signParams.validAfter ?? 0n;
|
|
204
|
+
const validBefore = signParams.validBefore ?? authorizationDeadlineFromNow(lifetime);
|
|
205
|
+
if (validBefore <= validAfter) {
|
|
206
|
+
throw new X402InvalidPayloadError(
|
|
207
|
+
"PaymentRequirements",
|
|
208
|
+
`\`validBefore\` (${validBefore}) must be greater than \`validAfter\` (${validAfter})`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
const nonce = generateAuthorizationNonce();
|
|
212
|
+
const signed = await signTransferWithAuthorization(
|
|
213
|
+
account,
|
|
214
|
+
{ name: domain.name, version: domain.version, chainId, verifyingContract: asset },
|
|
215
|
+
{
|
|
216
|
+
from: account.address,
|
|
217
|
+
to: payTo,
|
|
218
|
+
value,
|
|
219
|
+
validAfter,
|
|
220
|
+
validBefore,
|
|
221
|
+
nonce
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
const payload = {
|
|
225
|
+
signature: signed.signature,
|
|
226
|
+
authorization: {
|
|
227
|
+
from: signed.message.from,
|
|
228
|
+
to: signed.message.to,
|
|
229
|
+
value: signed.message.value.toString(),
|
|
230
|
+
validAfter: signed.message.validAfter.toString(),
|
|
231
|
+
validBefore: signed.message.validBefore.toString(),
|
|
232
|
+
nonce: signed.message.nonce
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
const result = signParams.resource ? {
|
|
236
|
+
x402Version: X402_VERSION,
|
|
237
|
+
resource: signParams.resource,
|
|
238
|
+
accepted: paymentRequirements,
|
|
239
|
+
payload: { ...payload }
|
|
240
|
+
} : {
|
|
241
|
+
x402Version: X402_VERSION,
|
|
242
|
+
accepted: paymentRequirements,
|
|
243
|
+
payload: { ...payload }
|
|
244
|
+
};
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
var X402_FACILITATOR_ERROR_CODES = {
|
|
250
|
+
insufficient_funds: "insufficient_funds",
|
|
251
|
+
invalid_exact_evm_payload_authorization_valid_after: "invalid_exact_evm_payload_authorization_valid_after",
|
|
252
|
+
invalid_exact_evm_payload_authorization_valid_before: "invalid_exact_evm_payload_authorization_valid_before",
|
|
253
|
+
invalid_exact_evm_payload_authorization_value_mismatch: "invalid_exact_evm_payload_authorization_value_mismatch",
|
|
254
|
+
invalid_exact_evm_payload_recipient_mismatch: "invalid_exact_evm_payload_recipient_mismatch",
|
|
255
|
+
invalid_exact_evm_payload_signature: "invalid_exact_evm_payload_signature",
|
|
256
|
+
invalid_network: "invalid_network",
|
|
257
|
+
invalid_payload: "invalid_payload",
|
|
258
|
+
invalid_scheme: "invalid_scheme",
|
|
259
|
+
invalid_transaction_state: "invalid_transaction_state",
|
|
260
|
+
unexpected_settle_error: "unexpected_settle_error",
|
|
261
|
+
unexpected_verify_error: "unexpected_verify_error"
|
|
262
|
+
};
|
|
263
|
+
function isHex(value) {
|
|
264
|
+
return typeof value === "string" && /^0x[0-9a-fA-F]*$/.test(value);
|
|
265
|
+
}
|
|
266
|
+
function isAddressLike(value) {
|
|
267
|
+
return typeof value === "string" && /^0x[0-9a-fA-F]{40}$/.test(value);
|
|
268
|
+
}
|
|
269
|
+
function isDecimalString(value) {
|
|
270
|
+
return typeof value === "string" && /^(0|[1-9][0-9]*)$/.test(value);
|
|
271
|
+
}
|
|
272
|
+
function narrowExactEvmPayload(payload) {
|
|
273
|
+
const p = payload;
|
|
274
|
+
if (!isHex(p.signature)) return null;
|
|
275
|
+
if (typeof p.authorization !== "object" || p.authorization === null) return null;
|
|
276
|
+
const a = p.authorization;
|
|
277
|
+
if (!isAddressLike(a.from)) return null;
|
|
278
|
+
if (!isAddressLike(a.to)) return null;
|
|
279
|
+
if (!isDecimalString(a.value)) return null;
|
|
280
|
+
if (!isDecimalString(a.validAfter)) return null;
|
|
281
|
+
if (!isDecimalString(a.validBefore)) return null;
|
|
282
|
+
if (!isHex(a.nonce)) return null;
|
|
283
|
+
return {
|
|
284
|
+
signature: p.signature,
|
|
285
|
+
authorization: {
|
|
286
|
+
from: a.from,
|
|
287
|
+
to: a.to,
|
|
288
|
+
value: a.value,
|
|
289
|
+
validAfter: a.validAfter,
|
|
290
|
+
validBefore: a.validBefore,
|
|
291
|
+
nonce: a.nonce
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
var TRANSFER_AUTHORIZATION_TYPES = {
|
|
296
|
+
TransferWithAuthorization: [
|
|
297
|
+
{ name: "from", type: "address" },
|
|
298
|
+
{ name: "to", type: "address" },
|
|
299
|
+
{ name: "value", type: "uint256" },
|
|
300
|
+
{ name: "validAfter", type: "uint256" },
|
|
301
|
+
{ name: "validBefore", type: "uint256" },
|
|
302
|
+
{ name: "nonce", type: "bytes32" }
|
|
303
|
+
]
|
|
304
|
+
};
|
|
305
|
+
function resolveDomain2(requirements) {
|
|
306
|
+
const extra = requirements.extra;
|
|
307
|
+
if (typeof extra.name === "string" && typeof extra.version === "string") {
|
|
308
|
+
return { name: extra.name, version: extra.version };
|
|
309
|
+
}
|
|
310
|
+
if (getAddress(requirements.asset) === getAddress(JPYC_V2_ADDRESS)) {
|
|
311
|
+
return JPYC_EIP712_DOMAIN_HINT;
|
|
312
|
+
}
|
|
313
|
+
throw new Error(
|
|
314
|
+
"resolveDomain: `extra.name` and `extra.version` are required for non-JPYC assets"
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
function failVerify(reason, message, payer) {
|
|
318
|
+
if (message !== void 0 && payer !== void 0) {
|
|
319
|
+
return { isValid: false, invalidReason: reason, invalidMessage: message, payer };
|
|
320
|
+
}
|
|
321
|
+
if (message !== void 0) {
|
|
322
|
+
return { isValid: false, invalidReason: reason, invalidMessage: message };
|
|
323
|
+
}
|
|
324
|
+
if (payer !== void 0) {
|
|
325
|
+
return { isValid: false, invalidReason: reason, payer };
|
|
326
|
+
}
|
|
327
|
+
return { isValid: false, invalidReason: reason };
|
|
328
|
+
}
|
|
329
|
+
function failSettle(network, reason, options = {}) {
|
|
330
|
+
const transaction = options.transaction ?? "";
|
|
331
|
+
const base = {
|
|
332
|
+
success: false,
|
|
333
|
+
errorReason: reason,
|
|
334
|
+
transaction,
|
|
335
|
+
network
|
|
336
|
+
};
|
|
337
|
+
if (options.message !== void 0 && options.payer !== void 0) {
|
|
338
|
+
return { ...base, errorMessage: options.message, payer: options.payer };
|
|
339
|
+
}
|
|
340
|
+
if (options.message !== void 0) {
|
|
341
|
+
return { ...base, errorMessage: options.message };
|
|
342
|
+
}
|
|
343
|
+
if (options.payer !== void 0) {
|
|
344
|
+
return { ...base, payer: options.payer };
|
|
345
|
+
}
|
|
346
|
+
return base;
|
|
347
|
+
}
|
|
348
|
+
function createSelfFacilitator(params) {
|
|
349
|
+
const { walletClient, publicClient } = params;
|
|
350
|
+
const receiptTimeoutMs = params.receiptTimeoutMs ?? 6e4;
|
|
351
|
+
const facilitatorChainId = walletClient.chain.id;
|
|
352
|
+
if (!isSupportedChainId(facilitatorChainId)) {
|
|
353
|
+
throw new Error(
|
|
354
|
+
`createSelfFacilitator: walletClient.chain.id ${facilitatorChainId} is not a kawasekit-supported chain`
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
const supportedChainId = facilitatorChainId;
|
|
358
|
+
const chain = getChain(supportedChainId);
|
|
359
|
+
if (params.network === "mainnet" && chain.isTestnet) {
|
|
360
|
+
throw new Error(
|
|
361
|
+
`createSelfFacilitator: network="mainnet" but walletClient.chain "${chain.name}" (chainId ${supportedChainId}) is a testnet`
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
if (params.network === "testnet" && !chain.isTestnet) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
`createSelfFacilitator: network="testnet" but walletClient.chain "${chain.name}" (chainId ${supportedChainId}) is a mainnet \u2014 refusing to broadcast with real funds`
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
const network = chainIdToX402Network(supportedChainId);
|
|
370
|
+
const hooks = params.hooks;
|
|
371
|
+
function buildVerifyEvent(req, response, startedAtMs) {
|
|
372
|
+
const durationMs = Date.now() - startedAtMs;
|
|
373
|
+
const eventNetwork = req.paymentRequirements.network;
|
|
374
|
+
if (response.isValid && response.payer !== void 0) {
|
|
375
|
+
return {
|
|
376
|
+
kind: "verify",
|
|
377
|
+
result: "success",
|
|
378
|
+
startedAtMs,
|
|
379
|
+
durationMs,
|
|
380
|
+
network: eventNetwork,
|
|
381
|
+
payer: response.payer,
|
|
382
|
+
amount: req.paymentRequirements.amount
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
if (response.isValid) {
|
|
386
|
+
return {
|
|
387
|
+
kind: "verify",
|
|
388
|
+
result: "failure",
|
|
389
|
+
startedAtMs,
|
|
390
|
+
durationMs,
|
|
391
|
+
network: eventNetwork,
|
|
392
|
+
invalidReason: "unexpected_verify_error",
|
|
393
|
+
invalidMessage: "verify succeeded but payer was not surfaced"
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
const base = {
|
|
397
|
+
kind: "verify",
|
|
398
|
+
result: "failure",
|
|
399
|
+
startedAtMs,
|
|
400
|
+
durationMs,
|
|
401
|
+
network: eventNetwork,
|
|
402
|
+
invalidReason: response.invalidReason ?? "unexpected_verify_error"
|
|
403
|
+
};
|
|
404
|
+
if (response.payer !== void 0 && response.invalidMessage !== void 0) {
|
|
405
|
+
return { ...base, payer: response.payer, invalidMessage: response.invalidMessage };
|
|
406
|
+
}
|
|
407
|
+
if (response.payer !== void 0) {
|
|
408
|
+
return { ...base, payer: response.payer };
|
|
409
|
+
}
|
|
410
|
+
if (response.invalidMessage !== void 0) {
|
|
411
|
+
return { ...base, invalidMessage: response.invalidMessage };
|
|
412
|
+
}
|
|
413
|
+
return base;
|
|
414
|
+
}
|
|
415
|
+
function buildSettleEvent(req, response, startedAtMs) {
|
|
416
|
+
const durationMs = Date.now() - startedAtMs;
|
|
417
|
+
const eventNetwork = req.paymentRequirements.network;
|
|
418
|
+
if (response.success && response.payer !== void 0) {
|
|
419
|
+
return {
|
|
420
|
+
kind: "settle",
|
|
421
|
+
result: "success",
|
|
422
|
+
startedAtMs,
|
|
423
|
+
durationMs,
|
|
424
|
+
network: eventNetwork,
|
|
425
|
+
payer: response.payer,
|
|
426
|
+
amount: req.paymentRequirements.amount,
|
|
427
|
+
transaction: response.transaction
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
if (response.success) {
|
|
431
|
+
return {
|
|
432
|
+
kind: "settle",
|
|
433
|
+
result: "failure",
|
|
434
|
+
startedAtMs,
|
|
435
|
+
durationMs,
|
|
436
|
+
network: eventNetwork,
|
|
437
|
+
errorReason: "unexpected_settle_error",
|
|
438
|
+
errorMessage: "settle succeeded but payer was not surfaced",
|
|
439
|
+
transaction: response.transaction
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
const base = {
|
|
443
|
+
kind: "settle",
|
|
444
|
+
result: "failure",
|
|
445
|
+
startedAtMs,
|
|
446
|
+
durationMs,
|
|
447
|
+
network: eventNetwork,
|
|
448
|
+
errorReason: response.errorReason ?? "unexpected_settle_error"
|
|
449
|
+
};
|
|
450
|
+
const withPayer = response.payer !== void 0 ? { ...base, payer: response.payer } : base;
|
|
451
|
+
const withMessage = response.errorMessage !== void 0 ? { ...withPayer, errorMessage: response.errorMessage } : withPayer;
|
|
452
|
+
if (response.transaction !== "" && response.transaction !== void 0) {
|
|
453
|
+
return { ...withMessage, transaction: response.transaction };
|
|
454
|
+
}
|
|
455
|
+
return withMessage;
|
|
456
|
+
}
|
|
457
|
+
async function verifyCore(req) {
|
|
458
|
+
if (req.paymentRequirements.scheme !== "exact") {
|
|
459
|
+
return failVerify("invalid_scheme");
|
|
460
|
+
}
|
|
461
|
+
if (req.paymentPayload.accepted.scheme !== "exact") {
|
|
462
|
+
return failVerify("invalid_scheme");
|
|
463
|
+
}
|
|
464
|
+
const reqChainId = x402NetworkToChainId(req.paymentRequirements.network);
|
|
465
|
+
if (reqChainId !== supportedChainId) {
|
|
466
|
+
return failVerify("invalid_network");
|
|
467
|
+
}
|
|
468
|
+
if (req.paymentPayload.accepted.network !== req.paymentRequirements.network) {
|
|
469
|
+
return failVerify("invalid_network");
|
|
470
|
+
}
|
|
471
|
+
const exact = narrowExactEvmPayload(req.paymentPayload.payload);
|
|
472
|
+
if (exact === null) {
|
|
473
|
+
return failVerify("invalid_payload");
|
|
474
|
+
}
|
|
475
|
+
const auth = exact.authorization;
|
|
476
|
+
if (auth.value !== req.paymentRequirements.amount) {
|
|
477
|
+
return failVerify(
|
|
478
|
+
"invalid_exact_evm_payload_authorization_value_mismatch",
|
|
479
|
+
void 0,
|
|
480
|
+
auth.from
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
if (getAddress(auth.to) !== getAddress(req.paymentRequirements.payTo)) {
|
|
484
|
+
return failVerify("invalid_exact_evm_payload_recipient_mismatch", void 0, auth.from);
|
|
485
|
+
}
|
|
486
|
+
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
487
|
+
const validAfter = BigInt(auth.validAfter);
|
|
488
|
+
const validBefore = BigInt(auth.validBefore);
|
|
489
|
+
if (now < validAfter) {
|
|
490
|
+
return failVerify(
|
|
491
|
+
"invalid_exact_evm_payload_authorization_valid_after",
|
|
492
|
+
void 0,
|
|
493
|
+
auth.from
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
if (now >= validBefore) {
|
|
497
|
+
return failVerify(
|
|
498
|
+
"invalid_exact_evm_payload_authorization_valid_before",
|
|
499
|
+
void 0,
|
|
500
|
+
auth.from
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
let recovered;
|
|
504
|
+
try {
|
|
505
|
+
const domain = resolveDomain2(req.paymentRequirements);
|
|
506
|
+
recovered = await recoverTypedDataAddress({
|
|
507
|
+
domain: {
|
|
508
|
+
name: domain.name,
|
|
509
|
+
version: domain.version,
|
|
510
|
+
chainId: reqChainId,
|
|
511
|
+
verifyingContract: req.paymentRequirements.asset
|
|
512
|
+
},
|
|
513
|
+
types: TRANSFER_AUTHORIZATION_TYPES,
|
|
514
|
+
primaryType: "TransferWithAuthorization",
|
|
515
|
+
message: {
|
|
516
|
+
from: auth.from,
|
|
517
|
+
to: auth.to,
|
|
518
|
+
value: BigInt(auth.value),
|
|
519
|
+
validAfter,
|
|
520
|
+
validBefore,
|
|
521
|
+
nonce: auth.nonce
|
|
522
|
+
},
|
|
523
|
+
signature: exact.signature
|
|
524
|
+
});
|
|
525
|
+
} catch (cause) {
|
|
526
|
+
return failVerify(
|
|
527
|
+
"unexpected_verify_error",
|
|
528
|
+
cause instanceof Error ? cause.message : String(cause),
|
|
529
|
+
auth.from
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
if (getAddress(recovered) !== getAddress(auth.from)) {
|
|
533
|
+
return failVerify("invalid_exact_evm_payload_signature", void 0, auth.from);
|
|
534
|
+
}
|
|
535
|
+
try {
|
|
536
|
+
const [balance, used] = await Promise.all([
|
|
537
|
+
publicClient.readContract({
|
|
538
|
+
address: req.paymentRequirements.asset,
|
|
539
|
+
abi: jpycAbi,
|
|
540
|
+
functionName: "balanceOf",
|
|
541
|
+
args: [auth.from]
|
|
542
|
+
}),
|
|
543
|
+
publicClient.readContract({
|
|
544
|
+
address: req.paymentRequirements.asset,
|
|
545
|
+
abi: jpycAbi,
|
|
546
|
+
functionName: "authorizationState",
|
|
547
|
+
args: [auth.from, auth.nonce]
|
|
548
|
+
})
|
|
549
|
+
]);
|
|
550
|
+
if (used) {
|
|
551
|
+
return failVerify("invalid_payload", "authorization nonce already used", auth.from);
|
|
552
|
+
}
|
|
553
|
+
if (balance < BigInt(auth.value)) {
|
|
554
|
+
return failVerify("insufficient_funds", void 0, auth.from);
|
|
555
|
+
}
|
|
556
|
+
} catch (cause) {
|
|
557
|
+
return failVerify(
|
|
558
|
+
"unexpected_verify_error",
|
|
559
|
+
cause instanceof Error ? cause.message : String(cause),
|
|
560
|
+
auth.from
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
return { isValid: true, payer: auth.from };
|
|
564
|
+
}
|
|
565
|
+
async function settleCore(req) {
|
|
566
|
+
const verifyResult = await verify(req);
|
|
567
|
+
if (!verifyResult.isValid) {
|
|
568
|
+
return failSettle(
|
|
569
|
+
req.paymentRequirements.network,
|
|
570
|
+
verifyResult.invalidReason ?? "unexpected_settle_error",
|
|
571
|
+
{
|
|
572
|
+
...verifyResult.invalidMessage !== void 0 ? { message: verifyResult.invalidMessage } : {},
|
|
573
|
+
...verifyResult.payer !== void 0 ? { payer: verifyResult.payer } : {}
|
|
574
|
+
}
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
const exact = narrowExactEvmPayload(req.paymentPayload.payload);
|
|
578
|
+
if (exact === null) {
|
|
579
|
+
return failSettle(req.paymentRequirements.network, "invalid_payload");
|
|
580
|
+
}
|
|
581
|
+
const auth = exact.authorization;
|
|
582
|
+
const parsed = parseSignature(exact.signature);
|
|
583
|
+
const v = parsed.v !== void 0 ? Number(parsed.v) : (parsed.yParity ?? 0) + 27;
|
|
584
|
+
let txHash;
|
|
585
|
+
try {
|
|
586
|
+
txHash = await walletClient.writeContract({
|
|
587
|
+
address: req.paymentRequirements.asset,
|
|
588
|
+
abi: jpycAbi,
|
|
589
|
+
functionName: "transferWithAuthorization",
|
|
590
|
+
args: [
|
|
591
|
+
auth.from,
|
|
592
|
+
auth.to,
|
|
593
|
+
BigInt(auth.value),
|
|
594
|
+
BigInt(auth.validAfter),
|
|
595
|
+
BigInt(auth.validBefore),
|
|
596
|
+
auth.nonce,
|
|
597
|
+
v,
|
|
598
|
+
parsed.r,
|
|
599
|
+
parsed.s
|
|
600
|
+
]
|
|
601
|
+
});
|
|
602
|
+
} catch (cause) {
|
|
603
|
+
return failSettle(req.paymentRequirements.network, "unexpected_settle_error", {
|
|
604
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
605
|
+
payer: auth.from
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
try {
|
|
609
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
610
|
+
hash: txHash,
|
|
611
|
+
timeout: receiptTimeoutMs
|
|
612
|
+
});
|
|
613
|
+
if (receipt.status !== "success") {
|
|
614
|
+
return failSettle(req.paymentRequirements.network, "invalid_transaction_state", {
|
|
615
|
+
transaction: txHash,
|
|
616
|
+
payer: auth.from
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
} catch (cause) {
|
|
620
|
+
return failSettle(req.paymentRequirements.network, "unexpected_settle_error", {
|
|
621
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
622
|
+
payer: auth.from,
|
|
623
|
+
transaction: txHash
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
return {
|
|
627
|
+
success: true,
|
|
628
|
+
transaction: txHash,
|
|
629
|
+
network: req.paymentRequirements.network,
|
|
630
|
+
payer: auth.from,
|
|
631
|
+
amount: auth.value
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
async function verify(req) {
|
|
635
|
+
const startedAtMs = Date.now();
|
|
636
|
+
const result = await verifyCore(req);
|
|
637
|
+
invokeHookSafely(hooks?.onVerify, buildVerifyEvent(req, result, startedAtMs));
|
|
638
|
+
return result;
|
|
639
|
+
}
|
|
640
|
+
async function settle(req) {
|
|
641
|
+
const startedAtMs = Date.now();
|
|
642
|
+
const result = await settleCore(req);
|
|
643
|
+
invokeHookSafely(hooks?.onSettle, buildSettleEvent(req, result, startedAtMs));
|
|
644
|
+
return result;
|
|
645
|
+
}
|
|
646
|
+
async function supportedInternal() {
|
|
647
|
+
const kind = {
|
|
648
|
+
x402Version: X402_VERSION,
|
|
649
|
+
scheme: "exact",
|
|
650
|
+
network
|
|
651
|
+
};
|
|
652
|
+
return {
|
|
653
|
+
kinds: [kind],
|
|
654
|
+
extensions: [],
|
|
655
|
+
signers: { "eip155:*": [walletClient.account.address] }
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
return {
|
|
659
|
+
verify,
|
|
660
|
+
settle,
|
|
661
|
+
supported: supportedInternal
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
function createHttpFacilitator(params) {
|
|
665
|
+
const baseUrl = params.baseUrl.replace(/\/$/, "");
|
|
666
|
+
const fetchImpl = params.fetch ?? fetch;
|
|
667
|
+
const getAuthHeaders = params.getAuthHeaders;
|
|
668
|
+
async function post(endpoint, body) {
|
|
669
|
+
const headers = { "content-type": "application/json" };
|
|
670
|
+
if (getAuthHeaders) {
|
|
671
|
+
Object.assign(headers, await getAuthHeaders(endpoint));
|
|
672
|
+
}
|
|
673
|
+
const response = await fetchImpl(`${baseUrl}/${endpoint}`, {
|
|
674
|
+
method: "POST",
|
|
675
|
+
headers,
|
|
676
|
+
body: JSON.stringify(body)
|
|
677
|
+
});
|
|
678
|
+
const text = await response.text();
|
|
679
|
+
let parsed;
|
|
680
|
+
try {
|
|
681
|
+
parsed = text === "" ? null : JSON.parse(text);
|
|
682
|
+
} catch {
|
|
683
|
+
throw new Error(
|
|
684
|
+
`Facilitator ${endpoint} returned non-JSON (status ${response.status}): ${text.slice(0, 200)}`
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
if (!response.ok) {
|
|
688
|
+
throw new Error(
|
|
689
|
+
`Facilitator ${endpoint} failed (status ${response.status}): ${JSON.stringify(parsed).slice(0, 200)}`
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
return parsed;
|
|
693
|
+
}
|
|
694
|
+
async function verifyInternal(req) {
|
|
695
|
+
return post("verify", {
|
|
696
|
+
x402Version: req.x402Version,
|
|
697
|
+
paymentPayload: req.paymentPayload,
|
|
698
|
+
paymentRequirements: req.paymentRequirements
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
async function settleInternal(req) {
|
|
702
|
+
return post("settle", {
|
|
703
|
+
x402Version: req.x402Version,
|
|
704
|
+
paymentPayload: req.paymentPayload,
|
|
705
|
+
paymentRequirements: req.paymentRequirements
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
async function supportedInternal() {
|
|
709
|
+
const headers = {};
|
|
710
|
+
if (getAuthHeaders) {
|
|
711
|
+
Object.assign(headers, await getAuthHeaders("supported"));
|
|
712
|
+
}
|
|
713
|
+
const response = await fetchImpl(`${baseUrl}/supported`, { method: "GET", headers });
|
|
714
|
+
const text = await response.text();
|
|
715
|
+
let parsed;
|
|
716
|
+
try {
|
|
717
|
+
parsed = text === "" ? null : JSON.parse(text);
|
|
718
|
+
} catch {
|
|
719
|
+
throw new Error(
|
|
720
|
+
`Facilitator supported returned non-JSON (status ${response.status}): ${text.slice(0, 200)}`
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
if (!response.ok) {
|
|
724
|
+
throw new Error(
|
|
725
|
+
`Facilitator supported failed (status ${response.status}): ${JSON.stringify(parsed).slice(0, 200)}`
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
return parsed;
|
|
729
|
+
}
|
|
730
|
+
return {
|
|
731
|
+
verify: verifyInternal,
|
|
732
|
+
settle: settleInternal,
|
|
733
|
+
supported: supportedInternal
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
var warnedCreateCoinbaseFacilitator = false;
|
|
737
|
+
function createCoinbaseFacilitator(params) {
|
|
738
|
+
if (!warnedCreateCoinbaseFacilitator) {
|
|
739
|
+
warnedCreateCoinbaseFacilitator = true;
|
|
740
|
+
process.emitWarning(
|
|
741
|
+
"createCoinbaseFacilitator() is deprecated and will be removed in kawasekit v0.2.0. Use createHttpFacilitator() instead \u2014 the function works with any x402 v2-compliant HTTP endpoint, not only Coinbase CDP.",
|
|
742
|
+
{ type: "DeprecationWarning", code: "KAWASEKIT_DEP_001" }
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
return createHttpFacilitator(params);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// src/x402/fetch.ts
|
|
749
|
+
async function readPaymentRequired(response) {
|
|
750
|
+
const headerValue = response.headers.get(X402_HEADER_PAYMENT_REQUIRED);
|
|
751
|
+
if (headerValue !== null && headerValue !== "") {
|
|
752
|
+
try {
|
|
753
|
+
return decodePaymentRequiredHeader(headerValue);
|
|
754
|
+
} catch {
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
try {
|
|
758
|
+
const body = await response.clone().text();
|
|
759
|
+
if (body === "") return null;
|
|
760
|
+
const parsed = JSON.parse(body);
|
|
761
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
762
|
+
return null;
|
|
763
|
+
}
|
|
764
|
+
return parsed;
|
|
765
|
+
} catch {
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
function defaultSelectRequirements(accepts) {
|
|
770
|
+
return accepts[0] ?? null;
|
|
771
|
+
}
|
|
772
|
+
function wrapFetch(params) {
|
|
773
|
+
const baseFetch = params.fetch ?? ((input, init) => fetch(input, init));
|
|
774
|
+
const selectRequirements = params.selectRequirements ?? defaultSelectRequirements;
|
|
775
|
+
const onPayment = params.onPayment;
|
|
776
|
+
const hooks = params.hooks;
|
|
777
|
+
return async function x402Fetch(input, init) {
|
|
778
|
+
const startedAtMs = Date.now();
|
|
779
|
+
const requestUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
780
|
+
const emitFailure = (reason, httpStatus) => {
|
|
781
|
+
const event = {
|
|
782
|
+
kind: "client_payment",
|
|
783
|
+
result: "failure",
|
|
784
|
+
startedAtMs,
|
|
785
|
+
durationMs: Date.now() - startedAtMs,
|
|
786
|
+
requestUrl,
|
|
787
|
+
reason,
|
|
788
|
+
...httpStatus !== void 0 ? { httpStatus } : {}
|
|
789
|
+
};
|
|
790
|
+
invokeHookSafely(hooks?.onClientPayment, event);
|
|
791
|
+
};
|
|
792
|
+
const initialResponse = await baseFetch(input, init);
|
|
793
|
+
if (initialResponse.status !== 402) {
|
|
794
|
+
return initialResponse;
|
|
795
|
+
}
|
|
796
|
+
const paymentRequired = await readPaymentRequired(initialResponse);
|
|
797
|
+
if (paymentRequired === null || paymentRequired.accepts.length === 0) {
|
|
798
|
+
emitFailure("no_acceptable_requirement", 402);
|
|
799
|
+
return initialResponse;
|
|
800
|
+
}
|
|
801
|
+
const chosen = selectRequirements(paymentRequired.accepts, initialResponse);
|
|
802
|
+
if (chosen === null) {
|
|
803
|
+
emitFailure("no_acceptable_requirement", 402);
|
|
804
|
+
return initialResponse;
|
|
805
|
+
}
|
|
806
|
+
if (onPayment) {
|
|
807
|
+
const proceed = await onPayment(chosen, paymentRequired);
|
|
808
|
+
if (proceed === false) {
|
|
809
|
+
emitFailure("onPayment_declined", 402);
|
|
810
|
+
return initialResponse;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
const paymentPayload = await params.signer.sign({
|
|
814
|
+
paymentRequirements: chosen,
|
|
815
|
+
...paymentRequired.resource ? { resource: paymentRequired.resource } : {}
|
|
816
|
+
});
|
|
817
|
+
const retryHeaders = new Headers(init?.headers);
|
|
818
|
+
retryHeaders.set(X402_HEADER_PAYMENT_SIGNATURE, encodePaymentSignatureHeader(paymentPayload));
|
|
819
|
+
const retryResponse = await baseFetch(input, { ...init, headers: retryHeaders });
|
|
820
|
+
if (retryResponse.status >= 200 && retryResponse.status < 300) {
|
|
821
|
+
const settlementHeader = retryResponse.headers.get(X402_HEADER_PAYMENT_RESPONSE);
|
|
822
|
+
let transaction;
|
|
823
|
+
if (settlementHeader !== null && settlementHeader !== "") {
|
|
824
|
+
try {
|
|
825
|
+
const settlement = decodePaymentResponseHeader(settlementHeader);
|
|
826
|
+
if (settlement.transaction !== "") {
|
|
827
|
+
transaction = settlement.transaction;
|
|
828
|
+
}
|
|
829
|
+
} catch {
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
const successEvent = {
|
|
833
|
+
kind: "client_payment",
|
|
834
|
+
result: "success",
|
|
835
|
+
startedAtMs,
|
|
836
|
+
durationMs: Date.now() - startedAtMs,
|
|
837
|
+
requestUrl,
|
|
838
|
+
payer: params.signer.address,
|
|
839
|
+
amount: chosen.amount,
|
|
840
|
+
network: chosen.network,
|
|
841
|
+
...transaction !== void 0 ? { transaction } : {}
|
|
842
|
+
};
|
|
843
|
+
invokeHookSafely(hooks?.onClientPayment, successEvent);
|
|
844
|
+
} else {
|
|
845
|
+
emitFailure(
|
|
846
|
+
retryResponse.status === 402 ? "settle_rejected" : "http_error",
|
|
847
|
+
retryResponse.status
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
return retryResponse;
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
export { X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, X402_FACILITATOR_ERROR_CODES, authorizationDeadlineFromNow, createCoinbaseFacilitator, createHttpFacilitator, createSelfFacilitator, createX402PaymentSigner, generateAuthorizationNonce, signCancelAuthorization, signReceiveWithAuthorization, signTransferWithAuthorization, wrapFetch };
|
|
855
|
+
//# sourceMappingURL=chunk-3S34WBAW.js.map
|
|
856
|
+
//# sourceMappingURL=chunk-3S34WBAW.js.map
|