@drm3/sdk 0.1.2
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 +75 -0
- package/README.md +426 -0
- package/bin/drm3.js +255 -0
- package/dist/alerts-bell.d.ts +7 -0
- package/dist/alerts-bell.d.ts.map +1 -0
- package/dist/alerts-bell.js +118 -0
- package/dist/alerts-bell.js.map +1 -0
- package/dist/alerts-fetch.d.ts +41 -0
- package/dist/alerts-fetch.d.ts.map +1 -0
- package/dist/alerts-fetch.js +60 -0
- package/dist/alerts-fetch.js.map +1 -0
- package/dist/alerts-styles.d.ts +4 -0
- package/dist/alerts-styles.d.ts.map +1 -0
- package/dist/alerts-styles.js +49 -0
- package/dist/alerts-styles.js.map +1 -0
- package/dist/alerts.d.ts +3 -0
- package/dist/alerts.d.ts.map +1 -0
- package/dist/alerts.global.js +206 -0
- package/dist/alerts.global.text.js +2 -0
- package/dist/alerts.js +21 -0
- package/dist/alerts.js.map +1 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +117 -0
- package/dist/index.js.map +1 -0
- package/dist/keys-canonical.d.ts +7 -0
- package/dist/keys-canonical.d.ts.map +1 -0
- package/dist/keys-canonical.js +57 -0
- package/dist/keys-canonical.js.map +1 -0
- package/dist/keys-generate.d.ts +39 -0
- package/dist/keys-generate.d.ts.map +1 -0
- package/dist/keys-generate.js +39 -0
- package/dist/keys-generate.js.map +1 -0
- package/dist/keys-verify.d.ts +62 -0
- package/dist/keys-verify.d.ts.map +1 -0
- package/dist/keys-verify.js +68 -0
- package/dist/keys-verify.js.map +1 -0
- package/dist/keys.d.ts +4 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +22 -0
- package/dist/keys.js.map +1 -0
- package/dist/meter/adapter.d.ts +35 -0
- package/dist/meter/adapter.d.ts.map +1 -0
- package/dist/meter/adapter.js +0 -0
- package/dist/meter/adapter.js.map +1 -0
- package/dist/meter/cascade.d.ts +56 -0
- package/dist/meter/cascade.d.ts.map +1 -0
- package/dist/meter/cascade.js +64 -0
- package/dist/meter/cascade.js.map +1 -0
- package/dist/meter/client.d.ts +78 -0
- package/dist/meter/client.d.ts.map +1 -0
- package/dist/meter/client.js +84 -0
- package/dist/meter/client.js.map +1 -0
- package/dist/meter/core.d.ts +37 -0
- package/dist/meter/core.d.ts.map +1 -0
- package/dist/meter/core.js +49 -0
- package/dist/meter/core.js.map +1 -0
- package/dist/meter/gate-client.d.ts +94 -0
- package/dist/meter/gate-client.d.ts.map +1 -0
- package/dist/meter/gate-client.js +77 -0
- package/dist/meter/gate-client.js.map +1 -0
- package/dist/meter/gate-decide.d.ts +61 -0
- package/dist/meter/gate-decide.d.ts.map +1 -0
- package/dist/meter/gate-decide.js +54 -0
- package/dist/meter/gate-decide.js.map +1 -0
- package/dist/meter/gate.d.ts +10 -0
- package/dist/meter/gate.d.ts.map +1 -0
- package/dist/meter/gate.js +10 -0
- package/dist/meter/gate.js.map +1 -0
- package/dist/meter/index.d.ts +28 -0
- package/dist/meter/index.d.ts.map +1 -0
- package/dist/meter/index.js +28 -0
- package/dist/meter/index.js.map +1 -0
- package/dist/meter/meters-buckets.d.ts +56 -0
- package/dist/meter/meters-buckets.d.ts.map +1 -0
- package/dist/meter/meters-buckets.js +111 -0
- package/dist/meter/meters-buckets.js.map +1 -0
- package/dist/meter/meters-charge.d.ts +13 -0
- package/dist/meter/meters-charge.d.ts.map +1 -0
- package/dist/meter/meters-charge.js +76 -0
- package/dist/meter/meters-charge.js.map +1 -0
- package/dist/meter/meters.d.ts +63 -0
- package/dist/meter/meters.d.ts.map +1 -0
- package/dist/meter/meters.js +44 -0
- package/dist/meter/meters.js.map +1 -0
- package/dist/meter/plans.d.ts +63 -0
- package/dist/meter/plans.d.ts.map +1 -0
- package/dist/meter/plans.js +114 -0
- package/dist/meter/plans.js.map +1 -0
- package/dist/meter/pricebook.d.ts +32 -0
- package/dist/meter/pricebook.d.ts.map +1 -0
- package/dist/meter/pricebook.js +38 -0
- package/dist/meter/pricebook.js.map +1 -0
- package/dist/meter/resolve.d.ts +103 -0
- package/dist/meter/resolve.d.ts.map +1 -0
- package/dist/meter/resolve.js +100 -0
- package/dist/meter/resolve.js.map +1 -0
- package/dist/meter/sink.d.ts +26 -0
- package/dist/meter/sink.d.ts.map +1 -0
- package/dist/meter/sink.js +9 -0
- package/dist/meter/sink.js.map +1 -0
- package/dist/meter/sql/d1.d.ts +32 -0
- package/dist/meter/sql/d1.d.ts.map +1 -0
- package/dist/meter/sql/d1.js +41 -0
- package/dist/meter/sql/d1.js.map +1 -0
- package/dist/meter/sql/driver.d.ts +34 -0
- package/dist/meter/sql/driver.d.ts.map +1 -0
- package/dist/meter/sql/driver.js +17 -0
- package/dist/meter/sql/driver.js.map +1 -0
- package/dist/meter/sql/postgres.d.ts +23 -0
- package/dist/meter/sql/postgres.d.ts.map +1 -0
- package/dist/meter/sql/postgres.js +36 -0
- package/dist/meter/sql/postgres.js.map +1 -0
- package/dist/meter/sql/schema.d.ts +13 -0
- package/dist/meter/sql/schema.d.ts.map +1 -0
- package/dist/meter/sql/schema.js +32 -0
- package/dist/meter/sql/schema.js.map +1 -0
- package/dist/meter/sql/sql-adapter.d.ts +36 -0
- package/dist/meter/sql/sql-adapter.d.ts.map +1 -0
- package/dist/meter/sql/sql-adapter.js +124 -0
- package/dist/meter/sql/sql-adapter.js.map +1 -0
- package/dist/meter/sql/statements.d.ts +30 -0
- package/dist/meter/sql/statements.d.ts.map +1 -0
- package/dist/meter/sql/statements.js +24 -0
- package/dist/meter/sql/statements.js.map +1 -0
- package/dist/meter/types.d.ts +48 -0
- package/dist/meter/types.d.ts.map +1 -0
- package/dist/meter/types.js +8 -0
- package/dist/meter/types.js.map +1 -0
- package/dist/meter/units.d.ts +33 -0
- package/dist/meter/units.d.ts.map +1 -0
- package/dist/meter/units.js +45 -0
- package/dist/meter/units.js.map +1 -0
- package/dist/meter/wallet-buckets.d.ts +63 -0
- package/dist/meter/wallet-buckets.d.ts.map +1 -0
- package/dist/meter/wallet-buckets.js +131 -0
- package/dist/meter/wallet-buckets.js.map +1 -0
- package/dist/meter/wallet-charge.d.ts +15 -0
- package/dist/meter/wallet-charge.d.ts.map +1 -0
- package/dist/meter/wallet-charge.js +64 -0
- package/dist/meter/wallet-charge.js.map +1 -0
- package/dist/meter/wallet.d.ts +68 -0
- package/dist/meter/wallet.d.ts.map +1 -0
- package/dist/meter/wallet.js +47 -0
- package/dist/meter/wallet.js.map +1 -0
- package/dist/receipts-api.d.ts +5 -0
- package/dist/receipts-api.d.ts.map +1 -0
- package/dist/receipts-api.js +117 -0
- package/dist/receipts-api.js.map +1 -0
- package/dist/receipts-chain.d.ts +3 -0
- package/dist/receipts-chain.d.ts.map +1 -0
- package/dist/receipts-chain.js +121 -0
- package/dist/receipts-chain.js.map +1 -0
- package/dist/receipts-modal.d.ts +14 -0
- package/dist/receipts-modal.d.ts.map +1 -0
- package/dist/receipts-modal.js +100 -0
- package/dist/receipts-modal.js.map +1 -0
- package/dist/receipts-registry.d.ts +4 -0
- package/dist/receipts-registry.d.ts.map +1 -0
- package/dist/receipts-registry.js +54 -0
- package/dist/receipts-registry.js.map +1 -0
- package/dist/receipts-render.d.ts +9 -0
- package/dist/receipts-render.d.ts.map +1 -0
- package/dist/receipts-render.js +83 -0
- package/dist/receipts-render.js.map +1 -0
- package/dist/receipts-types.d.ts +61 -0
- package/dist/receipts-types.d.ts.map +1 -0
- package/dist/receipts-types.js +12 -0
- package/dist/receipts-types.js.map +1 -0
- package/dist/receipts-ui.d.ts +10 -0
- package/dist/receipts-ui.d.ts.map +1 -0
- package/dist/receipts-ui.js +103 -0
- package/dist/receipts-ui.js.map +1 -0
- package/dist/receipts-verify.d.ts +8 -0
- package/dist/receipts-verify.d.ts.map +1 -0
- package/dist/receipts-verify.js +113 -0
- package/dist/receipts-verify.js.map +1 -0
- package/dist/receipts.d.ts +9 -0
- package/dist/receipts.d.ts.map +1 -0
- package/dist/receipts.global.js +587 -0
- package/dist/receipts.global.text.js +2 -0
- package/dist/receipts.js +28 -0
- package/dist/receipts.js.map +1 -0
- package/dist/sso/index.d.ts +4 -0
- package/dist/sso/index.d.ts.map +1 -0
- package/dist/sso/index.js +10 -0
- package/dist/sso/index.js.map +1 -0
- package/dist/sso/jwt.d.ts +29 -0
- package/dist/sso/jwt.d.ts.map +1 -0
- package/dist/sso/jwt.js +73 -0
- package/dist/sso/jwt.js.map +1 -0
- package/dist/sso/launch.d.ts +70 -0
- package/dist/sso/launch.d.ts.map +1 -0
- package/dist/sso/launch.js +75 -0
- package/dist/sso/launch.js.map +1 -0
- package/dist/sso/revocation.d.ts +23 -0
- package/dist/sso/revocation.d.ts.map +1 -0
- package/dist/sso/revocation.js +53 -0
- package/dist/sso/revocation.js.map +1 -0
- package/dist/switcher.d.ts +22 -0
- package/dist/switcher.d.ts.map +1 -0
- package/dist/switcher.js +174 -0
- package/dist/switcher.js.map +1 -0
- package/dist/x402/chain.d.ts +49 -0
- package/dist/x402/chain.d.ts.map +1 -0
- package/dist/x402/chain.js +33 -0
- package/dist/x402/chain.js.map +1 -0
- package/dist/x402/crypto.d.ts +25 -0
- package/dist/x402/crypto.d.ts.map +1 -0
- package/dist/x402/crypto.js +74 -0
- package/dist/x402/crypto.js.map +1 -0
- package/dist/x402/eip712.d.ts +20 -0
- package/dist/x402/eip712.d.ts.map +1 -0
- package/dist/x402/eip712.js +49 -0
- package/dist/x402/eip712.js.map +1 -0
- package/dist/x402/envelope.d.ts +45 -0
- package/dist/x402/envelope.d.ts.map +1 -0
- package/dist/x402/envelope.js +50 -0
- package/dist/x402/envelope.js.map +1 -0
- package/dist/x402/index.d.ts +41 -0
- package/dist/x402/index.d.ts.map +1 -0
- package/dist/x402/index.js +41 -0
- package/dist/x402/index.js.map +1 -0
- package/dist/x402/verify.d.ts +51 -0
- package/dist/x402/verify.d.ts.map +1 -0
- package/dist/x402/verify.js +110 -0
- package/dist/x402/verify.js.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @drm3/sdk/x402 - the ONE shared DRM3 x402 payment gateway core.
|
|
3
|
+
*
|
|
4
|
+
* x402 agent micropayments (https://www.x402.org) - the "exact" scheme on Base.
|
|
5
|
+
* This is the studio model applied to x402: like one Stripe is one gateway for
|
|
6
|
+
* every checkout, this is one x402 gateway library for every DRM3 app. Every app
|
|
7
|
+
* (except MorScan, which stays its own animal with its own wallet + commerce
|
|
8
|
+
* seam) imports THIS to advertise a 402 and verify the signed EIP-3009 payment
|
|
9
|
+
* that follows, and every app points at the ONE shared DRM3 x402 gateway wallet
|
|
10
|
+
* (the funded `X402_PAY_TO`). The payTo, the price, and the storage (the replay
|
|
11
|
+
* gate / settlement ledger) are the caller's app-specific config; the crypto,
|
|
12
|
+
* the verification, and the 402 envelope live here, once.
|
|
13
|
+
*
|
|
14
|
+
* What this module is:
|
|
15
|
+
* - the secp256k1 / keccak256 primitives (`keccak256`, `ecrecover`, hex helpers),
|
|
16
|
+
* - the EIP-712 / EIP-3009 `TransferWithAuthorization` digest + full server-side
|
|
17
|
+
* verification of an `X-PAYMENT` header (`verifyX402Payment`), and
|
|
18
|
+
* - the spec-shaped 402 envelope + offers-menu builder (`x402Requirements`,
|
|
19
|
+
* `x402Body`).
|
|
20
|
+
*
|
|
21
|
+
* What this module is NOT: it holds no signing key, touches no database, and
|
|
22
|
+
* broadcasts nothing on-chain. `verifyX402Payment` here is pure and synchronous
|
|
23
|
+
* (envelope structure, scheme/network, payTo, amount, validity window, and the
|
|
24
|
+
* EIP-712 signature recovering the payer). The nonce-replay gate, the per-payer
|
|
25
|
+
* abuse cap, and settlement are storage-specific and stay in the calling app
|
|
26
|
+
* (Newsboy runs them against Postgres, for example). The verification here is
|
|
27
|
+
* byte-identical to MorScan's reference implementation: DO NOT relax any check.
|
|
28
|
+
*
|
|
29
|
+
* Zero runtime deps beyond @noble; Workers, Bun, and Node.
|
|
30
|
+
*
|
|
31
|
+
* This file is a thin barrel: the implementation lives in sibling modules split
|
|
32
|
+
* by concern - `crypto.ts` (secp/keccak/hex), `chain.ts` (asset/chain config),
|
|
33
|
+
* `eip712.ts` (the TransferWithAuthorization digest), `envelope.ts` (the 402
|
|
34
|
+
* envelope), and `verify.ts` (X-PAYMENT decoding + verification).
|
|
35
|
+
*/
|
|
36
|
+
export { bytesToBigInt, bytesToHex, ecrecover, hexToBytes, keccak256 } from "./crypto.js";
|
|
37
|
+
export { BASE_CHAIN_ID, BASE_NETWORK, DEFAULT_GRACE_SECONDS, DEFAULT_MAX_TIMEOUT_SECONDS, USDC_DOMAIN_NAME, USDC_DOMAIN_VERSION, X402_ASSET_USDC_BASE, } from "./chain.js";
|
|
38
|
+
export { transferAuthDigest } from "./eip712.js";
|
|
39
|
+
export { x402Body, x402Requirements, } from "./envelope.js";
|
|
40
|
+
export { decodePaymentHeader, verifyX402Payment, } from "./verify.js";
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/x402/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,2BAA2B,EAC3B,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,GAErB,MAAM,YAAY,CAAC;AACpB,OAAO,EAA0B,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAGL,QAAQ,EACR,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,mBAAmB,EAInB,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @drm3/sdk/x402 - X-PAYMENT decoding + full server-side verification.
|
|
3
|
+
*
|
|
4
|
+
* `verifyX402Payment` is pure and synchronous: envelope structure,
|
|
5
|
+
* scheme/network, payTo, amount, validity window, and the EIP-712 signature
|
|
6
|
+
* recovering the payer. It holds no key, touches no database, and broadcasts
|
|
7
|
+
* nothing on-chain. The nonce-replay gate, per-payer cap, and settlement are
|
|
8
|
+
* storage-specific and stay in the calling app. Byte-identical to MorScan's
|
|
9
|
+
* reference implementation: DO NOT relax any check.
|
|
10
|
+
*/
|
|
11
|
+
import { type X402Authorization } from "./eip712.js";
|
|
12
|
+
import type { X402GatewayConfig } from "./envelope.js";
|
|
13
|
+
export interface X402Payment {
|
|
14
|
+
signature: string;
|
|
15
|
+
authorization: X402Authorization;
|
|
16
|
+
}
|
|
17
|
+
export interface DecodedPaymentHeader {
|
|
18
|
+
x402Version?: number;
|
|
19
|
+
scheme?: string;
|
|
20
|
+
network?: string;
|
|
21
|
+
payload?: X402Payment;
|
|
22
|
+
}
|
|
23
|
+
/** Decode the base64 X-PAYMENT header. Returns null when malformed. */
|
|
24
|
+
export declare function decodePaymentHeader(header: string): DecodedPaymentHeader | null;
|
|
25
|
+
export type X402VerifyResult = {
|
|
26
|
+
ok: true;
|
|
27
|
+
payment: X402Payment;
|
|
28
|
+
payer: string;
|
|
29
|
+
} | {
|
|
30
|
+
ok: false;
|
|
31
|
+
error: string;
|
|
32
|
+
};
|
|
33
|
+
/** Config for `verifyX402Payment`: the gateway (payTo + price) plus optional chain overrides + grace. */
|
|
34
|
+
export interface X402VerifyConfig extends X402GatewayConfig {
|
|
35
|
+
/** In-flight grace (seconds) subtracted from the near-expiry check. Default 6n. */
|
|
36
|
+
graceSeconds?: bigint;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Full CRYPTOGRAPHIC verification of an X-PAYMENT header: envelope structure,
|
|
40
|
+
* scheme/network, payTo, amount, validity window, and the EIP-712 signature
|
|
41
|
+
* recovering the payer. The signature is bound to the asset + chain by the
|
|
42
|
+
* EIP-712 domain (verifyingContract + chainId), so a signature for any other
|
|
43
|
+
* asset or chain cannot verify.
|
|
44
|
+
*
|
|
45
|
+
* This is pure and synchronous: it does NOT check nonce-replay or any per-payer
|
|
46
|
+
* cap - those are storage-specific and belong to the caller (run them against
|
|
47
|
+
* your ledger AFTER this returns `ok`, e.g. a UNIQUE(payer, nonce) gate). On
|
|
48
|
+
* success returns the decoded payment and the lowercase payer address.
|
|
49
|
+
*/
|
|
50
|
+
export declare function verifyX402Payment(header: string, config: X402VerifyConfig): X402VerifyResult;
|
|
51
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/x402/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,KAAK,iBAAiB,EAAsB,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAIvD,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,iBAAiB,CAAC;CAClC;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,uEAAuE;AACvE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAQ/E;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhH,yGAAyG;AACzG,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD,mFAAmF;IACnF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAoE5F"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @drm3/sdk/x402 - X-PAYMENT decoding + full server-side verification.
|
|
3
|
+
*
|
|
4
|
+
* `verifyX402Payment` is pure and synchronous: envelope structure,
|
|
5
|
+
* scheme/network, payTo, amount, validity window, and the EIP-712 signature
|
|
6
|
+
* recovering the payer. It holds no key, touches no database, and broadcasts
|
|
7
|
+
* nothing on-chain. The nonce-replay gate, per-payer cap, and settlement are
|
|
8
|
+
* storage-specific and stay in the calling app. Byte-identical to MorScan's
|
|
9
|
+
* reference implementation: DO NOT relax any check.
|
|
10
|
+
*/
|
|
11
|
+
import { DEFAULT_GRACE_SECONDS, resolveChain } from "./chain.js";
|
|
12
|
+
import { ecrecover } from "./crypto.js";
|
|
13
|
+
import { transferAuthDigest } from "./eip712.js";
|
|
14
|
+
/** Decode the base64 X-PAYMENT header. Returns null when malformed. */
|
|
15
|
+
export function decodePaymentHeader(header) {
|
|
16
|
+
try {
|
|
17
|
+
const json = atob(header.trim());
|
|
18
|
+
const parsed = JSON.parse(json);
|
|
19
|
+
return parsed;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Full CRYPTOGRAPHIC verification of an X-PAYMENT header: envelope structure,
|
|
27
|
+
* scheme/network, payTo, amount, validity window, and the EIP-712 signature
|
|
28
|
+
* recovering the payer. The signature is bound to the asset + chain by the
|
|
29
|
+
* EIP-712 domain (verifyingContract + chainId), so a signature for any other
|
|
30
|
+
* asset or chain cannot verify.
|
|
31
|
+
*
|
|
32
|
+
* This is pure and synchronous: it does NOT check nonce-replay or any per-payer
|
|
33
|
+
* cap - those are storage-specific and belong to the caller (run them against
|
|
34
|
+
* your ledger AFTER this returns `ok`, e.g. a UNIQUE(payer, nonce) gate). On
|
|
35
|
+
* success returns the decoded payment and the lowercase payer address.
|
|
36
|
+
*/
|
|
37
|
+
export function verifyX402Payment(header, config) {
|
|
38
|
+
const chain = resolveChain(config);
|
|
39
|
+
const decoded = decodePaymentHeader(header);
|
|
40
|
+
if (!decoded || !decoded.payload?.authorization || !decoded.payload.signature) {
|
|
41
|
+
return {
|
|
42
|
+
ok: false,
|
|
43
|
+
error: "malformed X-PAYMENT header (expected base64 JSON with payload.signature + payload.authorization)",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (decoded.x402Version !== 1)
|
|
47
|
+
return { ok: false, error: "unsupported x402Version (expected 1)" };
|
|
48
|
+
if (decoded.scheme !== "exact")
|
|
49
|
+
return { ok: false, error: "unsupported scheme (expected exact)" };
|
|
50
|
+
if (decoded.network !== chain.network)
|
|
51
|
+
return { ok: false, error: `unsupported network (expected ${chain.network})` };
|
|
52
|
+
const p = decoded.payload;
|
|
53
|
+
const a = p.authorization;
|
|
54
|
+
const isAddr = (s) => /^0x[0-9a-fA-F]{40}$/.test(s || "");
|
|
55
|
+
if (!isAddr(a.from) || !isAddr(a.to))
|
|
56
|
+
return { ok: false, error: "invalid from/to address" };
|
|
57
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(a.nonce || ""))
|
|
58
|
+
return { ok: false, error: "invalid nonce (expected bytes32 hex)" };
|
|
59
|
+
// payTo must be OUR configured address.
|
|
60
|
+
if (a.to.toLowerCase() !== config.payTo.toLowerCase()) {
|
|
61
|
+
return { ok: false, error: "authorization.to does not match required payTo" };
|
|
62
|
+
}
|
|
63
|
+
// Amount: the exact scheme pays the advertised price.
|
|
64
|
+
let value;
|
|
65
|
+
try {
|
|
66
|
+
value = BigInt(a.value);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return { ok: false, error: "invalid value" };
|
|
70
|
+
}
|
|
71
|
+
if (value < config.priceAtomic) {
|
|
72
|
+
return {
|
|
73
|
+
ok: false,
|
|
74
|
+
error: `insufficient amount: ${value} < required ${config.priceAtomic} (atomic units)`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
// Validity window (unix seconds), with a small grace so the authorization
|
|
78
|
+
// does not expire while the request is in flight.
|
|
79
|
+
const grace = config.graceSeconds ?? DEFAULT_GRACE_SECONDS;
|
|
80
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
81
|
+
let validAfter;
|
|
82
|
+
let validBefore;
|
|
83
|
+
try {
|
|
84
|
+
validAfter = BigInt(a.validAfter);
|
|
85
|
+
validBefore = BigInt(a.validBefore);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return { ok: false, error: "invalid validity window" };
|
|
89
|
+
}
|
|
90
|
+
if (now < validAfter)
|
|
91
|
+
return { ok: false, error: "authorization not yet valid (validAfter in the future)" };
|
|
92
|
+
if (now + grace > validBefore)
|
|
93
|
+
return { ok: false, error: "authorization expired (validBefore too soon)" };
|
|
94
|
+
// EIP-712 signature must recover the payer.
|
|
95
|
+
let recovered;
|
|
96
|
+
try {
|
|
97
|
+
recovered = ecrecover(transferAuthDigest(a, chain), p.signature);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
return {
|
|
101
|
+
ok: false,
|
|
102
|
+
error: `signature verification failed: ${e instanceof Error ? e.message : e}`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (recovered.toLowerCase() !== a.from.toLowerCase()) {
|
|
106
|
+
return { ok: false, error: "signature does not recover authorization.from" };
|
|
107
|
+
}
|
|
108
|
+
return { ok: true, payment: p, payer: a.from.toLowerCase() };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/x402/verify.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@drm3/sdk",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
5
|
+
"description": "The DRM3 network SDK. One package to integrate an app or agent with DRM3: identity (offline SSO verify), the user's credit balance, a cross-app switcher, cross-app alerts, an in-browser receipt viewer, partner key management, the x402 payment gateway core, and a non-custodial metering ledger. Ships the `drm3` CLI. Workers, Bun, Node.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"bin": {
|
|
11
|
+
"drm3": "./bin/drm3.js"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./sso": {
|
|
19
|
+
"types": "./dist/sso/index.d.ts",
|
|
20
|
+
"default": "./dist/sso/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./x402": {
|
|
23
|
+
"types": "./dist/x402/index.d.ts",
|
|
24
|
+
"default": "./dist/x402/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./meter": {
|
|
27
|
+
"types": "./dist/meter/index.d.ts",
|
|
28
|
+
"default": "./dist/meter/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./switcher": {
|
|
31
|
+
"types": "./dist/switcher.d.ts",
|
|
32
|
+
"default": "./dist/switcher.js"
|
|
33
|
+
},
|
|
34
|
+
"./receipts": {
|
|
35
|
+
"types": "./dist/receipts.d.ts",
|
|
36
|
+
"default": "./dist/receipts.js"
|
|
37
|
+
},
|
|
38
|
+
"./receipts/global": "./dist/receipts.global.js",
|
|
39
|
+
"./receipts/global-text": "./dist/receipts.global.text.js",
|
|
40
|
+
"./alerts": {
|
|
41
|
+
"types": "./dist/alerts.d.ts",
|
|
42
|
+
"default": "./dist/alerts.js"
|
|
43
|
+
},
|
|
44
|
+
"./alerts/global": "./dist/alerts.global.js",
|
|
45
|
+
"./alerts/global-text": "./dist/alerts.global.text.js",
|
|
46
|
+
"./keys": {
|
|
47
|
+
"types": "./dist/keys.d.ts",
|
|
48
|
+
"default": "./dist/keys.js"
|
|
49
|
+
},
|
|
50
|
+
"./package.json": "./package.json"
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"dist",
|
|
54
|
+
"bin",
|
|
55
|
+
"README.md",
|
|
56
|
+
"LICENSE"
|
|
57
|
+
],
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc -p tsconfig.build.json && npm run build:browser",
|
|
60
|
+
"build:browser": "esbuild src/receipts.ts --bundle --format=iife --global-name=drm3Receipts --outfile=dist/receipts.global.js --target=es2022 && esbuild src/alerts.ts --bundle --format=iife --global-name=drm3Alerts --outfile=dist/alerts.global.js --target=es2022 && node scripts/wrap-text.mjs",
|
|
61
|
+
"typecheck": "tsc --noEmit",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"lint": "biome check src test",
|
|
64
|
+
"format": "biome check --write src test",
|
|
65
|
+
"prepublishOnly": "npm run build"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"@noble/curves": "^2.2.0",
|
|
69
|
+
"@noble/hashes": "^2.2.0"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@biomejs/biome": "^1.9.4",
|
|
73
|
+
"@electric-sql/pglite": "^0.5.2",
|
|
74
|
+
"@types/node": "^22.19.21",
|
|
75
|
+
"@vitest/coverage-v8": "^2.1.9",
|
|
76
|
+
"esbuild": "^0.25.0",
|
|
77
|
+
"fast-check": "^3.0.0",
|
|
78
|
+
"happy-dom": "^15.11.7",
|
|
79
|
+
"typescript": "^5.3.0",
|
|
80
|
+
"vitest": "^2.0.0"
|
|
81
|
+
},
|
|
82
|
+
"engines": {
|
|
83
|
+
"node": ">=20"
|
|
84
|
+
},
|
|
85
|
+
"repository": {
|
|
86
|
+
"type": "git",
|
|
87
|
+
"url": "git+https://github.com/DRM3Labs-OSS/drm3-sdk.git"
|
|
88
|
+
},
|
|
89
|
+
"homepage": "https://drm3.network",
|
|
90
|
+
"keywords": [
|
|
91
|
+
"drm3",
|
|
92
|
+
"sso",
|
|
93
|
+
"x402",
|
|
94
|
+
"metering",
|
|
95
|
+
"provenance",
|
|
96
|
+
"receipts",
|
|
97
|
+
"agents",
|
|
98
|
+
"cloudflare-workers"
|
|
99
|
+
]
|
|
100
|
+
}
|