@genkaku/dsh-user-plugin 0.1.23 → 0.1.25
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/lib/client.js +159 -0
- package/package.json +3 -3
package/lib/client.js
CHANGED
|
@@ -126,6 +126,9 @@ function Page() {
|
|
|
126
126
|
const [notice, setNotice] = (0, import_react.useState)(null);
|
|
127
127
|
const [busy, setBusy] = (0, import_react.useState)(null);
|
|
128
128
|
const [newWorker, setNewWorker] = (0, import_react.useState)("");
|
|
129
|
+
const [exported, setExported] = (0, import_react.useState)(null);
|
|
130
|
+
const [importText, setImportText] = (0, import_react.useState)("");
|
|
131
|
+
const [showImport, setShowImport] = (0, import_react.useState)(false);
|
|
129
132
|
const originRef = (0, import_react.useRef)(null);
|
|
130
133
|
const models = useScrollThumb();
|
|
131
134
|
const load = (0, import_react.useCallback)(async () => {
|
|
@@ -164,6 +167,7 @@ function Page() {
|
|
|
164
167
|
});
|
|
165
168
|
const doc = await res.json().catch(() => null);
|
|
166
169
|
if (!res.ok) throw new Error(doc?.error?.message ?? `HTTP ${res.status}`);
|
|
170
|
+
return doc ?? {};
|
|
167
171
|
}, []);
|
|
168
172
|
const saveWorkers = (0, import_react.useCallback)(async (next) => {
|
|
169
173
|
setBusy("workers");
|
|
@@ -195,6 +199,78 @@ function Page() {
|
|
|
195
199
|
setBusy(null);
|
|
196
200
|
}
|
|
197
201
|
}, [load, post]);
|
|
202
|
+
const exportKey = (0, import_react.useCallback)(async () => {
|
|
203
|
+
setBusy("export");
|
|
204
|
+
setNotice(null);
|
|
205
|
+
try {
|
|
206
|
+
const doc = await post("/genkaku/wallet/export", { confirm: true });
|
|
207
|
+
setExported(typeof doc.privateKey === "string" ? doc.privateKey : null);
|
|
208
|
+
setNotice(t(
|
|
209
|
+
"Never share this key. Anyone who has it owns the wallet and its funds.",
|
|
210
|
+
"\u7D55\u5C0D\u4E0D\u8981\u5206\u4EAB\u9019\u628A\u79C1\u9470\u3002\u62FF\u5230\u5B83\u7684\u4EBA\u5C31\u7B49\u65BC\u64C1\u6709\u9019\u500B\u9322\u5305\u8207\u88E1\u9762\u7684\u8CC7\u91D1\u3002"
|
|
211
|
+
));
|
|
212
|
+
} catch (e) {
|
|
213
|
+
setNotice(e instanceof Error ? e.message : String(e));
|
|
214
|
+
} finally {
|
|
215
|
+
setBusy(null);
|
|
216
|
+
}
|
|
217
|
+
}, [post]);
|
|
218
|
+
const importKey = (0, import_react.useCallback)(async () => {
|
|
219
|
+
if (!window.confirm(t(
|
|
220
|
+
"Importing a key replaces this profile's user wallet. The current address keeps its funds and is no longer used. Continue?",
|
|
221
|
+
"\u532F\u5165\u79C1\u9470\u6703\u53D6\u4EE3\u6B64 profile \u7684\u4F7F\u7528\u8005\u9322\u5305\u3002\u76EE\u524D\u4F4D\u5740\u88E1\u7684\u8CC7\u91D1\u4E0D\u6703\u8F49\u79FB\uFF0C\u4E14\u4E0D\u518D\u4F7F\u7528\u3002\u8981\u7E7C\u7E8C\u55CE\uFF1F"
|
|
222
|
+
))) return;
|
|
223
|
+
setBusy("import");
|
|
224
|
+
setNotice(null);
|
|
225
|
+
try {
|
|
226
|
+
await post("/genkaku/wallet/import", { privateKey: importText.trim() });
|
|
227
|
+
setImportText("");
|
|
228
|
+
setShowImport(false);
|
|
229
|
+
setNotice(t("Wallet imported. The bridge is restarting.", "\u5DF2\u532F\u5165\u9322\u5305\uFF0Cbridge \u6B63\u5728\u91CD\u65B0\u555F\u52D5\u3002"));
|
|
230
|
+
setTimeout(() => {
|
|
231
|
+
void load();
|
|
232
|
+
}, 3e3);
|
|
233
|
+
} catch (e) {
|
|
234
|
+
setNotice(e instanceof Error ? e.message : String(e));
|
|
235
|
+
} finally {
|
|
236
|
+
setBusy(null);
|
|
237
|
+
}
|
|
238
|
+
}, [importText, load, post]);
|
|
239
|
+
const rotateKey = (0, import_react.useCallback)(async () => {
|
|
240
|
+
if (!window.confirm(t(
|
|
241
|
+
"Generate a fresh wallet? The old address keeps its ETH and USDC; this profile stops using it.",
|
|
242
|
+
"\u8981\u7522\u751F\u65B0\u7684\u9322\u5305\u55CE\uFF1F\u820A\u4F4D\u5740\u7684 ETH \u8207 USDC \u6703\u7559\u5728\u539F\u8655\uFF0C\u6B64 profile \u4E0D\u518D\u4F7F\u7528\u5B83\u3002"
|
|
243
|
+
))) return;
|
|
244
|
+
setBusy("rotate");
|
|
245
|
+
setNotice(null);
|
|
246
|
+
try {
|
|
247
|
+
await post("/genkaku/wallet/new", {});
|
|
248
|
+
setExported(null);
|
|
249
|
+
setNotice(t("New wallet generated. The bridge is restarting.", "\u5DF2\u7522\u751F\u65B0\u9322\u5305\uFF0Cbridge \u6B63\u5728\u91CD\u65B0\u555F\u52D5\u3002"));
|
|
250
|
+
setTimeout(() => {
|
|
251
|
+
void load();
|
|
252
|
+
}, 3e3);
|
|
253
|
+
} catch (e) {
|
|
254
|
+
setNotice(e instanceof Error ? e.message : String(e));
|
|
255
|
+
} finally {
|
|
256
|
+
setBusy(null);
|
|
257
|
+
}
|
|
258
|
+
}, [load, post]);
|
|
259
|
+
const mintTestUsdc = (0, import_react.useCallback)(async () => {
|
|
260
|
+
setBusy("mint");
|
|
261
|
+
setNotice(null);
|
|
262
|
+
try {
|
|
263
|
+
const doc = await post("/genkaku/wallet/mint", { amountUsdc: "100" });
|
|
264
|
+
setNotice(t(`Minted 100 test USDC (tx ${String(doc.tx).slice(0, 12)}\u2026).`, `\u5DF2\u9818\u53D6 100 \u6E2C\u8A66 USDC\uFF08tx ${String(doc.tx).slice(0, 12)}\u2026\uFF09\u3002`));
|
|
265
|
+
setTimeout(() => {
|
|
266
|
+
void load();
|
|
267
|
+
}, 4e3);
|
|
268
|
+
} catch (e) {
|
|
269
|
+
setNotice(e instanceof Error ? e.message : String(e));
|
|
270
|
+
} finally {
|
|
271
|
+
setBusy(null);
|
|
272
|
+
}
|
|
273
|
+
}, [load, post]);
|
|
198
274
|
const refreshNetwork = (0, import_react.useCallback)(async () => {
|
|
199
275
|
setBusy("refresh");
|
|
200
276
|
setNotice(null);
|
|
@@ -235,6 +311,13 @@ function Page() {
|
|
|
235
311
|
const n = Number(micro);
|
|
236
312
|
return Number.isFinite(n) ? `${(n / 1e6).toFixed(2)} USDC` : "\u2014";
|
|
237
313
|
};
|
|
314
|
+
const noGas = (() => {
|
|
315
|
+
try {
|
|
316
|
+
return BigInt(status.balances?.eth ?? "0") === 0n;
|
|
317
|
+
} catch {
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
})();
|
|
238
321
|
const short = (addr) => addr == null || addr.length < 12 ? addr ?? "\u2014" : `${addr.slice(0, 6)}\u2026${addr.slice(-4)}`;
|
|
239
322
|
const wallets = new Set(offers.map((o) => o.offer?.workerWallet).filter((w) => typeof w === "string" && w !== ""));
|
|
240
323
|
const workerCount = wallets.size > 0 ? wallets.size : (status.workers ?? []).length;
|
|
@@ -295,6 +378,82 @@ function Page() {
|
|
|
295
378
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
|
|
296
379
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Models offered" }),
|
|
297
380
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: offers.length })
|
|
381
|
+
] }),
|
|
382
|
+
noGas && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...dim, fontSize: 12, marginTop: 8 }, children: [
|
|
383
|
+
t(
|
|
384
|
+
"This wallet has no Base Sepolia ETH yet. Get test ETH for gas from a faucet, then mint test USDC here.",
|
|
385
|
+
"\u9019\u500B\u9322\u5305\u9084\u6C92\u6709 Base Sepolia ETH\u3002\u5148\u5230 faucet \u9818\u6E2C\u8A66 ETH \u4ED8 gas\uFF0C\u518D\u56DE\u4F86\u9818\u6E2C\u8A66 USDC\u3002"
|
|
386
|
+
),
|
|
387
|
+
" ",
|
|
388
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "https://www.alchemy.com/faucets/base-sepolia", target: "_blank", rel: "noreferrer", children: t("Open faucet", "\u958B\u555F faucet") })
|
|
389
|
+
] }),
|
|
390
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: 8, marginTop: 10 }, children: [
|
|
391
|
+
status.env === "base-sepolia" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
392
|
+
import_dsh_client_ui_primitives.Button,
|
|
393
|
+
{
|
|
394
|
+
variant: "outline",
|
|
395
|
+
size: "sm",
|
|
396
|
+
disabled: busy !== null || noGas,
|
|
397
|
+
onClick: () => {
|
|
398
|
+
void mintTestUsdc();
|
|
399
|
+
},
|
|
400
|
+
children: busy === "mint" ? t("Minting\u2026", "\u9818\u53D6\u4E2D\u2026") : t("Mint 100 test USDC", "\u9818\u53D6 100 \u6E2C\u8A66 USDC")
|
|
401
|
+
}
|
|
402
|
+
),
|
|
403
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", disabled: busy !== null, onClick: () => {
|
|
404
|
+
void exportKey();
|
|
405
|
+
}, children: busy === "export" ? t("Revealing\u2026", "\u8B80\u53D6\u4E2D\u2026") : t("Export key", "\u532F\u51FA\u79C1\u9470") }),
|
|
406
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", disabled: busy !== null, onClick: () => setShowImport((v) => !v), children: t("Import key", "\u532F\u5165\u79C1\u9470") }),
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", disabled: busy !== null, onClick: () => {
|
|
408
|
+
void rotateKey();
|
|
409
|
+
}, children: t("New wallet", "\u7522\u751F\u65B0\u9322\u5305") })
|
|
410
|
+
] }),
|
|
411
|
+
exported != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: 10 }, children: [
|
|
412
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, marginBottom: 4 }, children: t("Private key \u2014 keep it offline. Testnet only.", "\u79C1\u9470\u2014\u2014\u8ACB\u96E2\u7DDA\u4FDD\u5B58\u3002\u50C5\u9650\u6E2C\u8A66\u7DB2\u3002") }),
|
|
413
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
|
|
414
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Input, { readOnly: true, value: exported, onFocus: (e) => e.currentTarget.select(), "aria-label": t("Private key", "\u79C1\u9470") }),
|
|
415
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
416
|
+
import_dsh_client_ui_primitives.Button,
|
|
417
|
+
{
|
|
418
|
+
variant: "ghost",
|
|
419
|
+
size: "sm",
|
|
420
|
+
onClick: () => {
|
|
421
|
+
if (navigator.clipboard != null) {
|
|
422
|
+
void navigator.clipboard.writeText(exported);
|
|
423
|
+
setNotice(t("Private key copied.", "\u5DF2\u8907\u88FD\u79C1\u9470\u3002"));
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
children: t("copy", "\u8907\u88FD")
|
|
427
|
+
}
|
|
428
|
+
),
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "ghost", size: "sm", onClick: () => setExported(null), children: t("hide", "\u96B1\u85CF") })
|
|
430
|
+
] })
|
|
431
|
+
] }),
|
|
432
|
+
showImport && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: 10 }, children: [
|
|
433
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, marginBottom: 4 }, children: t("Paste a 0x\u2026 32-byte private key", "\u8CBC\u4E0A 0x\u2026 32 byte \u79C1\u9470") }),
|
|
434
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
|
|
435
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
436
|
+
import_dsh_client_ui_primitives.Input,
|
|
437
|
+
{
|
|
438
|
+
value: importText,
|
|
439
|
+
placeholder: "0x\u2026",
|
|
440
|
+
onChange: (e) => setImportText(e.target.value),
|
|
441
|
+
"aria-label": t("Private key to import", "\u8981\u532F\u5165\u7684\u79C1\u9470")
|
|
442
|
+
}
|
|
443
|
+
),
|
|
444
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
445
|
+
import_dsh_client_ui_primitives.Button,
|
|
446
|
+
{
|
|
447
|
+
variant: "primary",
|
|
448
|
+
size: "sm",
|
|
449
|
+
disabled: busy !== null || !/^(0x)?[0-9a-fA-F]{64}$/.test(importText.trim()),
|
|
450
|
+
onClick: () => {
|
|
451
|
+
void importKey();
|
|
452
|
+
},
|
|
453
|
+
children: busy === "import" ? t("Importing\u2026", "\u532F\u5165\u4E2D\u2026") : t("Import", "\u532F\u5165")
|
|
454
|
+
}
|
|
455
|
+
)
|
|
456
|
+
] })
|
|
298
457
|
] })
|
|
299
458
|
] }),
|
|
300
459
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: box, children: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genkaku/dsh-user-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "Buy peer-to-peer inference from the GenKaKu network",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@deepseek-ai/dsh-llm": "0.2.2-rc.1",
|
|
42
|
-
"@genkaku/dsh-runtime": "0.1.
|
|
43
|
-
"@genkaku/protocol": "0.1.
|
|
42
|
+
"@genkaku/dsh-runtime": "0.1.24",
|
|
43
|
+
"@genkaku/protocol": "0.1.17"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@deepseek-ai/cordis": "^4.1.0",
|