@daski/pay 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +18 -11
  2. package/dist/bin/daski.js +26 -11
  3. package/dist/bin/daski.js.map +1 -1
  4. package/dist/chain/reader.d.ts +92 -0
  5. package/dist/chain/reader.d.ts.map +1 -0
  6. package/dist/chain/reader.js +130 -0
  7. package/dist/chain/reader.js.map +1 -0
  8. package/dist/commands/approval.js +2 -2
  9. package/dist/commands/approval.js.map +1 -1
  10. package/dist/commands/buy.d.ts +0 -1
  11. package/dist/commands/buy.d.ts.map +1 -1
  12. package/dist/commands/buy.js +15 -22
  13. package/dist/commands/buy.js.map +1 -1
  14. package/dist/commands/confirmation.d.ts +322 -4
  15. package/dist/commands/confirmation.d.ts.map +1 -1
  16. package/dist/commands/confirmation.js +771 -60
  17. package/dist/commands/confirmation.js.map +1 -1
  18. package/dist/commands/doctor.d.ts +20 -0
  19. package/dist/commands/doctor.d.ts.map +1 -1
  20. package/dist/commands/doctor.js +204 -59
  21. package/dist/commands/doctor.js.map +1 -1
  22. package/dist/commands/order.d.ts +37 -6
  23. package/dist/commands/order.d.ts.map +1 -1
  24. package/dist/commands/order.js +181 -103
  25. package/dist/commands/order.js.map +1 -1
  26. package/dist/commands/signPayment.d.ts.map +1 -1
  27. package/dist/commands/signPayment.js +8 -3
  28. package/dist/commands/signPayment.js.map +1 -1
  29. package/dist/commands/wallet.d.ts +3 -0
  30. package/dist/commands/wallet.d.ts.map +1 -1
  31. package/dist/commands/wallet.js +72 -16
  32. package/dist/commands/wallet.js.map +1 -1
  33. package/dist/config.d.ts +10 -2
  34. package/dist/config.d.ts.map +1 -1
  35. package/dist/config.js +41 -1
  36. package/dist/config.js.map +1 -1
  37. package/dist/context.d.ts +28 -3
  38. package/dist/context.d.ts.map +1 -1
  39. package/dist/context.js +72 -3
  40. package/dist/context.js.map +1 -1
  41. package/dist/gateway/client.d.ts +20 -17
  42. package/dist/gateway/client.d.ts.map +1 -1
  43. package/dist/gateway/client.js +62 -43
  44. package/dist/gateway/client.js.map +1 -1
  45. package/dist/gateway/lifecycle.d.ts +4 -1
  46. package/dist/gateway/lifecycle.d.ts.map +1 -1
  47. package/dist/gateway/lifecycle.js +10 -5
  48. package/dist/gateway/lifecycle.js.map +1 -1
  49. package/dist/gateway/metadata.d.ts +66 -0
  50. package/dist/gateway/metadata.d.ts.map +1 -0
  51. package/dist/gateway/metadata.js +152 -0
  52. package/dist/gateway/metadata.js.map +1 -0
  53. package/dist/gateway/purchase.d.ts +51 -67
  54. package/dist/gateway/purchase.d.ts.map +1 -1
  55. package/dist/gateway/purchase.js +153 -125
  56. package/dist/gateway/purchase.js.map +1 -1
  57. package/dist/host.d.ts +41 -0
  58. package/dist/host.d.ts.map +1 -0
  59. package/dist/host.js +112 -0
  60. package/dist/host.js.map +1 -0
  61. package/dist/index.d.ts +12 -6
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +10 -4
  64. package/dist/index.js.map +1 -1
  65. package/dist/signers/circleAgent.d.ts +37 -0
  66. package/dist/signers/circleAgent.d.ts.map +1 -0
  67. package/dist/signers/circleAgent.js +244 -0
  68. package/dist/signers/circleAgent.js.map +1 -0
  69. package/dist/signers/contract.d.ts +34 -0
  70. package/dist/signers/contract.d.ts.map +1 -0
  71. package/dist/signers/contract.js +47 -0
  72. package/dist/signers/contract.js.map +1 -0
  73. package/dist/signers/index.d.ts +16 -7
  74. package/dist/signers/index.d.ts.map +1 -1
  75. package/dist/signers/index.js +7 -3
  76. package/dist/signers/index.js.map +1 -1
  77. package/dist/signers/local.d.ts +5 -1
  78. package/dist/signers/local.d.ts.map +1 -1
  79. package/dist/signers/local.js +16 -3
  80. package/dist/signers/local.js.map +1 -1
  81. package/dist/signers/selfTest.d.ts +32 -12
  82. package/dist/signers/selfTest.d.ts.map +1 -1
  83. package/dist/signers/selfTest.js +85 -12
  84. package/dist/signers/selfTest.js.map +1 -1
  85. package/dist/signers/signature.d.ts +10 -0
  86. package/dist/signers/signature.d.ts.map +1 -0
  87. package/dist/signers/signature.js +11 -0
  88. package/dist/signers/signature.js.map +1 -0
  89. package/dist/store/keystore.d.ts +48 -6
  90. package/dist/store/keystore.d.ts.map +1 -1
  91. package/dist/store/keystore.js +414 -110
  92. package/dist/store/keystore.js.map +1 -1
  93. package/dist/store/lock.d.ts +59 -0
  94. package/dist/store/lock.d.ts.map +1 -0
  95. package/dist/store/lock.js +269 -0
  96. package/dist/store/lock.js.map +1 -0
  97. package/dist/store/orders.d.ts +49 -9
  98. package/dist/store/orders.d.ts.map +1 -1
  99. package/dist/store/orders.js +173 -37
  100. package/dist/store/orders.js.map +1 -1
  101. package/package.json +2 -2
@@ -0,0 +1,34 @@
1
+ /**
2
+ * What a contract-account signer must satisfy before it may buy.
3
+ *
4
+ * Two facts, both read rather than trusted: the gateway must verify contract
5
+ * accounts at all (`payerAccounts.types` in its well-known document), and the
6
+ * wallet must be deployed (`getCode` non-empty), because a counterfactual
7
+ * signature is refused at the gateway and the facilitator alike and a refusal
8
+ * there must never be the first signal. An EOA signer passes through here
9
+ * without a single RPC call (T7).
10
+ */
11
+ import type { Address } from "viem";
12
+ import type { SignerAdapter } from "@daski/x402-scheme";
13
+ import { type ChainReader } from "../chain/reader.js";
14
+ import { CliError } from "../cli/errors.js";
15
+ import type { GatewayMetadata } from "../gateway/metadata.js";
16
+ export type Deployment = "deployed" | "not-deployed" | "not-applicable";
17
+ export declare const NOT_DEPLOYED_REMEDIATION = "Send a zero-value transfer from the wallet to itself with the circle CLI, then run doctor again.";
18
+ export declare function isContractSigner(signer: SignerAdapter): boolean;
19
+ export declare function signerNotDeployed(address: Address): CliError;
20
+ export declare function gatewayEoaOnly(gatewayUrl: string): CliError;
21
+ /** Whether a signer's wallet is deployed. EOA signers are not applicable and cost no RPC. */
22
+ export declare function checkDeployment(signer: SignerAdapter, chain: ChainReader): Promise<Deployment>;
23
+ /**
24
+ * Refuses a contract signer the gateway cannot verify or the chain has not
25
+ * seen deployed. Called before a purchase asks for a challenge, so nothing is
26
+ * signed for a wallet that cannot pay.
27
+ */
28
+ export declare function assertContractSignerUsable(args: {
29
+ signer: SignerAdapter;
30
+ chain: ChainReader;
31
+ metadata: () => Promise<GatewayMetadata>;
32
+ gatewayUrl: string;
33
+ }): Promise<void>;
34
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/signers/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,cAAc,GAAG,gBAAgB,CAAC;AAExE,eAAO,MAAM,wBAAwB,qGAC+D,CAAC;AAErG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAE/D;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAQ5D;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAW3D;AAED,6FAA6F;AAC7F,wBAAsB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAIpG;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE;IACrD,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhB"}
@@ -0,0 +1,47 @@
1
+ import { isDeployedCode } from "../chain/reader.js";
2
+ import { CliError } from "../cli/errors.js";
3
+ export const NOT_DEPLOYED_REMEDIATION = "Send a zero-value transfer from the wallet to itself with the circle CLI, then run doctor again.";
4
+ export function isContractSigner(signer) {
5
+ return signer.describe().accountType === "contract";
6
+ }
7
+ export function signerNotDeployed(address) {
8
+ return new CliError({
9
+ code: "DASKI_SIGNER_NOT_DEPLOYED",
10
+ message: `The contract wallet ${address} has no code on this chain, so its signatures cannot be ` +
11
+ "verified and its purchases would be refused as counterfactual.",
12
+ remediation: NOT_DEPLOYED_REMEDIATION,
13
+ });
14
+ }
15
+ export function gatewayEoaOnly(gatewayUrl) {
16
+ return new CliError({
17
+ code: "DASKI_GATEWAY_EOA_ONLY",
18
+ message: `The gateway at ${gatewayUrl} verifies plain wallets (EOA) only; it does not list ` +
19
+ "contract accounts under payerAccounts.types, so a contract wallet cannot buy there yet.",
20
+ remediation: "On a durable machine use a local key (daski wallet create). On an ephemeral host, stop " +
21
+ "and tell the user that purchasing from this host is not available until the gateway " +
22
+ "enables contract wallets.",
23
+ });
24
+ }
25
+ /** Whether a signer's wallet is deployed. EOA signers are not applicable and cost no RPC. */
26
+ export async function checkDeployment(signer, chain) {
27
+ if (!isContractSigner(signer))
28
+ return "not-applicable";
29
+ const code = await chain.getCode(await signer.getAddress());
30
+ return isDeployedCode(code) ? "deployed" : "not-deployed";
31
+ }
32
+ /**
33
+ * Refuses a contract signer the gateway cannot verify or the chain has not
34
+ * seen deployed. Called before a purchase asks for a challenge, so nothing is
35
+ * signed for a wallet that cannot pay.
36
+ */
37
+ export async function assertContractSignerUsable(args) {
38
+ if (!isContractSigner(args.signer))
39
+ return;
40
+ const metadata = await args.metadata();
41
+ if (!metadata.payerAccounts?.types.includes("contract"))
42
+ throw gatewayEoaOnly(args.gatewayUrl);
43
+ const address = await args.signer.getAddress();
44
+ if (!isDeployedCode(await args.chain.getCode(address)))
45
+ throw signerNotDeployed(address);
46
+ }
47
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/signers/contract.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,cAAc,EAAoB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAK5C,MAAM,CAAC,MAAM,wBAAwB,GACnC,kGAAkG,CAAC;AAErG,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IACpD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC,WAAW,KAAK,UAAU,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,2BAA2B;QACjC,OAAO,EACL,uBAAuB,OAAO,0DAA0D;YACxF,gEAAgE;QAClE,WAAW,EAAE,wBAAwB;KACtC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EACL,kBAAkB,UAAU,uDAAuD;YACnF,yFAAyF;QAC3F,WAAW,EACT,yFAAyF;YACzF,sFAAsF;YACtF,2BAA2B;KAC9B,CAAC,CAAC;AACL,CAAC;AAED,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAqB,EAAE,KAAkB;IAC7E,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;QAAE,OAAO,gBAAgB,CAAC;IACvD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5D,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC;AAC5D,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,IAKhD;IACC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO;IAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IACvC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,MAAM,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/F,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IAC/C,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAAE,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;AAC3F,CAAC"}
@@ -1,23 +1,32 @@
1
1
  /**
2
2
  * Signer selection.
3
3
  *
4
- * Three adapters behind one interface: `local` (a viem account from the key
5
- * store, verified by the conformance suite), and `cdp` and `circle`
6
- * (candidates pending conformance). Whatever the backend, the request it
7
- * signs has already been through the §4 validator, and `daski doctor` puts
8
- * every adapter through the same self-test before calling it usable.
4
+ * Four adapters behind one interface: `local` (a viem account from the key
5
+ * store, verified by the conformance suite), `circle-agent` (a deployed
6
+ * contract account operated through the pinned Circle CLI, the default
7
+ * signer on every host), and `cdp` and `circle` (developer-controlled
8
+ * candidates). Whatever the backend, the request it signs has already been
9
+ * through the §4 validator, and `daski doctor` puts every adapter through the
10
+ * self-test for its account type before calling it usable.
9
11
  */
10
12
  import type { SignerAdapter } from "@daski/x402-scheme";
11
- import type { SignerKind } from "../config.js";
13
+ import { type SignerKind } from "../config.js";
14
+ import type { HostEnvironment } from "../host.js";
12
15
  import { createCdpSigner } from "./cdp.js";
13
16
  import { createCircleSigner } from "./circle.js";
17
+ import { createCircleAgentSigner } from "./circleAgent.js";
14
18
  import { createLocalSigner } from "./local.js";
15
19
  export interface SignerSelection {
16
20
  kind: SignerKind;
17
21
  profile: string;
22
+ /** Where a local key may live on this host. */
23
+ host: HostEnvironment;
24
+ /** The profile's chain, which the Circle agent wallet maps to a chain name. */
25
+ chainId: number;
18
26
  cdpAccount?: string | undefined;
27
+ /** A Circle developer-controlled wallet id, or the agent wallet address to select. */
19
28
  circleWallet?: string | undefined;
20
29
  }
21
30
  export declare function createSigner(selection: SignerSelection): Promise<SignerAdapter>;
22
- export { createCdpSigner, createCircleSigner, createLocalSigner };
31
+ export { createCdpSigner, createCircleAgentSigner, createCircleSigner, createLocalSigner };
23
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,wBAAsB,YAAY,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAerF;AAED,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,IAAI,EAAE,eAAe,CAAC;IACtB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,wBAAsB,YAAY,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAiBrF;AAED,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1,11 +1,15 @@
1
1
  import { CliError } from "../cli/errors.js";
2
+ import { SIGNER_KINDS } from "../config.js";
2
3
  import { createCdpSigner } from "./cdp.js";
3
4
  import { createCircleSigner } from "./circle.js";
5
+ import { createCircleAgentSigner } from "./circleAgent.js";
4
6
  import { createLocalSigner } from "./local.js";
5
7
  export async function createSigner(selection) {
6
8
  switch (selection.kind) {
7
9
  case "local":
8
- return createLocalSigner(selection.profile);
10
+ return createLocalSigner(selection.profile, selection.host);
11
+ case "circle-agent":
12
+ return createCircleAgentSigner({ chainId: selection.chainId, address: selection.circleWallet });
9
13
  case "cdp":
10
14
  return createCdpSigner({ account: selection.cdpAccount });
11
15
  case "circle":
@@ -14,9 +18,9 @@ export async function createSigner(selection) {
14
18
  throw new CliError({
15
19
  code: "DASKI_SIGNER_UNKNOWN",
16
20
  message: `Unknown signer "${String(selection.kind)}".`,
17
- remediation: "Set profiles.<name>.signer to one of: local, cdp, circle.",
21
+ remediation: `Set profiles.<name>.signer to one of: ${SIGNER_KINDS.join(", ")}.`,
18
22
  });
19
23
  }
20
24
  }
21
- export { createCdpSigner, createCircleSigner, createLocalSigner };
25
+ export { createCdpSigner, createCircleAgentSigner, createCircleSigner, createLocalSigner };
22
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signers/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAS/C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAA0B;IAC3D,QAAQ,SAAS,CAAC,IAAI,EAAE,CAAC;QACvB,KAAK,OAAO;YACV,OAAO,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC9C,KAAK,KAAK;YACR,OAAO,eAAe,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5D,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;QAChE;YACE,MAAM,IAAI,QAAQ,CAAC;gBACjB,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,mBAAmB,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI;gBACtD,WAAW,EAAE,2DAA2D;aACzE,CAAC,CAAC;IACP,CAAC;AACH,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signers/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAmB,MAAM,cAAc,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAc/C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAA0B;IAC3D,QAAQ,SAAS,CAAC,IAAI,EAAE,CAAC;QACvB,KAAK,OAAO;YACV,OAAO,iBAAiB,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9D,KAAK,cAAc;YACjB,OAAO,uBAAuB,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;QAClG,KAAK,KAAK;YACR,OAAO,eAAe,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5D,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;QAChE;YACE,MAAM,IAAI,QAAQ,CAAC;gBACjB,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,mBAAmB,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI;gBACtD,WAAW,EAAE,yCAAyC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;aACjF,CAAC,CAAC;IACP,CAAC;AACH,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1,3 +1,7 @@
1
1
  import type { SignerAdapter } from "@daski/x402-scheme";
2
- export declare function createLocalSigner(profile: string): Promise<SignerAdapter>;
2
+ import { type HostEnvironment } from "../host.js";
3
+ import { type KeyStoreSelection } from "../store/keystore.js";
4
+ /** The store a profile's local key uses on this host. */
5
+ export declare function localKeyStore(host: HostEnvironment): KeyStoreSelection;
6
+ export declare function createLocalSigner(profile: string, host: HostEnvironment): Promise<SignerAdapter>;
3
7
  //# sourceMappingURL=local.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/signers/local.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAuC,MAAM,oBAAoB,CAAC;AAG7F,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAc/E"}
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/signers/local.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAuC,MAAM,oBAAoB,CAAC;AAC7F,OAAO,EACmD,KAAK,eAAe,EAC7E,MAAM,YAAY,CAAC;AACpB,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAElF,yDAAyD;AACzD,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,GAAG,iBAAiB,CAEtE;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAgBtG"}
@@ -3,13 +3,26 @@
3
3
  *
4
4
  * The key is held in this closure and never leaves it. `describe()` reports
5
5
  * where it came from so `doctor` can flag the developer environment variable.
6
+ *
7
+ * Before the key is loaded, the paid-use gate runs: a Linux host whose
8
+ * profile key was left in the kernel session keyring by an earlier release
9
+ * has no durable key, and that key is never used (`DASKI_KEY_NOT_DURABLE`).
10
+ * Hosted signers hold no local key and are not subject to this gate.
6
11
  */
7
12
  import { privateKeyToAccount } from "viem/accounts";
8
13
  import {} from "viem";
14
+ import { detectLegacyKeyringEntry, keyBackendFor, keyNotDurable, } from "../host.js";
9
15
  import { loadKey, locateKey } from "../store/keystore.js";
10
- export async function createLocalSigner(profile) {
11
- const location = await locateKey(profile);
12
- const account = privateKeyToAccount(await loadKey(profile));
16
+ /** The store a profile's local key uses on this host. */
17
+ export function localKeyStore(host) {
18
+ return { host, backend: keyBackendFor(host, "local") };
19
+ }
20
+ export async function createLocalSigner(profile, host) {
21
+ const store = localKeyStore(host);
22
+ const location = await locateKey(profile, store);
23
+ if (!location && detectLegacyKeyringEntry(host, profile))
24
+ throw keyNotDurable(profile);
25
+ const account = privateKeyToAccount(await loadKey(profile, store));
13
26
  const description = {
14
27
  provider: location?.source === "environment" ? "local (env)" : "local",
15
28
  accountType: "eoa",
@@ -1 +1 @@
1
- {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/signers/local.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAA0B,MAAM,MAAM,CAAC;AAE9C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAe;IACrD,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAsB;QACrC,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO;QACtE,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,UAAU;KACxB,CAAC;IACF,OAAO;QACL,UAAU,EAAE,KAAK,IAAsB,EAAE,CAAC,OAAO,CAAC,OAAO;QACzD,aAAa,EAAE,CAAC,OAAyB,EAAgB,EAAE,CACzD,OAAO,CAAC,aAAa,CAAC,OAAgB,CAAC;QACzC,QAAQ,EAAE,GAAG,EAAE,CAAC,WAAW;KAC5B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/signers/local.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAA0B,MAAM,MAAM,CAAC;AAE9C,OAAO,EACL,wBAAwB,EAAE,aAAa,EAAE,aAAa,GACvD,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,OAAO,EAAE,SAAS,EAA0B,MAAM,sBAAsB,CAAC;AAElF,yDAAyD;AACzD,MAAM,UAAU,aAAa,CAAC,IAAqB;IACjD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAe,EAAE,IAAqB;IAC5E,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ,IAAI,wBAAwB,CAAC,IAAI,EAAE,OAAO,CAAC;QAAE,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IACvF,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IACnE,MAAM,WAAW,GAAsB;QACrC,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO;QACtE,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,UAAU;KACxB,CAAC;IACF,OAAO;QACL,UAAU,EAAE,KAAK,IAAsB,EAAE,CAAC,OAAO,CAAC,OAAO;QACzD,aAAa,EAAE,CAAC,OAAyB,EAAgB,EAAE,CACzD,OAAO,CAAC,aAAa,CAAC,OAAgB,CAAC;QACzC,QAAQ,EAAE,GAAG,EAAE,CAAC,WAAW;KAC5B,CAAC;AACJ,CAAC"}
@@ -3,11 +3,15 @@
3
3
  *
4
4
  * `daski doctor` does not take a signer's word for it. Before reporting one as
5
5
  * usable it has the signer sign one fixed vector and checks the result the way
6
- * the gateway will: the address recovered from the typed data must be the
7
- * address the adapter claims, `s` must be in the low half of the curve order,
8
- * and the whole thing must be 65 bytes. A signer that rewrites a field, wraps
9
- * an ERC-1271 blob, emits a malleable twin, or simply throws fails here, on a
10
- * machine with nothing at stake, instead of at settlement.
6
+ * the gateway will. For a plain wallet (EOA): the address recovered from the
7
+ * typed data must be the address the adapter claims, `s` must be in the low
8
+ * half of the curve order, and the whole thing must be 65 bytes. For a
9
+ * deployed contract account: the bytes are opaque beyond their size, and the
10
+ * contract itself must answer `isValidSignature` with the ERC-1271 magic value
11
+ * for the hash this CLI computed, through one bounded read-only call against
12
+ * the profile RPC. A signer that rewrites a field, wraps an ERC-6492 blob,
13
+ * emits a malleable twin, or simply throws fails here, on a machine with
14
+ * nothing at stake, instead of at settlement.
11
15
  *
12
16
  * The vector has the *shape* of a purchase — the closed 6-field
13
17
  * `TransferWithAuthorization` type set, so an adapter that mishandles that
@@ -18,6 +22,7 @@
18
22
  */
19
23
  import { type Address, type Hex } from "viem";
20
24
  import { type SignerAdapter, type TypedDataRequest } from "@daski/x402-scheme";
25
+ import { type ChainReader } from "../chain/reader.js";
21
26
  /** The vector's nonce: a commitment to nothing but its own name. */
22
27
  export declare const SELF_TEST_NONCE: Hex;
23
28
  export declare const LOW_S_MAX: bigint;
@@ -30,17 +35,32 @@ export declare const LOW_S_MAX: bigint;
30
35
  export declare function selfTestVector(signerAddress: Address, chainId: number): TypedDataRequest;
31
36
  export interface SignerSelfTestResult {
32
37
  passed: boolean;
33
- /** The address the signature recovers to, or null when nothing recovers. */
38
+ /** How the signature verified: `recovery` for a plain wallet, `erc1271` for a contract account. */
39
+ verifiedVia: "recovery" | "erc1271" | null;
40
+ /** The address the signature recovers to on the EOA path, or null when nothing recovers. */
34
41
  recovered: Address | null;
35
- /** True when `s` is at most secp256k1n/2. */
36
- lowS: boolean;
42
+ /** True when `s` is at most secp256k1n/2 on the EOA path; null on the contract path. */
43
+ lowS: boolean | null;
37
44
  /** Why the test failed. Absent on a pass. */
38
45
  reason?: string;
39
46
  }
40
47
  /**
41
- * Signs the vector with `signer` and checks the signature the way the gateway
42
- * will. Never throws: a signer that throws has failed the test, and the reason
43
- * says so.
48
+ * Runs the self-test that matches the signer's account type. Never throws: a
49
+ * signer that throws has failed the test, and the reason says so.
44
50
  */
45
- export declare function runSignerSelfTest(signer: SignerAdapter, chainId: number): Promise<SignerSelfTestResult>;
51
+ export declare function runSignerSelfTest(signer: SignerAdapter, chainId: number, chain?: ChainReader): Promise<SignerSelfTestResult>;
52
+ /**
53
+ * Signs the vector with `signer` and checks the signature the way the
54
+ * gateway's EOA path will: exactly 65 bytes, low-s, recovering to the claimed
55
+ * address. No RPC is involved.
56
+ */
57
+ export declare function runEoaSignerSelfTest(signer: SignerAdapter, chainId: number): Promise<SignerSelfTestResult>;
58
+ /**
59
+ * Signs the vector and asks the deployed wallet itself whether the signature
60
+ * is valid for the EIP-712 hash this CLI computed: one `isValidSignature`
61
+ * `eth_call` with a gas bound and a deadline, accepting only the ERC-1271
62
+ * magic value. A revert, another value, or a malformed return fails; an RPC
63
+ * that cannot be reached fails with a reason that says so, never as invalid.
64
+ */
65
+ export declare function runContractSignerSelfTest(signer: SignerAdapter, chainId: number, chain: ChainReader | undefined): Promise<SignerSelfTestResult>;
46
66
  //# sourceMappingURL=selfTest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"selfTest.d.ts","sourceRoot":"","sources":["../../src/signers/selfTest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAOL,KAAK,OAAO,EACZ,KAAK,GAAG,EACT,MAAM,MAAM,CAAC;AACd,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAI5B,oEAAoE;AACpE,eAAO,MAAM,eAAe,EAAE,GAAsD,CAAC;AAIrF,eAAO,MAAM,SAAS,QAAmB,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAmBxF;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,6CAA6C;IAC7C,IAAI,EAAE,OAAO,CAAC;IACd,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,CA+C/B"}
1
+ {"version":3,"file":"selfTest.d.ts","sourceRoot":"","sources":["../../src/signers/selfTest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EASL,KAAK,OAAO,EACZ,KAAK,GAAG,EACT,MAAM,MAAM,CAAC;AACd,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAC0C,KAAK,WAAW,EAChE,MAAM,oBAAoB,CAAC;AAK5B,oEAAoE;AACpE,eAAO,MAAM,eAAe,EAAE,GAAsD,CAAC;AAIrF,eAAO,MAAM,SAAS,QAAmB,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAmBxF;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,mGAAmG;IACnG,WAAW,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC3C,4FAA4F;IAC5F,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,wFAAwF;IACxF,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,oBAAoB,CAAC,CAK/B;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,CAiD/B;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,WAAW,GAAG,SAAS,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAyC/B"}
@@ -3,11 +3,15 @@
3
3
  *
4
4
  * `daski doctor` does not take a signer's word for it. Before reporting one as
5
5
  * usable it has the signer sign one fixed vector and checks the result the way
6
- * the gateway will: the address recovered from the typed data must be the
7
- * address the adapter claims, `s` must be in the low half of the curve order,
8
- * and the whole thing must be 65 bytes. A signer that rewrites a field, wraps
9
- * an ERC-1271 blob, emits a malleable twin, or simply throws fails here, on a
10
- * machine with nothing at stake, instead of at settlement.
6
+ * the gateway will. For a plain wallet (EOA): the address recovered from the
7
+ * typed data must be the address the adapter claims, `s` must be in the low
8
+ * half of the curve order, and the whole thing must be 65 bytes. For a
9
+ * deployed contract account: the bytes are opaque beyond their size, and the
10
+ * contract itself must answer `isValidSignature` with the ERC-1271 magic value
11
+ * for the hash this CLI computed, through one bounded read-only call against
12
+ * the profile RPC. A signer that rewrites a field, wraps an ERC-6492 blob,
13
+ * emits a malleable twin, or simply throws fails here, on a machine with
14
+ * nothing at stake, instead of at settlement.
11
15
  *
12
16
  * The vector has the *shape* of a purchase — the closed 6-field
13
17
  * `TransferWithAuthorization` type set, so an adapter that mishandles that
@@ -16,8 +20,10 @@
16
20
  * and recipient are zero; the validity window is closed. No contract will
17
21
  * ever accept it.
18
22
  */
19
- import { getAddress, hexToBigInt, keccak256, parseSignature, recoverTypedDataAddress, stringToHex, } from "viem";
23
+ import { encodeFunctionData, getAddress, hashTypedData, hexToBigInt, keccak256, parseSignature, recoverTypedDataAddress, stringToHex, } from "viem";
20
24
  import { TRANSFER_WITH_AUTHORIZATION_PRIMARY_TYPE, TRANSFER_WITH_AUTHORIZATION_TYPES, } from "@daski/x402-scheme";
25
+ import { ERC1271_ABI, ERC1271_CALL_GAS, isErc1271Magic, } from "../chain/reader.js";
26
+ import { hasErc6492Suffix, isBoundedSignature, MAX_SIGNATURE_BYTES } from "./signature.js";
21
27
  const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
22
28
  /** The vector's nonce: a commitment to nothing but its own name. */
23
29
  export const SELF_TEST_NONCE = keccak256(stringToHex("daski-doctor-self-test"));
@@ -51,11 +57,21 @@ export function selfTestVector(signerAddress, chainId) {
51
57
  };
52
58
  }
53
59
  /**
54
- * Signs the vector with `signer` and checks the signature the way the gateway
55
- * will. Never throws: a signer that throws has failed the test, and the reason
56
- * says so.
60
+ * Runs the self-test that matches the signer's account type. Never throws: a
61
+ * signer that throws has failed the test, and the reason says so.
57
62
  */
58
- export async function runSignerSelfTest(signer, chainId) {
63
+ export async function runSignerSelfTest(signer, chainId, chain) {
64
+ if (signer.describe().accountType === "contract") {
65
+ return runContractSignerSelfTest(signer, chainId, chain);
66
+ }
67
+ return runEoaSignerSelfTest(signer, chainId);
68
+ }
69
+ /**
70
+ * Signs the vector with `signer` and checks the signature the way the
71
+ * gateway's EOA path will: exactly 65 bytes, low-s, recovering to the claimed
72
+ * address. No RPC is involved.
73
+ */
74
+ export async function runEoaSignerSelfTest(signer, chainId) {
59
75
  let claimed;
60
76
  let vector;
61
77
  let signature;
@@ -83,6 +99,7 @@ export async function runSignerSelfTest(signer, chainId) {
83
99
  if (recovered !== claimed) {
84
100
  return {
85
101
  passed: false,
102
+ verifiedVia: null,
86
103
  recovered,
87
104
  lowS,
88
105
  reason: `recovered-address mismatch: the signature recovers to ${recovered} but the ` +
@@ -93,16 +110,67 @@ export async function runSignerSelfTest(signer, chainId) {
93
110
  if (!lowS) {
94
111
  return {
95
112
  passed: false,
113
+ verifiedVia: null,
96
114
  recovered,
97
115
  lowS,
98
116
  reason: "high-s signature: s is above secp256k1n/2, which the gateway's low-s ECDSA " +
99
117
  "recovery rejects",
100
118
  };
101
119
  }
102
- return { passed: true, recovered, lowS };
120
+ return { passed: true, verifiedVia: "recovery", recovered, lowS };
121
+ }
122
+ /**
123
+ * Signs the vector and asks the deployed wallet itself whether the signature
124
+ * is valid for the EIP-712 hash this CLI computed: one `isValidSignature`
125
+ * `eth_call` with a gas bound and a deadline, accepting only the ERC-1271
126
+ * magic value. A revert, another value, or a malformed return fails; an RPC
127
+ * that cannot be reached fails with a reason that says so, never as invalid.
128
+ */
129
+ export async function runContractSignerSelfTest(signer, chainId, chain) {
130
+ let claimed;
131
+ let vector;
132
+ let signature;
133
+ try {
134
+ claimed = getAddress(await signer.getAddress());
135
+ vector = selfTestVector(claimed, chainId);
136
+ signature = await signer.signTypedData(vector);
137
+ }
138
+ catch (error) {
139
+ return failedContract(`the signer threw: ${errorMessage(error)}`);
140
+ }
141
+ if (!isBoundedSignature(signature)) {
142
+ return failedContract(`malformed signature: expected 0x-prefixed hex of at most ${MAX_SIGNATURE_BYTES} bytes, ` +
143
+ `got ${describeShape(signature)}`);
144
+ }
145
+ if (hasErc6492Suffix(signature)) {
146
+ return failedContract("counterfactual (ERC-6492) signature: the wallet is not deployed, and Daski refuses " +
147
+ "ERC-6492 wrappers");
148
+ }
149
+ if (!chain)
150
+ return failedContract("no RPC reader was available to call isValidSignature");
151
+ const hash = hashTypedData(vector);
152
+ const data = encodeFunctionData({
153
+ abi: ERC1271_ABI, functionName: "isValidSignature", args: [hash, signature],
154
+ });
155
+ let result;
156
+ try {
157
+ result = await chain.call({ to: claimed, data, gas: ERC1271_CALL_GAS });
158
+ }
159
+ catch (error) {
160
+ return failedContract(`isValidSignature could not be called: ${errorMessage(error)}`);
161
+ }
162
+ if (result.reverted)
163
+ return failedContract("isValidSignature reverted for the vector");
164
+ if (!isErc1271Magic(result.data)) {
165
+ return failedContract(`isValidSignature returned ${describeReturn(result.data)}, not the ERC-1271 magic value`);
166
+ }
167
+ return { passed: true, verifiedVia: "erc1271", recovered: null, lowS: null };
103
168
  }
104
169
  function failed(reason) {
105
- return { passed: false, recovered: null, lowS: false, reason };
170
+ return { passed: false, verifiedVia: null, recovered: null, lowS: false, reason };
171
+ }
172
+ function failedContract(reason) {
173
+ return { passed: false, verifiedVia: null, recovered: null, lowS: null, reason };
106
174
  }
107
175
  function errorMessage(error) {
108
176
  return error instanceof Error ? error.message : String(error);
@@ -110,4 +178,9 @@ function errorMessage(error) {
110
178
  function describeShape(value) {
111
179
  return typeof value === "string" ? `a ${value.length}-character string` : typeof value;
112
180
  }
181
+ function describeReturn(data) {
182
+ if (data === undefined || data === "0x")
183
+ return "no data";
184
+ return `${(data.length - 2) / 2} bytes starting ${data.slice(0, 10)}`;
185
+ }
113
186
  //# sourceMappingURL=selfTest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"selfTest.js","sourceRoot":"","sources":["../../src/signers/selfTest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"selfTest.js","sourceRoot":"","sources":["../../src/signers/selfTest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The shape rule for any signature this CLI validates: `0x` plus an even
3
+ * number of hex characters, at most 4,096 bytes. The 65-byte low-s rule is
4
+ * the EOA path's alone; a contract account's bytes are opaque beyond size.
5
+ */
6
+ import type { Hex } from "viem";
7
+ export declare const MAX_SIGNATURE_BYTES = 4096;
8
+ export declare function isBoundedSignature(value: unknown): value is Hex;
9
+ export declare function hasErc6492Suffix(signature: Hex): boolean;
10
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../src/signers/signature.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAEhC,eAAO,MAAM,mBAAmB,OAAQ,CAAC;AAKzC,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAG/D;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAExD"}
@@ -0,0 +1,11 @@
1
+ export const MAX_SIGNATURE_BYTES = 4_096;
2
+ /** The 32-byte suffix an ERC-6492 wrapper ends with. Daski never accepts one. */
3
+ const ERC6492_SUFFIX = "6492".repeat(16);
4
+ export function isBoundedSignature(value) {
5
+ return typeof value === "string" && /^0x(?:[0-9a-fA-F]{2})+$/.test(value) &&
6
+ (value.length - 2) / 2 <= MAX_SIGNATURE_BYTES;
7
+ }
8
+ export function hasErc6492Suffix(signature) {
9
+ return signature.length > 66 && signature.toLowerCase().endsWith(ERC6492_SUFFIX);
10
+ }
11
+ //# sourceMappingURL=signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.js","sourceRoot":"","sources":["../../src/signers/signature.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAEzC,iFAAiF;AACjF,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAEzC,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC;QACvE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,mBAAmB,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,SAAc;IAC7C,OAAO,SAAS,CAAC,MAAM,GAAG,EAAE,IAAI,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AACnF,CAAC"}
@@ -1,19 +1,61 @@
1
- import type { Hex } from "viem";
1
+ import { type Hex } from "viem";
2
+ import { CliError } from "../cli/errors.js";
3
+ import { type HostEnvironment, type KeyBackend, type KeyDurability } from "../host.js";
2
4
  export type KeySource = "keychain" | "encrypted-file" | "environment";
3
5
  export interface KeyLocation {
4
6
  source: KeySource;
5
7
  /** Human-readable, never the key. */
6
8
  description: string;
9
+ /** What the store guarantees by construction. */
10
+ durability: KeyDurability;
7
11
  }
12
+ /** Which store a profile's local key lives in on this host. */
13
+ export interface KeyStoreSelection {
14
+ host: HostEnvironment;
15
+ backend: KeyBackend;
16
+ }
17
+ interface KeyringEntry {
18
+ getPassword(): string | null;
19
+ setPassword(password: string): void;
20
+ deletePassword(): boolean;
21
+ }
22
+ export declare function keychainUnsupportedOnLinux(profile: string): CliError;
23
+ /**
24
+ * Reads the passphrase from the file `DASKI_KEYSTORE_PASSPHRASE_FILE` names.
25
+ * The file must be a regular file with owner-only permissions; a passphrase
26
+ * never travels on a command line.
27
+ */
28
+ export declare function readPassphraseFile(path: string, platform: NodeJS.Platform): string;
29
+ /**
30
+ * The passphrase for the file store: from `DASKI_KEYSTORE_PASSPHRASE_FILE`
31
+ * when set, otherwise from the terminal. With neither, the command refuses.
32
+ */
33
+ export declare function keystorePassphrase(host: HostEnvironment, purpose: "create" | "unlock", profile: string): Promise<string>;
34
+ /** The refusal for a host whose backend holds no local key. */
35
+ export declare function localKeyRefusedOnHost(profile: string, backend: KeyBackend): CliError;
8
36
  /** Where a key for this profile lives, without loading it. */
9
- export declare function locateKey(profile: string): Promise<KeyLocation | undefined>;
37
+ export declare function locateKey(profile: string, store: KeyStoreSelection): Promise<KeyLocation | undefined>;
10
38
  /** Loads the private key for a profile, prompting for a passphrase if needed. */
11
- export declare function loadKey(profile: string): Promise<Hex>;
39
+ export declare function loadKey(profile: string, store: KeyStoreSelection): Promise<Hex>;
40
+ /** Hooks a test uses to interrupt an update between its steps. Production passes none. */
41
+ export interface StoreKeyHooks {
42
+ /** Runs after the file has been replaced and before it is read back. */
43
+ afterWrite?: (() => void) | undefined;
44
+ /** Substitutes the native keychain entry, so the keychain path runs against a double. */
45
+ keyring?: ((profile: string) => KeyringEntry) | undefined;
46
+ /** Runs after the keychain existence check and before the write. */
47
+ beforeKeychainWrite?: (() => Promise<void> | void) | undefined;
48
+ /** Where the keychain lock lives; defaults to a per-user temporary directory. */
49
+ lockDirectory?: string | undefined;
50
+ }
12
51
  /**
13
52
  * Stores a key for a profile. Returns where it landed so the caller can tell
14
- * the operator — the caller prints the location, never the key.
53
+ * the operator — the caller prints the location, never the key. The store is
54
+ * re-read under the lock, so two creations for the same profile serialize to
55
+ * one key: the second finds the first and refuses.
15
56
  */
16
- export declare function storeKey(profile: string, privateKey: Hex): Promise<KeyLocation>;
57
+ export declare function storeKey(profile: string, privateKey: Hex, store: KeyStoreSelection, hooks?: StoreKeyHooks): Promise<KeyLocation>;
17
58
  /** True when a key already exists for this profile. */
18
- export declare function hasKey(profile: string): Promise<boolean>;
59
+ export declare function hasKey(profile: string, store: KeyStoreSelection): Promise<boolean>;
60
+ export {};
19
61
  //# sourceMappingURL=keystore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keystore.d.ts","sourceRoot":"","sources":["../../src/store/keystore.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAehC,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,gBAAgB,GAAG,aAAa,CAAC;AAEtE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;CACrB;AAkID,8DAA8D;AAC9D,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAqBjF;AAED,iFAAiF;AACjF,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAiC3D;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,CAgCrF;AAED,uDAAuD;AACvD,wBAAsB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE9D"}
1
+ {"version":3,"file":"keystore.d.ts","sourceRoot":"","sources":["../../src/store/keystore.ts"],"names":[],"mappings":"AAoCA,OAAO,EAA4B,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EACY,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAC3E,MAAM,YAAY,CAAC;AA2BpB,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,gBAAgB,GAAG,aAAa,CAAC;AAEtE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,UAAU,EAAE,aAAa,CAAC;CAC3B;AAED,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,UAAU,CAAC;CACrB;AAwED,UAAU,YAAY;IACpB,WAAW,IAAI,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,cAAc,IAAI,OAAO,CAAC;CAC3B;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAUpE;AA2LD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,CA4BlF;AAUD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,QAAQ,GAAG,QAAQ,EAC5B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CA4BjB;AAID,+DAA+D;AAC/D,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,CAYpF;AAED,8DAA8D;AAC9D,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAY3G;AAED,iFAAiF;AACjF,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,CAwBrF;AAUD,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,UAAU,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACtC,yFAAyF;IACzF,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,YAAY,CAAC,GAAG,SAAS,CAAC;IAC1D,oEAAoE;IACpE,mBAAmB,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/D,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AA2BD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,GAAG,EACf,KAAK,EAAE,iBAAiB,EACxB,KAAK,GAAE,aAAkB,GACxB,OAAO,CAAC,WAAW,CAAC,CA0CtB;AAsBD,uDAAuD;AACvD,wBAAsB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAExF"}