@arc402/daemon 1.2.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 (122) hide show
  1. package/bin/arc402-daemon +3 -0
  2. package/dist/abis.d.ts +20 -0
  3. package/dist/abis.d.ts.map +1 -0
  4. package/dist/abis.js +214 -0
  5. package/dist/abis.js.map +1 -0
  6. package/dist/api.d.ts +32 -0
  7. package/dist/api.d.ts.map +1 -0
  8. package/dist/api.js +430 -0
  9. package/dist/api.js.map +1 -0
  10. package/dist/auth-server.d.ts +50 -0
  11. package/dist/auth-server.d.ts.map +1 -0
  12. package/dist/auth-server.js +266 -0
  13. package/dist/auth-server.js.map +1 -0
  14. package/dist/bundler.d.ts +68 -0
  15. package/dist/bundler.d.ts.map +1 -0
  16. package/dist/bundler.js +181 -0
  17. package/dist/bundler.js.map +1 -0
  18. package/dist/capabilities.d.ts +17 -0
  19. package/dist/capabilities.d.ts.map +1 -0
  20. package/dist/capabilities.js +57 -0
  21. package/dist/capabilities.js.map +1 -0
  22. package/dist/compute-metering.d.ts +61 -0
  23. package/dist/compute-metering.d.ts.map +1 -0
  24. package/dist/compute-metering.js +299 -0
  25. package/dist/compute-metering.js.map +1 -0
  26. package/dist/compute-session.d.ts +100 -0
  27. package/dist/compute-session.d.ts.map +1 -0
  28. package/dist/compute-session.js +231 -0
  29. package/dist/compute-session.js.map +1 -0
  30. package/dist/config.d.ts +121 -0
  31. package/dist/config.d.ts.map +1 -0
  32. package/dist/config.js +397 -0
  33. package/dist/config.js.map +1 -0
  34. package/dist/context-manager.d.ts +17 -0
  35. package/dist/context-manager.d.ts.map +1 -0
  36. package/dist/context-manager.js +123 -0
  37. package/dist/context-manager.js.map +1 -0
  38. package/dist/credentials.d.ts +24 -0
  39. package/dist/credentials.d.ts.map +1 -0
  40. package/dist/credentials.js +80 -0
  41. package/dist/credentials.js.map +1 -0
  42. package/dist/delivery-client.d.ts +35 -0
  43. package/dist/delivery-client.d.ts.map +1 -0
  44. package/dist/delivery-client.js +231 -0
  45. package/dist/delivery-client.js.map +1 -0
  46. package/dist/endpoint-policy.d.ts +11 -0
  47. package/dist/endpoint-policy.d.ts.map +1 -0
  48. package/dist/endpoint-policy.js +107 -0
  49. package/dist/endpoint-policy.js.map +1 -0
  50. package/dist/event-watchers.d.ts +11 -0
  51. package/dist/event-watchers.d.ts.map +1 -0
  52. package/dist/event-watchers.js +24 -0
  53. package/dist/event-watchers.js.map +1 -0
  54. package/dist/exec-state.d.ts +37 -0
  55. package/dist/exec-state.d.ts.map +1 -0
  56. package/dist/exec-state.js +53 -0
  57. package/dist/exec-state.js.map +1 -0
  58. package/dist/file-delivery.d.ts +98 -0
  59. package/dist/file-delivery.d.ts.map +1 -0
  60. package/dist/file-delivery.js +473 -0
  61. package/dist/file-delivery.js.map +1 -0
  62. package/dist/handshake-watcher.d.ts +31 -0
  63. package/dist/handshake-watcher.d.ts.map +1 -0
  64. package/dist/handshake-watcher.js +157 -0
  65. package/dist/handshake-watcher.js.map +1 -0
  66. package/dist/hire-listener.d.ts +32 -0
  67. package/dist/hire-listener.d.ts.map +1 -0
  68. package/dist/hire-listener.js +237 -0
  69. package/dist/hire-listener.js.map +1 -0
  70. package/dist/index.d.ts +3 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +182 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/job-lifecycle.d.ts +62 -0
  75. package/dist/job-lifecycle.d.ts.map +1 -0
  76. package/dist/job-lifecycle.js +201 -0
  77. package/dist/job-lifecycle.js.map +1 -0
  78. package/dist/notify.d.ts +51 -0
  79. package/dist/notify.d.ts.map +1 -0
  80. package/dist/notify.js +276 -0
  81. package/dist/notify.js.map +1 -0
  82. package/dist/permission-gate.d.ts +30 -0
  83. package/dist/permission-gate.d.ts.map +1 -0
  84. package/dist/permission-gate.js +180 -0
  85. package/dist/permission-gate.js.map +1 -0
  86. package/dist/prompt-guard.d.ts +18 -0
  87. package/dist/prompt-guard.d.ts.map +1 -0
  88. package/dist/prompt-guard.js +70 -0
  89. package/dist/prompt-guard.js.map +1 -0
  90. package/dist/server.d.ts +27 -0
  91. package/dist/server.d.ts.map +1 -0
  92. package/dist/server.js +1956 -0
  93. package/dist/server.js.map +1 -0
  94. package/dist/session-manager.d.ts +55 -0
  95. package/dist/session-manager.d.ts.map +1 -0
  96. package/dist/session-manager.js +139 -0
  97. package/dist/session-manager.js.map +1 -0
  98. package/dist/signer.d.ts +19 -0
  99. package/dist/signer.d.ts.map +1 -0
  100. package/dist/signer.js +195 -0
  101. package/dist/signer.js.map +1 -0
  102. package/dist/token-metering.d.ts +42 -0
  103. package/dist/token-metering.d.ts.map +1 -0
  104. package/dist/token-metering.js +178 -0
  105. package/dist/token-metering.js.map +1 -0
  106. package/dist/userops.d.ts +24 -0
  107. package/dist/userops.d.ts.map +1 -0
  108. package/dist/userops.js +156 -0
  109. package/dist/userops.js.map +1 -0
  110. package/dist/wallet-monitor.d.ts +16 -0
  111. package/dist/wallet-monitor.d.ts.map +1 -0
  112. package/dist/wallet-monitor.js +57 -0
  113. package/dist/wallet-monitor.js.map +1 -0
  114. package/dist/worker-executor.d.ts +81 -0
  115. package/dist/worker-executor.d.ts.map +1 -0
  116. package/dist/worker-executor.js +527 -0
  117. package/dist/worker-executor.js.map +1 -0
  118. package/dist/worker-router.d.ts +63 -0
  119. package/dist/worker-router.d.ts.map +1 -0
  120. package/dist/worker-router.js +263 -0
  121. package/dist/worker-router.js.map +1 -0
  122. package/package.json +30 -0
@@ -0,0 +1,42 @@
1
+ export interface TokenUsageEntry {
2
+ model: string;
3
+ provider: string;
4
+ input: number;
5
+ output: number;
6
+ ts: string;
7
+ cost_usd?: number;
8
+ }
9
+ export interface AggregatedTokenUsage {
10
+ total_input: number;
11
+ total_output: number;
12
+ total_tokens: number;
13
+ estimated_cost_usd: number;
14
+ models_used: string[];
15
+ entries: number;
16
+ by_model: Record<string, {
17
+ input: number;
18
+ output: number;
19
+ calls: number;
20
+ cost_usd: number;
21
+ }>;
22
+ }
23
+ /**
24
+ * Get the path where the worker should write token usage for an agreement.
25
+ * The daemon sets this as an env var before calling exec_command.
26
+ */
27
+ export declare function getUsageReportPath(agreementId: string): string;
28
+ /**
29
+ * Create the parent directory and return the path.
30
+ * Called by the daemon before spawning the worker.
31
+ */
32
+ export declare function prepareUsageReport(agreementId: string): string;
33
+ /**
34
+ * Read the token usage report for an agreement and aggregate totals.
35
+ * Returns null if no report exists.
36
+ */
37
+ export declare function readUsageReport(agreementId: string): AggregatedTokenUsage | null;
38
+ /**
39
+ * Format token usage for CLI display.
40
+ */
41
+ export declare function formatUsageReport(usage: AggregatedTokenUsage): string;
42
+ //# sourceMappingURL=token-metering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-metering.d.ts","sourceRoot":"","sources":["../src/token-metering.ts"],"names":[],"mappings":"AA+BA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AA4BD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAI9D;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAqDhF;AAID;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAiBrE"}
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getUsageReportPath = getUsageReportPath;
37
+ exports.prepareUsageReport = prepareUsageReport;
38
+ exports.readUsageReport = readUsageReport;
39
+ exports.formatUsageReport = formatUsageReport;
40
+ /**
41
+ * ARC-402 Token Usage Metering
42
+ *
43
+ * Tracks LLM token consumption per agreement. The worker writes a usage report
44
+ * file during execution; the daemon reads it after delivery and includes the
45
+ * data in the execution receipt.
46
+ *
47
+ * Architecture:
48
+ * - Before execution: daemon creates a usage report path for the agreement
49
+ * - During execution: worker appends usage entries as it calls LLM APIs
50
+ * - After execution: daemon reads the report, aggregates totals, includes in receipt
51
+ *
52
+ * The worker writes entries in JSON Lines format to:
53
+ * /workroom/jobs/agreement-<id>/token-usage.jsonl
54
+ *
55
+ * Each line:
56
+ * {"model":"claude-sonnet-4-6","provider":"anthropic","input":1200,"output":450,"ts":"..."}
57
+ *
58
+ * This is non-invasive — no proxy, no network interception. The worker
59
+ * is responsible for reporting its own usage. OpenClaw agents can do this
60
+ * natively via session metadata.
61
+ */
62
+ const fs = __importStar(require("fs"));
63
+ const path = __importStar(require("path"));
64
+ const os = __importStar(require("os"));
65
+ const ARC402_DIR = path.join(os.homedir(), ".arc402");
66
+ const JOBS_DIR = path.join(ARC402_DIR, "jobs");
67
+ // ─── Known model pricing (USD per 1M tokens, as of 2026-03) ──────────────────
68
+ const MODEL_PRICING = {
69
+ // Anthropic
70
+ "claude-opus-4-6": { input: 15.0, output: 75.0 },
71
+ "claude-sonnet-4-6": { input: 3.0, output: 15.0 },
72
+ "claude-haiku-4-5": { input: 0.8, output: 4.0 },
73
+ // OpenAI
74
+ "gpt-5.4": { input: 2.5, output: 10.0 },
75
+ "gpt-5.3-codex": { input: 2.5, output: 10.0 },
76
+ "gpt-4o": { input: 2.5, output: 10.0 },
77
+ "gpt-4o-mini": { input: 0.15, output: 0.6 },
78
+ // Google
79
+ "gemini-2.5-pro": { input: 1.25, output: 10.0 },
80
+ "gemini-2.5-flash": { input: 0.15, output: 0.6 },
81
+ // Defaults
82
+ "default": { input: 2.0, output: 8.0 },
83
+ };
84
+ function estimateCost(model, inputTokens, outputTokens) {
85
+ const pricing = MODEL_PRICING[model] ?? MODEL_PRICING["default"];
86
+ return (inputTokens * pricing.input + outputTokens * pricing.output) / 1000000;
87
+ }
88
+ // ─── Usage report path ────────────────────────────────────────────────────────
89
+ /**
90
+ * Get the path where the worker should write token usage for an agreement.
91
+ * The daemon sets this as an env var before calling exec_command.
92
+ */
93
+ function getUsageReportPath(agreementId) {
94
+ return path.join(JOBS_DIR, `agreement-${agreementId}`, "token-usage.jsonl");
95
+ }
96
+ /**
97
+ * Create the parent directory and return the path.
98
+ * Called by the daemon before spawning the worker.
99
+ */
100
+ function prepareUsageReport(agreementId) {
101
+ const reportPath = getUsageReportPath(agreementId);
102
+ fs.mkdirSync(path.dirname(reportPath), { recursive: true });
103
+ return reportPath;
104
+ }
105
+ // ─── Read and aggregate ───────────────────────────────────────────────────────
106
+ /**
107
+ * Read the token usage report for an agreement and aggregate totals.
108
+ * Returns null if no report exists.
109
+ */
110
+ function readUsageReport(agreementId) {
111
+ const reportPath = getUsageReportPath(agreementId);
112
+ if (!fs.existsSync(reportPath))
113
+ return null;
114
+ const content = fs.readFileSync(reportPath, "utf-8").trim();
115
+ if (!content)
116
+ return null;
117
+ const lines = content.split("\n").filter(Boolean);
118
+ const entries = [];
119
+ for (const line of lines) {
120
+ try {
121
+ entries.push(JSON.parse(line));
122
+ }
123
+ catch {
124
+ // Skip malformed lines
125
+ }
126
+ }
127
+ if (entries.length === 0)
128
+ return null;
129
+ // Aggregate
130
+ const byModel = {};
131
+ let totalInput = 0;
132
+ let totalOutput = 0;
133
+ let totalCost = 0;
134
+ for (const entry of entries) {
135
+ totalInput += entry.input;
136
+ totalOutput += entry.output;
137
+ const model = entry.model || "unknown";
138
+ if (!byModel[model]) {
139
+ byModel[model] = { input: 0, output: 0, calls: 0, cost_usd: 0 };
140
+ }
141
+ byModel[model].input += entry.input;
142
+ byModel[model].output += entry.output;
143
+ byModel[model].calls += 1;
144
+ const cost = entry.cost_usd ?? estimateCost(model, entry.input, entry.output);
145
+ byModel[model].cost_usd += cost;
146
+ totalCost += cost;
147
+ }
148
+ return {
149
+ total_input: totalInput,
150
+ total_output: totalOutput,
151
+ total_tokens: totalInput + totalOutput,
152
+ estimated_cost_usd: Math.round(totalCost * 10000) / 10000, // 4 decimal places
153
+ models_used: Object.keys(byModel),
154
+ entries: entries.length,
155
+ by_model: byModel,
156
+ };
157
+ }
158
+ // ─── CLI display helper ───────────────────────────────────────────────────────
159
+ /**
160
+ * Format token usage for CLI display.
161
+ */
162
+ function formatUsageReport(usage) {
163
+ const lines = [];
164
+ lines.push(`Token Usage`);
165
+ lines.push(`───────────`);
166
+ lines.push(`Total tokens: ${usage.total_tokens.toLocaleString()} (${usage.total_input.toLocaleString()} in / ${usage.total_output.toLocaleString()} out)`);
167
+ lines.push(`Est. cost: $${usage.estimated_cost_usd.toFixed(4)}`);
168
+ lines.push(`LLM calls: ${usage.entries}`);
169
+ lines.push(``);
170
+ if (Object.keys(usage.by_model).length > 1) {
171
+ lines.push(`By model:`);
172
+ for (const [model, data] of Object.entries(usage.by_model)) {
173
+ lines.push(` ${model.padEnd(24)} ${data.calls} calls ${(data.input + data.output).toLocaleString()} tokens $${data.cost_usd.toFixed(4)}`);
174
+ }
175
+ }
176
+ return lines.join("\n");
177
+ }
178
+ //# sourceMappingURL=token-metering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-metering.js","sourceRoot":"","sources":["../src/token-metering.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * UserOperation builder and submitter for the ARC-402 daemon.
3
+ * Wraps protocol calls (accept, fulfill) into ERC-4337 UserOperations.
4
+ */
5
+ import { ethers } from "ethers";
6
+ import type { UserOperation } from "./bundler";
7
+ import type { DaemonConfig } from "./config";
8
+ export declare function encodeWalletCall(target: string, innerCalldata: string, value?: bigint): string;
9
+ export declare function buildAcceptCalldata(serviceAgreementAddress: string, agreementId: string, walletAddress: string): string;
10
+ export declare function buildFulfillCalldata(serviceAgreementAddress: string, agreementId: string, deliveryHash: string, walletAddress: string): string;
11
+ export declare class UserOpsManager {
12
+ private bundlerClient;
13
+ private provider;
14
+ private config;
15
+ private machineKeySigner;
16
+ constructor(config: DaemonConfig, provider: ethers.Provider, machineKeySigner?: ethers.Wallet);
17
+ private getBundlerGasPrice;
18
+ buildUserOp(callData: string, senderWallet: string): Promise<UserOperation>;
19
+ private hashUserOp;
20
+ submit(callData: string, senderWallet: string): Promise<string>;
21
+ waitForInclusion(userOpHash: string): Promise<void>;
22
+ pingBundler(): Promise<boolean>;
23
+ }
24
+ //# sourceMappingURL=userops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userops.d.ts","sourceRoot":"","sources":["../src/userops.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAY7C,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,KAAK,SAAY,GAChB,MAAM,CASR;AAED,wBAAgB,mBAAmB,CACjC,uBAAuB,EAAE,MAAM,EAC/B,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,MAAM,CAGR;AAED,wBAAgB,oBAAoB,CAClC,uBAAuB,EAAE,MAAM,EAC/B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,MAAM,CAGR;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,gBAAgB,CAAuB;gBAEnC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM;YAc/E,kBAAkB;IAqC1B,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAsBjF,OAAO,CAAC,UAAU;IA+CZ,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW/D,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CActC"}
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserOpsManager = void 0;
4
+ exports.encodeWalletCall = encodeWalletCall;
5
+ exports.buildAcceptCalldata = buildAcceptCalldata;
6
+ exports.buildFulfillCalldata = buildFulfillCalldata;
7
+ /**
8
+ * UserOperation builder and submitter for the ARC-402 daemon.
9
+ * Wraps protocol calls (accept, fulfill) into ERC-4337 UserOperations.
10
+ */
11
+ const ethers_1 = require("ethers");
12
+ const bundler_1 = require("./bundler");
13
+ const abis_1 = require("./abis");
14
+ // ServiceAgreement calldata encoders
15
+ const SA_IFACE = new ethers_1.ethers.Interface([
16
+ "function accept(uint256 agreementId) external",
17
+ "function commitDeliverable(uint256 agreementId, bytes32 deliverableHash) external",
18
+ ]);
19
+ // ARC402Wallet.executeContractCall param type
20
+ const WALLET_EXEC_IFACE = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_EXECUTE_ABI);
21
+ function encodeWalletCall(target, innerCalldata, value = BigInt(0)) {
22
+ return WALLET_EXEC_IFACE.encodeFunctionData("executeContractCall", [{
23
+ target,
24
+ data: innerCalldata,
25
+ value,
26
+ minReturnValue: BigInt(0),
27
+ maxApprovalAmount: BigInt(0),
28
+ approvalToken: ethers_1.ethers.ZeroAddress,
29
+ }]);
30
+ }
31
+ function buildAcceptCalldata(serviceAgreementAddress, agreementId, walletAddress) {
32
+ const inner = SA_IFACE.encodeFunctionData("accept", [BigInt(agreementId)]);
33
+ return encodeWalletCall(serviceAgreementAddress, inner);
34
+ }
35
+ function buildFulfillCalldata(serviceAgreementAddress, agreementId, deliveryHash, walletAddress) {
36
+ const inner = SA_IFACE.encodeFunctionData("commitDeliverable", [BigInt(agreementId), deliveryHash]);
37
+ return encodeWalletCall(serviceAgreementAddress, inner);
38
+ }
39
+ class UserOpsManager {
40
+ constructor(config, provider, machineKeySigner) {
41
+ this.config = config;
42
+ this.provider = provider;
43
+ this.machineKeySigner = machineKeySigner ?? null;
44
+ const bundlerUrl = config.bundler.endpoint || "https://api.pimlico.io/v2/base/rpc";
45
+ this.bundlerClient = new bundler_1.BundlerClient(bundlerUrl, config.network.entry_point, config.network.chain_id);
46
+ }
47
+ async getBundlerGasPrice() {
48
+ try {
49
+ const bundlerUrl = this.config.bundler.endpoint || "https://public.pimlico.io/v2/8453/rpc";
50
+ const response = await fetch(bundlerUrl, {
51
+ method: "POST",
52
+ headers: { "Content-Type": "application/json" },
53
+ body: JSON.stringify({
54
+ jsonrpc: "2.0",
55
+ id: 1,
56
+ method: "pimlico_getUserOperationGasPrice",
57
+ params: [],
58
+ }),
59
+ });
60
+ if (!response.ok)
61
+ throw new Error(`HTTP ${response.status}`);
62
+ const json = await response.json();
63
+ if (json.error)
64
+ throw new Error(JSON.stringify(json.error));
65
+ const standard = json.result?.standard;
66
+ if (standard) {
67
+ return {
68
+ maxFeePerGas: BigInt(standard.maxFeePerGas),
69
+ maxPriorityFeePerGas: BigInt(standard.maxPriorityFeePerGas),
70
+ };
71
+ }
72
+ }
73
+ catch {
74
+ // fallback to provider fee data
75
+ }
76
+ const feeData = await this.provider.getFeeData();
77
+ return {
78
+ maxFeePerGas: feeData.maxFeePerGas ?? BigInt(2000000000),
79
+ maxPriorityFeePerGas: feeData.maxPriorityFeePerGas ?? BigInt(1500000),
80
+ };
81
+ }
82
+ async buildUserOp(callData, senderWallet) {
83
+ const entryPointContract = new ethers_1.ethers.Contract(this.config.network.entry_point, ["function getNonce(address sender, uint192 key) external view returns (uint256)"], this.provider);
84
+ const nonce = await entryPointContract.getNonce(senderWallet, 0);
85
+ const { maxFeePerGas, maxPriorityFeePerGas } = await this.getBundlerGasPrice();
86
+ return {
87
+ sender: senderWallet,
88
+ nonce: ethers_1.ethers.toBeHex(nonce),
89
+ callData,
90
+ callGasLimit: ethers_1.ethers.toBeHex(300000),
91
+ verificationGasLimit: ethers_1.ethers.toBeHex(150000),
92
+ preVerificationGas: ethers_1.ethers.toBeHex(50000),
93
+ maxFeePerGas: ethers_1.ethers.toBeHex(maxFeePerGas),
94
+ maxPriorityFeePerGas: ethers_1.ethers.toBeHex(maxPriorityFeePerGas),
95
+ signature: "0x",
96
+ };
97
+ }
98
+ hashUserOp(userOp) {
99
+ const initCode = (userOp.factory && userOp.factoryData)
100
+ ? ethers_1.ethers.concat([userOp.factory, userOp.factoryData])
101
+ : "0x";
102
+ const paymasterAndData = userOp.paymaster
103
+ ? ethers_1.ethers.concat([
104
+ userOp.paymaster,
105
+ userOp.paymasterVerificationGasLimit ?? "0x",
106
+ userOp.paymasterPostOpGasLimit ?? "0x",
107
+ userOp.paymasterData ?? "0x",
108
+ ])
109
+ : "0x";
110
+ const verGasLimit = BigInt(userOp.verificationGasLimit);
111
+ const callGasLimit = BigInt(userOp.callGasLimit);
112
+ const accountGasLimits = ethers_1.ethers.zeroPadValue(ethers_1.ethers.toBeHex((verGasLimit << BigInt(128)) | callGasLimit), 32);
113
+ const maxPrioFee = BigInt(userOp.maxPriorityFeePerGas);
114
+ const maxFee = BigInt(userOp.maxFeePerGas);
115
+ const gasFees = ethers_1.ethers.zeroPadValue(ethers_1.ethers.toBeHex((maxPrioFee << BigInt(128)) | maxFee), 32);
116
+ const packedHash = ethers_1.ethers.keccak256(ethers_1.ethers.AbiCoder.defaultAbiCoder().encode(["address", "uint256", "bytes32", "bytes32", "bytes32", "uint256", "bytes32", "bytes32"], [
117
+ userOp.sender,
118
+ BigInt(userOp.nonce),
119
+ ethers_1.ethers.keccak256(initCode),
120
+ ethers_1.ethers.keccak256(userOp.callData),
121
+ accountGasLimits,
122
+ BigInt(userOp.preVerificationGas),
123
+ gasFees,
124
+ ethers_1.ethers.keccak256(paymasterAndData),
125
+ ]));
126
+ return ethers_1.ethers.keccak256(ethers_1.ethers.AbiCoder.defaultAbiCoder().encode(["bytes32", "address", "uint256"], [packedHash, this.config.network.entry_point, this.config.network.chain_id]));
127
+ }
128
+ async submit(callData, senderWallet) {
129
+ const userOp = await this.buildUserOp(callData, senderWallet);
130
+ if (this.machineKeySigner) {
131
+ const userOpHash = this.hashUserOp(userOp);
132
+ userOp.signature = await this.machineKeySigner.signMessage(ethers_1.ethers.getBytes(userOpHash));
133
+ }
134
+ return this.bundlerClient.sendUserOperation(userOp);
135
+ }
136
+ async waitForInclusion(userOpHash) {
137
+ await this.bundlerClient.getUserOperationReceipt(userOpHash);
138
+ }
139
+ async pingBundler() {
140
+ try {
141
+ const bundlerUrl = this.config.bundler.endpoint || "https://api.pimlico.io/v2/base/rpc";
142
+ const response = await fetch(bundlerUrl, {
143
+ method: "POST",
144
+ headers: { "Content-Type": "application/json" },
145
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_chainId", params: [] }),
146
+ signal: AbortSignal.timeout(5000),
147
+ });
148
+ return response.ok;
149
+ }
150
+ catch {
151
+ return false;
152
+ }
153
+ }
154
+ }
155
+ exports.UserOpsManager = UserOpsManager;
156
+ //# sourceMappingURL=userops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userops.js","sourceRoot":"","sources":["../src/userops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Wallet monitor — verifies wallet contract exists and is operational.
3
+ * Steps 4 and 5 of the daemon startup sequence (Spec 32 §3).
4
+ */
5
+ import { ethers } from "ethers";
6
+ import type { DaemonConfig } from "./config";
7
+ export interface WalletStatus {
8
+ contractAddress: string;
9
+ ownerAddress: string;
10
+ isFrozen: boolean;
11
+ machineKeyAuthorized: boolean;
12
+ ethBalance: string;
13
+ }
14
+ export declare function verifyWallet(config: DaemonConfig, provider: ethers.Provider, machineKeyAddress: string): Promise<WalletStatus>;
15
+ export declare function getWalletBalance(contractAddress: string, provider: ethers.Provider): Promise<string>;
16
+ //# sourceMappingURL=wallet-monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-monitor.d.ts","sourceRoot":"","sources":["../src/wallet-monitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAM7C,MAAM,WAAW,YAAY;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,YAAY,CAAC,CA0DvB;AAED,wBAAsB,gBAAgB,CACpC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ,GACxB,OAAO,CAAC,MAAM,CAAC,CAGjB"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyWallet = verifyWallet;
4
+ exports.getWalletBalance = getWalletBalance;
5
+ /**
6
+ * Wallet monitor — verifies wallet contract exists and is operational.
7
+ * Steps 4 and 5 of the daemon startup sequence (Spec 32 §3).
8
+ */
9
+ const ethers_1 = require("ethers");
10
+ const abis_1 = require("./abis");
11
+ async function verifyWallet(config, provider, machineKeyAddress) {
12
+ const { contract_address, owner_address } = config.wallet;
13
+ // Step 4: Verify wallet contract exists
14
+ const code = await provider.getCode(contract_address);
15
+ if (code === "0x") {
16
+ throw new Error(`No contract at wallet address ${contract_address}`);
17
+ }
18
+ const guardianContract = new ethers_1.ethers.Contract(contract_address, abis_1.ARC402_WALLET_GUARDIAN_ABI, provider);
19
+ // Verify owner matches config (if owner_address is set)
20
+ if (owner_address) {
21
+ const onChainOwner = await guardianContract.owner();
22
+ if (onChainOwner.toLowerCase() !== owner_address.toLowerCase()) {
23
+ throw new Error(`Wallet owner mismatch. Config: ${owner_address}, On-chain: ${onChainOwner}`);
24
+ }
25
+ }
26
+ const onChainOwner = await guardianContract.owner();
27
+ // Step 5: Check wallet is not frozen
28
+ const frozen = await guardianContract.frozen();
29
+ if (frozen) {
30
+ throw new Error("Wallet is frozen. Daemon cannot operate.");
31
+ }
32
+ // Check machine key authorization (best effort — v1 wallets may not have registry)
33
+ let machineKeyAuthorized = false;
34
+ try {
35
+ const machineKeyContract = new ethers_1.ethers.Contract(contract_address, abis_1.ARC402_WALLET_MACHINE_KEY_ABI, provider);
36
+ machineKeyAuthorized = await machineKeyContract.authorizedMachineKeys(machineKeyAddress);
37
+ }
38
+ catch {
39
+ // v1 wallet may not have machine key registry — policy-based auth, continue
40
+ machineKeyAuthorized = true;
41
+ }
42
+ // Get ETH balance
43
+ const balanceBig = await provider.getBalance(contract_address);
44
+ const ethBalance = ethers_1.ethers.formatEther(balanceBig);
45
+ return {
46
+ contractAddress: contract_address,
47
+ ownerAddress: onChainOwner,
48
+ isFrozen: false,
49
+ machineKeyAuthorized,
50
+ ethBalance,
51
+ };
52
+ }
53
+ async function getWalletBalance(contractAddress, provider) {
54
+ const balanceBig = await provider.getBalance(contractAddress);
55
+ return ethers_1.ethers.formatEther(balanceBig);
56
+ }
57
+ //# sourceMappingURL=wallet-monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-monitor.js","sourceRoot":"","sources":["../src/wallet-monitor.ts"],"names":[],"mappings":";;AAmBA,oCA8DC;AAED,4CAMC;AAzFD;;;GAGG;AACH,mCAAgC;AAEhC,iCAGgB;AAUT,KAAK,UAAU,YAAY,CAChC,MAAoB,EACpB,QAAyB,EACzB,iBAAyB;IAEzB,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC;IAE1D,wCAAwC;IACxC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACtD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,iCAAiC,gBAAgB,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,gBAAgB,GAAG,IAAI,eAAM,CAAC,QAAQ,CAC1C,gBAAgB,EAChB,iCAA0B,EAC1B,QAAQ,CACT,CAAC;IAEF,wDAAwD;IACxD,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,YAAY,GAAW,MAAM,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC5D,IAAI,YAAY,CAAC,WAAW,EAAE,KAAK,aAAa,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CACb,kCAAkC,aAAa,eAAe,YAAY,EAAE,CAC7E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAW,MAAM,gBAAgB,CAAC,KAAK,EAAE,CAAC;IAE5D,qCAAqC;IACrC,MAAM,MAAM,GAAY,MAAM,gBAAgB,CAAC,MAAM,EAAE,CAAC;IACxD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,mFAAmF;IACnF,IAAI,oBAAoB,GAAG,KAAK,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,kBAAkB,GAAG,IAAI,eAAM,CAAC,QAAQ,CAC5C,gBAAgB,EAChB,oCAA6B,EAC7B,QAAQ,CACT,CAAC;QACF,oBAAoB,GAAG,MAAM,kBAAkB,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,CAAC;IAC3F,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;QAC5E,oBAAoB,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED,kBAAkB;IAClB,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAC/D,MAAM,UAAU,GAAG,eAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAElD,OAAO;QACL,eAAe,EAAE,gBAAgB;QACjC,YAAY,EAAE,YAAY;QAC1B,QAAQ,EAAE,KAAK;QACf,oBAAoB;QACpB,UAAU;KACX,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,gBAAgB,CACpC,eAAuB,EACvB,QAAyB;IAEzB,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAC9D,OAAO,eAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,81 @@
1
+ import { ethers } from "ethers";
2
+ import { FileDeliveryManager } from "./file-delivery.js";
3
+ export type WorkerStatus = "queued" | "running" | "completed" | "failed";
4
+ export type AgentType = "openclaw" | "claude-code" | "codex" | "shell";
5
+ export interface WorkerExecution {
6
+ agreementId: string;
7
+ capability: string;
8
+ specHash: string;
9
+ jobDir: string;
10
+ agentType: AgentType;
11
+ pid: number | null;
12
+ status: WorkerStatus;
13
+ startedAt: number;
14
+ completedAt: number | null;
15
+ exitCode: number | null;
16
+ deliverableHash: string | null;
17
+ error: string | null;
18
+ }
19
+ export declare class WorkerExecutor {
20
+ private readonly maxConcurrentJobs;
21
+ private readonly jobTimeoutMs;
22
+ private readonly agentType;
23
+ private readonly autoExecute;
24
+ private readonly delivery;
25
+ private readonly signer;
26
+ private readonly serviceAgreementAddress;
27
+ private readonly jobs;
28
+ private queue;
29
+ private runningCount;
30
+ onJobCompleted: ((agreementId: string, rootHash: string) => void) | null;
31
+ onJobFailed: ((agreementId: string, error: string) => void) | null;
32
+ log: (entry: Record<string, unknown>) => void;
33
+ constructor(opts: {
34
+ maxConcurrentJobs?: number;
35
+ jobTimeoutSeconds?: number;
36
+ agentType?: AgentType;
37
+ autoExecute?: boolean;
38
+ delivery: FileDeliveryManager;
39
+ signer?: ethers.Signer | null;
40
+ serviceAgreementAddress?: string | null;
41
+ });
42
+ /**
43
+ * Enqueue a job. If auto_execute is true, starts immediately (up to concurrency limit).
44
+ * Returns the WorkerExecution record.
45
+ */
46
+ enqueue(params: {
47
+ agreementId: string;
48
+ capability: string;
49
+ specHash: string;
50
+ taskDescription?: string;
51
+ }): WorkerExecution;
52
+ /**
53
+ * Get current status of a job.
54
+ */
55
+ getStatus(agreementId: string): WorkerExecution | null;
56
+ /**
57
+ * Get all jobs (for status IPC command).
58
+ */
59
+ listAll(): WorkerExecution[];
60
+ /**
61
+ * Read job log contents (for worker-logs IPC command).
62
+ */
63
+ readLog(agreementId: string, tail?: number): string;
64
+ /**
65
+ * Cancel a queued job. Cannot cancel running jobs.
66
+ */
67
+ cancel(agreementId: string): boolean;
68
+ private drainQueue;
69
+ private runJob;
70
+ /**
71
+ * Execute a job via the host OpenClaw gateway OpenAI-compatible HTTP API.
72
+ * Uses POST /v1/chat/completions (not /agent).
73
+ */
74
+ private runViaGateway;
75
+ private spawnAgent;
76
+ private buildCommand;
77
+ private buildTask;
78
+ private collectDeliverables;
79
+ private toPublic;
80
+ }
81
+ //# sourceMappingURL=worker-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-executor.d.ts","sourceRoot":"","sources":["../src/worker-executor.ts"],"names":[],"mappings":"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"}