kawasekit 0.1.0-beta.4 → 0.1.0-beta.6
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/dist/asset-domain-CpJuDkI2.d.cts +102 -0
- package/dist/asset-domain-CpJuDkI2.d.ts +102 -0
- package/dist/{chunk-Y6AJKMAL.js → chunk-E2EG72U2.js} +102 -176
- package/dist/chunk-E2EG72U2.js.map +1 -0
- package/dist/chunk-E47SIVFY.js +44 -0
- package/dist/chunk-E47SIVFY.js.map +1 -0
- package/dist/chunk-KT7XDT2T.js +209 -0
- package/dist/chunk-KT7XDT2T.js.map +1 -0
- package/dist/{chunk-NRGSI52C.js → chunk-PVUKX6IF.js} +6 -235
- package/dist/chunk-PVUKX6IF.js.map +1 -0
- package/dist/chunk-RUWCCP37.js +76 -0
- package/dist/chunk-RUWCCP37.js.map +1 -0
- package/dist/chunk-UQ7WJY6O.js +43 -0
- package/dist/chunk-UQ7WJY6O.js.map +1 -0
- package/dist/chunk-VPRR3TNA.js +204 -0
- package/dist/chunk-VPRR3TNA.js.map +1 -0
- package/dist/chunk-WMVJNPX2.js +41 -0
- package/dist/chunk-WMVJNPX2.js.map +1 -0
- package/dist/chunk-YMABXRCK.js +125 -0
- package/dist/chunk-YMABXRCK.js.map +1 -0
- package/dist/cli/index.cjs +1 -1
- package/dist/cli/index.js +11 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/{index-CJfDUtpx.d.ts → index-BaAOB0xd.d.ts} +86 -83
- package/dist/{index-CGO7bOx5.d.cts → index-Z6AL1MR_.d.cts} +86 -83
- package/dist/index.cjs +416 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -62
- package/dist/index.d.ts +8 -62
- package/dist/index.js +10 -4
- package/dist/policy/index.cjs +419 -0
- package/dist/policy/index.cjs.map +1 -0
- package/dist/policy/index.d.cts +66 -0
- package/dist/policy/index.d.ts +66 -0
- package/dist/policy/index.js +7 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/signer/index.cjs +360 -0
- package/dist/signer/index.cjs.map +1 -0
- package/dist/signer/index.d.cts +131 -0
- package/dist/signer/index.d.ts +131 -0
- package/dist/signer/index.js +9 -0
- package/dist/signer/index.js.map +1 -0
- package/dist/spending-policy-DZSNHqnD.d.ts +135 -0
- package/dist/spending-policy-DqBRDUxx.d.cts +135 -0
- package/dist/types-IEl-iOIx.d.cts +148 -0
- package/dist/types-IEl-iOIx.d.ts +148 -0
- package/dist/x402/hono/index.cjs.map +1 -1
- package/dist/x402/hono/index.js +4 -2
- package/dist/x402/hono/index.js.map +1 -1
- package/dist/x402/index.cjs +205 -73
- package/dist/x402/index.cjs.map +1 -1
- package/dist/x402/index.d.cts +3 -1
- package/dist/x402/index.d.ts +3 -1
- package/dist/x402/index.js +6 -3
- package/package.json +21 -1
- package/dist/chunk-DGWKPDDQ.js +0 -81
- package/dist/chunk-DGWKPDDQ.js.map +0 -1
- package/dist/chunk-NRGSI52C.js.map +0 -1
- package/dist/chunk-Y6AJKMAL.js.map +0 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Address } from 'viem';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Known-asset registry for {@link createX402PaymentSigner}'s
|
|
5
|
+
* `asset: { kind: "known", id }` discriminated-union branch.
|
|
6
|
+
*
|
|
7
|
+
* kawasekit only ships pinned EIP-712 domain definitions for assets it has
|
|
8
|
+
* verified empirically against the deployed contracts. Adding a new entry
|
|
9
|
+
* here requires citing the source-file + line reference for the contract
|
|
10
|
+
* that owns the `name` / `version` (so the next reviewer can spot-check the
|
|
11
|
+
* claim, the same discipline `docs/THREAT_MODEL.md` §0 demands of any ✅
|
|
12
|
+
* verdict that delegates to an out-of-scope component).
|
|
13
|
+
*
|
|
14
|
+
* @packageDocumentation
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** Known asset identifiers. New entries must update this union AND the table. */
|
|
18
|
+
type KnownAssetId = "jpyc-v2";
|
|
19
|
+
/** Fully-pinned EIP-712 domain for a known asset. */
|
|
20
|
+
interface KnownAssetDomain {
|
|
21
|
+
readonly id: KnownAssetId;
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly version: string;
|
|
24
|
+
readonly verifyingContract: Address;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Look up a known asset's pinned EIP-712 domain by id.
|
|
28
|
+
*
|
|
29
|
+
* @returns The domain, or `undefined` if the id is not in the registry.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { getKnownAssetDomain } from "kawasekit";
|
|
34
|
+
*
|
|
35
|
+
* const jpyc = getKnownAssetDomain("jpyc-v2");
|
|
36
|
+
* if (jpyc === undefined) throw new Error("unreachable");
|
|
37
|
+
* console.log(jpyc.verifyingContract); // 0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
declare function getKnownAssetDomain(id: KnownAssetId): KnownAssetDomain | undefined;
|
|
41
|
+
/** List every known asset id (for diagnostics / error messages). */
|
|
42
|
+
declare function listKnownAssetIds(): readonly KnownAssetId[];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* EIP-712 asset-domain resolution for x402 / EIP-3009 signing.
|
|
46
|
+
*
|
|
47
|
+
* Construction-time pinning of the EIP-712 domain (`name` / `version` /
|
|
48
|
+
* `verifyingContract`) a signer will use. The integrator declares an
|
|
49
|
+
* {@link X402AssetParam} — either a kawasekit-maintained `known` asset or a
|
|
50
|
+
* loud `unsafeOverride` — and {@link resolveAssetParam} resolves it to a pinned
|
|
51
|
+
* {@link ResolvedAsset}. The signer then trusts only this pinned domain and
|
|
52
|
+
* refuses to sign for a mismatched advertised asset (Threat 1.4: misadvertised
|
|
53
|
+
* EIP-712 domain).
|
|
54
|
+
*
|
|
55
|
+
* Token-domain concern, reused by both the x402 signer (`src/x402/client.ts`)
|
|
56
|
+
* and the M6 PolicyGatedSigner (`src/signer/`).
|
|
57
|
+
*
|
|
58
|
+
* @packageDocumentation
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/** EIP-712 token domain `name` / `version` pair. */
|
|
62
|
+
interface X402TokenDomain {
|
|
63
|
+
readonly name: string;
|
|
64
|
+
readonly version: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Asset binding for {@link createX402PaymentSigner} and the M6 PolicyGatedSigner.
|
|
68
|
+
* Required, discriminated.
|
|
69
|
+
*
|
|
70
|
+
* **Default-on whitelist**: integrators MUST declare which asset they intend
|
|
71
|
+
* to sign for. The `known` branch references a kawasekit-maintained
|
|
72
|
+
* whitelist (see `src/tokens/known-assets.ts`); the `unsafeOverride` branch
|
|
73
|
+
* is the deliberate escape hatch for any other asset and is named loudly so
|
|
74
|
+
* it survives a code review. Either way, the signer pins the EIP-712 domain
|
|
75
|
+
* at construction time and refuses to sign if `paymentRequirements.asset`
|
|
76
|
+
* disagrees with the pinned `verifyingContract`.
|
|
77
|
+
*
|
|
78
|
+
* Closes Threat 1.4 (misadvertised EIP-712 domain): the server's advertised
|
|
79
|
+
* `extra.name` / `extra.version` and `asset` are all ignored for signing
|
|
80
|
+
* purposes — the signer trusts only what the integrator declared here.
|
|
81
|
+
*/
|
|
82
|
+
type X402AssetParam = {
|
|
83
|
+
/** Use a kawasekit-maintained pinned EIP-712 domain. */
|
|
84
|
+
readonly kind: "known";
|
|
85
|
+
/** The asset id to pin. See {@link KnownAssetId} for the registry. */
|
|
86
|
+
readonly id: KnownAssetId;
|
|
87
|
+
} | {
|
|
88
|
+
/**
|
|
89
|
+
* Use a caller-supplied EIP-712 domain for an asset NOT on the
|
|
90
|
+
* kawasekit whitelist. The name is deliberately loud — pick this
|
|
91
|
+
* branch only when you have separately audited the contract and its
|
|
92
|
+
* `eip712Domain()` output.
|
|
93
|
+
*/
|
|
94
|
+
readonly kind: "unsafeOverride";
|
|
95
|
+
readonly domain: {
|
|
96
|
+
readonly name: string;
|
|
97
|
+
readonly version: string;
|
|
98
|
+
readonly verifyingContract: Address;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export { type KnownAssetDomain as K, type X402AssetParam as X, type KnownAssetId as a, type X402TokenDomain as b, getKnownAssetDomain as g, listKnownAssetIds as l };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Address } from 'viem';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Known-asset registry for {@link createX402PaymentSigner}'s
|
|
5
|
+
* `asset: { kind: "known", id }` discriminated-union branch.
|
|
6
|
+
*
|
|
7
|
+
* kawasekit only ships pinned EIP-712 domain definitions for assets it has
|
|
8
|
+
* verified empirically against the deployed contracts. Adding a new entry
|
|
9
|
+
* here requires citing the source-file + line reference for the contract
|
|
10
|
+
* that owns the `name` / `version` (so the next reviewer can spot-check the
|
|
11
|
+
* claim, the same discipline `docs/THREAT_MODEL.md` §0 demands of any ✅
|
|
12
|
+
* verdict that delegates to an out-of-scope component).
|
|
13
|
+
*
|
|
14
|
+
* @packageDocumentation
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** Known asset identifiers. New entries must update this union AND the table. */
|
|
18
|
+
type KnownAssetId = "jpyc-v2";
|
|
19
|
+
/** Fully-pinned EIP-712 domain for a known asset. */
|
|
20
|
+
interface KnownAssetDomain {
|
|
21
|
+
readonly id: KnownAssetId;
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly version: string;
|
|
24
|
+
readonly verifyingContract: Address;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Look up a known asset's pinned EIP-712 domain by id.
|
|
28
|
+
*
|
|
29
|
+
* @returns The domain, or `undefined` if the id is not in the registry.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { getKnownAssetDomain } from "kawasekit";
|
|
34
|
+
*
|
|
35
|
+
* const jpyc = getKnownAssetDomain("jpyc-v2");
|
|
36
|
+
* if (jpyc === undefined) throw new Error("unreachable");
|
|
37
|
+
* console.log(jpyc.verifyingContract); // 0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
declare function getKnownAssetDomain(id: KnownAssetId): KnownAssetDomain | undefined;
|
|
41
|
+
/** List every known asset id (for diagnostics / error messages). */
|
|
42
|
+
declare function listKnownAssetIds(): readonly KnownAssetId[];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* EIP-712 asset-domain resolution for x402 / EIP-3009 signing.
|
|
46
|
+
*
|
|
47
|
+
* Construction-time pinning of the EIP-712 domain (`name` / `version` /
|
|
48
|
+
* `verifyingContract`) a signer will use. The integrator declares an
|
|
49
|
+
* {@link X402AssetParam} — either a kawasekit-maintained `known` asset or a
|
|
50
|
+
* loud `unsafeOverride` — and {@link resolveAssetParam} resolves it to a pinned
|
|
51
|
+
* {@link ResolvedAsset}. The signer then trusts only this pinned domain and
|
|
52
|
+
* refuses to sign for a mismatched advertised asset (Threat 1.4: misadvertised
|
|
53
|
+
* EIP-712 domain).
|
|
54
|
+
*
|
|
55
|
+
* Token-domain concern, reused by both the x402 signer (`src/x402/client.ts`)
|
|
56
|
+
* and the M6 PolicyGatedSigner (`src/signer/`).
|
|
57
|
+
*
|
|
58
|
+
* @packageDocumentation
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/** EIP-712 token domain `name` / `version` pair. */
|
|
62
|
+
interface X402TokenDomain {
|
|
63
|
+
readonly name: string;
|
|
64
|
+
readonly version: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Asset binding for {@link createX402PaymentSigner} and the M6 PolicyGatedSigner.
|
|
68
|
+
* Required, discriminated.
|
|
69
|
+
*
|
|
70
|
+
* **Default-on whitelist**: integrators MUST declare which asset they intend
|
|
71
|
+
* to sign for. The `known` branch references a kawasekit-maintained
|
|
72
|
+
* whitelist (see `src/tokens/known-assets.ts`); the `unsafeOverride` branch
|
|
73
|
+
* is the deliberate escape hatch for any other asset and is named loudly so
|
|
74
|
+
* it survives a code review. Either way, the signer pins the EIP-712 domain
|
|
75
|
+
* at construction time and refuses to sign if `paymentRequirements.asset`
|
|
76
|
+
* disagrees with the pinned `verifyingContract`.
|
|
77
|
+
*
|
|
78
|
+
* Closes Threat 1.4 (misadvertised EIP-712 domain): the server's advertised
|
|
79
|
+
* `extra.name` / `extra.version` and `asset` are all ignored for signing
|
|
80
|
+
* purposes — the signer trusts only what the integrator declared here.
|
|
81
|
+
*/
|
|
82
|
+
type X402AssetParam = {
|
|
83
|
+
/** Use a kawasekit-maintained pinned EIP-712 domain. */
|
|
84
|
+
readonly kind: "known";
|
|
85
|
+
/** The asset id to pin. See {@link KnownAssetId} for the registry. */
|
|
86
|
+
readonly id: KnownAssetId;
|
|
87
|
+
} | {
|
|
88
|
+
/**
|
|
89
|
+
* Use a caller-supplied EIP-712 domain for an asset NOT on the
|
|
90
|
+
* kawasekit whitelist. The name is deliberately loud — pick this
|
|
91
|
+
* branch only when you have separately audited the contract and its
|
|
92
|
+
* `eip712Domain()` output.
|
|
93
|
+
*/
|
|
94
|
+
readonly kind: "unsafeOverride";
|
|
95
|
+
readonly domain: {
|
|
96
|
+
readonly name: string;
|
|
97
|
+
readonly version: string;
|
|
98
|
+
readonly verifyingContract: Address;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export { type KnownAssetDomain as K, type X402AssetParam as X, type KnownAssetId as a, type X402TokenDomain as b, getKnownAssetDomain as g, listKnownAssetIds as l };
|
|
@@ -1,132 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { X402_HEADER_PAYMENT_SIGNATURE, encodePaymentSignatureHeader, X402_HEADER_IDEMPOTENCY_KEY, X402_HEADER_PAYMENT_RESPONSE, decodePaymentResponseHeader, X402_HEADER_PAYMENT_REQUIRED, decodePaymentRequiredHeader } from './chunk-PVUKX6IF.js';
|
|
2
|
+
import { invokeHookSafely } from './chunk-LEHWRDVS.js';
|
|
2
3
|
import { X402_VERSION, chainIdToX402Network, x402NetworkToChainId } from './chunk-QHUCU5YX.js';
|
|
4
|
+
import { resolveAssetParam, authorizationDeadlineFromNow, deriveAuthorizationNonce, generateAuthorizationNonce, signTransferWithAuthorization, assertNonBypassable } from './chunk-VPRR3TNA.js';
|
|
5
|
+
import { X402InvalidPayloadError, X402PolicyRejectedError } from './chunk-WMVJNPX2.js';
|
|
6
|
+
import { jpycAbi, JPYC_V2_ADDRESS, JPYC_EIP712_DOMAIN_HINT } from './chunk-KT7XDT2T.js';
|
|
3
7
|
import { getChain, isSupportedChainId } from './chunk-SOTYGX67.js';
|
|
4
|
-
import {
|
|
5
|
-
import { getAddress, keccak256, stringToHex, parseSignature, isAddress, recoverTypedDataAddress } from 'viem';
|
|
8
|
+
import { getAddress, recoverTypedDataAddress, parseSignature, isAddress } from 'viem';
|
|
6
9
|
|
|
7
|
-
var transferWithAuthorizationTypes = {
|
|
8
|
-
TransferWithAuthorization: [
|
|
9
|
-
{ name: "from", type: "address" },
|
|
10
|
-
{ name: "to", type: "address" },
|
|
11
|
-
{ name: "value", type: "uint256" },
|
|
12
|
-
{ name: "validAfter", type: "uint256" },
|
|
13
|
-
{ name: "validBefore", type: "uint256" },
|
|
14
|
-
{ name: "nonce", type: "bytes32" }
|
|
15
|
-
]
|
|
16
|
-
};
|
|
17
|
-
var receiveWithAuthorizationTypes = {
|
|
18
|
-
ReceiveWithAuthorization: [
|
|
19
|
-
{ name: "from", type: "address" },
|
|
20
|
-
{ name: "to", type: "address" },
|
|
21
|
-
{ name: "value", type: "uint256" },
|
|
22
|
-
{ name: "validAfter", type: "uint256" },
|
|
23
|
-
{ name: "validBefore", type: "uint256" },
|
|
24
|
-
{ name: "nonce", type: "bytes32" }
|
|
25
|
-
]
|
|
26
|
-
};
|
|
27
|
-
var cancelAuthorizationTypes = {
|
|
28
|
-
CancelAuthorization: [
|
|
29
|
-
{ name: "authorizer", type: "address" },
|
|
30
|
-
{ name: "nonce", type: "bytes32" }
|
|
31
|
-
]
|
|
32
|
-
};
|
|
33
|
-
function generateAuthorizationNonce() {
|
|
34
|
-
const bytes = new Uint8Array(32);
|
|
35
|
-
crypto.getRandomValues(bytes);
|
|
36
|
-
return `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
37
|
-
}
|
|
38
|
-
var EIP3009_NONCE_DOMAIN_TAG = "kawasekit/eip3009-nonce/1";
|
|
39
|
-
function deriveAuthorizationNonce(input, scope) {
|
|
40
|
-
if (input.idempotencyKey === "") {
|
|
41
|
-
throw new Error("deriveAuthorizationNonce: idempotencyKey must be a non-empty string");
|
|
42
|
-
}
|
|
43
|
-
const preimage = JSON.stringify([
|
|
44
|
-
EIP3009_NONCE_DOMAIN_TAG,
|
|
45
|
-
input.idempotencyKey,
|
|
46
|
-
getAddress(scope.from),
|
|
47
|
-
getAddress(scope.verifyingContract),
|
|
48
|
-
scope.chainId
|
|
49
|
-
]);
|
|
50
|
-
return keccak256(stringToHex(preimage));
|
|
51
|
-
}
|
|
52
|
-
function authorizationDeadlineFromNow(seconds, nowSec) {
|
|
53
|
-
const now = nowSec ?? BigInt(Math.floor(Date.now() / 1e3));
|
|
54
|
-
return now + BigInt(seconds);
|
|
55
|
-
}
|
|
56
|
-
function requireSignTypedData(account) {
|
|
57
|
-
if (!account.signTypedData) {
|
|
58
|
-
throw new Error(
|
|
59
|
-
`Account ${account.address} cannot sign typed data \u2014 pass a LocalAccount or a JsonRpcAccount bound to a WalletClient.`
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
return account.signTypedData.bind(account);
|
|
63
|
-
}
|
|
64
|
-
function assertSignerMatches(account, expectedFrom, role) {
|
|
65
|
-
if (getAddress(account.address) !== getAddress(expectedFrom)) {
|
|
66
|
-
throw new Error(
|
|
67
|
-
`EIP-3009 ${role} signature must come from \`${role === "cancel" ? "authorizer" : "from"}\`: account is ${account.address}, message says ${expectedFrom}.`
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
async function signTransferWithAuthorization(account, domain, message) {
|
|
72
|
-
assertSignerMatches(account, message.from, "transfer");
|
|
73
|
-
const sign = requireSignTypedData(account);
|
|
74
|
-
const signature = await sign({
|
|
75
|
-
domain,
|
|
76
|
-
types: transferWithAuthorizationTypes,
|
|
77
|
-
primaryType: "TransferWithAuthorization",
|
|
78
|
-
message
|
|
79
|
-
});
|
|
80
|
-
return splitAuthorization(signature, domain, message);
|
|
81
|
-
}
|
|
82
|
-
async function signReceiveWithAuthorization(account, domain, message) {
|
|
83
|
-
assertSignerMatches(account, message.from, "receive");
|
|
84
|
-
const sign = requireSignTypedData(account);
|
|
85
|
-
const signature = await sign({
|
|
86
|
-
domain,
|
|
87
|
-
types: receiveWithAuthorizationTypes,
|
|
88
|
-
primaryType: "ReceiveWithAuthorization",
|
|
89
|
-
message
|
|
90
|
-
});
|
|
91
|
-
return splitAuthorization(signature, domain, message);
|
|
92
|
-
}
|
|
93
|
-
async function signCancelAuthorization(account, domain, message) {
|
|
94
|
-
assertSignerMatches(account, message.authorizer, "cancel");
|
|
95
|
-
const sign = requireSignTypedData(account);
|
|
96
|
-
const signature = await sign({
|
|
97
|
-
domain,
|
|
98
|
-
types: cancelAuthorizationTypes,
|
|
99
|
-
primaryType: "CancelAuthorization",
|
|
100
|
-
message
|
|
101
|
-
});
|
|
102
|
-
return splitAuthorization(signature, domain, message);
|
|
103
|
-
}
|
|
104
|
-
function splitAuthorization(signature, domain, message) {
|
|
105
|
-
const parsed = parseSignature(signature);
|
|
106
|
-
const v = parsed.v !== void 0 ? Number(parsed.v) : (parsed.yParity ?? 0) + 27;
|
|
107
|
-
return {
|
|
108
|
-
signature,
|
|
109
|
-
v,
|
|
110
|
-
r: parsed.r,
|
|
111
|
-
s: parsed.s,
|
|
112
|
-
domain,
|
|
113
|
-
message
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
var KNOWN_ASSETS = [
|
|
117
|
-
{
|
|
118
|
-
id: "jpyc-v2",
|
|
119
|
-
name: JPYC_EIP712_DOMAIN_HINT.name,
|
|
120
|
-
version: JPYC_EIP712_DOMAIN_HINT.version,
|
|
121
|
-
verifyingContract: getAddress(JPYC_V2_ADDRESS)
|
|
122
|
-
}
|
|
123
|
-
];
|
|
124
|
-
function getKnownAssetDomain(id) {
|
|
125
|
-
return KNOWN_ASSETS.find((entry) => entry.id === id);
|
|
126
|
-
}
|
|
127
|
-
function listKnownAssetIds() {
|
|
128
|
-
return KNOWN_ASSETS.map((entry) => entry.id);
|
|
129
|
-
}
|
|
130
10
|
var X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS = 300;
|
|
131
11
|
var UINT256_MAX = (1n << 256n) - 1n;
|
|
132
12
|
var UINT256_DECIMAL = /^(0|[1-9][0-9]*)$/;
|
|
@@ -155,53 +35,6 @@ function assertAddress(value, field) {
|
|
|
155
35
|
}
|
|
156
36
|
return value;
|
|
157
37
|
}
|
|
158
|
-
function resolveAssetParam(asset) {
|
|
159
|
-
if (asset.kind === "known") {
|
|
160
|
-
const entry = getKnownAssetDomain(asset.id);
|
|
161
|
-
if (entry === void 0) {
|
|
162
|
-
throw new X402InvalidConfigError(
|
|
163
|
-
"asset.id",
|
|
164
|
-
`unknown asset id ${JSON.stringify(asset.id)}. Supported: ${listKnownAssetIds().map((id) => JSON.stringify(id)).join(", ")}.`
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
return {
|
|
168
|
-
name: entry.name,
|
|
169
|
-
version: entry.version,
|
|
170
|
-
verifyingContract: entry.verifyingContract
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
if (asset.kind === "unsafeOverride") {
|
|
174
|
-
const { domain } = asset;
|
|
175
|
-
if (typeof domain.name !== "string" || domain.name === "") {
|
|
176
|
-
throw new X402InvalidConfigError(
|
|
177
|
-
"asset.domain.name",
|
|
178
|
-
"`unsafeOverride.domain.name` must be a non-empty string"
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
if (typeof domain.version !== "string" || domain.version === "") {
|
|
182
|
-
throw new X402InvalidConfigError(
|
|
183
|
-
"asset.domain.version",
|
|
184
|
-
"`unsafeOverride.domain.version` must be a non-empty string"
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
if (!isAddress(domain.verifyingContract, { strict: false })) {
|
|
188
|
-
throw new X402InvalidConfigError(
|
|
189
|
-
"asset.domain.verifyingContract",
|
|
190
|
-
`\`unsafeOverride.domain.verifyingContract\` must be a valid address, got ${JSON.stringify(domain.verifyingContract)}`
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
return {
|
|
194
|
-
name: domain.name,
|
|
195
|
-
version: domain.version,
|
|
196
|
-
verifyingContract: getAddress(domain.verifyingContract)
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
const exhaustive = asset;
|
|
200
|
-
throw new X402InvalidConfigError(
|
|
201
|
-
"asset.kind",
|
|
202
|
-
`unsupported kind ${JSON.stringify(exhaustive.kind)}. Expected "known" or "unsafeOverride".`
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
38
|
function validateRequirements(requirements) {
|
|
206
39
|
if (requirements.scheme !== "exact") {
|
|
207
40
|
throw new X402InvalidPayloadError(
|
|
@@ -231,6 +64,9 @@ function validateRequirements(requirements) {
|
|
|
231
64
|
return { chainId, value, asset, payTo };
|
|
232
65
|
}
|
|
233
66
|
function createX402PaymentSigner(params) {
|
|
67
|
+
if (params.signer !== void 0) {
|
|
68
|
+
return createSignerBackedX402PaymentSigner(params);
|
|
69
|
+
}
|
|
234
70
|
const { account, network } = params;
|
|
235
71
|
const defaultLifetimeSeconds = params.defaultLifetimeSeconds ?? X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS;
|
|
236
72
|
if (defaultLifetimeSeconds <= 0) {
|
|
@@ -336,6 +172,96 @@ function createX402PaymentSigner(params) {
|
|
|
336
172
|
}
|
|
337
173
|
};
|
|
338
174
|
}
|
|
175
|
+
function createSignerBackedX402PaymentSigner(params) {
|
|
176
|
+
const { signer, network } = params;
|
|
177
|
+
const defaultLifetimeSeconds = params.defaultLifetimeSeconds ?? X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS;
|
|
178
|
+
if (defaultLifetimeSeconds <= 0) {
|
|
179
|
+
throw new X402InvalidPayloadError(
|
|
180
|
+
"X402PaymentSignerConfig",
|
|
181
|
+
`\`defaultLifetimeSeconds\` must be positive, got ${defaultLifetimeSeconds}`
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
if (params.requireEnforcement !== void 0) {
|
|
185
|
+
assertNonBypassable(signer);
|
|
186
|
+
}
|
|
187
|
+
const pinnedDomain = resolveAssetParam(params.asset);
|
|
188
|
+
const from = signer.from;
|
|
189
|
+
return {
|
|
190
|
+
address: from,
|
|
191
|
+
async sign(signParams) {
|
|
192
|
+
const { paymentRequirements } = signParams;
|
|
193
|
+
const { chainId, value, asset, payTo } = validateRequirements(paymentRequirements);
|
|
194
|
+
const chain = getChain(chainId);
|
|
195
|
+
if (network === "mainnet" && chain.isTestnet) {
|
|
196
|
+
throw new X402InvalidPayloadError(
|
|
197
|
+
"PaymentRequirements",
|
|
198
|
+
`signer was configured for network="mainnet" but requirements.network="${paymentRequirements.network}" (chainId ${chainId}) is a testnet`
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
if (network === "testnet" && !chain.isTestnet) {
|
|
202
|
+
throw new X402InvalidPayloadError(
|
|
203
|
+
"PaymentRequirements",
|
|
204
|
+
`signer was configured for network="testnet" but requirements.network="${paymentRequirements.network}" (chainId ${chainId}) is a mainnet \u2014 refusing to sign payment for real funds`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (getAddress(asset) !== pinnedDomain.verifyingContract) {
|
|
208
|
+
throw new X402InvalidPayloadError(
|
|
209
|
+
"PaymentRequirements",
|
|
210
|
+
`requirements.asset (${getAddress(asset)}) does not match the signer's pinned verifyingContract (${pinnedDomain.verifyingContract}) \u2014 refusing to sign for an asset the signer was not configured to handle`
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
const lifetime = Math.min(defaultLifetimeSeconds, paymentRequirements.maxTimeoutSeconds);
|
|
214
|
+
const validAfter = signParams.validAfter ?? 0n;
|
|
215
|
+
const validBefore = signParams.validBefore ?? authorizationDeadlineFromNow(lifetime);
|
|
216
|
+
if (validBefore <= validAfter) {
|
|
217
|
+
throw new X402InvalidPayloadError(
|
|
218
|
+
"PaymentRequirements",
|
|
219
|
+
`\`validBefore\` (${validBefore}) must be greater than \`validAfter\` (${validAfter})`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
const nonce = signParams.idempotencyKey !== void 0 ? deriveAuthorizationNonce(
|
|
223
|
+
{ idempotencyKey: signParams.idempotencyKey },
|
|
224
|
+
{ from, verifyingContract: pinnedDomain.verifyingContract, chainId }
|
|
225
|
+
) : generateAuthorizationNonce();
|
|
226
|
+
const intent = {
|
|
227
|
+
token: pinnedDomain.verifyingContract,
|
|
228
|
+
chainId,
|
|
229
|
+
from,
|
|
230
|
+
to: payTo,
|
|
231
|
+
value,
|
|
232
|
+
validAfter,
|
|
233
|
+
validBefore,
|
|
234
|
+
nonce
|
|
235
|
+
};
|
|
236
|
+
const signResult = await signer.sign(intent);
|
|
237
|
+
if (!signResult.ok) {
|
|
238
|
+
throw new X402PolicyRejectedError(signResult.rejection);
|
|
239
|
+
}
|
|
240
|
+
const payload = {
|
|
241
|
+
signature: signResult.signature,
|
|
242
|
+
authorization: {
|
|
243
|
+
from,
|
|
244
|
+
to: payTo,
|
|
245
|
+
value: value.toString(),
|
|
246
|
+
validAfter: validAfter.toString(),
|
|
247
|
+
validBefore: validBefore.toString(),
|
|
248
|
+
nonce
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
const result = signParams.resource ? {
|
|
252
|
+
x402Version: X402_VERSION,
|
|
253
|
+
resource: signParams.resource,
|
|
254
|
+
accepted: paymentRequirements,
|
|
255
|
+
payload: { ...payload }
|
|
256
|
+
} : {
|
|
257
|
+
x402Version: X402_VERSION,
|
|
258
|
+
accepted: paymentRequirements,
|
|
259
|
+
payload: { ...payload }
|
|
260
|
+
};
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
339
265
|
var X402_FACILITATOR_ERROR_CODES = {
|
|
340
266
|
insufficient_funds: "insufficient_funds",
|
|
341
267
|
invalid_exact_evm_payload_authorization_valid_after: "invalid_exact_evm_payload_authorization_valid_after",
|
|
@@ -958,6 +884,6 @@ function wrapFetch(params) {
|
|
|
958
884
|
};
|
|
959
885
|
}
|
|
960
886
|
|
|
961
|
-
export { X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, X402_FACILITATOR_ERROR_CODES,
|
|
962
|
-
//# sourceMappingURL=chunk-
|
|
963
|
-
//# sourceMappingURL=chunk-
|
|
887
|
+
export { X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, X402_FACILITATOR_ERROR_CODES, createCoinbaseFacilitator, createHttpFacilitator, createSelfFacilitator, createX402PaymentSigner, deriveReceiptTimeoutMs, wrapFetch };
|
|
888
|
+
//# sourceMappingURL=chunk-E2EG72U2.js.map
|
|
889
|
+
//# sourceMappingURL=chunk-E2EG72U2.js.map
|