@daski/pay 0.2.0 → 0.3.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.
Files changed (45) hide show
  1. package/README.md +35 -80
  2. package/dist/bin/daski.js +28 -11
  3. package/dist/bin/daski.js.map +1 -1
  4. package/dist/commands/approval.d.ts +52 -0
  5. package/dist/commands/approval.d.ts.map +1 -0
  6. package/dist/commands/approval.js +59 -0
  7. package/dist/commands/approval.js.map +1 -0
  8. package/dist/commands/buy.d.ts +4 -4
  9. package/dist/commands/buy.d.ts.map +1 -1
  10. package/dist/commands/buy.js +38 -57
  11. package/dist/commands/buy.js.map +1 -1
  12. package/dist/commands/confirmation.d.ts +29 -0
  13. package/dist/commands/confirmation.d.ts.map +1 -0
  14. package/dist/commands/confirmation.js +123 -0
  15. package/dist/commands/confirmation.js.map +1 -0
  16. package/dist/commands/doctor.d.ts.map +1 -1
  17. package/dist/commands/doctor.js +4 -1
  18. package/dist/commands/doctor.js.map +1 -1
  19. package/dist/commands/order.d.ts +17 -2
  20. package/dist/commands/order.d.ts.map +1 -1
  21. package/dist/commands/order.js +15 -11
  22. package/dist/commands/order.js.map +1 -1
  23. package/dist/commands/signPayment.d.ts +1 -0
  24. package/dist/commands/signPayment.d.ts.map +1 -1
  25. package/dist/commands/signPayment.js +7 -2
  26. package/dist/commands/signPayment.js.map +1 -1
  27. package/dist/commands/wallet.d.ts.map +1 -1
  28. package/dist/commands/wallet.js +5 -17
  29. package/dist/commands/wallet.js.map +1 -1
  30. package/dist/config.d.ts +15 -11
  31. package/dist/config.d.ts.map +1 -1
  32. package/dist/config.js +59 -33
  33. package/dist/config.js.map +1 -1
  34. package/dist/gateway/purchase.d.ts +2 -5
  35. package/dist/gateway/purchase.d.ts.map +1 -1
  36. package/dist/gateway/purchase.js +19 -62
  37. package/dist/gateway/purchase.js.map +1 -1
  38. package/dist/index.d.ts +3 -3
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +3 -3
  41. package/dist/index.js.map +1 -1
  42. package/dist/store/orders.d.ts +11 -0
  43. package/dist/store/orders.d.ts.map +1 -1
  44. package/dist/store/orders.js.map +1 -1
  45. package/package.json +2 -2
package/README.md CHANGED
@@ -1,101 +1,56 @@
1
- # `@daski/pay`
1
+ # @daski/pay
2
2
 
3
- The Daski buyer bridge. A CLI that buys outcomes, tracks orders across
4
- processes, and refuses to sign anything it has not independently checked.
3
+ The Daski buyer CLI obtains a quote, validates and signs an approved payment, and tracks the order across processes. Wallet keys stay in their protected store.
4
+
5
+ ## Setup and purchase
5
6
 
6
7
  ```bash
7
- npx @daski/pay@0.2.0 doctor --json
8
+ npm install -g @daski/pay@0.3.0
9
+ daski doctor --json
8
10
  ```
9
11
 
10
- > Server proposes; buyer bridge validates against its own expectations and
11
- > recomputes; wallet signs; the gateway never sees the key.
12
-
13
- ## Commands
14
-
15
- | Command | What it does |
16
- |---|---|
17
- | `daski doctor` | Readiness report; exits 0 only when nothing blocks, including one read-only MCP round trip that proves this CLI can read the gateway's results. Every issue carries a remediation |
18
- | `daski wallet create` | Generate a local EOA — interactive human confirmation required |
19
- | `daski wallet address` / `balance` | The active payer address; native + USDC balances |
20
- | `daski buy --provider <id> --outcome <id> --request <file.json>` | Challenge → approve → validate → sign → submit → record |
21
- | `daski order status <handle>` | Read an order's state |
22
- | `daski order artifact <handle>` | Write the result **to a file**, never to stdout |
23
- | `daski order confirm/input/cancel <handle>` | Mutating lifecycle actions |
24
- | `daski sign-payment --challenge <file.json>` | Validate, recompute, sign; print the exact `paymentPayload` |
25
-
26
- All support `--json`. Global flags: `--profile`, `--signer <local|cdp|circle>`,
27
- `--cdp-account`, `--circle-wallet`, `--max-per-order`, `--session-cap`.
28
-
29
- ## Spend caps are yours, not the agent's
30
-
31
- `maxPerOrderUsdc`, `sessionCapUsdc` and `requireApprovalAboveUsdc` live only
32
- in `~/.daski/config.json`. **No flag and no environment variable can raise
33
- them.** `--max-per-order` and `--session-cap` may lower a cap for a single
34
- invocation; a value above the configured one is refused.
35
-
36
- Above `requireApprovalAboveUsdc`, `daski buy` shows the approval summary and
37
- waits for a human. In `--json` or non-TTY mode it does not quietly proceed —
38
- it exits `2` and explains how a human can approve.
12
+ Doctor reports the configured signer, its self-test, native state paths, network, balances, spending settings, and gateway compatibility. Reuse a healthy signer. Create a wallet only if one is missing: `daski wallet create` prompts interactively; authorized agent setup uses `daski wallet create --yes-human-approved`.
39
13
 
40
- The running session total is read from `~/.daski/orders.json`, so the cap
41
- holds across processes rather than resetting whenever an agent restarts.
14
+ Complete the request using gateway discovery and `daski_get_outcome_requirements`, then run:
42
15
 
43
- ## Orders survive the process that placed them
44
-
45
- Every order is recorded in `~/.daski/orders.json` — handle, intent id,
46
- provider/outcome, amount, state, read capability and expiry. `daski order
47
- status` works from a cold start with nothing but the handle.
48
-
49
- The intent is recorded **before** the signature goes out, which is what makes
50
- an interrupted purchase recoverable.
51
-
52
- ## Interrupted purchases are reconciled, never re-signed
53
-
54
- On a timeout, a `PAYMENT_PENDING_RECONCILIATION`, or a transport drop after
55
- submit, the CLI replays the *identical* signed authorization — idempotent by
56
- the gateway's own published retry policy — and corroborates against the
57
- payer's own order history. Only when both agree no order exists does it report
58
- the purchase as safely retryable.
59
-
60
- A second signature over a fresh challenge is a second order, and a second
61
- charge. See [reconciliation](../../docs/policy.md#reconciliation).
16
+ ```bash
17
+ daski buy --provider <id> --outcome <id> --request <file.json> --json
18
+ ```
62
19
 
63
- ## Artifacts are written, not printed
20
+ The command returns the actual quote and an approval identifier. After the user approves, repeat with `--approve <approval.id>`. Interactive use prompts directly. New profiles approve each paid quote and have no extra default budget. Existing settings remain in place on upgrade.
64
21
 
65
- `daski order artifact` writes the provider's bytes to a file and prints only
66
- the envelope metadata. Provider results are validated but untrusted, and both
67
- a terminal and an agent's context window are interpreters: dumping untrusted
68
- content into one is how "here is your result" becomes "here are your
69
- instructions".
22
+ ## Commands
70
23
 
71
- ## Signers
24
+ | Command | Behavior |
25
+ |---|---|
26
+ | `doctor --json` | Diagnose signer, paths, settings, funds, and gateway |
27
+ | `wallet create` | Create a local signer when missing |
28
+ | `wallet address` / `wallet balance` | Read the active payer and balances |
29
+ | `budget [--per-order <usdc\|none>] [--total <usdc\|none>] [--approval-above <usdc>]` | View or explicitly change spending settings |
30
+ | `buy --provider <id> --outcome <id> --request <file.json>` | Quote, approve, validate, sign, submit, and record |
31
+ | `order status <handle>` | Read order state using cached read access or a fresh authorization |
32
+ | `order artifact <handle> [--output <file>]` | Save the provider result to a file |
33
+ | `order input <handle> --request <file.json>` | Submit customer input |
34
+ | `order cancel <handle>` | Request cancellation |
35
+ | `order confirm <handle> --choice <Confirmed\|NotConfirmed>` | Prepare, validate, sign, and submit the user's review |
36
+ | `order revoke-confirmation <handle>` | Withdraw the active review |
37
+ | `order confirm <handle> --resume` | Reconcile the stored review without another EAS signature |
38
+ | `order reconcile <intentId>` | Query settlement for one payment identifier |
39
+ | `sign-payment --challenge <file.json>` | Advanced payment signer; supports the same --approve flow |
72
40
 
73
- `local` is the default and the one adapter the conformance suite has verified.
74
- `cdp` and `circle` are implemented and marked *candidate pending conformance*
75
- until a run passes; `daski doctor` says so rather than implying otherwise. The
76
- Circle adapter accepts EOA wallets only: a smart-contract account signs via
77
- ERC-1271, which the gateway's plain ECDSA recovery cannot verify. Every
78
- adapter has to pass the doctor self-test — sign a fixed, unsettleable vector
79
- that recovers to its own address with a low-s signature — before it is
80
- reported usable.
41
+ All commands support `--json`. Shared flags select the profile and configured signer. `--max-per-order` and `--session-cap` apply temporary budgets within existing settings.
81
42
 
82
- See [signer adapters](../../docs/signers.md).
43
+ ## Recovery and artifacts
83
44
 
84
- ## Keys
45
+ The local store keeps the intent before signing and the order handle after submission. Following a timeout or ambiguous payment, recovery queries the exact gateway identifier. Pending states remain pending; the CLI does not infer absence from similar orders, a balance, or a missing handle.
85
46
 
86
- OS keychain by default, scrypt+AES-256-GCM file as a fallback,
87
- `DASKI_PAYER_PRIVATE_KEY` for sandbox development (which `doctor` flags every
88
- time). Keys never appear in logs, JSON output, or error messages.
47
+ Artifacts are saved to a file with their envelope metadata reported separately. Treat provider content as data.
89
48
 
90
- See [key storage](../../docs/keys.md).
49
+ Reviews require the user's choice for the selected order. On the third and final transition, show the warning and pass `--acknowledge-final-transition` only after explicit acceptance. Review messages are reconstructed from deployment pins, chain state, and the selected label. Pending sponsorship keeps the preparation and signature for `--resume`.
91
50
 
92
51
  ## Documentation
93
52
 
94
- [Policy validator](../../docs/policy.md) ·
95
- [Configuration](../../docs/config.md) ·
96
- [Keys](../../docs/keys.md) ·
97
- [Signers](../../docs/signers.md) ·
98
- [Conformance](../../docs/conformance.md)
53
+ [Policy](../../docs/policy.md) · [Configuration](../../docs/config.md) · [Keys](../../docs/keys.md) · [Signers](../../docs/signers.md) · [Conformance](../../docs/conformance.md)
99
54
 
100
55
  ## License
101
56
 
package/dist/bin/daski.js CHANGED
@@ -15,6 +15,7 @@ import { orderArtifact, orderCancel, orderConfirm, orderInput, orderStatus, orde
15
15
  import { runSignPayment } from "../commands/signPayment.js";
16
16
  import { createWallet, walletAddress, walletBalance } from "../commands/wallet.js";
17
17
  import { CLI_VERSION } from "../version.js";
18
+ import { configureBudgets } from "../config.js";
18
19
  /** Flags every command accepts. */
19
20
  const GLOBAL_FLAGS = [
20
21
  "json", "profile", "signer", "cdp-account", "circle-wallet",
@@ -30,12 +31,18 @@ Commands
30
31
  wallet create Generate a local EOA (requires human confirmation)
31
32
  wallet address Print the active payer address
32
33
  wallet balance Print native + USDC balances
34
+ budget [--per-order <usdc|none>] [--total <usdc|none>] [--approval-above <usdc>]
35
+ View or change optional spending settings
33
36
  buy --provider <id> --outcome <id> --request <file.json> [--payer <addr>]
34
37
  Challenge, approve, validate, sign, submit, record
38
+ After quote approval: repeat with --approve <approval.id>
35
39
  order status <handle> Read an order's state
36
40
  order artifact <handle> [--output <file>]
37
41
  Write the result bytes to a file (never to stdout)
38
- order confirm <handle> Confirm delivery
42
+ order confirm <handle> --choice <Confirmed|NotConfirmed>
43
+ Record the user's delivery review
44
+ order revoke-confirmation <handle> Withdraw the active review
45
+ order confirm <handle> --resume Reconcile a pending review submission
39
46
  order input <handle> --request <file.json>
40
47
  Submit requested customer input
41
48
  order cancel <handle> Request cancellation
@@ -49,11 +56,11 @@ Global flags
49
56
  --signer <local|cdp|circle> Override the profile's signer
50
57
  --cdp-account <name> CDP account for --signer cdp (or DASKI_CDP_ACCOUNT)
51
58
  --circle-wallet <id> Circle wallet id for --signer circle (or DASKI_CIRCLE_WALLET)
52
- --max-per-order <usdc> Lower the per-order cap for this run only
53
- --session-cap <usdc> Lower the session cap for this run only
59
+ --max-per-order <usdc> Apply a temporary per-order budget
60
+ --session-cap <usdc> Apply a temporary total budget
54
61
 
55
- Caps live in ~/.daski/config.json and are human-owned: a flag may lower one,
56
- never raise it. See https://github.com/daski-io/buyer#readme
62
+ New profiles use quote approval, with optional budgets. Doctor reports the
63
+ active configuration path. See https://github.com/daski-io/buyer#readme
57
64
  `;
58
65
  async function main(argv) {
59
66
  const { command, flags } = parseArgs(argv);
@@ -76,6 +83,12 @@ async function main(argv) {
76
83
  sessionCapUsdc: stringFlag(flags, "session-cap"),
77
84
  };
78
85
  switch (command[0]) {
86
+ case "budget": {
87
+ assertKnownFlags(flags, ["json", "profile", "per-order", "total", "approval-above"]);
88
+ emit(configureBudgets({ profile: shared.profile, perOrder: stringFlag(flags, "per-order"),
89
+ total: stringFlag(flags, "total"), approvalAbove: stringFlag(flags, "approval-above") }), output);
90
+ return 0;
91
+ }
79
92
  case "doctor": {
80
93
  assertKnownFlags(flags, GLOBAL_FLAGS);
81
94
  const report = await runDoctor(shared);
@@ -106,7 +119,7 @@ async function main(argv) {
106
119
  }
107
120
  }
108
121
  case "buy": {
109
- assertKnownFlags(flags, [...GLOBAL_FLAGS, "provider", "outcome", "request", "payer", "legacy-arg", "yes"]);
122
+ assertKnownFlags(flags, [...GLOBAL_FLAGS, "provider", "outcome", "request", "payer", "legacy-arg", "approve"]);
110
123
  const result = await runBuy({
111
124
  ...shared,
112
125
  providerAgentId: requireFlag(flags, "provider"),
@@ -114,7 +127,7 @@ async function main(argv) {
114
127
  requestFile: requireFlag(flags, "request"),
115
128
  payer: stringFlag(flags, "payer"),
116
129
  legacyArg: boolFlag(flags, "legacy-arg"),
117
- yes: boolFlag(flags, "yes"),
130
+ approved: stringFlag(flags, "approve"),
118
131
  json,
119
132
  });
120
133
  emit(result, output);
@@ -140,8 +153,11 @@ async function main(argv) {
140
153
  emit(await orderArtifact({ ...base, output: stringFlag(flags, "output") }), output);
141
154
  return 0;
142
155
  case "confirm":
143
- assertKnownFlags(flags, GLOBAL_FLAGS);
144
- emit(await orderConfirm(base), output);
156
+ case "revoke-confirmation":
157
+ assertKnownFlags(flags, [...GLOBAL_FLAGS, "choice", "resume", "acknowledge-final-transition"]);
158
+ emit(await orderConfirm({ ...base, confirmation: stringFlag(flags, "choice"),
159
+ revoke: command[1] === "revoke-confirmation", resume: boolFlag(flags, "resume"),
160
+ acknowledgeFinalTransition: boolFlag(flags, "acknowledge-final-transition") }), output);
145
161
  return 0;
146
162
  case "cancel":
147
163
  assertKnownFlags(flags, GLOBAL_FLAGS);
@@ -156,16 +172,17 @@ async function main(argv) {
156
172
  emit(await orderReconcile(base), output);
157
173
  return 0;
158
174
  default:
159
- throw unknownSubcommand("order", command[1], ["status", "artifact", "confirm", "input", "cancel", "reconcile"]);
175
+ throw unknownSubcommand("order", command[1], ["status", "artifact", "confirm", "revoke-confirmation", "input", "cancel", "reconcile"]);
160
176
  }
161
177
  }
162
178
  case "sign-payment": {
163
- assertKnownFlags(flags, [...GLOBAL_FLAGS, "challenge", "provider", "outcome"]);
179
+ assertKnownFlags(flags, [...GLOBAL_FLAGS, "challenge", "provider", "outcome", "approve"]);
164
180
  emit(await runSignPayment({
165
181
  ...shared,
166
182
  challengeFile: requireFlag(flags, "challenge"),
167
183
  providerAgentId: stringFlag(flags, "provider"),
168
184
  outcomeId: stringFlag(flags, "outcome"),
185
+ approved: stringFlag(flags, "approve"),
169
186
  json,
170
187
  }), output);
171
188
  return 0;
@@ -1 +1 @@
1
- {"version":3,"file":"daski.js","sourceRoot":"","sources":["../../src/bin/daski.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daski.js","sourceRoot":"","sources":["../../src/bin/daski.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { type OrderBinding } from "@daski/x402-scheme";
2
+ import type { PaymentRequirement } from "../gateway/client.js";
3
+ /** Approval survives quote expiry only while all purchase terms stay the same. */
4
+ export declare function purchaseApproval(args: {
5
+ gatewayUrl: string;
6
+ payer: string;
7
+ providerAgentId: string;
8
+ outcomeId: string;
9
+ requirement: PaymentRequirement;
10
+ binding: OrderBinding;
11
+ purchaseNumber?: number;
12
+ }): {
13
+ gateway: string;
14
+ payer: `0x${string}`;
15
+ providerAgentId: string;
16
+ outcomeId: string;
17
+ network: string;
18
+ token: `0x${string}`;
19
+ payTo: `0x${string}`;
20
+ amount: string;
21
+ requestHash: `0x${string}`;
22
+ listing: `0x${string}`;
23
+ providerTerms: `0x${string}`;
24
+ id: `0x${string}`;
25
+ termsHash: `0x${string}`;
26
+ purchaseNumber: number;
27
+ };
28
+ /** A consumed approval cannot authorize another purchase with identical terms. */
29
+ export declare function nextPurchaseApproval(args: Parameters<typeof purchaseApproval>[0], profile: string): {
30
+ gateway: string;
31
+ payer: `0x${string}`;
32
+ providerAgentId: string;
33
+ outcomeId: string;
34
+ network: string;
35
+ token: `0x${string}`;
36
+ payTo: `0x${string}`;
37
+ amount: string;
38
+ requestHash: `0x${string}`;
39
+ listing: `0x${string}`;
40
+ providerTerms: `0x${string}`;
41
+ id: `0x${string}`;
42
+ termsHash: `0x${string}`;
43
+ purchaseNumber: number;
44
+ };
45
+ export declare function approvePurchase(args: {
46
+ approval: ReturnType<typeof purchaseApproval>;
47
+ approved?: string | undefined;
48
+ threshold: string;
49
+ json: boolean;
50
+ summary?: unknown;
51
+ }): Promise<void>;
52
+ //# sourceMappingURL=approval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../../src/commands/approval.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAC9E,WAAW,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,YAAY,CAAC;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;;;;;;;;;;;;;;;EAcA;AAED,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;EASjG;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,QAAQ,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7E,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CACrD,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBhB"}
@@ -0,0 +1,59 @@
1
+ import { canonicalHash, formatUsdc } from "@daski/x402-scheme";
2
+ import { getAddress } from "viem";
3
+ import { atomicUsdc } from "../config.js";
4
+ import { CliError } from "../cli/errors.js";
5
+ import { confirm, isInteractive } from "../cli/prompt.js";
6
+ import { note } from "../cli/output.js";
7
+ import { isUnspent, listOrders } from "../store/orders.js";
8
+ /** Approval survives quote expiry only while all purchase terms stay the same. */
9
+ export function purchaseApproval(args) {
10
+ const binding = args.binding;
11
+ const terms = {
12
+ gateway: args.gatewayUrl.replace(/\/$/, ""), payer: getAddress(args.payer),
13
+ providerAgentId: args.providerAgentId, outcomeId: args.outcomeId,
14
+ network: args.requirement.network, token: getAddress(args.requirement.asset),
15
+ payTo: getAddress(args.requirement.payTo), amount: BigInt(args.requirement.amount).toString(),
16
+ requestHash: binding.canonicalRequestHash,
17
+ listing: binding.version === 2 ? binding.runtimeCommitmentHash : binding.listingManifestHash,
18
+ providerTerms: binding.version === 2 ? binding.providerIntentHash : binding.providerOfferHash,
19
+ };
20
+ const termsHash = canonicalHash(terms);
21
+ const purchaseNumber = args.purchaseNumber ?? 1;
22
+ return { id: canonicalHash({ termsHash, purchaseNumber }), termsHash, purchaseNumber, ...terms };
23
+ }
24
+ /** A consumed approval cannot authorize another purchase with identical terms. */
25
+ export function nextPurchaseApproval(args, profile) {
26
+ const first = purchaseApproval(args);
27
+ const prior = listOrders(profile).filter((order) => order.approvalTermsHash === first.termsHash && !isUnspent(order));
28
+ const pending = prior.find((order) => ["AUTHORIZED", "SUBMITTED", "PENDING_RECONCILIATION"].includes(order.state));
29
+ if (pending)
30
+ throw new CliError({ code: "DASKI_PAYMENT_PENDING_RECONCILIATION",
31
+ message: "This purchase already has an authorized or pending order.",
32
+ remediation: `Continue with daski order reconcile ${pending.intentId}.`,
33
+ details: { intentId: pending.intentId, orderHandle: pending.handle ?? null } });
34
+ return purchaseApproval({ ...args, purchaseNumber: prior.length + 1 });
35
+ }
36
+ export async function approvePurchase(args) {
37
+ if (args.approved !== undefined) {
38
+ if (args.approved === args.approval.id)
39
+ return;
40
+ throw new CliError({ code: "DASKI_QUOTE_CHANGED",
41
+ message: "The quote or purchase differs from the approved one.",
42
+ remediation: "Show the new quote to the user, then pass its approval.id with --approve.",
43
+ details: { approval: args.approval, approvalSummary: args.summary }, exitCode: 2 });
44
+ }
45
+ if (BigInt(args.approval.amount) <= atomicUsdc(args.threshold))
46
+ return;
47
+ if (args.json || !isInteractive()) {
48
+ throw new CliError({ code: "DASKI_HUMAN_APPROVAL_REQUIRED",
49
+ message: `Approve this purchase for ${formatUsdc(BigInt(args.approval.amount))}.`,
50
+ remediation: "Show the quote to the user. After approval, repeat the command with --approve <approval.id>.",
51
+ details: { approval: args.approval, approvalSummary: args.summary }, exitCode: 2 });
52
+ }
53
+ note(JSON.stringify(args.summary ?? args.approval, null, 2));
54
+ if (!await confirm(`Pay ${formatUsdc(BigInt(args.approval.amount))} on ${args.approval.network}?`)) {
55
+ throw new CliError({ code: "DASKI_PURCHASE_DECLINED", message: "The purchase was declined.",
56
+ remediation: "Run the command again when ready.", exitCode: 2 });
57
+ }
58
+ }
59
+ //# sourceMappingURL=approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval.js","sourceRoot":"","sources":["../../src/commands/approval.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { PolicyRefusal } from "@daski/x402-scheme";
2
- import { type ContextOptions } from "../context.js";
2
+ import { type ContextOptions, type CommandContext } from "../context.js";
3
3
  export interface BuyOptions extends ContextOptions {
4
4
  providerAgentId: string;
5
5
  outcomeId: string;
@@ -7,9 +7,9 @@ export interface BuyOptions extends ContextOptions {
7
7
  payer?: string | undefined;
8
8
  json: boolean;
9
9
  legacyArg?: boolean;
10
- /** Skips only the interactive prompt, never the policy validator. */
11
- yes?: boolean;
10
+ /** The identifier of the quote the user approved. */
11
+ approved?: string | undefined;
12
12
  }
13
- export declare function runBuy(options: BuyOptions): Promise<Record<string, unknown>>;
13
+ export declare function runBuy(options: BuyOptions, contextFactory?: (options: ContextOptions) => Promise<CommandContext>): Promise<Record<string, unknown>>;
14
14
  export { PolicyRefusal };
15
15
  //# sourceMappingURL=buy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"buy.d.ts","sourceRoot":"","sources":["../../src/commands/buy.ts"],"names":[],"mappings":"AAQA,OAAO,EAAc,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAK/D,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAanE,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qEAAqE;IACrE,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAoLlF;AAyID,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"buy.d.ts","sourceRoot":"","sources":["../../src/commands/buy.ts"],"names":[],"mappings":"AAQA,OAAO,EAA6B,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAG9E,OAAO,EAAiB,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAcxF,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,cAAc,GAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,cAAc,CAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAwKxK;AA+HD,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -6,18 +6,17 @@
6
6
  * and any re-sign.
7
7
  */
8
8
  import { readFileSync } from "node:fs";
9
- import { formatUsdc, PolicyRefusal } from "@daski/x402-scheme";
9
+ import { canonicalHash, formatUsdc, PolicyRefusal } from "@daski/x402-scheme";
10
10
  import { CliError } from "../cli/errors.js";
11
- import { confirm, isInteractive } from "../cli/prompt.js";
12
11
  import { note } from "../cli/output.js";
13
- import { atomicUsdc } from "../config.js";
14
12
  import { createContext } from "../context.js";
13
+ import { approvePurchase, nextPurchaseApproval } from "./approval.js";
15
14
  import { GatewayClient } from "../gateway/client.js";
16
- import { authorizePayment, challengeIntentId, isAmbiguousPurchaseAnswer, reconcileAmbiguousPurchase, recordIntent, requestChallenge, submitPayment, } from "../gateway/purchase.js";
15
+ import { authorizePayment, challengeIntentId, isAmbiguousPurchaseAnswer, reconcileByIdentifier, recordIntent, requestChallenge, submitPayment, } from "../gateway/purchase.js";
17
16
  import { updateOrder } from "../store/orders.js";
18
- export async function runBuy(options) {
17
+ export async function runBuy(options, contextFactory = createContext) {
19
18
  const request = readRequestFile(options.requestFile);
20
- const context = await createContext(options);
19
+ const context = await contextFactory(options);
21
20
  try {
22
21
  if (options.payer && options.payer.toLowerCase() !== context.payerAddress.toLowerCase()) {
23
22
  throw new CliError({
@@ -38,51 +37,40 @@ export async function runBuy(options) {
38
37
  });
39
38
  const amountAtomic = BigInt(challenge.requirement.amount);
40
39
  const preflight = challenge.preflight;
40
+ const requestHash = canonicalHash({ method: "POST", resource: challenge.challenge.resource?.url,
41
+ providerAgentId: options.providerAgentId, outcomeId: options.outcomeId, body: request });
42
+ if (!challenge.binding || challenge.binding.canonicalRequestHash !== requestHash) {
43
+ throw new CliError({ code: "DASKI_REQUEST_BINDING_MISMATCH",
44
+ message: "The challenge does not match the requested purchase.",
45
+ remediation: "Obtain a challenge for the same provider, outcome, and request." });
46
+ }
47
+ const approval = nextPurchaseApproval({ gatewayUrl: context.profile.gatewayUrl,
48
+ payer: context.payerAddress, providerAgentId: options.providerAgentId, outcomeId: options.outcomeId,
49
+ requirement: challenge.requirement, binding: challenge.binding }, context.profileName);
50
+ const outcome = await context.catalog.getOutcome(options.providerAgentId, options.outcomeId);
51
+ const summary = approvalSummary(challenge.challenge.extensions, outcome, amountAtomic, preflight);
41
52
  if (preflight?.sufficient === false) {
42
53
  // The gateway already read the payer's balance: a signature now would be
43
54
  // a doomed one. Say what is needed and stop; where the USDC comes from
44
55
  // is the operator's business.
45
56
  const network = String(preflight.network ?? context.profile.network);
46
57
  const balance = typeof preflight.usdcBalance === "string"
47
- ? `${formatUsdc(BigInt(preflight.usdcBalance))} USDC`
58
+ ? formatUsdc(BigInt(preflight.usdcBalance))
48
59
  : "an unknown USDC balance";
49
60
  throw new CliError({
50
61
  code: "DASKI_INSUFFICIENT_USDC",
51
62
  message: `${context.payerAddress} holds ${balance} on ${network}; this purchase ` +
52
63
  `needs ${formatUsdc(amountAtomic)}.`,
53
64
  remediation: `Fund ${context.payerAddress} with USDC on ${network}, then re-run. Nothing was signed.`,
54
- details: { preflight, priceUsdc: formatUsdc(amountAtomic) },
65
+ details: { preflight, priceUsdc: formatUsdc(amountAtomic), approval, approvalSummary: summary,
66
+ shortfallUsdc: typeof preflight.usdcBalance === "string"
67
+ ? formatUsdc(amountAtomic > BigInt(preflight.usdcBalance) ? amountAtomic - BigInt(preflight.usdcBalance) : 0n) : null },
55
68
  exitCode: 2,
56
69
  });
57
70
  }
58
71
  // -- 2. approval -------------------------------------------------------
59
- const outcome = await context.catalog.getOutcome(options.providerAgentId, options.outcomeId);
60
- const summary = approvalSummary(challenge.challenge.extensions, outcome, amountAtomic, preflight);
61
- const threshold = atomicUsdc(context.profile.requireApprovalAboveUsdc);
62
- if (amountAtomic > threshold && !options.yes) {
63
- if (options.json || !isInteractive()) {
64
- throw new CliError({
65
- code: "DASKI_HUMAN_APPROVAL_REQUIRED",
66
- message: `${formatUsdc(amountAtomic)} is above this profile's ` +
67
- `requireApprovalAboveUsdc of ${context.profile.requireApprovalAboveUsdc} USDC, ` +
68
- "and this session cannot ask a human.",
69
- remediation: "Have a human run this command in an interactive terminal and confirm " +
70
- "the prompt, or — if a human has already approved this exact purchase " +
71
- "— re-run with --yes. Raising the threshold is a manual config edit.",
72
- details: { approvalSummary: summary, priceUsdc: formatUsdc(amountAtomic) },
73
- exitCode: 2,
74
- });
75
- }
76
- note(renderApproval(summary, amountAtomic));
77
- if (!await confirm("Authorize this payment?")) {
78
- throw new CliError({
79
- code: "DASKI_PURCHASE_DECLINED",
80
- message: "The purchase was not approved.",
81
- remediation: "Nothing was signed and no money moved. Re-run when ready.",
82
- exitCode: 2,
83
- });
84
- }
85
- }
72
+ await approvePurchase({ approval, approved: options.approved,
73
+ threshold: context.profile.requireApprovalAboveUsdc, json: options.json, summary });
86
74
  // -- 3 & 4. validate, recompute, sign ----------------------------------
87
75
  // The gateway bound its own payment identifier to the challenge; the
88
76
  // submission must carry that one, so it is the ledger key as well.
@@ -95,6 +83,7 @@ export async function runBuy(options) {
95
83
  outcomeId: options.outcomeId,
96
84
  payer: context.payerAddress,
97
85
  amount: amountAtomic.toString(),
86
+ approvalTermsHash: approval.termsHash,
98
87
  state: "INTENT_RECORDED",
99
88
  request,
100
89
  });
@@ -127,7 +116,7 @@ export async function runBuy(options) {
127
116
  // The signature left the process and the answer did not come back. This
128
117
  // is the ambiguous case: reconcile, never re-sign.
129
118
  return await reconcile(context, {
130
- intentId, options, request, authorized,
119
+ intentId,
131
120
  cause: `transport failure after submit: ${error.message}`,
132
121
  });
133
122
  }
@@ -135,7 +124,7 @@ export async function runBuy(options) {
135
124
  const code = typeof body?.code === "string" ? body.code : undefined;
136
125
  if (result.isError && isAmbiguousPurchaseAnswer(code, body)) {
137
126
  return await reconcile(context, {
138
- intentId, options, request, authorized,
127
+ intentId,
139
128
  cause: `gateway reported ${code ?? "an error"} with the payment outcome unknown`,
140
129
  });
141
130
  }
@@ -144,7 +133,7 @@ export async function runBuy(options) {
144
133
  // payload. The signature is out and the outcome is unknown: that is the
145
134
  // ambiguous case, so reconcile — never report failure, never re-sign.
146
135
  return await reconcile(context, {
147
- intentId, options, request, authorized,
136
+ intentId,
148
137
  cause: "the paid result carried no payload this CLI could read",
149
138
  });
150
139
  }
@@ -189,21 +178,18 @@ async function reconcile(context, args) {
189
178
  updateOrder(args.intentId, { state: "PENDING_RECONCILIATION" });
190
179
  note(`payment outcome unclear (${args.cause}); reconciling before any re-sign...`);
191
180
  const record = updateOrder(args.intentId, {});
192
- const outcome = await reconcileAmbiguousPurchase({
181
+ const outcome = await reconcileByIdentifier({
193
182
  client: context.client,
194
183
  signer: context.signer,
195
- record,
184
+ intentId: args.intentId,
196
185
  payer: context.payerAddress,
197
186
  chainId: context.profile.chainId,
198
187
  gatewayUrl: context.profile.gatewayUrl,
199
- submission: args.authorized.submission,
200
- request: args.request,
201
- ...(args.options.legacyArg === undefined ? {} : { legacyArg: args.options.legacyArg }),
202
188
  });
203
189
  if (outcome.status === "settled") {
204
190
  const settled = updateOrder(args.intentId, {
205
191
  handle: outcome.orderHandle,
206
- state: normalizeState(outcome.body?.status),
192
+ state: normalizeState(outcome.gatewayState),
207
193
  });
208
194
  return {
209
195
  purchased: true,
@@ -217,7 +203,13 @@ async function reconcile(context, args) {
217
203
  gatewayCalls: context.client.callCount,
218
204
  };
219
205
  }
220
- // Provably absent: the caller may safely start over with a fresh challenge.
206
+ if (outcome.status !== "absent") {
207
+ throw new CliError({ code: "DASKI_PAYMENT_PENDING_RECONCILIATION",
208
+ message: "The gateway is still resolving this payment.",
209
+ remediation: `Check again with daski order reconcile ${args.intentId}.`,
210
+ details: { intentId: args.intentId, status: outcome.status, reconciliation: outcome.evidence }, exitCode: 3 });
211
+ }
212
+ updateOrder(args.intentId, { state: "NOT_SETTLED" });
221
213
  throw new CliError({
222
214
  code: "DASKI_PAYMENT_UNRESOLVED_NO_ORDER",
223
215
  message: `The purchase was interrupted (${args.cause}) and no order exists for it: ` +
@@ -248,7 +240,7 @@ function approvalSummary(extensions, outcome, amountAtomic, preflight) {
248
240
  const supplied = preflight?.approvalSummary ?? extensions?.approvalSummary;
249
241
  if (supplied && typeof supplied === "object")
250
242
  return supplied;
251
- const terms = extensions?.["daski-order-terms"];
243
+ const terms = extensions?.["daski-order-terms"] ?? outcome.terms;
252
244
  return {
253
245
  ...(typeof supplied === "string" ? { gateway: supplied } : {}),
254
246
  what: [outcome.serviceName, outcome.skillName].filter(Boolean).join(" / ") || "Daski outcome",
@@ -260,17 +252,6 @@ function approvalSummary(extensions, outcome, amountAtomic, preflight) {
260
252
  marketplaceTerms: terms?.marketplaceTermsUrl ?? null,
261
253
  };
262
254
  }
263
- function renderApproval(summary, amountAtomic) {
264
- const lines = ["", " ─ Purchase approval ─────────────────────────────"];
265
- for (const [key, value] of Object.entries(summary)) {
266
- if (value === null || value === undefined)
267
- continue;
268
- lines.push(` ${key.padEnd(18)} ${String(value)}`);
269
- }
270
- lines.push(` ${"you will pay".padEnd(18)} ${formatUsdc(amountAtomic)}`);
271
- lines.push(" ─────────────────────────────────────────────────", "");
272
- return lines.join("\n");
273
- }
274
255
  function readRequestFile(path) {
275
256
  let raw;
276
257
  try {