@daski/x402-scheme 0.1.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 +21 -0
- package/README.md +81 -0
- package/dist/binding.d.ts +37 -0
- package/dist/binding.d.ts.map +1 -0
- package/dist/binding.js +74 -0
- package/dist/binding.js.map +1 -0
- package/dist/canonical.d.ts +12 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +53 -0
- package/dist/canonical.js.map +1 -0
- package/dist/eip712.d.ts +72 -0
- package/dist/eip712.d.ts.map +1 -0
- package/dist/eip712.js +61 -0
- package/dist/eip712.js.map +1 -0
- package/dist/errors.d.ts +34 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +32 -0
- package/dist/errors.js.map +1 -0
- package/dist/extensions.d.ts +29 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +65 -0
- package/dist/extensions.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle.d.ts +177 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +345 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/policy.d.ts +113 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +357 -0
- package/dist/policy.js.map +1 -0
- package/dist/recipe.d.ts +40 -0
- package/dist/recipe.d.ts.map +1 -0
- package/dist/recipe.js +61 -0
- package/dist/recipe.js.map +1 -0
- package/dist/register.d.ts +36 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +12 -0
- package/dist/register.js.map +1 -0
- package/dist/scheme.d.ts +92 -0
- package/dist/scheme.d.ts.map +1 -0
- package/dist/scheme.js +182 -0
- package/dist/scheme.js.map +1 -0
- package/dist/signRequest.d.ts +30 -0
- package/dist/signRequest.d.ts.map +1 -0
- package/dist/signRequest.js +83 -0
- package/dist/signRequest.js.map +1 -0
- package/dist/signer.d.ts +38 -0
- package/dist/signer.d.ts.map +1 -0
- package/dist/signer.js +12 -0
- package/dist/signer.js.map +1 -0
- package/package.json +53 -0
package/dist/register.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DaskiExactEvmScheme } from "./scheme.js";
|
|
2
|
+
/**
|
|
3
|
+
* Wraps `stock` in the Daski composite and registers it for one network.
|
|
4
|
+
* Returns the composite so the caller can inspect or reuse it.
|
|
5
|
+
*/
|
|
6
|
+
export function registerDaskiExactEvmScheme(client, options) {
|
|
7
|
+
const { network, ...rest } = options;
|
|
8
|
+
const composite = new DaskiExactEvmScheme(rest);
|
|
9
|
+
client.register(network, composite);
|
|
10
|
+
return composite;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,mBAAmB,EAAiE,MAAM,aAAa,CAAC;AAsBjH;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,MAAsB,EACtB,OAAwB;IAExB,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACrC,MAAM,SAAS,GAAG,IAAI,mBAAmB,CAAC,IAAyC,CAAC,CAAC;IACrF,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACpC,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/scheme.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §3 — the composite Exact-EVM client.
|
|
3
|
+
*
|
|
4
|
+
* This is a *wrapper*, not a replacement. The facilitator knows one scheme
|
|
5
|
+
* name, `exact`, so inventing a second one would make our payments
|
|
6
|
+
* unverifiable; and clobbering the stock handler for a network would silently
|
|
7
|
+
* change the semantics of every non-Daski payment the host makes. So:
|
|
8
|
+
*
|
|
9
|
+
* - `scheme` stays `"exact"`;
|
|
10
|
+
* - a challenge without `daski-order-binding` is handed to the stock
|
|
11
|
+
* handler untouched, context and all;
|
|
12
|
+
* - a challenge with one takes the Daski path, which validates and
|
|
13
|
+
* recomputes before it signs.
|
|
14
|
+
*
|
|
15
|
+
* Hooks and `findDefaultAsset` are forwarded so the host's spend controls and
|
|
16
|
+
* money parsing keep working exactly as they did before registration.
|
|
17
|
+
*/
|
|
18
|
+
import { type Address } from "viem";
|
|
19
|
+
import { type PolicyConfig } from "./policy.js";
|
|
20
|
+
import type { SignerAdapter } from "./signer.js";
|
|
21
|
+
/** Structural mirrors of the `@x402/core` types, so this package needs no
|
|
22
|
+
* value import from the SDK and stays usable with any 2.x host. */
|
|
23
|
+
export interface PaymentRequirementsLike {
|
|
24
|
+
scheme: string;
|
|
25
|
+
network: string;
|
|
26
|
+
asset: string;
|
|
27
|
+
amount: string;
|
|
28
|
+
payTo: string;
|
|
29
|
+
maxTimeoutSeconds: number;
|
|
30
|
+
extra?: {
|
|
31
|
+
assetTransferMethod?: string;
|
|
32
|
+
name?: string;
|
|
33
|
+
version?: string;
|
|
34
|
+
} | undefined;
|
|
35
|
+
}
|
|
36
|
+
export interface PaymentPayloadContextLike {
|
|
37
|
+
extensions?: Record<string, unknown> | undefined;
|
|
38
|
+
}
|
|
39
|
+
export interface PaymentPayloadResultLike {
|
|
40
|
+
x402Version: number;
|
|
41
|
+
payload: unknown;
|
|
42
|
+
extensions?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
/** The subset of `SchemeNetworkClient` this package produces and consumes. */
|
|
45
|
+
export interface SchemeNetworkClientLike {
|
|
46
|
+
readonly scheme: string;
|
|
47
|
+
readonly schemeHooks?: unknown;
|
|
48
|
+
findDefaultAsset?: unknown;
|
|
49
|
+
createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirementsLike, context?: PaymentPayloadContextLike): Promise<PaymentPayloadResultLike>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolves the purchase this challenge belongs to, and the quote a human
|
|
53
|
+
* approved for it. The scheme cannot infer either from the challenge — that
|
|
54
|
+
* would be the counterparty supplying its own expectations — so the host app
|
|
55
|
+
* states them.
|
|
56
|
+
*/
|
|
57
|
+
export interface PurchaseContextResolver {
|
|
58
|
+
(requirements: PaymentRequirementsLike, context: PaymentPayloadContextLike | undefined): Promise<{
|
|
59
|
+
providerAgentId: string;
|
|
60
|
+
outcomeId: string;
|
|
61
|
+
/** Atomic units the human approved. */
|
|
62
|
+
approvedQuoteAtomic: bigint;
|
|
63
|
+
/** Idempotency key for this intent; also the reconciliation key. */
|
|
64
|
+
paymentIdentifier?: string | undefined;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
export interface DaskiExactEvmSchemeOptions {
|
|
68
|
+
/** The wallet. Never the gateway's. */
|
|
69
|
+
signer: SignerAdapter;
|
|
70
|
+
/** Resolved once so the stock handler's synchronous `address` works. */
|
|
71
|
+
payerAddress: Address;
|
|
72
|
+
/** §4 policy. Without it there is no signing. */
|
|
73
|
+
policy: PolicyConfig;
|
|
74
|
+
/** The stock handler this composite wraps. */
|
|
75
|
+
stock: SchemeNetworkClientLike;
|
|
76
|
+
/** How the host names the purchase and the approved quote. */
|
|
77
|
+
resolvePurchaseContext: PurchaseContextResolver;
|
|
78
|
+
/** Injectable clock, for tests. */
|
|
79
|
+
now?: () => number;
|
|
80
|
+
}
|
|
81
|
+
export declare class DaskiExactEvmScheme implements SchemeNetworkClientLike {
|
|
82
|
+
#private;
|
|
83
|
+
/** The facilitator knows exactly one name. We do not invent a second. */
|
|
84
|
+
readonly scheme = "exact";
|
|
85
|
+
constructor(options: DaskiExactEvmSchemeOptions);
|
|
86
|
+
/** Forwarded so the host's spend controls keep resolving default assets. */
|
|
87
|
+
get findDefaultAsset(): unknown;
|
|
88
|
+
/** Forwarded so registering the composite does not drop stock hooks. */
|
|
89
|
+
get schemeHooks(): unknown;
|
|
90
|
+
createPaymentPayload(x402Version: number, requirements: PaymentRequirementsLike, context?: PaymentPayloadContextLike): Promise<PaymentPayloadResultLike>;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=scheme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheme.d.ts","sourceRoot":"","sources":["../src/scheme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAc,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAChD,OAAO,EAAwD,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAYtG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;oEACoE;AACpE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE;QAAE,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACvF;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAClD;AAED,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,8EAA8E;AAC9E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAClB,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,uBAAuB,EAC5C,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACtC;AAED;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,CAAC,YAAY,EAAE,uBAAuB,EAAE,OAAO,EAAE,yBAAyB,GAAG,SAAS,GAAG,OAAO,CAAC;QAC/F,eAAe,EAAE,MAAM,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,uCAAuC;QACvC,mBAAmB,EAAE,MAAM,CAAC;QAC5B,oEAAoE;QACpE,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACxC,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,0BAA0B;IACzC,uCAAuC;IACvC,MAAM,EAAE,aAAa,CAAC;IACtB,wEAAwE;IACxE,YAAY,EAAE,OAAO,CAAC;IACtB,iDAAiD;IACjD,MAAM,EAAE,YAAY,CAAC;IACrB,8CAA8C;IAC9C,KAAK,EAAE,uBAAuB,CAAC;IAC/B,8DAA8D;IAC9D,sBAAsB,EAAE,uBAAuB,CAAC;IAChD,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAKD,qBAAa,mBAAoB,YAAW,uBAAuB;;IACjE,yEAAyE;IACzE,QAAQ,CAAC,MAAM,WAAW;gBAId,OAAO,EAAE,0BAA0B;IAc/C,4EAA4E;IAC5E,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,wEAAwE;IACxE,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEK,oBAAoB,CACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,uBAAuB,EACrC,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,wBAAwB,CAAC;CAoHrC"}
|
package/dist/scheme.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §3 — the composite Exact-EVM client.
|
|
3
|
+
*
|
|
4
|
+
* This is a *wrapper*, not a replacement. The facilitator knows one scheme
|
|
5
|
+
* name, `exact`, so inventing a second one would make our payments
|
|
6
|
+
* unverifiable; and clobbering the stock handler for a network would silently
|
|
7
|
+
* change the semantics of every non-Daski payment the host makes. So:
|
|
8
|
+
*
|
|
9
|
+
* - `scheme` stays `"exact"`;
|
|
10
|
+
* - a challenge without `daski-order-binding` is handed to the stock
|
|
11
|
+
* handler untouched, context and all;
|
|
12
|
+
* - a challenge with one takes the Daski path, which validates and
|
|
13
|
+
* recomputes before it signs.
|
|
14
|
+
*
|
|
15
|
+
* Hooks and `findDefaultAsset` are forwarded so the host's spend controls and
|
|
16
|
+
* money parsing keep working exactly as they did before registration.
|
|
17
|
+
*/
|
|
18
|
+
import { getAddress } from "viem";
|
|
19
|
+
import { bindingFromExtensions, validatePurchaseAuthorization } from "./policy.js";
|
|
20
|
+
import { transferWithAuthorizationTypedData } from "./eip712.js";
|
|
21
|
+
import { refuse } from "./errors.js";
|
|
22
|
+
import { DASKI_ORDER_BINDING, DASKI_SIGN_REQUEST, issuedPaymentIdentifier, paymentEchoExtensions, withPaymentIdentifier, } from "./extensions.js";
|
|
23
|
+
import { deriveBindingNonce } from "./recipe.js";
|
|
24
|
+
import { parseSignRequest } from "./signRequest.js";
|
|
25
|
+
/** Backdate tolerance applied to `validAfter` on the locally-computed path. */
|
|
26
|
+
const AUTHORIZATION_CLOCK_SKEW_SECONDS = 30;
|
|
27
|
+
export class DaskiExactEvmScheme {
|
|
28
|
+
/** The facilitator knows exactly one name. We do not invent a second. */
|
|
29
|
+
scheme = "exact";
|
|
30
|
+
#options;
|
|
31
|
+
constructor(options) {
|
|
32
|
+
if (!options.policy) {
|
|
33
|
+
refuse({
|
|
34
|
+
check: "challenge-shape",
|
|
35
|
+
code: "DASKI_SCHEME_POLICY_REQUIRED",
|
|
36
|
+
expected: "a PolicyConfig",
|
|
37
|
+
remediation: "No config, no signing. Supply a PolicyConfig when constructing " +
|
|
38
|
+
"DaskiExactEvmScheme.",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
this.#options = options;
|
|
42
|
+
}
|
|
43
|
+
/** Forwarded so the host's spend controls keep resolving default assets. */
|
|
44
|
+
get findDefaultAsset() {
|
|
45
|
+
return this.#options.stock.findDefaultAsset;
|
|
46
|
+
}
|
|
47
|
+
/** Forwarded so registering the composite does not drop stock hooks. */
|
|
48
|
+
get schemeHooks() {
|
|
49
|
+
return this.#options.stock.schemeHooks;
|
|
50
|
+
}
|
|
51
|
+
async createPaymentPayload(x402Version, requirements, context) {
|
|
52
|
+
const extensions = context?.extensions;
|
|
53
|
+
// Not a Daski challenge: the stock handler owns this entirely.
|
|
54
|
+
if (extensions?.[DASKI_ORDER_BINDING] === undefined) {
|
|
55
|
+
return this.#options.stock.createPaymentPayload(x402Version, requirements, context);
|
|
56
|
+
}
|
|
57
|
+
return this.#createDaskiPayload(x402Version, requirements, context);
|
|
58
|
+
}
|
|
59
|
+
async #createDaskiPayload(x402Version, requirements, context) {
|
|
60
|
+
const { policy, signer } = this.#options;
|
|
61
|
+
if (x402Version !== 2) {
|
|
62
|
+
refuse({
|
|
63
|
+
check: "challenge-shape",
|
|
64
|
+
code: "DASKI_SCHEME_VERSION_UNSUPPORTED",
|
|
65
|
+
expected: "x402 version 2",
|
|
66
|
+
actual: `version ${x402Version}`,
|
|
67
|
+
remediation: "Daski settles on x402 V2 only.",
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
assertExactEvmRequirement(requirements);
|
|
71
|
+
const issued = context?.extensions ?? {};
|
|
72
|
+
const binding = bindingFromExtensions(issued);
|
|
73
|
+
const purchase = await this.#options.resolvePurchaseContext(requirements, context);
|
|
74
|
+
const now = (this.#options.now ?? (() => Math.floor(Date.now() / 1_000)))();
|
|
75
|
+
// The server may propose the whole document; we still recompute it and
|
|
76
|
+
// require agreement, so the proposal is an input, never an authority.
|
|
77
|
+
const proposed = parseSignRequest(issued[DASKI_SIGN_REQUEST]);
|
|
78
|
+
const domain = {
|
|
79
|
+
name: requirements.extra.name,
|
|
80
|
+
version: requirements.extra.version,
|
|
81
|
+
chainId: policy.chainId,
|
|
82
|
+
verifyingContract: getAddress(requirements.asset),
|
|
83
|
+
};
|
|
84
|
+
const authorization = proposed
|
|
85
|
+
? authorizationFromProposal(proposed)
|
|
86
|
+
: this.#computeAuthorization(requirements, binding, now);
|
|
87
|
+
const typedData = proposed ?? transferWithAuthorizationTypedData(domain, authorization);
|
|
88
|
+
const identifier = purchase.paymentIdentifier ?? issuedPaymentIdentifier(issued);
|
|
89
|
+
const validated = await validatePurchaseAuthorization(policy, typedData, {
|
|
90
|
+
providerAgentId: purchase.providerAgentId,
|
|
91
|
+
outcomeId: purchase.outcomeId,
|
|
92
|
+
challengeAmountAtomic: BigInt(requirements.amount),
|
|
93
|
+
challengeAsset: getAddress(requirements.asset),
|
|
94
|
+
challengePayTo: getAddress(requirements.payTo),
|
|
95
|
+
challengeNetwork: requirements.network,
|
|
96
|
+
approvedQuoteAtomic: purchase.approvedQuoteAtomic,
|
|
97
|
+
paymentIdentifier: identifier,
|
|
98
|
+
binding,
|
|
99
|
+
nowSeconds: now,
|
|
100
|
+
});
|
|
101
|
+
const signature = await signer.signTypedData(transferWithAuthorizationTypedData(domain, validated.authorization));
|
|
102
|
+
return {
|
|
103
|
+
x402Version,
|
|
104
|
+
payload: { authorization: validated.authorization, signature },
|
|
105
|
+
extensions: withPaymentIdentifier(paymentEchoExtensions(issued), identifier),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The verify-and-sign tier: build the authorization ourselves from the
|
|
110
|
+
* binding, so a gateway that ships no `daski-sign-request` is fully
|
|
111
|
+
* supported and the recompute path stays exercised.
|
|
112
|
+
*/
|
|
113
|
+
#computeAuthorization(requirements, binding, now) {
|
|
114
|
+
const { policy } = this.#options;
|
|
115
|
+
const payer = getAddress(policy.payerAddress);
|
|
116
|
+
const splitter = getAddress(requirements.payTo);
|
|
117
|
+
const grossAmount = BigInt(requirements.amount);
|
|
118
|
+
const validAfter = binding
|
|
119
|
+
? BigInt(Math.max(0, now - AUTHORIZATION_CLOCK_SKEW_SECONDS))
|
|
120
|
+
: 0n;
|
|
121
|
+
const validBefore = BigInt(Math.min(now + requirements.maxTimeoutSeconds, binding?.expiresAt ?? Number.MAX_SAFE_INTEGER));
|
|
122
|
+
const nonce = binding
|
|
123
|
+
? deriveBindingNonce(binding, {
|
|
124
|
+
chainId: policy.chainId,
|
|
125
|
+
canonicalToken: getAddress(policy.canonicalToken),
|
|
126
|
+
payer,
|
|
127
|
+
splitter,
|
|
128
|
+
grossAmount,
|
|
129
|
+
})
|
|
130
|
+
: refuse({
|
|
131
|
+
check: "recipe-recompute",
|
|
132
|
+
code: "DASKI_SCHEME_BINDING_REQUIRED",
|
|
133
|
+
expected: "a daski-order-binding extension on the Daski path",
|
|
134
|
+
remediation: "A Daski purchase without a binding cannot be recomputed. Request a " +
|
|
135
|
+
"fresh challenge.",
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
from: payer,
|
|
139
|
+
to: splitter,
|
|
140
|
+
value: grossAmount.toString(),
|
|
141
|
+
validAfter: validAfter.toString(),
|
|
142
|
+
validBefore: validBefore.toString(),
|
|
143
|
+
nonce,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function authorizationFromProposal(proposal) {
|
|
148
|
+
const message = proposal.message;
|
|
149
|
+
return {
|
|
150
|
+
from: String(message.from),
|
|
151
|
+
to: String(message.to),
|
|
152
|
+
value: String(message.value),
|
|
153
|
+
validAfter: String(message.validAfter),
|
|
154
|
+
validBefore: String(message.validBefore),
|
|
155
|
+
nonce: String(message.nonce),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function assertExactEvmRequirement(requirements) {
|
|
159
|
+
if (requirements.scheme !== "exact") {
|
|
160
|
+
refuse({
|
|
161
|
+
check: "challenge-shape",
|
|
162
|
+
code: "DASKI_SCHEME_UNSUPPORTED_SCHEME",
|
|
163
|
+
expected: "scheme exact",
|
|
164
|
+
actual: `scheme ${requirements.scheme}`,
|
|
165
|
+
remediation: "Daski settles only on the standard Exact-EVM rail.",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const extra = requirements.extra;
|
|
169
|
+
if (extra?.assetTransferMethod !== "eip3009" || !extra.name || !extra.version ||
|
|
170
|
+
!/^\d+$/.test(requirements.amount) ||
|
|
171
|
+
!Number.isSafeInteger(requirements.maxTimeoutSeconds) ||
|
|
172
|
+
requirements.maxTimeoutSeconds <= 10) {
|
|
173
|
+
refuse({
|
|
174
|
+
check: "challenge-shape",
|
|
175
|
+
code: "DASKI_SCHEME_REQUIREMENT_INCOMPLETE",
|
|
176
|
+
expected: "eip3009 transfer metadata, an integer amount, and a sane timeout",
|
|
177
|
+
actual: `assetTransferMethod=${String(extra?.assetTransferMethod)} amount=${requirements.amount}`,
|
|
178
|
+
remediation: "Request a fresh challenge from the gateway.",
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=scheme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheme.js","sourceRoot":"","sources":["../src/scheme.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `daski-sign-request` — the server's proposed authorization.
|
|
3
|
+
*
|
|
4
|
+
* When the gateway ships this extension it hands the buyer a fully-formed
|
|
5
|
+
* typed-data document. That is a convenience, not an authority: the bridge
|
|
6
|
+
* parses it into a closed shape, hands it to the policy validator like any
|
|
7
|
+
* other proposal, and recomputes the recipe nonce. A proposal that survives
|
|
8
|
+
* all of that is signed; one that does not is reported, never repaired.
|
|
9
|
+
*/
|
|
10
|
+
import type { Hex } from "viem";
|
|
11
|
+
import type { Eip712Domain, TypedDataRequest } from "./eip712.js";
|
|
12
|
+
export interface ParsedSignRequest {
|
|
13
|
+
domain: Eip712Domain;
|
|
14
|
+
primaryType: string;
|
|
15
|
+
types: Record<string, readonly {
|
|
16
|
+
name: string;
|
|
17
|
+
type: string;
|
|
18
|
+
}[]>;
|
|
19
|
+
message: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parses a `daski-sign-request` extension into a typed-data proposal.
|
|
23
|
+
*
|
|
24
|
+
* Nothing is validated here beyond structural sanity — the §4 validator owns
|
|
25
|
+
* every semantic check, so this cannot become a second, weaker gate.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseSignRequest(value: unknown): TypedDataRequest | undefined;
|
|
28
|
+
/** The nonce a proposal carries, for the recompute-and-compare in §4.3. */
|
|
29
|
+
export declare function proposedNonce(proposal: TypedDataRequest): Hex | undefined;
|
|
30
|
+
//# sourceMappingURL=signRequest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signRequest.d.ts","sourceRoot":"","sources":["../src/signRequest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAW,GAAG,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAKlE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAC;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAmE7E;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,gBAAgB,GAAG,GAAG,GAAG,SAAS,CAKzE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { refuse } from "./errors.js";
|
|
2
|
+
const DOC = "https://github.com/daski-io/buyer/blob/main/docs/policy.md#sign-request";
|
|
3
|
+
/**
|
|
4
|
+
* Parses a `daski-sign-request` extension into a typed-data proposal.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is validated here beyond structural sanity — the §4 validator owns
|
|
7
|
+
* every semantic check, so this cannot become a second, weaker gate.
|
|
8
|
+
*/
|
|
9
|
+
export function parseSignRequest(value) {
|
|
10
|
+
if (value === undefined)
|
|
11
|
+
return undefined;
|
|
12
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
13
|
+
refuse({
|
|
14
|
+
check: "challenge-shape",
|
|
15
|
+
code: "DASKI_SIGN_REQUEST_NOT_AN_OBJECT",
|
|
16
|
+
expected: "an object under extensions['daski-sign-request']",
|
|
17
|
+
actual: Array.isArray(value) ? "an array" : typeof value,
|
|
18
|
+
remediation: `Request a fresh challenge; see ${DOC}`,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const request = value;
|
|
22
|
+
const keys = Object.keys(request).sort();
|
|
23
|
+
if (keys.join(",") !== "domain,message,primaryType,types") {
|
|
24
|
+
refuse({
|
|
25
|
+
check: "challenge-shape",
|
|
26
|
+
code: "DASKI_SIGN_REQUEST_OPEN_SHAPE",
|
|
27
|
+
expected: "exactly [domain, message, primaryType, types]",
|
|
28
|
+
actual: `[${keys.join(", ")}]`,
|
|
29
|
+
remediation: "An unrecognized sign-request layout cannot be validated, so it cannot " +
|
|
30
|
+
`be signed. Upgrade @daski/x402-scheme; see ${DOC}`,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const domain = request.domain;
|
|
34
|
+
if (!domain || typeof domain !== "object" || Array.isArray(domain)) {
|
|
35
|
+
refuse({
|
|
36
|
+
check: "challenge-shape",
|
|
37
|
+
code: "DASKI_SIGN_REQUEST_MALFORMED_DOMAIN",
|
|
38
|
+
expected: "an EIP-712 domain object",
|
|
39
|
+
actual: typeof domain,
|
|
40
|
+
remediation: `Request a fresh challenge; see ${DOC}`,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const domainKeys = Object.keys(domain).sort();
|
|
44
|
+
if (domainKeys.join(",") !== "chainId,name,verifyingContract,version") {
|
|
45
|
+
refuse({
|
|
46
|
+
check: "challenge-shape",
|
|
47
|
+
code: "DASKI_SIGN_REQUEST_OPEN_DOMAIN",
|
|
48
|
+
expected: "exactly [chainId, name, verifyingContract, version]",
|
|
49
|
+
actual: `[${domainKeys.join(", ")}]`,
|
|
50
|
+
remediation: "A domain with extra or missing fields hashes differently than the one " +
|
|
51
|
+
`we would validate; see ${DOC}`,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const message = request.message;
|
|
55
|
+
if (!message || typeof message !== "object" || Array.isArray(message)) {
|
|
56
|
+
refuse({
|
|
57
|
+
check: "challenge-shape",
|
|
58
|
+
code: "DASKI_SIGN_REQUEST_MALFORMED_MESSAGE",
|
|
59
|
+
expected: "an EIP-712 message object",
|
|
60
|
+
actual: typeof message,
|
|
61
|
+
remediation: `Request a fresh challenge; see ${DOC}`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
domain: {
|
|
66
|
+
name: String(domain.name),
|
|
67
|
+
version: String(domain.version),
|
|
68
|
+
chainId: Number(domain.chainId),
|
|
69
|
+
verifyingContract: domain.verifyingContract,
|
|
70
|
+
},
|
|
71
|
+
primaryType: String(request.primaryType),
|
|
72
|
+
types: request.types,
|
|
73
|
+
message: message,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** The nonce a proposal carries, for the recompute-and-compare in §4.3. */
|
|
77
|
+
export function proposedNonce(proposal) {
|
|
78
|
+
const nonce = proposal.message.nonce;
|
|
79
|
+
return typeof nonce === "string" && /^0x[0-9a-fA-F]{64}$/.test(nonce)
|
|
80
|
+
? nonce
|
|
81
|
+
: undefined;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=signRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signRequest.js","sourceRoot":"","sources":["../src/signRequest.ts"],"names":[],"mappings":"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"}
|
package/dist/signer.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signer boundary.
|
|
3
|
+
*
|
|
4
|
+
* Everything above this line decides *what* may be signed; everything below
|
|
5
|
+
* it holds the key. The gateway is on neither side — it never sees key
|
|
6
|
+
* material, and no adapter here returns any.
|
|
7
|
+
*/
|
|
8
|
+
import type { Address, Hex } from "viem";
|
|
9
|
+
import type { TypedDataRequest } from "./eip712.js";
|
|
10
|
+
/** How a signer describes itself to `daski doctor`. */
|
|
11
|
+
export interface SignerDescription {
|
|
12
|
+
/** e.g. `local`, `cdp`, `circle`. */
|
|
13
|
+
provider: string;
|
|
14
|
+
/** e.g. `eoa`, `smart-contract`. */
|
|
15
|
+
accountType: "eoa" | "smart-contract" | "unknown";
|
|
16
|
+
/** Set when an adapter has not yet passed the §6 conformance suite. */
|
|
17
|
+
conformance?: "verified" | "candidate-pending-conformance";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The one interface every wallet backend implements. Deliberately tiny: an
|
|
21
|
+
* address, a typed-data signature, and a self-description. No raw message
|
|
22
|
+
* signing, no transaction signing, no key export.
|
|
23
|
+
*/
|
|
24
|
+
export interface SignerAdapter {
|
|
25
|
+
getAddress(): Promise<Address>;
|
|
26
|
+
signTypedData(payload: TypedDataRequest): Promise<Hex>;
|
|
27
|
+
describe(): SignerDescription;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Adapts a `SignerAdapter` to the shape `@x402/evm`'s stock scheme expects.
|
|
31
|
+
* The stock handler wants a synchronous `address`, so the caller resolves it
|
|
32
|
+
* once up front.
|
|
33
|
+
*/
|
|
34
|
+
export declare function toClientEvmSigner(address: Address, adapter: SignerAdapter): {
|
|
35
|
+
address: Address;
|
|
36
|
+
signTypedData(payload: TypedDataRequest): Promise<Hex>;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=signer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,WAAW,EAAE,KAAK,GAAG,gBAAgB,GAAG,SAAS,CAAC;IAClD,uEAAuE;IACvE,WAAW,CAAC,EAAE,UAAU,GAAG,+BAA+B,CAAC;CAC5D;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACvD,QAAQ,IAAI,iBAAiB,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,aAAa,GACrB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;CAAE,CAK9E"}
|
package/dist/signer.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapts a `SignerAdapter` to the shape `@x402/evm`'s stock scheme expects.
|
|
3
|
+
* The stock handler wants a synchronous `address`, so the caller resolves it
|
|
4
|
+
* once up front.
|
|
5
|
+
*/
|
|
6
|
+
export function toClientEvmSigner(address, adapter) {
|
|
7
|
+
return {
|
|
8
|
+
address,
|
|
9
|
+
signTypedData: (payload) => adapter.signTypedData(payload),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=signer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signer.js","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AA+BA;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAgB,EAChB,OAAsB;IAEtB,OAAO;QACL,OAAO;QACP,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC;KAC3D,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@daski/x402-scheme",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Composite Exact-EVM client plugin for the modular x402 v2 SDK: wraps the stock handler, adds Daski recipe-order binding, and refuses to sign anything its policy validator has not independently checked.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=20"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/daski-io/buyer.git",
|
|
13
|
+
"directory": "packages/x402-scheme"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/daski-io/buyer/tree/main/packages/x402-scheme#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/daski-io/buyer/issues"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"x402",
|
|
21
|
+
"daski",
|
|
22
|
+
"eip-3009",
|
|
23
|
+
"exact-evm",
|
|
24
|
+
"agent-payments"
|
|
25
|
+
],
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"sideEffects": false,
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc --build tsconfig.build.json",
|
|
40
|
+
"test": "tsc -p tsconfig.test.json && node --test .test-dist/test/*.test.js",
|
|
41
|
+
"prepublishOnly": "npm run build"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"viem": "2.21.55"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@x402/core": ">=2.20.0 <3"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public",
|
|
51
|
+
"provenance": true
|
|
52
|
+
}
|
|
53
|
+
}
|