@genkaku/protocol 0.1.18 → 0.1.19

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/dist/bridge.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Libp2p } from 'libp2p';
2
+ import { type WalletControl } from './walletControl.ts';
2
3
  import type { Hex } from 'viem';
3
4
  import type { ModeManager, RoleMode } from './modeManager.ts';
4
5
  import type { NetEnvironment } from './netconfig.ts';
@@ -39,15 +40,8 @@ export type BridgeOptions = {
39
40
  settle?: boolean;
40
41
  }) => void | Promise<void>;
41
42
  /** Wallet operations the panel drives. Key material only ever leaves over
42
- * loopback CORS, and only after an explicit confirmation flag. */
43
- wallet?: {
44
- address: () => string;
45
- exportKey: () => string;
46
- importKey: (privateKey: string) => void;
47
- rotate: () => void;
48
- /** testnet only; mints MockUSDC to the current user wallet */
49
- mint?: (amount: bigint) => Promise<string>;
50
- };
43
+ * the panel CORS gate, and only after an explicit confirmation flag. */
44
+ wallet?: WalletControl;
51
45
  /** P4.9h: derived credit per worker wallet (escrow events, not self-report).
52
46
  * Absent = offers keep whatever the worker claimed. */
53
47
  credit?: (wallets: string[]) => Map<string, {
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAGpC,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAc/B,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,EAAgB,MAAM,EAAc,MAAM,YAAY,CAAA;AAI7D,uEAAuE;AACvE,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAA;KAAE,CAAC,CAAA;IACjE,GAAG,EAAE,MAAM,CAAA;IACX,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAA;CAChD,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,cAAc,CAAA;IACnB,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9B,OAAO,EAAE,MAAM,GAAG,CAAA;IAClB,yEAAyE;IACzE,MAAM,EAAE,OAAO,CAAA;IACf,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,wFAAwF;IACxF,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACnC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAC3F,wDAAwD;IACxD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD;gFAC4E;IAC5E,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtF;6EACyE;IACzE,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB;4DACwD;IACxD,MAAM,CAAC,EAAE,CACP,OAAO,EAAE,MAAM,EAAE,KACd,GAAG,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CAClH,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B,CAAA;AAuJD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAskBlF"}
package/dist/bridge.js CHANGED
@@ -5,6 +5,7 @@
5
5
  import { appendFileSync } from 'node:fs';
6
6
  import { createServer } from 'node:http';
7
7
  import { applyPanelCors } from "./cors.js";
8
+ import { runWalletAction } from "./walletControl.js";
8
9
  import { openEscrow, publicClientFor, readWorker, refundSession, settleSession, signReceiptPayload, walletAddress, walletClientFor, } from "./chain.js";
9
10
  import { dialWorkerAny, fetchOffers, requestSettleCosign } from "./dial.js";
10
11
  import { dedupeOffers, toWire } from "./offer.js";
@@ -579,60 +580,10 @@ export async function startOpenAiBridge(opts) {
579
580
  failure(res, 400, 'invalid JSON body');
580
581
  return;
581
582
  }
582
- if (action === 'export') {
583
- // The key is the wallet: require an explicit acknowledgement so a
584
- // stray click (or a scripted call without intent) cannot read it.
585
- if (body.confirm !== true) {
586
- failure(res, 400, 'export requires confirm: true');
587
- return;
588
- }
583
+ const reply = await runWalletAction(action, body, opts.wallet);
584
+ if (reply.status === 200 && action === 'export')
589
585
  res.setHeader('cache-control', 'no-store');
590
- json(res, 200, { ok: true, address: opts.wallet.address(), privateKey: opts.wallet.exportKey() });
591
- return;
592
- }
593
- if (action === 'import') {
594
- const key = typeof body.privateKey === 'string' ? body.privateKey.trim() : '';
595
- if (key === '') {
596
- failure(res, 400, 'privateKey is required');
597
- return;
598
- }
599
- try {
600
- opts.wallet.importKey(key);
601
- }
602
- catch (error) {
603
- failure(res, 400, error instanceof Error ? error.message : String(error));
604
- return;
605
- }
606
- json(res, 200, { ok: true, address: opts.wallet.address(), restarting: true });
607
- return;
608
- }
609
- if (action === 'new') {
610
- opts.wallet.rotate();
611
- json(res, 200, { ok: true, address: opts.wallet.address(), restarting: true });
612
- return;
613
- }
614
- if (action === 'mint') {
615
- if (opts.wallet.mint == null) {
616
- failure(res, 400, 'test USDC mint is only available on base-sepolia');
617
- return;
618
- }
619
- const raw = body.amountUsdc === undefined ? '100' : String(body.amountUsdc);
620
- const amount = Math.round(Number(raw) * 1e6);
621
- if (!Number.isFinite(amount) || amount <= 0 || amount > 10_000e6) {
622
- failure(res, 400, 'amountUsdc must be between 0 and 10000');
623
- return;
624
- }
625
- try {
626
- const tx = await opts.wallet.mint(BigInt(amount));
627
- json(res, 200, { ok: true, tx, amountUsdc: Number(raw) });
628
- }
629
- catch (error) {
630
- failure(res, 500, error instanceof Error ? error.message : String(error));
631
- }
632
- return;
633
- }
634
- failure(res, 404, 'unknown wallet action');
635
- return;
586
+ json(res, reply.status, reply.doc);
636
587
  }
637
588
  if (req.method === 'POST' && (path === '/genkaku/settings' || path === '/genkaku/settings/')) {
638
589
  let body;
package/dist/index.d.ts CHANGED
@@ -30,5 +30,6 @@ export * from './registry.ts';
30
30
  export * from './rpc.ts';
31
31
  export * from './status.ts';
32
32
  export * from './userSession.ts';
33
+ export * from './walletControl.ts';
33
34
  export * from './workerSession.ts';
34
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA"}
package/dist/index.js CHANGED
@@ -30,5 +30,6 @@ export * from "./registry.js";
30
30
  export * from "./rpc.js";
31
31
  export * from "./status.js";
32
32
  export * from "./userSession.js";
33
+ export * from "./walletControl.js";
33
34
  export * from "./workerSession.js";
34
35
  //# sourceMappingURL=index.js.map
package/dist/keys.d.ts CHANGED
@@ -14,6 +14,8 @@ export type KeyVault = {
14
14
  workerKey(): PrivKey;
15
15
  /** replace the user key (import / rotate); refuses while an env key wins */
16
16
  setUserKey(key: PrivKey): void;
17
+ /** replace the worker identity key (import / rotate); same env guard */
18
+ setWorkerKey(key: PrivKey): void;
17
19
  /** derived addresses only (renderer-safe mirror of the keys) */
18
20
  addresses(): {
19
21
  user: EthAddress;
@@ -1 +1 @@
1
- {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAG/B,MAAM,MAAM,OAAO,GAAG,GAAG,CAAA;AACzB,MAAM,MAAM,UAAU,GAAG,KAAK,MAAM,EAAE,CAAA;AAEtC;gFACgF;AAChF,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAC9B,CAAA;AASD,MAAM,MAAM,QAAQ,GAAG;IACrB,2DAA2D;IAC3D,OAAO,IAAI,OAAO,CAAA;IAClB,6DAA6D;IAC7D,SAAS,IAAI,OAAO,CAAA;IACpB,4EAA4E;IAC5E,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;IAC9B,gEAAgE;IAChE,SAAS,IAAI;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAA;IACrD,qEAAqE;IACrE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;CACpC,CAAA;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,QAAQ,CAAA;CACjB,GAAG,QAAQ,CAuHX;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAQnD"}
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAG/B,MAAM,MAAM,OAAO,GAAG,GAAG,CAAA;AACzB,MAAM,MAAM,UAAU,GAAG,KAAK,MAAM,EAAE,CAAA;AAEtC;gFACgF;AAChF,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAC9B,CAAA;AASD,MAAM,MAAM,QAAQ,GAAG;IACrB,2DAA2D;IAC3D,OAAO,IAAI,OAAO,CAAA;IAClB,6DAA6D;IAC7D,SAAS,IAAI,OAAO,CAAA;IACpB,4EAA4E;IAC5E,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;IAC9B,wEAAwE;IACxE,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;IAChC,gEAAgE;IAChE,SAAS,IAAI;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAA;IACrD,qEAAqE;IACrE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;CACpC,CAAA;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,QAAQ,CAAA;CACjB,GAAG,QAAQ,CAmIX;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAQnD"}
package/dist/keys.js CHANGED
@@ -108,6 +108,17 @@ export function createKeyVault(opts) {
108
108
  vault.userKeyEnc = codec.encrypt(next).toString('base64');
109
109
  persist();
110
110
  },
111
+ setWorkerKey(key) {
112
+ // Same reasoning as setUserKey: an env key is process-scoped, so claiming
113
+ // a successful replacement while the old identity stays live would lie.
114
+ if (envWorker != null) {
115
+ throw new Error('the worker key comes from GENKAKU_WORKER_KEY; unset it before importing or rotating');
116
+ }
117
+ const next = normalizeKey(key);
118
+ workerKey = next;
119
+ vault.workerKeyEnc = codec.encrypt(next).toString('base64');
120
+ persist();
121
+ },
111
122
  get usingEnvOverrides() {
112
123
  return envUser != null || envWorker != null;
113
124
  },
package/dist/status.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type WalletControl } from './walletControl.ts';
1
2
  import type { RoleMode } from './modeManager.ts';
2
3
  import type { OfferWire } from './offer.ts';
3
4
  /** One offer row rendered by the dashboard. */
@@ -26,6 +27,11 @@ export type StatusSnapshot = {
26
27
  transport?: 'direct' | 'relay' | 'lan';
27
28
  /** Relay hops this worker reserved (seed VM), for the panel to explain relay mode. */
28
29
  relayHints?: string[];
30
+ /** Live wallet figures, base units as decimal strings (wei / 6-dec USDC). */
31
+ balances?: {
32
+ eth: string;
33
+ usdc: string;
34
+ };
29
35
  };
30
36
  export type StatusHandle = {
31
37
  url: string;
@@ -60,5 +66,19 @@ export type OllamaControl = {
60
66
  remove: (model: string) => Promise<void>;
61
67
  };
62
68
  /** Serve the dashboard and live status JSON on 127.0.0.1. */
63
- export declare function startStatusServer(port: number, snapshot: () => StatusSnapshot | Promise<StatusSnapshot>, onCatalog?: CatalogUpdateHandler, onMode?: ModeUpdateHandler, ollama?: OllamaControl, onPublish?: PublishUpdateHandler): Promise<StatusHandle>;
69
+ /** Everything the worker dashboard can drive. Named fields rather than a long
70
+ * positional list: the wallet joined five other callbacks, and a positional
71
+ * boolean trade at the end is how panels end up wiring the wrong handler. */
72
+ export type StatusServerOptions = {
73
+ port: number;
74
+ snapshot: () => StatusSnapshot | Promise<StatusSnapshot>;
75
+ onCatalog?: CatalogUpdateHandler;
76
+ onMode?: ModeUpdateHandler;
77
+ ollama?: OllamaControl;
78
+ onPublish?: PublishUpdateHandler;
79
+ /** Worker identity wallet: export/import/rotate. No mint — a worker earns
80
+ * USDC and only ever needs gas, which it cannot buy from a faucet button. */
81
+ wallet?: WalletControl;
82
+ };
83
+ export declare function startStatusServer(opts: StatusServerOptions): Promise<StatusHandle>;
64
84
  //# sourceMappingURL=status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,+CAA+C;AAC/C,MAAM,MAAM,WAAW,GAAG;IACxB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,0EAA0E;AAC1E,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAA;IAClB,2EAA2E;IAC3E,cAAc,EAAE,OAAO,CAAA;IACvB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,oFAAoF;IACpF,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,iFAAiF;IACjF,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAA;IACtC,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B,CAAA;AAED,mEAAmE;AACnE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB,CAAA;AAED,6DAA6D;AAC7D,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAEzF,0DAA0D;AAC1D,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAExE,2DAA2D;AAC3D,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE7E,8DAA8D;AAC9D,MAAM,MAAM,aAAa,GAAG;IAC1B,mEAAmE;IACnE,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7B,2CAA2C;IAC3C,aAAa,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IACrC,sEAAsE;IACtE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC1H,0CAA0C;IAC1C,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACzC,CAAA;AAyKD,6DAA6D;AAC7D,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,EACxD,SAAS,CAAC,EAAE,oBAAoB,EAChC,MAAM,CAAC,EAAE,iBAAiB,EAC1B,MAAM,CAAC,EAAE,aAAa,EACtB,SAAS,CAAC,EAAE,oBAAoB,GAC/B,OAAO,CAAC,YAAY,CAAC,CA+LvB"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAOA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,+CAA+C;AAC/C,MAAM,MAAM,WAAW,GAAG;IACxB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,0EAA0E;AAC1E,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAA;IAClB,2EAA2E;IAC3E,cAAc,EAAE,OAAO,CAAA;IACvB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,oFAAoF;IACpF,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,iFAAiF;IACjF,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAA;IACtC,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CACzC,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B,CAAA;AAED,mEAAmE;AACnE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB,CAAA;AAED,6DAA6D;AAC7D,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAEzF,0DAA0D;AAC1D,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAExE,2DAA2D;AAC3D,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE7E,8DAA8D;AAC9D,MAAM,MAAM,aAAa,GAAG;IAC1B,mEAAmE;IACnE,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7B,2CAA2C;IAC3C,aAAa,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IACrC,sEAAsE;IACtE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC1H,0CAA0C;IAC1C,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACzC,CAAA;AAyKD,6DAA6D;AAC7D;;8EAE8E;AAC9E,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;IACxD,SAAS,CAAC,EAAE,oBAAoB,CAAA;IAChC,MAAM,CAAC,EAAE,iBAAiB,CAAA;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,SAAS,CAAC,EAAE,oBAAoB,CAAA;IAChC;kFAC8E;IAC9E,MAAM,CAAC,EAAE,aAAa,CAAA;CACvB,CAAA;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAsNxF"}
package/dist/status.js CHANGED
@@ -3,6 +3,7 @@
3
3
  // the JSON always reflect the live sidecar, never a boot-time copy.
4
4
  import { createServer } from 'node:http';
5
5
  import { applyPanelCors } from "./cors.js";
6
+ import { runWalletAction } from "./walletControl.js";
6
7
  /** Self-contained dashboard; mirrors the user bridge style and polls the JSON. */
7
8
  const DASHBOARD_HTML = `<!doctype html>
8
9
  <html lang="en">
@@ -165,8 +166,8 @@ function parseCatalog(body) {
165
166
  }
166
167
  return { ok: true, catalog };
167
168
  }
168
- /** Serve the dashboard and live status JSON on 127.0.0.1. */
169
- export async function startStatusServer(port, snapshot, onCatalog, onMode, ollama, onPublish) {
169
+ export async function startStatusServer(opts) {
170
+ const { port, snapshot, onCatalog, onMode, ollama, onPublish, wallet } = opts;
170
171
  const server = createServer((req, res) => {
171
172
  void (async () => {
172
173
  try {
@@ -246,6 +247,28 @@ export async function startStatusServer(port, snapshot, onCatalog, onMode, ollam
246
247
  json(res, { ok: true });
247
248
  return;
248
249
  }
250
+ if (req.method === 'POST' && path.startsWith('/genkaku/wallet/')) {
251
+ const action = path.slice('/genkaku/wallet/'.length).replace(/\/$/, '');
252
+ if (wallet == null) {
253
+ failure(res, 501, 'wallet operations are not enabled in this role');
254
+ return;
255
+ }
256
+ let body = {};
257
+ try {
258
+ body = await readJson(req);
259
+ }
260
+ catch {
261
+ failure(res, 400, 'invalid JSON body');
262
+ return;
263
+ }
264
+ const reply = await runWalletAction(action, body, wallet);
265
+ res.writeHead(reply.status, {
266
+ 'content-type': 'application/json',
267
+ ...(action === 'export' ? { 'cache-control': 'no-store' } : {}),
268
+ });
269
+ res.end(JSON.stringify(reply.doc));
270
+ return;
271
+ }
249
272
  if (path === '/genkaku/ollama' || path === '/genkaku/ollama/') {
250
273
  if (ollama == null) {
251
274
  failure(res, 501, 'ollama onboarding is not enabled in this role');
@@ -0,0 +1,17 @@
1
+ /** Wallet operations a control plane may offer. */
2
+ export type WalletControl = {
3
+ address: () => string;
4
+ exportKey: () => string;
5
+ importKey: (privateKey: string) => void | Promise<void>;
6
+ rotate: () => void | Promise<void>;
7
+ /** base-sepolia only; mints MockUSDC to the panel's own address */
8
+ mint?: (amount: bigint) => Promise<string>;
9
+ };
10
+ /** One action's HTTP answer: status code plus JSON body. */
11
+ export type WalletActionReply = {
12
+ status: number;
13
+ doc: Record<string, unknown>;
14
+ };
15
+ /** Validate and run one `/genkaku/wallet/<action>` call. */
16
+ export declare function runWalletAction(action: string, body: Record<string, unknown>, wallet: WalletControl): Promise<WalletActionReply>;
17
+ //# sourceMappingURL=walletControl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walletControl.d.ts","sourceRoot":"","sources":["../src/walletControl.ts"],"names":[],"mappings":"AAYA,mDAAmD;AACnD,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,MAAM,CAAA;IACvB,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvD,MAAM,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,mEAAmE;IACnE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAC3C,CAAA;AAED,4DAA4D;AAC5D,MAAM,MAAM,iBAAiB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAA;AAEhF,4DAA4D;AAC5D,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAwD5B"}
@@ -0,0 +1,63 @@
1
+ // GENKAKU: wallet operations shared by both control planes.
2
+ //
3
+ // The user bridge and the worker status server expose the same four actions —
4
+ // export, import, new, mint — against different keys: the buyer's key signs
5
+ // escrows, the worker's key signs receipts and binds the directory entry. The
6
+ // HTTP shape and the safeguards are identical, so they live here instead of
7
+ // being copied into two request handlers that can drift apart.
8
+ //
9
+ // Key material only ever leaves over the panel CORS gate (see cors.ts), and
10
+ // export additionally requires `confirm: true` so a stray click — or a script
11
+ // that reached the port without intent — cannot read it.
12
+ /** Validate and run one `/genkaku/wallet/<action>` call. */
13
+ export async function runWalletAction(action, body, wallet) {
14
+ if (action === 'export') {
15
+ // The key IS the wallet: require an explicit acknowledgement.
16
+ if (body.confirm !== true)
17
+ return { status: 400, doc: { error: { message: 'export requires confirm: true' } } };
18
+ return {
19
+ status: 200,
20
+ doc: { ok: true, address: wallet.address(), privateKey: wallet.exportKey() },
21
+ };
22
+ }
23
+ if (action === 'import') {
24
+ const key = typeof body.privateKey === 'string' ? body.privateKey.trim() : '';
25
+ if (key === '')
26
+ return { status: 400, doc: { error: { message: 'privateKey is required' } } };
27
+ try {
28
+ await wallet.importKey(key);
29
+ }
30
+ catch (error) {
31
+ return { status: 400, doc: { error: { message: error instanceof Error ? error.message : String(error) } } };
32
+ }
33
+ return { status: 200, doc: { ok: true, address: wallet.address(), restarting: true } };
34
+ }
35
+ if (action === 'new') {
36
+ try {
37
+ await wallet.rotate();
38
+ }
39
+ catch (error) {
40
+ return { status: 500, doc: { error: { message: error instanceof Error ? error.message : String(error) } } };
41
+ }
42
+ return { status: 200, doc: { ok: true, address: wallet.address(), restarting: true } };
43
+ }
44
+ if (action === 'mint') {
45
+ if (wallet.mint == null) {
46
+ return { status: 400, doc: { error: { message: 'test USDC mint is only available on base-sepolia' } } };
47
+ }
48
+ const raw = body.amountUsdc === undefined ? '100' : String(body.amountUsdc);
49
+ const amount = Math.round(Number(raw) * 1e6);
50
+ if (!Number.isFinite(amount) || amount <= 0 || amount > 10_000e6) {
51
+ return { status: 400, doc: { error: { message: 'amountUsdc must be between 0 and 10000' } } };
52
+ }
53
+ try {
54
+ const tx = await wallet.mint(BigInt(amount));
55
+ return { status: 200, doc: { ok: true, tx, amountUsdc: Number(raw) } };
56
+ }
57
+ catch (error) {
58
+ return { status: 500, doc: { error: { message: error instanceof Error ? error.message : String(error) } } };
59
+ }
60
+ }
61
+ return { status: 404, doc: { error: { message: 'unknown wallet action' } } };
62
+ }
63
+ //# sourceMappingURL=walletControl.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genkaku/protocol",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "GenKaKu protocol core: on-chain worker directory, USDC escrow billing, libp2p transport, Ollama lifecycle",
5
5
  "license": "MIT",
6
6
  "type": "module",