@hardclaw/mcp-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # HardClaw MCP Server
2
+
3
+ Model Context Protocol server and TypeScript SDK for the HardClaw Proof-of-Verification protocol.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @hardclaw/mcp-server
9
+ ```
10
+
11
+ Or use directly with npx:
12
+
13
+ ```bash
14
+ npx @hardclaw/mcp-server
15
+ ```
16
+
17
+ ## MCP Configuration
18
+
19
+ Add to your MCP client settings:
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "hardclaw": {
25
+ "command": "npx",
26
+ "args": ["-y", "@hardclaw/mcp-server"]
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ ## Available Tools
33
+
34
+ ### Wallet Management
35
+ - **create_wallet** - Generate a new wallet with BIP39 mnemonic
36
+ - **load_wallet** - Load wallet from mnemonic phrase
37
+ - **get_address** - Get current wallet address
38
+
39
+ ### Job Lifecycle
40
+ - **submit_job** - Submit a job with bounty
41
+ - `description`: Job description
42
+ - `input`: Input data (hex or plain text)
43
+ - `bounty`: Bounty in HCLAW tokens
44
+ - `jobType`: "deterministic" or "subjective"
45
+ - `expectedHash`: Expected output hash (optional, for deterministic)
46
+ - `timeout`: Timeout in seconds (default: 3600)
47
+
48
+ - **submit_solution** - Submit solution for a job
49
+ - `jobId`: Job ID (hex hash)
50
+ - `output`: Solution output (hex or plain text)
51
+
52
+ - **verify_solution** - Verify a solution (verifier operation)
53
+ - `jobId`: Job ID
54
+ - `solutionId`: Solution ID
55
+
56
+ ### Network
57
+ - **get_balance** - Check wallet balance
58
+ - **list_jobs** - List available jobs
59
+
60
+ ## Usage Example
61
+
62
+ ### For Agents (Solvers)
63
+
64
+ ```typescript
65
+ // 1. Create or load wallet
66
+ await mcp.call("create_wallet");
67
+
68
+ // 2. Wait for jobs from requesters
69
+ await mcp.call("list_jobs", { limit: 5 });
70
+
71
+ // 3. Execute work off-chain
72
+
73
+ // 4. Submit solution
74
+ await mcp.call("submit_solution", {
75
+ jobId: "abc123...",
76
+ output: "computation result here"
77
+ });
78
+
79
+ // 5. Earn 95% of bounty when verified
80
+ ```
81
+
82
+ ### For Requesters
83
+
84
+ ```typescript
85
+ // 1. Load wallet
86
+ await mcp.call("load_wallet", {
87
+ mnemonic: "your twelve or twenty four words..."
88
+ });
89
+
90
+ // 2. Submit job
91
+ await mcp.call("submit_job", {
92
+ description: "Analyze sentiment of text",
93
+ input: "The product exceeded expectations",
94
+ bounty: 10,
95
+ jobType: "subjective"
96
+ });
97
+ ```
98
+
99
+ ### For Verifiers
100
+
101
+ ```typescript
102
+ // 1. Load wallet with stake
103
+ await mcp.call("load_wallet", { mnemonic: "..." });
104
+
105
+ // 2. Verify solutions
106
+ await mcp.call("verify_solution", {
107
+ jobId: "abc123...",
108
+ solutionId: "def456..."
109
+ });
110
+
111
+ // 3. Earn 4% of bounty
112
+ ```
113
+
114
+ ## Network Integration
115
+
116
+ The MCP server operates in local/simulation mode by default. To connect to the live network:
117
+
118
+ 1. Install and run `hardclaw-node`
119
+ 2. The MCP server will auto-detect and connect
120
+ 3. All operations will be broadcast to the network
121
+
122
+ ## Development
123
+
124
+ ```bash
125
+ npm install
126
+ npm run build
127
+ npm start
128
+ ```
129
+
130
+ ## License
131
+
132
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,275 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { HardClawSDK } from "./sdk.js";
6
+ const sdk = new HardClawSDK();
7
+ const server = new Server({
8
+ name: "hardclaw-mcp",
9
+ version: "0.1.0",
10
+ }, {
11
+ capabilities: {
12
+ tools: {},
13
+ },
14
+ });
15
+ const tools = [
16
+ {
17
+ name: "create_wallet",
18
+ description: "Create a new HardClaw wallet with BIP39 mnemonic",
19
+ inputSchema: {
20
+ type: "object",
21
+ properties: {},
22
+ required: [],
23
+ },
24
+ },
25
+ {
26
+ name: "load_wallet",
27
+ description: "Load wallet from mnemonic phrase",
28
+ inputSchema: {
29
+ type: "object",
30
+ properties: {
31
+ mnemonic: {
32
+ type: "string",
33
+ description: "BIP39 mnemonic phrase (12 or 24 words)",
34
+ },
35
+ },
36
+ required: ["mnemonic"],
37
+ },
38
+ },
39
+ {
40
+ name: "get_address",
41
+ description: "Get the current wallet address",
42
+ inputSchema: {
43
+ type: "object",
44
+ properties: {},
45
+ required: [],
46
+ },
47
+ },
48
+ {
49
+ name: "submit_job",
50
+ description: "Submit a job to the HardClaw network with a bounty",
51
+ inputSchema: {
52
+ type: "object",
53
+ properties: {
54
+ description: {
55
+ type: "string",
56
+ description: "Description of the job",
57
+ },
58
+ input: {
59
+ type: "string",
60
+ description: "Input data (hex-encoded or plain text)",
61
+ },
62
+ bounty: {
63
+ type: "number",
64
+ description: "Bounty amount in HCLAW tokens",
65
+ },
66
+ jobType: {
67
+ type: "string",
68
+ enum: ["deterministic", "subjective"],
69
+ description: "Type of job verification",
70
+ },
71
+ expectedHash: {
72
+ type: "string",
73
+ description: "Expected output hash for deterministic jobs (optional)",
74
+ },
75
+ timeout: {
76
+ type: "number",
77
+ description: "Job timeout in seconds (default: 3600)",
78
+ },
79
+ },
80
+ required: ["description", "input", "bounty", "jobType"],
81
+ },
82
+ },
83
+ {
84
+ name: "submit_solution",
85
+ description: "Submit a solution for a job",
86
+ inputSchema: {
87
+ type: "object",
88
+ properties: {
89
+ jobId: {
90
+ type: "string",
91
+ description: "Job ID (hex hash)",
92
+ },
93
+ output: {
94
+ type: "string",
95
+ description: "Solution output data (hex-encoded or plain text)",
96
+ },
97
+ },
98
+ required: ["jobId", "output"],
99
+ },
100
+ },
101
+ {
102
+ name: "verify_solution",
103
+ description: "Verify a solution against a job (verifier operation)",
104
+ inputSchema: {
105
+ type: "object",
106
+ properties: {
107
+ jobId: {
108
+ type: "string",
109
+ description: "Job ID (hex hash)",
110
+ },
111
+ solutionId: {
112
+ type: "string",
113
+ description: "Solution ID (hex hash)",
114
+ },
115
+ },
116
+ required: ["jobId", "solutionId"],
117
+ },
118
+ },
119
+ {
120
+ name: "get_balance",
121
+ description: "Get wallet balance (requires network connection)",
122
+ inputSchema: {
123
+ type: "object",
124
+ properties: {},
125
+ required: [],
126
+ },
127
+ },
128
+ {
129
+ name: "list_jobs",
130
+ description: "List available jobs from the network",
131
+ inputSchema: {
132
+ type: "object",
133
+ properties: {
134
+ limit: {
135
+ type: "number",
136
+ description: "Maximum number of jobs to return (default: 10)",
137
+ },
138
+ },
139
+ required: [],
140
+ },
141
+ },
142
+ ];
143
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
144
+ tools,
145
+ }));
146
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
147
+ const { name, arguments: args } = request.params;
148
+ try {
149
+ switch (name) {
150
+ case "create_wallet": {
151
+ const result = sdk.createWallet();
152
+ return {
153
+ content: [
154
+ {
155
+ type: "text",
156
+ text: `Created new wallet\nAddress: ${result.address}\nMnemonic: ${result.mnemonic}\n\n⚠️ Save this mnemonic securely!`,
157
+ },
158
+ ],
159
+ };
160
+ }
161
+ case "load_wallet": {
162
+ const { mnemonic } = args;
163
+ const address = sdk.loadWallet(mnemonic);
164
+ return {
165
+ content: [
166
+ {
167
+ type: "text",
168
+ text: `Loaded wallet\nAddress: ${address}`,
169
+ },
170
+ ],
171
+ };
172
+ }
173
+ case "get_address": {
174
+ const address = sdk.getAddress();
175
+ return {
176
+ content: [
177
+ {
178
+ type: "text",
179
+ text: address,
180
+ },
181
+ ],
182
+ };
183
+ }
184
+ case "submit_job": {
185
+ const { description, input, bounty, jobType, expectedHash, timeout } = args;
186
+ const job = sdk.createJob({
187
+ description,
188
+ input,
189
+ bounty,
190
+ jobType,
191
+ expectedHash,
192
+ timeout: timeout || 3600,
193
+ });
194
+ return {
195
+ content: [
196
+ {
197
+ type: "text",
198
+ text: `Job created:\n ID: ${job.id}\n Type: ${job.jobType}\n Bounty: ${bounty} HCLAW\n Burn: 1 HCLAW\n Timeout: ${job.timeout}s\n\n📡 Broadcast this to the network using hardclaw-node`,
199
+ },
200
+ ],
201
+ };
202
+ }
203
+ case "submit_solution": {
204
+ const { jobId, output } = args;
205
+ const solution = sdk.createSolution(jobId, output);
206
+ return {
207
+ content: [
208
+ {
209
+ type: "text",
210
+ text: `Solution created:\n Job ID: ${jobId}\n Solution ID: ${solution.id}\n Solver: ${solution.solver}\n\n📡 Broadcast this to the network using hardclaw-node`,
211
+ },
212
+ ],
213
+ };
214
+ }
215
+ case "verify_solution": {
216
+ const { jobId, solutionId } = args;
217
+ const result = sdk.verifySolution(jobId, solutionId);
218
+ return {
219
+ content: [
220
+ {
221
+ type: "text",
222
+ text: `Verification result:\n Valid: ${result.valid}\n Reason: ${result.reason || "N/A"}\n\n${result.valid ? "✅ Solution passes verification" : "❌ Solution failed verification"}`,
223
+ },
224
+ ],
225
+ };
226
+ }
227
+ case "get_balance": {
228
+ const address = sdk.getAddress();
229
+ return {
230
+ content: [
231
+ {
232
+ type: "text",
233
+ text: `Balance for ${address}: 0.0 HCLAW\n\n⚠️ Balance lookup requires connection to hardclaw-node`,
234
+ },
235
+ ],
236
+ };
237
+ }
238
+ case "list_jobs": {
239
+ const { limit = 10 } = args;
240
+ return {
241
+ content: [
242
+ {
243
+ type: "text",
244
+ text: `Fetching ${limit} jobs from network...\n\n⚠️ Job listing requires connection to hardclaw-node`,
245
+ },
246
+ ],
247
+ };
248
+ }
249
+ default:
250
+ throw new Error(`Unknown tool: ${name}`);
251
+ }
252
+ }
253
+ catch (error) {
254
+ const message = error instanceof Error ? error.message : String(error);
255
+ return {
256
+ content: [
257
+ {
258
+ type: "text",
259
+ text: `Error: ${message}`,
260
+ },
261
+ ],
262
+ isError: true,
263
+ };
264
+ }
265
+ });
266
+ async function main() {
267
+ const transport = new StdioServerTransport();
268
+ await server.connect(transport);
269
+ console.error("HardClaw MCP server running on stdio");
270
+ }
271
+ main().catch((error) => {
272
+ console.error("Fatal error:", error);
273
+ process.exit(1);
274
+ });
275
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GAEvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;AAE9B,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,cAAc;IACpB,OAAO,EAAE,OAAO;CACjB,EACD;IACE,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;KACV;CACF,CACF,CAAC;AAEF,MAAM,KAAK,GAAW;IACpB;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,kDAAkD;QAC/D,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,EAAE;SACb;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,kCAAkC;QAC/C,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wCAAwC;iBACtD;aACF;YACD,QAAQ,EAAE,CAAC,UAAU,CAAC;SACvB;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,gCAAgC;QAC7C,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,EAAE;SACb;KACF;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,oDAAoD;QACjE,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wBAAwB;iBACtC;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wCAAwC;iBACtD;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,+BAA+B;iBAC7C;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,eAAe,EAAE,YAAY,CAAC;oBACrC,WAAW,EAAE,0BAA0B;iBACxC;gBACD,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wDAAwD;iBACtE;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wCAAwC;iBACtD;aACF;YACD,QAAQ,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC;SACxD;KACF;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,6BAA6B;QAC1C,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,mBAAmB;iBACjC;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kDAAkD;iBAChE;aACF;YACD,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;SAC9B;KACF;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,sDAAsD;QACnE,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,mBAAmB;iBACjC;gBACD,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wBAAwB;iBACtC;aACF;YACD,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;SAClC;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,kDAAkD;QAC/D,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,EAAE;SACb;KACF;IACD;QACE,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,sCAAsC;QACnD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,gDAAgD;iBAC9D;aACF;YACD,QAAQ,EAAE,EAAE;SACb;KACF;CACF,CAAC;AAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK;CACN,CAAC,CAAC,CAAC;AAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAEjD,IAAI,CAAC;QACH,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,eAAe,CAAC,CAAC,CAAC;gBACrB,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;gBAClC,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,gCAAgC,MAAM,CAAC,OAAO,eAAe,MAAM,CAAC,QAAQ,sCAAsC;yBACzH;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,EAAE,QAAQ,EAAE,GAAG,IAA4B,CAAC;gBAClD,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACzC,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,2BAA2B,OAAO,EAAE;yBAC3C;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;gBACjC,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,OAAO;yBACd;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,GAClE,IAOC,CAAC;gBAEJ,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC;oBACxB,WAAW;oBACX,KAAK;oBACL,MAAM;oBACN,OAAO;oBACP,YAAY;oBACZ,OAAO,EAAE,OAAO,IAAI,IAAI;iBACzB,CAAC,CAAC;gBAEH,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,uBAAuB,GAAG,CAAC,EAAE,aAAa,GAAG,CAAC,OAAO,eAAe,MAAM,uCAAuC,GAAG,CAAC,OAAO,2DAA2D;yBAC9L;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAyC,CAAC;gBACpE,MAAM,QAAQ,GAAG,GAAG,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAEnD,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,gCAAgC,KAAK,oBAAoB,QAAQ,CAAC,EAAE,eAAe,QAAQ,CAAC,MAAM,0DAA0D;yBACnK;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,IAG7B,CAAC;gBACF,MAAM,MAAM,GAAG,GAAG,CAAC,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;gBAErD,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,kCAAkC,MAAM,CAAC,KAAK,eAAe,MAAM,CAAC,MAAM,IAAI,KAAK,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,gCAAgC,EAAE;yBACrL;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;gBACjC,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,eAAe,OAAO,wEAAwE;yBACrG;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,IAA0B,CAAC;gBAClD,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,YAAY,KAAK,+EAA+E;yBACvG;qBACF;iBACF,CAAC;YACJ,CAAC;YAED;gBACE,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,UAAU,OAAO,EAAE;iBAC1B;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;AACxD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/dist/sdk.d.ts ADDED
@@ -0,0 +1,48 @@
1
+ export interface Job {
2
+ id: string;
3
+ jobType: "deterministic" | "subjective";
4
+ requester: string;
5
+ description: string;
6
+ input: string;
7
+ bounty: number;
8
+ burnFee: number;
9
+ timeout: number;
10
+ expectedHash?: string;
11
+ timestamp: number;
12
+ }
13
+ export interface Solution {
14
+ id: string;
15
+ jobId: string;
16
+ solver: string;
17
+ output: string;
18
+ timestamp: number;
19
+ signature: string;
20
+ }
21
+ export interface VerificationResult {
22
+ valid: boolean;
23
+ reason?: string;
24
+ }
25
+ export declare class HardClawSDK {
26
+ private keypair;
27
+ private mnemonic;
28
+ createWallet(): {
29
+ address: string;
30
+ mnemonic: string;
31
+ };
32
+ loadWallet(mnemonic: string): string;
33
+ getAddress(): string;
34
+ createJob(params: {
35
+ description: string;
36
+ input: string;
37
+ bounty: number;
38
+ jobType: "deterministic" | "subjective";
39
+ expectedHash?: string;
40
+ timeout: number;
41
+ }): Job;
42
+ createSolution(jobId: string, output: string): Solution;
43
+ verifySolution(jobId: string, solutionId: string): VerificationResult;
44
+ private publicKeyToAddress;
45
+ private hash;
46
+ private encodeInput;
47
+ }
48
+ //# sourceMappingURL=sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,eAAe,GAAG,YAAY,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,QAAQ,CAAuB;IAEvC,YAAY,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAWrD,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAapC,UAAU,IAAI,MAAM;IAOpB,SAAS,CAAC,MAAM,EAAE;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,eAAe,GAAG,YAAY,CAAC;QACxC,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,GAAG;IAgCP,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ;IA2BvD,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,kBAAkB;IAarE,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,WAAW;CAQpB"}
package/dist/sdk.js ADDED
@@ -0,0 +1,106 @@
1
+ import * as nacl from "tweetnacl";
2
+ import * as bip39 from "bip39";
3
+ import { derivePath } from "ed25519-hd-key";
4
+ import { createHash } from "crypto";
5
+ export class HardClawSDK {
6
+ keypair = null;
7
+ mnemonic = null;
8
+ createWallet() {
9
+ this.mnemonic = bip39.generateMnemonic(256); // 24 words
10
+ const seed = bip39.mnemonicToSeedSync(this.mnemonic);
11
+ const derivedSeed = derivePath("m/44'/501'/0'/0'", seed.toString("hex")).key;
12
+ this.keypair = nacl.sign.keyPair.fromSeed(derivedSeed);
13
+ const address = this.publicKeyToAddress(this.keypair.publicKey);
14
+ return { address, mnemonic: this.mnemonic };
15
+ }
16
+ loadWallet(mnemonic) {
17
+ if (!bip39.validateMnemonic(mnemonic)) {
18
+ throw new Error("Invalid mnemonic phrase");
19
+ }
20
+ this.mnemonic = mnemonic;
21
+ const seed = bip39.mnemonicToSeedSync(mnemonic);
22
+ const derivedSeed = derivePath("m/44'/501'/0'/0'", seed.toString("hex")).key;
23
+ this.keypair = nacl.sign.keyPair.fromSeed(derivedSeed);
24
+ return this.publicKeyToAddress(this.keypair.publicKey);
25
+ }
26
+ getAddress() {
27
+ if (!this.keypair) {
28
+ throw new Error("No wallet loaded. Use createWallet() or loadWallet() first.");
29
+ }
30
+ return this.publicKeyToAddress(this.keypair.publicKey);
31
+ }
32
+ createJob(params) {
33
+ if (!this.keypair) {
34
+ throw new Error("No wallet loaded");
35
+ }
36
+ const inputData = this.encodeInput(params.input);
37
+ const expectedHash = params.expectedHash || this.hash(Buffer.from(inputData, "hex"));
38
+ const job = {
39
+ id: this.hash(Buffer.concat([
40
+ this.keypair.publicKey,
41
+ Buffer.from(inputData, "hex"),
42
+ Buffer.from(params.description),
43
+ Buffer.from(Date.now().toString()),
44
+ ])),
45
+ jobType: params.jobType,
46
+ requester: this.publicKeyToAddress(this.keypair.publicKey),
47
+ description: params.description,
48
+ input: inputData,
49
+ bounty: params.bounty,
50
+ burnFee: 1,
51
+ timeout: params.timeout,
52
+ expectedHash: params.jobType === "deterministic" ? expectedHash : undefined,
53
+ timestamp: Date.now(),
54
+ };
55
+ return job;
56
+ }
57
+ createSolution(jobId, output) {
58
+ if (!this.keypair) {
59
+ throw new Error("No wallet loaded");
60
+ }
61
+ const outputData = this.encodeInput(output);
62
+ const solutionData = Buffer.concat([
63
+ Buffer.from(jobId, "hex"),
64
+ this.keypair.publicKey,
65
+ Buffer.from(outputData, "hex"),
66
+ Buffer.from(Date.now().toString()),
67
+ ]);
68
+ const signature = nacl.sign.detached(solutionData, this.keypair.secretKey);
69
+ const solution = {
70
+ id: this.hash(solutionData),
71
+ jobId,
72
+ solver: this.publicKeyToAddress(this.keypair.publicKey),
73
+ output: outputData,
74
+ timestamp: Date.now(),
75
+ signature: Buffer.from(signature).toString("hex"),
76
+ };
77
+ return solution;
78
+ }
79
+ verifySolution(jobId, solutionId) {
80
+ // Simulated verification - in production this would:
81
+ // 1. Fetch the job from network
82
+ // 2. Fetch the solution from network
83
+ // 3. Verify signature
84
+ // 4. Check hash match (deterministic) or run Schelling voting (subjective)
85
+ return {
86
+ valid: true,
87
+ reason: "Verification simulated - connect to hardclaw-node for real verification",
88
+ };
89
+ }
90
+ publicKeyToAddress(publicKey) {
91
+ const hash = this.hash(Buffer.from(publicKey));
92
+ return `hc1${hash.slice(0, 40)}`;
93
+ }
94
+ hash(data) {
95
+ return createHash("blake2s256").update(data).digest("hex");
96
+ }
97
+ encodeInput(input) {
98
+ // If already hex, return as-is
99
+ if (/^[0-9a-f]+$/i.test(input)) {
100
+ return input.toLowerCase();
101
+ }
102
+ // Otherwise encode as hex
103
+ return Buffer.from(input).toString("hex");
104
+ }
105
+ }
106
+ //# sourceMappingURL=sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@hardclaw/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "Model Context Protocol server for HardClaw - Proof-of-Verification Protocol",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "hardclaw-mcp": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/index.js",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "mcp",
18
+ "model-context-protocol",
19
+ "hardclaw",
20
+ "blockchain",
21
+ "proof-of-verification",
22
+ "agents"
23
+ ],
24
+ "author": "HardClaw Collective",
25
+ "license": "MIT",
26
+ "dependencies": {
27
+ "@modelcontextprotocol/sdk": "^0.5.0",
28
+ "ed25519-hd-key": "^1.3.0",
29
+ "tweetnacl": "^1.0.3",
30
+ "bip39": "^3.1.0",
31
+ "blake3": "^2.1.7",
32
+ "zod": "^3.22.4"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^20.11.0",
36
+ "typescript": "^5.3.3"
37
+ },
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ }
41
+ }
package/src/index.ts ADDED
@@ -0,0 +1,312 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import {
6
+ CallToolRequestSchema,
7
+ ListToolsRequestSchema,
8
+ Tool,
9
+ } from "@modelcontextprotocol/sdk/types.js";
10
+ import { HardClawSDK } from "./sdk.js";
11
+
12
+ const sdk = new HardClawSDK();
13
+
14
+ const server = new Server(
15
+ {
16
+ name: "hardclaw-mcp",
17
+ version: "0.1.0",
18
+ },
19
+ {
20
+ capabilities: {
21
+ tools: {},
22
+ },
23
+ }
24
+ );
25
+
26
+ const tools: Tool[] = [
27
+ {
28
+ name: "create_wallet",
29
+ description: "Create a new HardClaw wallet with BIP39 mnemonic",
30
+ inputSchema: {
31
+ type: "object",
32
+ properties: {},
33
+ required: [],
34
+ },
35
+ },
36
+ {
37
+ name: "load_wallet",
38
+ description: "Load wallet from mnemonic phrase",
39
+ inputSchema: {
40
+ type: "object",
41
+ properties: {
42
+ mnemonic: {
43
+ type: "string",
44
+ description: "BIP39 mnemonic phrase (12 or 24 words)",
45
+ },
46
+ },
47
+ required: ["mnemonic"],
48
+ },
49
+ },
50
+ {
51
+ name: "get_address",
52
+ description: "Get the current wallet address",
53
+ inputSchema: {
54
+ type: "object",
55
+ properties: {},
56
+ required: [],
57
+ },
58
+ },
59
+ {
60
+ name: "submit_job",
61
+ description: "Submit a job to the HardClaw network with a bounty",
62
+ inputSchema: {
63
+ type: "object",
64
+ properties: {
65
+ description: {
66
+ type: "string",
67
+ description: "Description of the job",
68
+ },
69
+ input: {
70
+ type: "string",
71
+ description: "Input data (hex-encoded or plain text)",
72
+ },
73
+ bounty: {
74
+ type: "number",
75
+ description: "Bounty amount in HCLAW tokens",
76
+ },
77
+ jobType: {
78
+ type: "string",
79
+ enum: ["deterministic", "subjective"],
80
+ description: "Type of job verification",
81
+ },
82
+ expectedHash: {
83
+ type: "string",
84
+ description: "Expected output hash for deterministic jobs (optional)",
85
+ },
86
+ timeout: {
87
+ type: "number",
88
+ description: "Job timeout in seconds (default: 3600)",
89
+ },
90
+ },
91
+ required: ["description", "input", "bounty", "jobType"],
92
+ },
93
+ },
94
+ {
95
+ name: "submit_solution",
96
+ description: "Submit a solution for a job",
97
+ inputSchema: {
98
+ type: "object",
99
+ properties: {
100
+ jobId: {
101
+ type: "string",
102
+ description: "Job ID (hex hash)",
103
+ },
104
+ output: {
105
+ type: "string",
106
+ description: "Solution output data (hex-encoded or plain text)",
107
+ },
108
+ },
109
+ required: ["jobId", "output"],
110
+ },
111
+ },
112
+ {
113
+ name: "verify_solution",
114
+ description: "Verify a solution against a job (verifier operation)",
115
+ inputSchema: {
116
+ type: "object",
117
+ properties: {
118
+ jobId: {
119
+ type: "string",
120
+ description: "Job ID (hex hash)",
121
+ },
122
+ solutionId: {
123
+ type: "string",
124
+ description: "Solution ID (hex hash)",
125
+ },
126
+ },
127
+ required: ["jobId", "solutionId"],
128
+ },
129
+ },
130
+ {
131
+ name: "get_balance",
132
+ description: "Get wallet balance (requires network connection)",
133
+ inputSchema: {
134
+ type: "object",
135
+ properties: {},
136
+ required: [],
137
+ },
138
+ },
139
+ {
140
+ name: "list_jobs",
141
+ description: "List available jobs from the network",
142
+ inputSchema: {
143
+ type: "object",
144
+ properties: {
145
+ limit: {
146
+ type: "number",
147
+ description: "Maximum number of jobs to return (default: 10)",
148
+ },
149
+ },
150
+ required: [],
151
+ },
152
+ },
153
+ ];
154
+
155
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
156
+ tools,
157
+ }));
158
+
159
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
160
+ const { name, arguments: args } = request.params;
161
+
162
+ try {
163
+ switch (name) {
164
+ case "create_wallet": {
165
+ const result = sdk.createWallet();
166
+ return {
167
+ content: [
168
+ {
169
+ type: "text",
170
+ text: `Created new wallet\nAddress: ${result.address}\nMnemonic: ${result.mnemonic}\n\n⚠️ Save this mnemonic securely!`,
171
+ },
172
+ ],
173
+ };
174
+ }
175
+
176
+ case "load_wallet": {
177
+ const { mnemonic } = args as { mnemonic: string };
178
+ const address = sdk.loadWallet(mnemonic);
179
+ return {
180
+ content: [
181
+ {
182
+ type: "text",
183
+ text: `Loaded wallet\nAddress: ${address}`,
184
+ },
185
+ ],
186
+ };
187
+ }
188
+
189
+ case "get_address": {
190
+ const address = sdk.getAddress();
191
+ return {
192
+ content: [
193
+ {
194
+ type: "text",
195
+ text: address,
196
+ },
197
+ ],
198
+ };
199
+ }
200
+
201
+ case "submit_job": {
202
+ const { description, input, bounty, jobType, expectedHash, timeout } =
203
+ args as {
204
+ description: string;
205
+ input: string;
206
+ bounty: number;
207
+ jobType: "deterministic" | "subjective";
208
+ expectedHash?: string;
209
+ timeout?: number;
210
+ };
211
+
212
+ const job = sdk.createJob({
213
+ description,
214
+ input,
215
+ bounty,
216
+ jobType,
217
+ expectedHash,
218
+ timeout: timeout || 3600,
219
+ });
220
+
221
+ return {
222
+ content: [
223
+ {
224
+ type: "text",
225
+ text: `Job created:\n ID: ${job.id}\n Type: ${job.jobType}\n Bounty: ${bounty} HCLAW\n Burn: 1 HCLAW\n Timeout: ${job.timeout}s\n\n📡 Broadcast this to the network using hardclaw-node`,
226
+ },
227
+ ],
228
+ };
229
+ }
230
+
231
+ case "submit_solution": {
232
+ const { jobId, output } = args as { jobId: string; output: string };
233
+ const solution = sdk.createSolution(jobId, output);
234
+
235
+ return {
236
+ content: [
237
+ {
238
+ type: "text",
239
+ text: `Solution created:\n Job ID: ${jobId}\n Solution ID: ${solution.id}\n Solver: ${solution.solver}\n\n📡 Broadcast this to the network using hardclaw-node`,
240
+ },
241
+ ],
242
+ };
243
+ }
244
+
245
+ case "verify_solution": {
246
+ const { jobId, solutionId } = args as {
247
+ jobId: string;
248
+ solutionId: string;
249
+ };
250
+ const result = sdk.verifySolution(jobId, solutionId);
251
+
252
+ return {
253
+ content: [
254
+ {
255
+ type: "text",
256
+ text: `Verification result:\n Valid: ${result.valid}\n Reason: ${result.reason || "N/A"}\n\n${result.valid ? "✅ Solution passes verification" : "❌ Solution failed verification"}`,
257
+ },
258
+ ],
259
+ };
260
+ }
261
+
262
+ case "get_balance": {
263
+ const address = sdk.getAddress();
264
+ return {
265
+ content: [
266
+ {
267
+ type: "text",
268
+ text: `Balance for ${address}: 0.0 HCLAW\n\n⚠️ Balance lookup requires connection to hardclaw-node`,
269
+ },
270
+ ],
271
+ };
272
+ }
273
+
274
+ case "list_jobs": {
275
+ const { limit = 10 } = args as { limit?: number };
276
+ return {
277
+ content: [
278
+ {
279
+ type: "text",
280
+ text: `Fetching ${limit} jobs from network...\n\n⚠️ Job listing requires connection to hardclaw-node`,
281
+ },
282
+ ],
283
+ };
284
+ }
285
+
286
+ default:
287
+ throw new Error(`Unknown tool: ${name}`);
288
+ }
289
+ } catch (error) {
290
+ const message = error instanceof Error ? error.message : String(error);
291
+ return {
292
+ content: [
293
+ {
294
+ type: "text",
295
+ text: `Error: ${message}`,
296
+ },
297
+ ],
298
+ isError: true,
299
+ };
300
+ }
301
+ });
302
+
303
+ async function main() {
304
+ const transport = new StdioServerTransport();
305
+ await server.connect(transport);
306
+ console.error("HardClaw MCP server running on stdio");
307
+ }
308
+
309
+ main().catch((error) => {
310
+ console.error("Fatal error:", error);
311
+ process.exit(1);
312
+ });
package/src/sdk.ts ADDED
@@ -0,0 +1,164 @@
1
+ import * as nacl from "tweetnacl";
2
+ import * as bip39 from "bip39";
3
+ import { derivePath } from "ed25519-hd-key";
4
+ import { createHash } from "crypto";
5
+
6
+ export interface Job {
7
+ id: string;
8
+ jobType: "deterministic" | "subjective";
9
+ requester: string;
10
+ description: string;
11
+ input: string;
12
+ bounty: number;
13
+ burnFee: number;
14
+ timeout: number;
15
+ expectedHash?: string;
16
+ timestamp: number;
17
+ }
18
+
19
+ export interface Solution {
20
+ id: string;
21
+ jobId: string;
22
+ solver: string;
23
+ output: string;
24
+ timestamp: number;
25
+ signature: string;
26
+ }
27
+
28
+ export interface VerificationResult {
29
+ valid: boolean;
30
+ reason?: string;
31
+ }
32
+
33
+ export class HardClawSDK {
34
+ private keypair: nacl.SignKeyPair | null = null;
35
+ private mnemonic: string | null = null;
36
+
37
+ createWallet(): { address: string; mnemonic: string } {
38
+ this.mnemonic = bip39.generateMnemonic(256); // 24 words
39
+ const seed = bip39.mnemonicToSeedSync(this.mnemonic);
40
+ const derivedSeed = derivePath("m/44'/501'/0'/0'", seed.toString("hex")).key;
41
+
42
+ this.keypair = nacl.sign.keyPair.fromSeed(derivedSeed);
43
+ const address = this.publicKeyToAddress(this.keypair.publicKey);
44
+
45
+ return { address, mnemonic: this.mnemonic };
46
+ }
47
+
48
+ loadWallet(mnemonic: string): string {
49
+ if (!bip39.validateMnemonic(mnemonic)) {
50
+ throw new Error("Invalid mnemonic phrase");
51
+ }
52
+
53
+ this.mnemonic = mnemonic;
54
+ const seed = bip39.mnemonicToSeedSync(mnemonic);
55
+ const derivedSeed = derivePath("m/44'/501'/0'/0'", seed.toString("hex")).key;
56
+
57
+ this.keypair = nacl.sign.keyPair.fromSeed(derivedSeed);
58
+ return this.publicKeyToAddress(this.keypair.publicKey);
59
+ }
60
+
61
+ getAddress(): string {
62
+ if (!this.keypair) {
63
+ throw new Error("No wallet loaded. Use createWallet() or loadWallet() first.");
64
+ }
65
+ return this.publicKeyToAddress(this.keypair.publicKey);
66
+ }
67
+
68
+ createJob(params: {
69
+ description: string;
70
+ input: string;
71
+ bounty: number;
72
+ jobType: "deterministic" | "subjective";
73
+ expectedHash?: string;
74
+ timeout: number;
75
+ }): Job {
76
+ if (!this.keypair) {
77
+ throw new Error("No wallet loaded");
78
+ }
79
+
80
+ const inputData = this.encodeInput(params.input);
81
+ const expectedHash =
82
+ params.expectedHash || this.hash(Buffer.from(inputData, "hex"));
83
+
84
+ const job: Job = {
85
+ id: this.hash(
86
+ Buffer.concat([
87
+ this.keypair.publicKey,
88
+ Buffer.from(inputData, "hex"),
89
+ Buffer.from(params.description),
90
+ Buffer.from(Date.now().toString()),
91
+ ])
92
+ ),
93
+ jobType: params.jobType,
94
+ requester: this.publicKeyToAddress(this.keypair.publicKey),
95
+ description: params.description,
96
+ input: inputData,
97
+ bounty: params.bounty,
98
+ burnFee: 1,
99
+ timeout: params.timeout,
100
+ expectedHash: params.jobType === "deterministic" ? expectedHash : undefined,
101
+ timestamp: Date.now(),
102
+ };
103
+
104
+ return job;
105
+ }
106
+
107
+ createSolution(jobId: string, output: string): Solution {
108
+ if (!this.keypair) {
109
+ throw new Error("No wallet loaded");
110
+ }
111
+
112
+ const outputData = this.encodeInput(output);
113
+ const solutionData = Buffer.concat([
114
+ Buffer.from(jobId, "hex"),
115
+ this.keypair.publicKey,
116
+ Buffer.from(outputData, "hex"),
117
+ Buffer.from(Date.now().toString()),
118
+ ]);
119
+
120
+ const signature = nacl.sign.detached(solutionData, this.keypair.secretKey);
121
+
122
+ const solution: Solution = {
123
+ id: this.hash(solutionData),
124
+ jobId,
125
+ solver: this.publicKeyToAddress(this.keypair.publicKey),
126
+ output: outputData,
127
+ timestamp: Date.now(),
128
+ signature: Buffer.from(signature).toString("hex"),
129
+ };
130
+
131
+ return solution;
132
+ }
133
+
134
+ verifySolution(jobId: string, solutionId: string): VerificationResult {
135
+ // Simulated verification - in production this would:
136
+ // 1. Fetch the job from network
137
+ // 2. Fetch the solution from network
138
+ // 3. Verify signature
139
+ // 4. Check hash match (deterministic) or run Schelling voting (subjective)
140
+
141
+ return {
142
+ valid: true,
143
+ reason: "Verification simulated - connect to hardclaw-node for real verification",
144
+ };
145
+ }
146
+
147
+ private publicKeyToAddress(publicKey: Uint8Array): string {
148
+ const hash = this.hash(Buffer.from(publicKey));
149
+ return `hc1${hash.slice(0, 40)}`;
150
+ }
151
+
152
+ private hash(data: Buffer): string {
153
+ return createHash("blake2s256").update(data).digest("hex");
154
+ }
155
+
156
+ private encodeInput(input: string): string {
157
+ // If already hex, return as-is
158
+ if (/^[0-9a-f]+$/i.test(input)) {
159
+ return input.toLowerCase();
160
+ }
161
+ // Otherwise encode as hex
162
+ return Buffer.from(input).toString("hex");
163
+ }
164
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }