@toon-protocol/rig 3.6.0 → 4.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 +112 -153
- package/dist/{chunk-HJDPM37T.js → chunk-7VCVR4GK.js} +12 -8
- package/dist/{chunk-HJDPM37T.js.map → chunk-7VCVR4GK.js.map} +1 -1
- package/dist/chunk-CDSFVZDV.js +290 -0
- package/dist/chunk-CDSFVZDV.js.map +1 -0
- package/dist/{chunk-B5ISARMU.js → chunk-GVXBUL3C.js} +15 -2
- package/dist/chunk-GVXBUL3C.js.map +1 -0
- package/dist/chunk-LTFMPOHU.js +194 -0
- package/dist/chunk-LTFMPOHU.js.map +1 -0
- package/dist/{chunk-2KJJ7LSO.js → chunk-NCEMQUPA.js} +40 -2
- package/dist/chunk-NCEMQUPA.js.map +1 -0
- package/dist/{chunk-LCYCKWAT.js → chunk-YZRR2UO6.js} +86 -5
- package/dist/chunk-YZRR2UO6.js.map +1 -0
- package/dist/cli/rig.js +631 -568
- package/dist/cli/rig.js.map +1 -1
- package/dist/index.d.ts +10 -115
- package/dist/index.js +16 -122
- package/dist/index.js.map +1 -1
- package/dist/{publisher-BFcnZeJI.d.ts → publisher-DMJ06cuL.d.ts} +98 -2
- package/dist/standalone/index.d.ts +241 -438
- package/dist/standalone/index.js +19 -11
- package/dist/standalone-mode-KTYRTUS6.js +390 -0
- package/dist/standalone-mode-KTYRTUS6.js.map +1 -0
- package/package.json +7 -5
- package/dist/chunk-2KJJ7LSO.js.map +0 -1
- package/dist/chunk-B5ISARMU.js.map +0 -1
- package/dist/chunk-IZ6KLYQ6.js +0 -724
- package/dist/chunk-IZ6KLYQ6.js.map +0 -1
- package/dist/chunk-LCYCKWAT.js.map +0 -1
- package/dist/chunk-PWNZWQOH.js +0 -404
- package/dist/chunk-PWNZWQOH.js.map +0 -1
- package/dist/chunk-UZZ2RN7A.js +0 -469
- package/dist/chunk-UZZ2RN7A.js.map +0 -1
- package/dist/network-bootstrap-27FYE3N7.js +0 -40
- package/dist/network-bootstrap-27FYE3N7.js.map +0 -1
- package/dist/standalone-mode-5MNNJC2D.js +0 -928
- package/dist/standalone-mode-5MNNJC2D.js.map +0 -1
package/dist/cli/rig.js
CHANGED
|
@@ -18,34 +18,17 @@ import {
|
|
|
18
18
|
setHeadSymref,
|
|
19
19
|
updateRef,
|
|
20
20
|
writeGitObjects
|
|
21
|
-
} from "../chunk-
|
|
21
|
+
} from "../chunk-7VCVR4GK.js";
|
|
22
22
|
import {
|
|
23
23
|
DEFAULT_KEYSTORE_PASSWORD,
|
|
24
|
-
MinaZkAppStore,
|
|
25
24
|
MissingIdentityError,
|
|
26
|
-
TOPOLOGY_CACHE_FILENAME,
|
|
27
25
|
clientConfigPath,
|
|
28
26
|
clientKeystorePath,
|
|
29
27
|
linkKeystoreInClientConfig,
|
|
30
28
|
readClientConfigFile,
|
|
31
29
|
resolveAccountIndex,
|
|
32
30
|
resolveIdentity
|
|
33
|
-
} from "../chunk-
|
|
34
|
-
import {
|
|
35
|
-
ChannelMapStore,
|
|
36
|
-
RIG_STANDALONE_ENV,
|
|
37
|
-
channelStatus,
|
|
38
|
-
defaultDaemonPort,
|
|
39
|
-
resolveChannelPaths,
|
|
40
|
-
resolveConflictingPath,
|
|
41
|
-
standaloneForced
|
|
42
|
-
} from "../chunk-LCYCKWAT.js";
|
|
43
|
-
import {
|
|
44
|
-
MAX_OBJECT_SIZE
|
|
45
|
-
} from "../chunk-B5ISARMU.js";
|
|
46
|
-
import {
|
|
47
|
-
minaPresetForChain
|
|
48
|
-
} from "../chunk-UZZ2RN7A.js";
|
|
31
|
+
} from "../chunk-LTFMPOHU.js";
|
|
49
32
|
import {
|
|
50
33
|
ARWEAVE_GATEWAYS,
|
|
51
34
|
COMMENT_KIND,
|
|
@@ -56,9 +39,24 @@ import {
|
|
|
56
39
|
buildRepoAnnouncement,
|
|
57
40
|
buildStatus,
|
|
58
41
|
fetchRemoteState,
|
|
42
|
+
isValidEvmPayoutAddress,
|
|
59
43
|
parseMaintainers,
|
|
60
44
|
queryRelay
|
|
61
|
-
} from "../chunk-
|
|
45
|
+
} from "../chunk-NCEMQUPA.js";
|
|
46
|
+
import {
|
|
47
|
+
ChannelMapStore,
|
|
48
|
+
RIG_STANDALONE_ENV,
|
|
49
|
+
channelStatus,
|
|
50
|
+
defaultDaemonPort,
|
|
51
|
+
deriveNostrKeyFromMnemonic,
|
|
52
|
+
resolveChannelPaths,
|
|
53
|
+
resolveConflictingPath,
|
|
54
|
+
standaloneForced
|
|
55
|
+
} from "../chunk-YZRR2UO6.js";
|
|
56
|
+
import {
|
|
57
|
+
MAX_OBJECT_SIZE,
|
|
58
|
+
uploadChargeFor
|
|
59
|
+
} from "../chunk-GVXBUL3C.js";
|
|
62
60
|
|
|
63
61
|
// src/cli/rig.ts
|
|
64
62
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
@@ -624,6 +622,21 @@ function generateRigPointerHtml(options) {
|
|
|
624
622
|
`;
|
|
625
623
|
}
|
|
626
624
|
|
|
625
|
+
// src/gateway-preference.ts
|
|
626
|
+
var TESTNET_GATEWAY = /(^|\.)ar-io\.dev$/i;
|
|
627
|
+
function isMainnetGateway(url) {
|
|
628
|
+
try {
|
|
629
|
+
return !TESTNET_GATEWAY.test(new URL(url).hostname);
|
|
630
|
+
} catch {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
var PREFERRED_GATEWAY = ARWEAVE_GATEWAYS.find(isMainnetGateway) ?? "https://arweave.net";
|
|
635
|
+
function mirrorGatewaysFor(primary) {
|
|
636
|
+
const p = primary.replace(/\/+$/, "");
|
|
637
|
+
return ARWEAVE_GATEWAYS.filter((g) => g.replace(/\/+$/, "") !== p);
|
|
638
|
+
}
|
|
639
|
+
|
|
627
640
|
// src/cli/rig-pointer-record.ts
|
|
628
641
|
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
629
642
|
import { homedir } from "os";
|
|
@@ -1098,7 +1111,7 @@ function loadPaidSession(deps, relayUrl) {
|
|
|
1098
1111
|
});
|
|
1099
1112
|
}
|
|
1100
1113
|
var defaultLoadStandalone = async (options) => {
|
|
1101
|
-
const mod = await import("../standalone-mode-
|
|
1114
|
+
const mod = await import("../standalone-mode-KTYRTUS6.js");
|
|
1102
1115
|
return mod.createStandaloneContext(options);
|
|
1103
1116
|
};
|
|
1104
1117
|
function identityReport(ctx) {
|
|
@@ -1240,11 +1253,10 @@ function parsePushArgs(args) {
|
|
|
1240
1253
|
return flags;
|
|
1241
1254
|
}
|
|
1242
1255
|
function pointerGateway(env) {
|
|
1243
|
-
|
|
1244
|
-
return (env["RIG_ARWEAVE_GATEWAY"] ?? preferred).replace(/\/+$/, "");
|
|
1256
|
+
return (env["RIG_ARWEAVE_GATEWAY"] ?? PREFERRED_GATEWAY).replace(/\/+$/, "");
|
|
1245
1257
|
}
|
|
1246
1258
|
function mirrorGateways(primary) {
|
|
1247
|
-
return
|
|
1259
|
+
return mirrorGatewaysFor(primary);
|
|
1248
1260
|
}
|
|
1249
1261
|
function planRigPointer(args) {
|
|
1250
1262
|
const html = generateRigPointerHtml({
|
|
@@ -1280,7 +1292,7 @@ function planRigPointer(args) {
|
|
|
1280
1292
|
html,
|
|
1281
1293
|
contentHash,
|
|
1282
1294
|
bytes,
|
|
1283
|
-
fee: args.
|
|
1295
|
+
fee: uploadChargeFor(args.feeRates, bytes)
|
|
1284
1296
|
};
|
|
1285
1297
|
}
|
|
1286
1298
|
async function runPush(args, deps) {
|
|
@@ -1401,7 +1413,7 @@ async function runPush(args, deps) {
|
|
|
1401
1413
|
ownerPubkey: ctx.ownerPubkey,
|
|
1402
1414
|
repoId,
|
|
1403
1415
|
relay: relaysUsed[0],
|
|
1404
|
-
|
|
1416
|
+
feeRates
|
|
1405
1417
|
});
|
|
1406
1418
|
}
|
|
1407
1419
|
} else {
|
|
@@ -2041,9 +2053,6 @@ async function runChain(args, deps) {
|
|
|
2041
2053
|
}
|
|
2042
2054
|
|
|
2043
2055
|
// src/cli/channel.ts
|
|
2044
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
2045
|
-
import { homedir as homedir3 } from "os";
|
|
2046
|
-
import { join as join3 } from "path";
|
|
2047
2056
|
import { parseArgs as parseArgs5 } from "util";
|
|
2048
2057
|
var CHANNEL_USAGE = `Usage: rig channel <subcommand>
|
|
2049
2058
|
|
|
@@ -2066,17 +2075,6 @@ Subcommands:
|
|
|
2066
2075
|
apex); --deposit adds that much extra collateral after the
|
|
2067
2076
|
open/resume. On-chain: asks for confirmation (--yes skips).
|
|
2068
2077
|
|
|
2069
|
-
deploy-zkapp [--graphql-url <url>]
|
|
2070
|
-
deploy a dedicated Mina PaymentChannel zkApp for THIS
|
|
2071
|
-
identity (the zkApp is single-pair; Mina channels open on
|
|
2072
|
-
an identity-owned deployment). Normally automatic \u2014 the
|
|
2073
|
-
Mina open path deploys one when needed \u2014 this explicit
|
|
2074
|
-
form pre-deploys it (compile \u22481-3 min, inclusion \u22483-6 min).
|
|
2075
|
-
On-chain: costs the 1 MINA account-creation fee + tx fee
|
|
2076
|
-
from the wallet's MINA. The zkApp key is saved under
|
|
2077
|
-
TOON_CLIENT_HOME/keys/. Asks for confirmation (--yes
|
|
2078
|
-
skips).
|
|
2079
|
-
|
|
2080
2078
|
close <channelId>
|
|
2081
2079
|
close a recorded channel \u2014 an on-chain tx that starts the
|
|
2082
2080
|
settlement challenge window (the peer's settlementTimeout).
|
|
@@ -2100,8 +2098,6 @@ async function runChannel(args, deps) {
|
|
|
2100
2098
|
return runChannelList(rest, deps);
|
|
2101
2099
|
case "open":
|
|
2102
2100
|
return runChannelOpen(rest, deps);
|
|
2103
|
-
case "deploy-zkapp":
|
|
2104
|
-
return runChannelDeployZkApp(rest, deps);
|
|
2105
2101
|
case "close":
|
|
2106
2102
|
return runChannelWithdrawStep(rest, deps, "close");
|
|
2107
2103
|
case "settle":
|
|
@@ -2294,9 +2290,6 @@ async function runChannelOpen(args, deps) {
|
|
|
2294
2290
|
io2.out(
|
|
2295
2291
|
"If a live channel is already recorded for this peer it is RESUMED (no on-chain spend); otherwise an on-chain channel open locks the peer-negotiated initial deposit from your wallet (plus gas)."
|
|
2296
2292
|
);
|
|
2297
|
-
io2.out(
|
|
2298
|
-
"On a Mina chain a first open may also deploy a dedicated PaymentChannel zkApp for this identity (~1.1 MINA + fees; compile \u22481-3 min, inclusion \u22483-6 min \u2014 progress is printed)."
|
|
2299
|
-
);
|
|
2300
2293
|
}
|
|
2301
2294
|
const gate = await confirmOnChain(
|
|
2302
2295
|
io2,
|
|
@@ -2355,160 +2348,6 @@ async function runChannelOpen(args, deps) {
|
|
|
2355
2348
|
await stopQuietly(ctx);
|
|
2356
2349
|
}
|
|
2357
2350
|
}
|
|
2358
|
-
async function runChannelDeployZkApp(args, deps) {
|
|
2359
|
-
const { io: io2, env } = deps;
|
|
2360
|
-
let graphqlFlag;
|
|
2361
|
-
let yes = false;
|
|
2362
|
-
let json = false;
|
|
2363
|
-
try {
|
|
2364
|
-
const { values } = parseArgs5({
|
|
2365
|
-
args,
|
|
2366
|
-
options: {
|
|
2367
|
-
"graphql-url": { type: "string" },
|
|
2368
|
-
yes: { type: "boolean", default: false },
|
|
2369
|
-
json: { type: "boolean", default: false },
|
|
2370
|
-
help: { type: "boolean", short: "h", default: false }
|
|
2371
|
-
}
|
|
2372
|
-
});
|
|
2373
|
-
if (values.help) {
|
|
2374
|
-
io2.out(CHANNEL_USAGE);
|
|
2375
|
-
return 0;
|
|
2376
|
-
}
|
|
2377
|
-
graphqlFlag = values["graphql-url"];
|
|
2378
|
-
yes = values.yes ?? false;
|
|
2379
|
-
json = values.json ?? false;
|
|
2380
|
-
} catch (err) {
|
|
2381
|
-
io2.err(err instanceof Error ? err.message : String(err));
|
|
2382
|
-
io2.err(CHANNEL_USAGE);
|
|
2383
|
-
return 2;
|
|
2384
|
-
}
|
|
2385
|
-
try {
|
|
2386
|
-
const dir = env["TOON_CLIENT_HOME"] ?? join3(homedir3(), ".toon-client");
|
|
2387
|
-
let file = {};
|
|
2388
|
-
try {
|
|
2389
|
-
file = JSON.parse(readFileSync3(join3(dir, "config.json"), "utf8"));
|
|
2390
|
-
} catch {
|
|
2391
|
-
}
|
|
2392
|
-
const pinned = env["TOON_CLIENT_CHAIN"] ?? file.chain;
|
|
2393
|
-
const chain = pinned !== void 0 && pinned.startsWith("mina:") ? pinned : "mina:devnet";
|
|
2394
|
-
const graphqlUrl = graphqlFlag ?? file.minaChannel?.graphqlUrl ?? minaPresetForChain(chain)?.graphqlUrl;
|
|
2395
|
-
if (!graphqlUrl) {
|
|
2396
|
-
throw new Error(
|
|
2397
|
-
`no Mina GraphQL endpoint for ${chain} \u2014 pass --graphql-url or set minaChannel.graphqlUrl in the client config`
|
|
2398
|
-
);
|
|
2399
|
-
}
|
|
2400
|
-
const resolved = await resolveIdentity({
|
|
2401
|
-
env,
|
|
2402
|
-
cwd: deps.cwd,
|
|
2403
|
-
warn: (line) => io2.err(line)
|
|
2404
|
-
});
|
|
2405
|
-
const identity = {
|
|
2406
|
-
pubkey: resolved.pubkey,
|
|
2407
|
-
source: resolved.source,
|
|
2408
|
-
sourceLabel: resolved.sourceLabel
|
|
2409
|
-
};
|
|
2410
|
-
const store = MinaZkAppStore.forHome(dir);
|
|
2411
|
-
const existing = store.lookup(resolved.pubkey, chain);
|
|
2412
|
-
if (existing) {
|
|
2413
|
-
if (json) {
|
|
2414
|
-
io2.emitJson({
|
|
2415
|
-
command: "channel deploy-zkapp",
|
|
2416
|
-
identity,
|
|
2417
|
-
executed: false,
|
|
2418
|
-
plan: { chain, graphqlUrl },
|
|
2419
|
-
result: {
|
|
2420
|
-
zkAppAddress: existing.zkAppAddress,
|
|
2421
|
-
deployTxHash: existing.deployTxHash ?? null,
|
|
2422
|
-
vkHash: existing.vkHash ?? null,
|
|
2423
|
-
storePath: store.filePath
|
|
2424
|
-
},
|
|
2425
|
-
hint: "a zkApp is already recorded for this identity/chain \u2014 the open path reuses it"
|
|
2426
|
-
});
|
|
2427
|
-
return 0;
|
|
2428
|
-
}
|
|
2429
|
-
io2.out(
|
|
2430
|
-
`A Mina zkApp is already recorded for this identity on ${chain}: ` + existing.zkAppAddress
|
|
2431
|
-
);
|
|
2432
|
-
io2.out(`The open path reuses it (record: ${store.filePath}).`);
|
|
2433
|
-
return 0;
|
|
2434
|
-
}
|
|
2435
|
-
const plan = { chain, graphqlUrl };
|
|
2436
|
-
if (!json) {
|
|
2437
|
-
io2.out("Mina zkApp deploy plan:");
|
|
2438
|
-
io2.out(` chain ${chain}`);
|
|
2439
|
-
io2.out(` graphql ${graphqlUrl}`);
|
|
2440
|
-
io2.out(renderIdentityLine(identity));
|
|
2441
|
-
io2.out(
|
|
2442
|
-
"Deploys a dedicated PaymentChannel zkApp for this identity \u2014 on-chain: the 1 MINA account-creation fee + a 0.1 MINA tx fee from your wallet. Compile \u22481-3 min; inclusion \u22483-6 min."
|
|
2443
|
-
);
|
|
2444
|
-
}
|
|
2445
|
-
const gate = await confirmOnChain(
|
|
2446
|
-
io2,
|
|
2447
|
-
{ yes, json },
|
|
2448
|
-
"Proceed with the on-chain zkApp deploy? [y/N] "
|
|
2449
|
-
);
|
|
2450
|
-
if (gate === "json-plan") {
|
|
2451
|
-
io2.emitJson({
|
|
2452
|
-
command: "channel deploy-zkapp",
|
|
2453
|
-
identity,
|
|
2454
|
-
executed: false,
|
|
2455
|
-
plan,
|
|
2456
|
-
hint: "plan only \u2014 re-run with --yes to deploy (on-chain: ~1.1 MINA + fees)"
|
|
2457
|
-
});
|
|
2458
|
-
return 0;
|
|
2459
|
-
}
|
|
2460
|
-
if (gate !== "proceed") return gate;
|
|
2461
|
-
const client = await import("@toon-protocol/client");
|
|
2462
|
-
const derived = await client.deriveFullIdentity(
|
|
2463
|
-
resolved.mnemonic,
|
|
2464
|
-
resolved.accountIndex
|
|
2465
|
-
);
|
|
2466
|
-
if (!derived.mina.privateKey) {
|
|
2467
|
-
throw new Error(
|
|
2468
|
-
"no Mina key derived \u2014 the optional `mina-signer` dependency is not installed"
|
|
2469
|
-
);
|
|
2470
|
-
}
|
|
2471
|
-
const record = await client.deployMinaChannelZkApp({
|
|
2472
|
-
graphqlUrl,
|
|
2473
|
-
payerPrivateKey: derived.mina.privateKey,
|
|
2474
|
-
onProgress: (line) => io2.err(`rig: mina: ${line}`)
|
|
2475
|
-
});
|
|
2476
|
-
store.save({
|
|
2477
|
-
identity: resolved.pubkey,
|
|
2478
|
-
chain,
|
|
2479
|
-
zkAppAddress: record.zkAppAddress,
|
|
2480
|
-
zkAppPrivateKey: record.zkAppPrivateKey,
|
|
2481
|
-
feePayer: record.feePayer,
|
|
2482
|
-
...record.deployTxHash !== void 0 ? { deployTxHash: record.deployTxHash } : {},
|
|
2483
|
-
...record.vkHash !== void 0 ? { vkHash: record.vkHash } : {},
|
|
2484
|
-
deployedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2485
|
-
source: "rig channel deploy-zkapp (npm @toon-protocol/mina-zkapp build)"
|
|
2486
|
-
});
|
|
2487
|
-
if (json) {
|
|
2488
|
-
io2.emitJson({
|
|
2489
|
-
command: "channel deploy-zkapp",
|
|
2490
|
-
identity,
|
|
2491
|
-
executed: true,
|
|
2492
|
-
plan,
|
|
2493
|
-
result: {
|
|
2494
|
-
zkAppAddress: record.zkAppAddress,
|
|
2495
|
-
deployTxHash: record.deployTxHash ?? null,
|
|
2496
|
-
vkHash: record.vkHash ?? null,
|
|
2497
|
-
storePath: store.filePath
|
|
2498
|
-
}
|
|
2499
|
-
});
|
|
2500
|
-
return 0;
|
|
2501
|
-
}
|
|
2502
|
-
io2.out(`Deployed Mina PaymentChannel zkApp ${record.zkAppAddress}.`);
|
|
2503
|
-
if (record.deployTxHash) io2.out(` deploy tx ${record.deployTxHash}`);
|
|
2504
|
-
if (record.vkHash) io2.out(` vk hash ${record.vkHash}`);
|
|
2505
|
-
io2.out(` record ${store.filePath} (holds the zkApp key \u2014 back it up)`);
|
|
2506
|
-
io2.out("The next Mina channel open/push finds and reuses this zkApp.");
|
|
2507
|
-
return 0;
|
|
2508
|
-
} catch (err) {
|
|
2509
|
-
return emitCliError(io2, json, "channel deploy-zkapp", err);
|
|
2510
|
-
}
|
|
2511
|
-
}
|
|
2512
2351
|
function withdrawPrecheck(step, channelId, watermark, nowSec) {
|
|
2513
2352
|
const status = channelStatus(watermark, nowSec);
|
|
2514
2353
|
if (status === "settled") {
|
|
@@ -2678,7 +2517,7 @@ async function stopQuietly(ctx) {
|
|
|
2678
2517
|
|
|
2679
2518
|
// src/cli/clone.ts
|
|
2680
2519
|
import { mkdtemp, mkdir, readdir, rename, rm, rmdir } from "fs/promises";
|
|
2681
|
-
import { basename, dirname as dirname2, join as
|
|
2520
|
+
import { basename, dirname as dirname2, join as join3, resolve } from "path";
|
|
2682
2521
|
import { parseArgs as parseArgs6 } from "util";
|
|
2683
2522
|
var CLONE_USAGE = `Usage: rig clone <relay-url> <owner>/<repo-id> [dir] [options]
|
|
2684
2523
|
|
|
@@ -2849,7 +2688,7 @@ async function runClone(args, deps) {
|
|
|
2849
2688
|
}
|
|
2850
2689
|
const parent = dirname2(dest);
|
|
2851
2690
|
await mkdir(parent, { recursive: true });
|
|
2852
|
-
tempDir = await mkdtemp(
|
|
2691
|
+
tempDir = await mkdtemp(join3(parent, `.${basename(dest)}.rig-clone-`));
|
|
2853
2692
|
await runGit(tempDir, [
|
|
2854
2693
|
"init",
|
|
2855
2694
|
"--quiet",
|
|
@@ -4102,48 +3941,39 @@ async function warnIfNotMaintainer(deps, args) {
|
|
|
4102
3941
|
}
|
|
4103
3942
|
|
|
4104
3943
|
// src/cli/entry.ts
|
|
4105
|
-
import { mkdirSync as mkdirSync3, readFileSync as
|
|
4106
|
-
import { homedir as
|
|
4107
|
-
import { dirname as dirname3, join as
|
|
3944
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
3945
|
+
import { homedir as homedir3 } from "os";
|
|
3946
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
4108
3947
|
import { parseArgs as parseArgs9 } from "util";
|
|
4109
|
-
var
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
rig entry
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
btp ${SANDBOX_BTP_URL}
|
|
4123
|
-
relay ${SANDBOX_RELAY_URL}
|
|
4124
|
-
rig entry <wss-url> an explicit BTP endpoint (ws:// or wss://); pass
|
|
4125
|
-
--relay <url> to also set the relay
|
|
4126
|
-
|
|
4127
|
-
Switching entries deletes the cached topology (the next paid command
|
|
4128
|
-
re-discovers the new entry's announce) and leaves existing payment channels
|
|
4129
|
-
behind \u2014 channels are per-entry-peer; the next paid command opens or resumes
|
|
4130
|
-
one with the new peer.
|
|
3948
|
+
var ENTRY_USAGE = `Usage: rig entry [<connector-url> | clear] [options]
|
|
3949
|
+
|
|
3950
|
+
Name the TOON connector rig pays. A connector describes itself on GET /ilp
|
|
3951
|
+
(its addresses, routes and prices, settlement chains), so its URL is the
|
|
3952
|
+
whole configuration. Free: only the local config file is touched.
|
|
3953
|
+
|
|
3954
|
+
rig entry show the effective connector + relay and their source
|
|
3955
|
+
rig entry <connector-url> record the node's client-edge URL (https://\u2026);
|
|
3956
|
+
pass --relay <wss-url> to also record its free-read relay
|
|
3957
|
+
rig entry clear forget the recorded connector (and relay)
|
|
3958
|
+
|
|
3959
|
+
Existing payment channels are per node: after switching, the next paid
|
|
3960
|
+
command opens or adopts a channel with the new node.
|
|
4131
3961
|
|
|
4132
3962
|
NOTE for repos: the relay a repo publishes to is its git \`origin\` remote,
|
|
4133
|
-
which OVERRIDES the config relayUrl. After switching
|
|
4134
|
-
|
|
3963
|
+
which OVERRIDES the config relayUrl. After switching, point the repo too:
|
|
3964
|
+
\`rig remote add origin <relay-url>\` (or use a fresh repo).
|
|
4135
3965
|
|
|
4136
3966
|
Options:
|
|
4137
|
-
--relay <url> with <
|
|
3967
|
+
--relay <url> with <connector-url>: also record the relay URL (ws:// or wss://)
|
|
4138
3968
|
--json machine-readable envelope
|
|
4139
3969
|
-h, --help show this help`;
|
|
4140
3970
|
function configPathFor2(env) {
|
|
4141
|
-
const dir = env["TOON_CLIENT_HOME"] ??
|
|
4142
|
-
return
|
|
3971
|
+
const dir = env["TOON_CLIENT_HOME"] ?? join4(homedir3(), ".toon-client");
|
|
3972
|
+
return join4(dir, "config.json");
|
|
4143
3973
|
}
|
|
4144
3974
|
function readEntryConfig(configPath) {
|
|
4145
3975
|
try {
|
|
4146
|
-
return JSON.parse(
|
|
3976
|
+
return JSON.parse(readFileSync3(configPath, "utf8"));
|
|
4147
3977
|
} catch (err) {
|
|
4148
3978
|
if (err.code === "ENOENT") return {};
|
|
4149
3979
|
throw new Error(
|
|
@@ -4156,20 +3986,28 @@ function writeEntryConfig(configPath, file) {
|
|
|
4156
3986
|
writeFileSync3(configPath, `${JSON.stringify(file, null, 2)}
|
|
4157
3987
|
`, "utf8");
|
|
4158
3988
|
}
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
}
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
if (
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
3989
|
+
function effectiveEntry(env, file) {
|
|
3990
|
+
let connectorUrl = null;
|
|
3991
|
+
let connectorSource = null;
|
|
3992
|
+
if (env["TOON_CONNECTOR"]) {
|
|
3993
|
+
connectorUrl = env["TOON_CONNECTOR"];
|
|
3994
|
+
connectorSource = "env";
|
|
3995
|
+
} else if (env["TOON_CLIENT_PROXY_URL"]) {
|
|
3996
|
+
connectorUrl = env["TOON_CLIENT_PROXY_URL"];
|
|
3997
|
+
connectorSource = "legacy-env";
|
|
3998
|
+
} else if (file.connectorUrl) {
|
|
3999
|
+
connectorUrl = file.connectorUrl;
|
|
4000
|
+
connectorSource = "config";
|
|
4001
|
+
} else if (file.proxyUrl) {
|
|
4002
|
+
connectorUrl = file.proxyUrl;
|
|
4003
|
+
connectorSource = "legacy-config";
|
|
4004
|
+
}
|
|
4005
|
+
const relayUrl = env["TOON_CLIENT_RELAY_URL"] ?? file.relayUrl ?? null;
|
|
4006
|
+
const relaySource = env["TOON_CLIENT_RELAY_URL"] ? "env" : file.relayUrl ? "config" : null;
|
|
4007
|
+
return { connectorUrl, connectorSource, relayUrl, relaySource };
|
|
4008
|
+
}
|
|
4009
|
+
var HTTP_URL = /^https?:\/\/.+/i;
|
|
4010
|
+
var WS_URL = /^wss?:\/\/.+/i;
|
|
4173
4011
|
async function runEntry(args, deps) {
|
|
4174
4012
|
const { io: io2, env } = deps;
|
|
4175
4013
|
let positionals;
|
|
@@ -4199,7 +4037,7 @@ async function runEntry(args, deps) {
|
|
|
4199
4037
|
}
|
|
4200
4038
|
if (positionals.length > 1) {
|
|
4201
4039
|
io2.err(
|
|
4202
|
-
`rig entry takes at most one argument, got ${positionals.length}: ${positionals.join(" ")}`
|
|
4040
|
+
`rig entry takes at most one argument, got ${String(positionals.length)}: ${positionals.join(" ")}`
|
|
4203
4041
|
);
|
|
4204
4042
|
io2.err(ENTRY_USAGE);
|
|
4205
4043
|
return 2;
|
|
@@ -4207,36 +4045,33 @@ async function runEntry(args, deps) {
|
|
|
4207
4045
|
const target = positionals[0];
|
|
4208
4046
|
let mutation;
|
|
4209
4047
|
if (target !== void 0) {
|
|
4210
|
-
if (target === "
|
|
4211
|
-
if (relayFlag !== void 0) {
|
|
4212
|
-
io2.err("--relay only applies to an explicit <wss-url> entry");
|
|
4213
|
-
io2.err(ENTRY_USAGE);
|
|
4214
|
-
return 2;
|
|
4215
|
-
}
|
|
4216
|
-
mutation = { kind: "apex" };
|
|
4217
|
-
} else if (target === "sandbox") {
|
|
4048
|
+
if (target === "clear") {
|
|
4218
4049
|
if (relayFlag !== void 0) {
|
|
4219
|
-
io2.err("--relay only applies to
|
|
4050
|
+
io2.err("--relay only applies to a <connector-url> entry");
|
|
4220
4051
|
io2.err(ENTRY_USAGE);
|
|
4221
4052
|
return 2;
|
|
4222
4053
|
}
|
|
4223
|
-
mutation = { kind: "
|
|
4224
|
-
} else if (
|
|
4225
|
-
if (relayFlag !== void 0 &&
|
|
4226
|
-
io2.err(
|
|
4227
|
-
`--relay must be a ws(s) URL, got ${JSON.stringify(relayFlag)}`
|
|
4228
|
-
);
|
|
4054
|
+
mutation = { kind: "clear" };
|
|
4055
|
+
} else if (HTTP_URL.test(target)) {
|
|
4056
|
+
if (relayFlag !== void 0 && !WS_URL.test(relayFlag)) {
|
|
4057
|
+
io2.err(`--relay must be a ws(s) URL, got ${JSON.stringify(relayFlag)}`);
|
|
4229
4058
|
io2.err(ENTRY_USAGE);
|
|
4230
4059
|
return 2;
|
|
4231
4060
|
}
|
|
4232
4061
|
mutation = {
|
|
4233
4062
|
kind: "url",
|
|
4234
|
-
|
|
4063
|
+
connectorUrl: target.replace(/\/+$/, ""),
|
|
4235
4064
|
...relayFlag !== void 0 ? { relayUrl: relayFlag } : {}
|
|
4236
4065
|
};
|
|
4066
|
+
} else if (WS_URL.test(target)) {
|
|
4067
|
+
io2.err(
|
|
4068
|
+
`${JSON.stringify(target)} is a WebSocket URL \u2014 the entry is the connector's http(s) URL (the one whose GET /ilp describes it); pass the relay with --relay`
|
|
4069
|
+
);
|
|
4070
|
+
io2.err(ENTRY_USAGE);
|
|
4071
|
+
return 2;
|
|
4237
4072
|
} else {
|
|
4238
4073
|
io2.err(
|
|
4239
|
-
`unknown entry ${JSON.stringify(target)} \u2014 expected
|
|
4074
|
+
`unknown entry ${JSON.stringify(target)} \u2014 expected a connector http(s):// URL or \`clear\``
|
|
4240
4075
|
);
|
|
4241
4076
|
io2.err(ENTRY_USAGE);
|
|
4242
4077
|
return 2;
|
|
@@ -4245,136 +4080,78 @@ async function runEntry(args, deps) {
|
|
|
4245
4080
|
try {
|
|
4246
4081
|
const configPath = configPathFor2(env);
|
|
4247
4082
|
const file = readEntryConfig(configPath);
|
|
4248
|
-
const
|
|
4249
|
-
const effective = () => {
|
|
4250
|
-
const btpExplicit = env["TOON_CLIENT_PROXY_URL"] ?? env["TOON_CLIENT_BTP_URL"] ?? file.proxyUrl ?? file.btpUrl;
|
|
4251
|
-
const btpFromEnv = env["TOON_CLIENT_PROXY_URL"] ?? env["TOON_CLIENT_BTP_URL"];
|
|
4252
|
-
const relayExplicit = env["TOON_CLIENT_RELAY_URL"] ?? file.relayUrl;
|
|
4253
|
-
return {
|
|
4254
|
-
btpUrl: btpExplicit ?? seed?.btpEndpoint ?? null,
|
|
4255
|
-
btpSource: btpExplicit ? btpFromEnv ? "env" : "config" : seed?.btpEndpoint ? "genesis-seed" : null,
|
|
4256
|
-
relayUrl: relayExplicit ?? seed?.relayUrl ?? null,
|
|
4257
|
-
relaySource: env["TOON_CLIENT_RELAY_URL"] ? "env" : file.relayUrl ? "config" : seed?.relayUrl ? "genesis-seed" : null
|
|
4258
|
-
};
|
|
4259
|
-
};
|
|
4083
|
+
const label = (source) => source === "env" ? "env" : source === "legacy-env" ? "env (TOON_CLIENT_PROXY_URL, pre-4.0 spelling \u2014 set TOON_CONNECTOR)" : source === "config" ? `config (${configPath})` : source === "legacy-config" ? `config proxyUrl (${configPath}, pre-4.0 spelling)` : "not configured";
|
|
4260
4084
|
if (mutation === void 0) {
|
|
4261
|
-
const state2 =
|
|
4262
|
-
const entry = classifyEntry(state2.btpUrl, seed?.btpEndpoint, state2.btpSource);
|
|
4085
|
+
const state2 = effectiveEntry(env, file);
|
|
4263
4086
|
if (json) {
|
|
4264
4087
|
io2.emitJson({
|
|
4265
4088
|
command: "entry",
|
|
4266
|
-
|
|
4267
|
-
btpUrl: state2.btpUrl,
|
|
4268
|
-
btpSource: state2.btpSource,
|
|
4269
|
-
relayUrl: state2.relayUrl,
|
|
4270
|
-
relaySource: state2.relaySource,
|
|
4089
|
+
...state2,
|
|
4271
4090
|
configPath
|
|
4272
4091
|
});
|
|
4273
4092
|
return 0;
|
|
4274
4093
|
}
|
|
4275
|
-
const label = (source) => source === "env" ? "env" : source === "config" ? `config (${configPath})` : source === "genesis-seed" ? "default apex \u2014 genesis seed" : "not configured";
|
|
4276
4094
|
io2.out(
|
|
4277
|
-
`
|
|
4095
|
+
`Connector ${state2.connectorUrl ?? "(none)"} [${label(state2.connectorSource)}]`
|
|
4278
4096
|
);
|
|
4279
|
-
io2.out(` btp ${state2.btpUrl ?? "(none)"} [${label(state2.btpSource)}]`);
|
|
4280
|
-
io2.out(` relay ${state2.relayUrl ?? "(none)"} [${label(state2.relaySource)}]`);
|
|
4281
4097
|
io2.out(
|
|
4282
|
-
|
|
4098
|
+
`Relay ${state2.relayUrl ?? "(none)"} [${label(state2.relaySource)}]`
|
|
4283
4099
|
);
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
for (const envVar of [
|
|
4288
|
-
"TOON_CLIENT_BTP_URL",
|
|
4289
|
-
"TOON_CLIENT_PROXY_URL",
|
|
4290
|
-
"TOON_CLIENT_RELAY_URL"
|
|
4291
|
-
]) {
|
|
4292
|
-
if (env[envVar] !== void 0) {
|
|
4293
|
-
warnings.push(
|
|
4294
|
-
`${envVar}=${env[envVar]} is set in the environment and overrides the config value you just wrote \u2014 unset it for this entry to take effect.`
|
|
4100
|
+
if (!state2.connectorUrl) {
|
|
4101
|
+
io2.out(
|
|
4102
|
+
"Set one with `rig entry <connector-url>` (or export TOON_CONNECTOR)."
|
|
4295
4103
|
);
|
|
4296
4104
|
}
|
|
4105
|
+
return 0;
|
|
4297
4106
|
}
|
|
4298
|
-
warnings
|
|
4299
|
-
|
|
4300
|
-
)
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
let wroteRelay;
|
|
4304
|
-
if (mutation.kind === "apex") {
|
|
4305
|
-
wroteBtp = null;
|
|
4306
|
-
wroteRelay = null;
|
|
4307
|
-
delete file.btpUrl;
|
|
4308
|
-
delete file.relayUrl;
|
|
4309
|
-
delete file.proxyUrl;
|
|
4310
|
-
} else if (mutation.kind === "sandbox") {
|
|
4311
|
-
wroteBtp = SANDBOX_BTP_URL;
|
|
4312
|
-
wroteRelay = SANDBOX_RELAY_URL;
|
|
4313
|
-
file.btpUrl = SANDBOX_BTP_URL;
|
|
4314
|
-
file.relayUrl = SANDBOX_RELAY_URL;
|
|
4315
|
-
delete file.proxyUrl;
|
|
4316
|
-
} else {
|
|
4317
|
-
wroteBtp = mutation.btpUrl;
|
|
4318
|
-
wroteRelay = mutation.relayUrl ?? null;
|
|
4319
|
-
file.btpUrl = mutation.btpUrl;
|
|
4320
|
-
if (mutation.relayUrl !== void 0) file.relayUrl = mutation.relayUrl;
|
|
4321
|
-
delete file.proxyUrl;
|
|
4322
|
-
}
|
|
4323
|
-
if (hadProxyUrl) {
|
|
4107
|
+
const warnings = [];
|
|
4108
|
+
const next = { ...file };
|
|
4109
|
+
if (file.proxyUrl !== void 0 || file.btpUrl !== void 0) {
|
|
4110
|
+
delete next.proxyUrl;
|
|
4111
|
+
delete next.btpUrl;
|
|
4324
4112
|
warnings.push(
|
|
4325
|
-
"
|
|
4113
|
+
"removed the pre-4.0 proxyUrl/btpUrl fields (the connector URL replaces both)"
|
|
4326
4114
|
);
|
|
4327
4115
|
}
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4116
|
+
if (mutation.kind === "clear") {
|
|
4117
|
+
delete next.connectorUrl;
|
|
4118
|
+
delete next.relayUrl;
|
|
4119
|
+
} else {
|
|
4120
|
+
next.connectorUrl = mutation.connectorUrl;
|
|
4121
|
+
if (mutation.relayUrl !== void 0) next.relayUrl = mutation.relayUrl;
|
|
4334
4122
|
}
|
|
4335
|
-
if (
|
|
4336
|
-
const effectiveChain = env["TOON_CLIENT_CHAIN"] ?? file.chain ?? file.supportedChains?.[0];
|
|
4337
|
-
if (effectiveChain === void 0 || !effectiveChain.startsWith("mina")) {
|
|
4338
|
-
warnings.push(
|
|
4339
|
-
"The sandbox entry settles ONLY mina:devnet \u2014 run `rig chain set mina` " + (effectiveChain !== void 0 ? `(currently ${effectiveChain}).` : "to pin it.")
|
|
4340
|
-
);
|
|
4341
|
-
}
|
|
4123
|
+
if (env["TOON_CONNECTOR"] || env["TOON_CLIENT_PROXY_URL"]) {
|
|
4342
4124
|
warnings.push(
|
|
4343
|
-
|
|
4125
|
+
"TOON_CONNECTOR / TOON_CLIENT_PROXY_URL is set in this shell and outranks the config file"
|
|
4344
4126
|
);
|
|
4345
4127
|
}
|
|
4346
|
-
|
|
4128
|
+
writeEntryConfig(configPath, next);
|
|
4129
|
+
const wrote = {
|
|
4130
|
+
connectorUrl: next.connectorUrl ?? null,
|
|
4131
|
+
relayUrl: next.relayUrl ?? null
|
|
4132
|
+
};
|
|
4133
|
+
const state = effectiveEntry(env, next);
|
|
4347
4134
|
if (json) {
|
|
4348
4135
|
io2.emitJson({
|
|
4349
4136
|
command: "entry",
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
btpSource: state.btpSource,
|
|
4353
|
-
relayUrl: state.relayUrl,
|
|
4354
|
-
relaySource: state.relaySource,
|
|
4355
|
-
wrote: { btpUrl: wroteBtp, relayUrl: wroteRelay },
|
|
4356
|
-
clearedTopologyCache,
|
|
4137
|
+
...state,
|
|
4138
|
+
wrote,
|
|
4357
4139
|
configPath,
|
|
4358
|
-
...warnings.length ? { warnings } : {}
|
|
4140
|
+
...warnings.length > 0 ? { warnings } : {}
|
|
4359
4141
|
});
|
|
4360
4142
|
return 0;
|
|
4361
4143
|
}
|
|
4362
|
-
if (mutation.kind === "
|
|
4363
|
-
io2.out(
|
|
4364
|
-
io2.out(` btp ${state.btpUrl ?? "(genesis seed unavailable)"}`);
|
|
4365
|
-
io2.out(` relay ${state.relayUrl ?? "(genesis seed unavailable)"}`);
|
|
4366
|
-
} else if (mutation.kind === "sandbox") {
|
|
4367
|
-
io2.out("Entry set to the devnet sandbox (Mina USDC only \u2014 multihop demo path).");
|
|
4368
|
-
io2.out(` btp ${SANDBOX_BTP_URL}`);
|
|
4369
|
-
io2.out(` relay ${SANDBOX_RELAY_URL}`);
|
|
4144
|
+
if (mutation.kind === "clear") {
|
|
4145
|
+
io2.out(`Cleared the recorded connector in ${configPath}.`);
|
|
4370
4146
|
} else {
|
|
4371
|
-
io2.out(`
|
|
4372
|
-
if (mutation.relayUrl !== void 0)
|
|
4147
|
+
io2.out(`Recorded connector ${mutation.connectorUrl} in ${configPath}.`);
|
|
4148
|
+
if (mutation.relayUrl !== void 0)
|
|
4149
|
+
io2.out(`Recorded relay ${mutation.relayUrl}.`);
|
|
4373
4150
|
}
|
|
4151
|
+
for (const w of warnings) io2.out(`warning: ${w}`);
|
|
4374
4152
|
io2.out(
|
|
4375
|
-
`
|
|
4153
|
+
`Effective connector: ${state.connectorUrl ?? "(none)"} [${label(state.connectorSource)}]`
|
|
4376
4154
|
);
|
|
4377
|
-
for (const w of warnings) io2.err(`warning: ${w}`);
|
|
4378
4155
|
return 0;
|
|
4379
4156
|
} catch (err) {
|
|
4380
4157
|
return emitCliError(io2, json, "entry", err);
|
|
@@ -4601,21 +4378,20 @@ async function runFetch(args, deps) {
|
|
|
4601
4378
|
}
|
|
4602
4379
|
|
|
4603
4380
|
// src/cli/fund.ts
|
|
4604
|
-
import { readFileSync as
|
|
4605
|
-
import { homedir as
|
|
4606
|
-
import { join as
|
|
4381
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
4382
|
+
import { homedir as homedir4 } from "os";
|
|
4383
|
+
import { join as join5 } from "path";
|
|
4607
4384
|
import { parseArgs as parseArgs11 } from "util";
|
|
4608
4385
|
var DEVNET_FAUCET_URL = "https://faucet.devnet.toonprotocol.dev";
|
|
4609
|
-
var CHAINS = ["evm", "solana"
|
|
4386
|
+
var CHAINS = ["evm", "solana"];
|
|
4610
4387
|
var CHAIN_ALIASES = {
|
|
4611
4388
|
evm: "evm",
|
|
4612
4389
|
eth: "evm",
|
|
4613
4390
|
sol: "solana",
|
|
4614
4391
|
solana: "solana",
|
|
4615
|
-
mina: "mina",
|
|
4616
4392
|
all: "all"
|
|
4617
4393
|
};
|
|
4618
|
-
var CHAIN_ARG_LIST2 = "evm | sol | solana |
|
|
4394
|
+
var CHAIN_ARG_LIST2 = "evm | sol | solana | all";
|
|
4619
4395
|
function resolveChainArg(raw) {
|
|
4620
4396
|
if (raw === void 0) return void 0;
|
|
4621
4397
|
const canonical = CHAIN_ALIASES[raw.toLowerCase()];
|
|
@@ -4681,13 +4457,8 @@ function sharedDevnetOrigin(env, file, originRelays = []) {
|
|
|
4681
4457
|
}
|
|
4682
4458
|
return void 0;
|
|
4683
4459
|
}
|
|
4684
|
-
async function
|
|
4685
|
-
|
|
4686
|
-
const { loadGenesisSeed } = await import("../network-bootstrap-27FYE3N7.js");
|
|
4687
|
-
return loadGenesisSeed();
|
|
4688
|
-
} catch {
|
|
4689
|
-
return void 0;
|
|
4690
|
-
}
|
|
4460
|
+
async function loadGenesisSeedDefault() {
|
|
4461
|
+
return void 0;
|
|
4691
4462
|
}
|
|
4692
4463
|
async function resolveEffectiveNetwork(opts) {
|
|
4693
4464
|
const { env, cwd } = opts;
|
|
@@ -4705,7 +4476,7 @@ async function resolveEffectiveNetwork(opts) {
|
|
|
4705
4476
|
...originRelays
|
|
4706
4477
|
].some((url) => url !== void 0);
|
|
4707
4478
|
if (!anyConfiguredOrigin) {
|
|
4708
|
-
const seed = await (opts.loadGenesisSeed ??
|
|
4479
|
+
const seed = await (opts.loadGenesisSeed ?? loadGenesisSeedDefault)();
|
|
4709
4480
|
devnetOrigin = devnetHost(seed?.relayUrl) ?? devnetHost(seed?.btpEndpoint);
|
|
4710
4481
|
seededOrigin = devnetOrigin !== void 0;
|
|
4711
4482
|
}
|
|
@@ -4748,11 +4519,11 @@ function noFaucetGuidance(network, devnetOrigin) {
|
|
|
4748
4519
|
return `${head}. If you meant the shared devnet, set TOON_CLIENT_NETWORK=devnet and re-run \`rig fund\` \u2014 no faucet URL is needed there. If this is a self-hosted network with its own faucet, set TOON_CLIENT_FAUCET_URL (or the faucetUrl config field). ${external}`;
|
|
4749
4520
|
}
|
|
4750
4521
|
function readFundConfig(env) {
|
|
4751
|
-
const dir = env["TOON_CLIENT_HOME"] ??
|
|
4752
|
-
const configPath =
|
|
4522
|
+
const dir = env["TOON_CLIENT_HOME"] ?? join5(homedir4(), ".toon-client");
|
|
4523
|
+
const configPath = join5(dir, "config.json");
|
|
4753
4524
|
try {
|
|
4754
4525
|
return {
|
|
4755
|
-
file: JSON.parse(
|
|
4526
|
+
file: JSON.parse(readFileSync4(configPath, "utf8")),
|
|
4756
4527
|
configPath
|
|
4757
4528
|
};
|
|
4758
4529
|
} catch (err) {
|
|
@@ -4830,14 +4601,13 @@ async function runFund(args, deps) {
|
|
|
4830
4601
|
sourceLabel: resolved.sourceLabel
|
|
4831
4602
|
};
|
|
4832
4603
|
const client = await import("@toon-protocol/client");
|
|
4833
|
-
const derived =
|
|
4834
|
-
resolved.
|
|
4835
|
-
|
|
4836
|
-
);
|
|
4604
|
+
const derived = client.deriveFullIdentity(resolved.mnemonic, {
|
|
4605
|
+
accountIndex: resolved.accountIndex,
|
|
4606
|
+
scheme: "legacy"
|
|
4607
|
+
});
|
|
4837
4608
|
const addresses = {
|
|
4838
4609
|
evm: derived.evm.address || null,
|
|
4839
|
-
solana: derived.solana.publicKey || null
|
|
4840
|
-
mina: derived.mina.publicKey || null
|
|
4610
|
+
solana: derived.solana.publicKey || null
|
|
4841
4611
|
};
|
|
4842
4612
|
if (!faucetUrl) {
|
|
4843
4613
|
const guidance = noFaucetGuidance(network, devnetOrigin);
|
|
@@ -4857,14 +4627,13 @@ async function runFund(args, deps) {
|
|
|
4857
4627
|
io2.out("Wallet addresses:");
|
|
4858
4628
|
io2.out(` evm ${addresses.evm ?? "(no key derived)"}`);
|
|
4859
4629
|
io2.out(` solana ${addresses.solana ?? "(no key derived)"}`);
|
|
4860
|
-
io2.out(` mina ${addresses.mina ?? "(no key derived \u2014 optional mina-signer dependency missing)"}`);
|
|
4861
4630
|
return 0;
|
|
4862
4631
|
}
|
|
4863
4632
|
const timeoutEnv = env["TOON_CLIENT_FAUCET_TIMEOUT_MS"];
|
|
4864
|
-
const timeoutFor = (
|
|
4633
|
+
const timeoutFor = () => {
|
|
4865
4634
|
if (timeoutEnv && Number.isFinite(Number(timeoutEnv))) return Number(timeoutEnv);
|
|
4866
4635
|
if (file.faucetTimeoutMs !== void 0) return file.faucetTimeoutMs;
|
|
4867
|
-
return
|
|
4636
|
+
return 9e4;
|
|
4868
4637
|
};
|
|
4869
4638
|
if (!json && inferredDevnet) {
|
|
4870
4639
|
io2.out(
|
|
@@ -4874,7 +4643,7 @@ async function runFund(args, deps) {
|
|
|
4874
4643
|
if (!json) {
|
|
4875
4644
|
const list = targetChains.join(", ");
|
|
4876
4645
|
io2.out(
|
|
4877
|
-
`Requesting ${targetChains.length === 1 ? "" : "parallel "}USDC drip${targetChains.length === 1 ? "" : "s"} from ${faucetUrl} for ${list} \u2026`
|
|
4646
|
+
`Requesting ${targetChains.length === 1 ? "" : "parallel "}USDC drip${targetChains.length === 1 ? "" : "s"} from ${faucetUrl} for ${list} \u2026`
|
|
4878
4647
|
);
|
|
4879
4648
|
}
|
|
4880
4649
|
const singleChain = targetChains.length === 1;
|
|
@@ -4885,13 +4654,13 @@ async function runFund(args, deps) {
|
|
|
4885
4654
|
chain,
|
|
4886
4655
|
funded: false,
|
|
4887
4656
|
address: null,
|
|
4888
|
-
error: `no ${chain} address could be derived for this identity`
|
|
4657
|
+
error: `no ${chain} address could be derived for this identity`
|
|
4889
4658
|
};
|
|
4890
4659
|
}
|
|
4891
4660
|
const started = Date.now();
|
|
4892
4661
|
try {
|
|
4893
4662
|
const { response } = await client.fundWallet(faucetUrl, address, chain, {
|
|
4894
|
-
timeout: timeoutFor(
|
|
4663
|
+
timeout: timeoutFor(),
|
|
4895
4664
|
...deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}
|
|
4896
4665
|
});
|
|
4897
4666
|
return {
|
|
@@ -5000,7 +4769,8 @@ import { dirname as dirname4 } from "path";
|
|
|
5000
4769
|
import { createInterface } from "readline/promises";
|
|
5001
4770
|
import { parseArgs as parseArgs12 } from "util";
|
|
5002
4771
|
async function loadKeyOps() {
|
|
5003
|
-
|
|
4772
|
+
const { generateKeystore, importKeystore } = await import("@toon-protocol/client");
|
|
4773
|
+
return { generateKeystore, importKeystore, deriveNostrKeyFromMnemonic };
|
|
5004
4774
|
}
|
|
5005
4775
|
var IdentityExistsError = class extends Error {
|
|
5006
4776
|
constructor(pubkey, sourceLabel) {
|
|
@@ -5544,12 +5314,6 @@ async function resolveProfileRelay(flagRelay, originRelay, toonRelays) {
|
|
|
5544
5314
|
...toonRelays
|
|
5545
5315
|
].filter((u) => u !== void 0 && isWebSocketRelay2(u));
|
|
5546
5316
|
if (candidates[0] !== void 0) return candidates[0];
|
|
5547
|
-
try {
|
|
5548
|
-
const { loadGenesisSeed } = await import("../network-bootstrap-27FYE3N7.js");
|
|
5549
|
-
const seed = loadGenesisSeed();
|
|
5550
|
-
if (seed?.relayUrl && isWebSocketRelay2(seed.relayUrl)) return seed.relayUrl;
|
|
5551
|
-
} catch {
|
|
5552
|
-
}
|
|
5553
5317
|
return void 0;
|
|
5554
5318
|
}
|
|
5555
5319
|
async function resolveOrInitGitRepo(deps, flags) {
|
|
@@ -5735,33 +5499,10 @@ async function runInit(args, deps) {
|
|
|
5735
5499
|
|
|
5736
5500
|
// src/cli/maintainers.ts
|
|
5737
5501
|
import { parseArgs as parseArgs14 } from "util";
|
|
5738
|
-
var HEX64_RE3 = /^[0-9a-f]{64}$/;
|
|
5739
|
-
var WS_URL_RE4 = /^wss?:\/\//i;
|
|
5740
|
-
var MAINTAINERS_USAGE = `Usage: rig maintainers <list|add|remove> [<pubkey>] [options]
|
|
5741
5502
|
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
maintainer; this command edits the explicit set on the kind:30617 announcement.
|
|
5746
|
-
|
|
5747
|
-
Subcommands:
|
|
5748
|
-
list show the owner + declared maintainers \u2014 FREE (relay read)
|
|
5749
|
-
add <pubkey> add a maintainer (npub or 64-char hex) \u2014 PAID: republishes
|
|
5750
|
-
the kind:30617 (permanent, non-refundable)
|
|
5751
|
-
remove <pubkey> remove a maintainer \u2014 PAID: republishes the kind:30617
|
|
5752
|
-
|
|
5753
|
-
add/remove must run under the repo OWNER's identity (only the owner's
|
|
5754
|
-
announcement is authoritative).
|
|
5755
|
-
|
|
5756
|
-
Options:
|
|
5757
|
-
--repo-id <id> repository id / NIP-34 d-tag (default: git config)
|
|
5758
|
-
--owner <pubkey> repository owner (npub or hex; default: git config)
|
|
5759
|
-
--remote <name> publish/read via this configured git remote (default: origin)
|
|
5760
|
-
--relay <url> ad-hoc relay override (exactly one for add/remove)
|
|
5761
|
-
--yes skip the fee confirmation (required when not a TTY)
|
|
5762
|
-
--json machine-readable envelope
|
|
5763
|
-
-h, --help show this help`;
|
|
5764
|
-
var MAINT_OPTIONS = {
|
|
5503
|
+
// src/cli/repo-command.ts
|
|
5504
|
+
var WS_URL_RE4 = /^wss?:\/\//i;
|
|
5505
|
+
var REPO_COMMAND_OPTIONS = {
|
|
5765
5506
|
json: { type: "boolean", default: false },
|
|
5766
5507
|
yes: { type: "boolean", default: false },
|
|
5767
5508
|
relay: { type: "string", multiple: true },
|
|
@@ -5770,7 +5511,7 @@ var MAINT_OPTIONS = {
|
|
|
5770
5511
|
owner: { type: "string" },
|
|
5771
5512
|
help: { type: "boolean", short: "h", default: false }
|
|
5772
5513
|
};
|
|
5773
|
-
function
|
|
5514
|
+
function pickRepoCommandFlags(values) {
|
|
5774
5515
|
const flags = {
|
|
5775
5516
|
json: values["json"] === true,
|
|
5776
5517
|
yes: values["yes"] === true,
|
|
@@ -5783,7 +5524,7 @@ function pickFlags(values) {
|
|
|
5783
5524
|
flags.owner = ownerToHex(values["owner"]);
|
|
5784
5525
|
return flags;
|
|
5785
5526
|
}
|
|
5786
|
-
async function
|
|
5527
|
+
async function resolveRepoContext(flags, deps) {
|
|
5787
5528
|
let repoRoot;
|
|
5788
5529
|
let toonConfig = {
|
|
5789
5530
|
relays: []
|
|
@@ -5812,6 +5553,33 @@ async function resolveContext(flags, deps) {
|
|
|
5812
5553
|
...repoRoot !== void 0 ? { repoRoot } : {}
|
|
5813
5554
|
};
|
|
5814
5555
|
}
|
|
5556
|
+
|
|
5557
|
+
// src/cli/maintainers.ts
|
|
5558
|
+
var HEX64_RE3 = /^[0-9a-f]{64}$/;
|
|
5559
|
+
var MAINTAINERS_USAGE = `Usage: rig maintainers <list|add|remove> [<pubkey>] [options]
|
|
5560
|
+
|
|
5561
|
+
Manage a repo's declared maintainers (#287). Status authority is consumer-side:
|
|
5562
|
+
rig and rig-web honor an issue/PR status (kind:1630-1633) ONLY when its author
|
|
5563
|
+
is the repo owner or a declared maintainer. The owner is always an implicit
|
|
5564
|
+
maintainer; this command edits the explicit set on the kind:30617 announcement.
|
|
5565
|
+
|
|
5566
|
+
Subcommands:
|
|
5567
|
+
list show the owner + declared maintainers \u2014 FREE (relay read)
|
|
5568
|
+
add <pubkey> add a maintainer (npub or 64-char hex) \u2014 PAID: republishes
|
|
5569
|
+
the kind:30617 (permanent, non-refundable)
|
|
5570
|
+
remove <pubkey> remove a maintainer \u2014 PAID: republishes the kind:30617
|
|
5571
|
+
|
|
5572
|
+
add/remove must run under the repo OWNER's identity (only the owner's
|
|
5573
|
+
announcement is authoritative).
|
|
5574
|
+
|
|
5575
|
+
Options:
|
|
5576
|
+
--repo-id <id> repository id / NIP-34 d-tag (default: git config)
|
|
5577
|
+
--owner <pubkey> repository owner (npub or hex; default: git config)
|
|
5578
|
+
--remote <name> publish/read via this configured git remote (default: origin)
|
|
5579
|
+
--relay <url> ad-hoc relay override (exactly one for add/remove)
|
|
5580
|
+
--yes skip the fee confirmation (required when not a TTY)
|
|
5581
|
+
--json machine-readable envelope
|
|
5582
|
+
-h, --help show this help`;
|
|
5815
5583
|
async function runMaintainers(args, deps) {
|
|
5816
5584
|
const { io: io2 } = deps;
|
|
5817
5585
|
const [sub, ...rest] = args;
|
|
@@ -5841,13 +5609,13 @@ async function runList2(args, deps) {
|
|
|
5841
5609
|
try {
|
|
5842
5610
|
const { values, positionals } = parseArgs14({
|
|
5843
5611
|
args,
|
|
5844
|
-
options:
|
|
5612
|
+
options: REPO_COMMAND_OPTIONS,
|
|
5845
5613
|
allowPositionals: true
|
|
5846
5614
|
});
|
|
5847
5615
|
if (positionals.length > 0) {
|
|
5848
5616
|
throw new Error("rig maintainers list takes no positional arguments");
|
|
5849
5617
|
}
|
|
5850
|
-
flags =
|
|
5618
|
+
flags = pickRepoCommandFlags(values);
|
|
5851
5619
|
} catch (err) {
|
|
5852
5620
|
io2.err(err instanceof Error ? err.message : String(err));
|
|
5853
5621
|
io2.err(MAINTAINERS_USAGE);
|
|
@@ -5858,7 +5626,7 @@ async function runList2(args, deps) {
|
|
|
5858
5626
|
return 0;
|
|
5859
5627
|
}
|
|
5860
5628
|
try {
|
|
5861
|
-
const ctx = await
|
|
5629
|
+
const ctx = await resolveRepoContext(flags, deps);
|
|
5862
5630
|
const wsRelays = ctx.relays.filter((url) => WS_URL_RE4.test(url));
|
|
5863
5631
|
if (wsRelays.length === 0) {
|
|
5864
5632
|
throw new InvalidRelayUrlError(
|
|
@@ -5908,10 +5676,10 @@ async function runMutate(op, args, deps) {
|
|
|
5908
5676
|
try {
|
|
5909
5677
|
const { values, positionals } = parseArgs14({
|
|
5910
5678
|
args,
|
|
5911
|
-
options:
|
|
5679
|
+
options: REPO_COMMAND_OPTIONS,
|
|
5912
5680
|
allowPositionals: true
|
|
5913
5681
|
});
|
|
5914
|
-
flags =
|
|
5682
|
+
flags = pickRepoCommandFlags(values);
|
|
5915
5683
|
if (flags.help) {
|
|
5916
5684
|
io2.out(MAINTAINERS_USAGE);
|
|
5917
5685
|
return 0;
|
|
@@ -5930,7 +5698,7 @@ async function runMutate(op, args, deps) {
|
|
|
5930
5698
|
}
|
|
5931
5699
|
let standaloneCtx;
|
|
5932
5700
|
try {
|
|
5933
|
-
const ctx = await
|
|
5701
|
+
const ctx = await resolveRepoContext(flags, deps);
|
|
5934
5702
|
if (ctx.relays.length > 1) {
|
|
5935
5703
|
io2.err(singleRelayRefusal(ctx.resolved, "Nothing was published or paid."));
|
|
5936
5704
|
return 1;
|
|
@@ -5985,7 +5753,13 @@ async function runMutate(op, args, deps) {
|
|
|
5985
5753
|
const next = op === "add" ? [...current, pubkey] : current.filter((m) => m !== pubkey);
|
|
5986
5754
|
const name = remote.name ?? ctx.repoId;
|
|
5987
5755
|
const description = remote.description ?? "";
|
|
5988
|
-
const event = buildRepoAnnouncement(
|
|
5756
|
+
const event = buildRepoAnnouncement(
|
|
5757
|
+
ctx.repoId,
|
|
5758
|
+
name,
|
|
5759
|
+
description,
|
|
5760
|
+
next,
|
|
5761
|
+
remote.payout
|
|
5762
|
+
);
|
|
5989
5763
|
const fee = (await standaloneCtx.publisher.getFeeRates()).eventFee.toString();
|
|
5990
5764
|
const action = `kind:30617 maintainers ${op} ${pubkey.slice(0, 8)}\u2026`;
|
|
5991
5765
|
if (!flags.json) {
|
|
@@ -6314,57 +6088,39 @@ var DvmBuyJobError = class extends Error {
|
|
|
6314
6088
|
}
|
|
6315
6089
|
};
|
|
6316
6090
|
var defaultSubmitDvmBuyJob = async (request) => {
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
{
|
|
6091
|
+
let answer;
|
|
6092
|
+
try {
|
|
6093
|
+
answer = await request.submit({
|
|
6320
6094
|
kind: ARNS_BUY_JOB_KIND,
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
["
|
|
6325
|
-
["
|
|
6326
|
-
...request.years !== null ? [["param", "years", String(request.years)]] : [],
|
|
6327
|
-
["param", "processId", request.processId]
|
|
6095
|
+
params: [
|
|
6096
|
+
["name", request.name],
|
|
6097
|
+
["type", request.type],
|
|
6098
|
+
...request.years !== null ? [["years", String(request.years)]] : [],
|
|
6099
|
+
["processId", request.processId]
|
|
6328
6100
|
]
|
|
6329
|
-
},
|
|
6330
|
-
request.nostrSecretKey
|
|
6331
|
-
);
|
|
6332
|
-
const url = `${request.viaUrl.replace(/\/+$/, "")}/store`;
|
|
6333
|
-
let response;
|
|
6334
|
-
try {
|
|
6335
|
-
response = await fetch(url, {
|
|
6336
|
-
method: "POST",
|
|
6337
|
-
headers: { "content-type": "application/json" },
|
|
6338
|
-
body: JSON.stringify({ event })
|
|
6339
6101
|
});
|
|
6340
6102
|
} catch (err) {
|
|
6341
6103
|
throw new DvmBuyJobError(
|
|
6342
|
-
`could not reach the DVM at ${
|
|
6104
|
+
`could not reach the DVM at ${request.destination}: ${err instanceof Error ? err.message : String(err)}`
|
|
6343
6105
|
);
|
|
6344
6106
|
}
|
|
6345
|
-
|
|
6346
|
-
try {
|
|
6347
|
-
body = await response.json();
|
|
6348
|
-
} catch {
|
|
6107
|
+
if (!answer.accept) {
|
|
6349
6108
|
throw new DvmBuyJobError(
|
|
6350
|
-
`the DVM at ${
|
|
6109
|
+
`the DVM at ${request.destination} rejected the kind:${ARNS_BUY_JOB_KIND} buy job (HTTP ${answer.status}${answer.code ? `, ${answer.code}` : ""})${answer.message ? `: ${answer.message}` : ""}`
|
|
6351
6110
|
);
|
|
6352
6111
|
}
|
|
6353
|
-
|
|
6354
|
-
throw new DvmBuyJobError(
|
|
6355
|
-
`the DVM rejected the kind:${ARNS_BUY_JOB_KIND} buy job (HTTP ${response.status}${body.code ? `, ${body.code}` : ""})${body.message ? `: ${body.message}` : ""}`
|
|
6356
|
-
);
|
|
6357
|
-
}
|
|
6358
|
-
const registryTxId = body.result?.registryTxId;
|
|
6112
|
+
const registryTxId = answer.result?.["registryTxId"];
|
|
6359
6113
|
if (typeof registryTxId !== "string" || registryTxId.length === 0) {
|
|
6360
6114
|
throw new DvmBuyJobError(
|
|
6361
|
-
`the DVM accepted the job but returned no registryTxId \u2014 response: ` + JSON.stringify(
|
|
6115
|
+
`the DVM accepted the job but returned no registryTxId \u2014 response: ` + JSON.stringify(answer.result ?? null)
|
|
6362
6116
|
);
|
|
6363
6117
|
}
|
|
6118
|
+
const quotedMario = answer.result?.["quotedMario"];
|
|
6119
|
+
const syncAttributesTxId = answer.result?.["syncAttributesTxId"];
|
|
6364
6120
|
return {
|
|
6365
6121
|
registryTxId,
|
|
6366
|
-
quotedMario: typeof
|
|
6367
|
-
syncAttributesTxId: typeof
|
|
6122
|
+
quotedMario: typeof quotedMario === "string" ? quotedMario : null,
|
|
6123
|
+
syncAttributesTxId: typeof syncAttributesTxId === "string" ? syncAttributesTxId : null
|
|
6368
6124
|
};
|
|
6369
6125
|
};
|
|
6370
6126
|
var GAS_STATION_JOB_KIND = 5096;
|
|
@@ -6376,47 +6132,23 @@ var GasStationJobError = class extends Error {
|
|
|
6376
6132
|
}
|
|
6377
6133
|
reason;
|
|
6378
6134
|
};
|
|
6379
|
-
async function
|
|
6380
|
-
|
|
6381
|
-
const event = finalizeEvent(
|
|
6382
|
-
{
|
|
6383
|
-
kind: GAS_STATION_JOB_KIND,
|
|
6384
|
-
created_at: Math.floor(Date.now() / 1e3),
|
|
6385
|
-
content: "",
|
|
6386
|
-
tags: params.map(([k, v]) => ["param", k, v])
|
|
6387
|
-
},
|
|
6388
|
-
nostrSecretKey
|
|
6389
|
-
);
|
|
6390
|
-
const url = `${viaUrl.replace(/\/+$/, "")}/store`;
|
|
6391
|
-
let response;
|
|
6135
|
+
async function submitGasStationJob(destination, params, submit) {
|
|
6136
|
+
let answer;
|
|
6392
6137
|
try {
|
|
6393
|
-
|
|
6394
|
-
method: "POST",
|
|
6395
|
-
headers: { "content-type": "application/json" },
|
|
6396
|
-
body: JSON.stringify({ event })
|
|
6397
|
-
});
|
|
6138
|
+
answer = await submit({ kind: GAS_STATION_JOB_KIND, params });
|
|
6398
6139
|
} catch (err) {
|
|
6399
6140
|
throw new GasStationJobError(
|
|
6400
6141
|
"unreachable",
|
|
6401
|
-
`could not reach the DVM at ${
|
|
6142
|
+
`could not reach the DVM at ${destination}: ${err instanceof Error ? err.message : String(err)}`
|
|
6402
6143
|
);
|
|
6403
6144
|
}
|
|
6404
|
-
|
|
6405
|
-
try {
|
|
6406
|
-
body = await response.json();
|
|
6407
|
-
} catch {
|
|
6408
|
-
throw new GasStationJobError(
|
|
6409
|
-
"bad_response",
|
|
6410
|
-
`the DVM at ${url} returned a non-JSON response (HTTP ${response.status})`
|
|
6411
|
-
);
|
|
6412
|
-
}
|
|
6413
|
-
if (!response.ok || body.accept !== true || !body.result) {
|
|
6145
|
+
if (!answer.accept || !answer.result) {
|
|
6414
6146
|
throw new GasStationJobError(
|
|
6415
|
-
String(
|
|
6416
|
-
`the DVM rejected the kind:${GAS_STATION_JOB_KIND} job (HTTP ${
|
|
6147
|
+
String(answer.code ?? "rejected"),
|
|
6148
|
+
`the DVM at ${destination} rejected the kind:${GAS_STATION_JOB_KIND} job (HTTP ${answer.status}${answer.code ? `, ${answer.code}` : ""})${answer.message ? `: ${answer.message}` : ""}`
|
|
6417
6149
|
);
|
|
6418
6150
|
}
|
|
6419
|
-
const result =
|
|
6151
|
+
const result = answer.result;
|
|
6420
6152
|
if (result["status"] === "failed") {
|
|
6421
6153
|
throw new GasStationJobError(
|
|
6422
6154
|
String(result["reason"] ?? "failed"),
|
|
@@ -6427,13 +6159,13 @@ async function postGasStationJob(viaUrl, params, nostrSecretKey) {
|
|
|
6427
6159
|
}
|
|
6428
6160
|
var defaultGasStationClient = {
|
|
6429
6161
|
quote: async (args) => {
|
|
6430
|
-
const result = await
|
|
6431
|
-
args.
|
|
6162
|
+
const result = await submitGasStationJob(
|
|
6163
|
+
args.destination,
|
|
6432
6164
|
[
|
|
6433
6165
|
["phase", "quote"],
|
|
6434
6166
|
...args.transaction !== void 0 ? [["transaction", args.transaction]] : []
|
|
6435
6167
|
],
|
|
6436
|
-
args.
|
|
6168
|
+
args.submit
|
|
6437
6169
|
);
|
|
6438
6170
|
const { quoteId, feePayer, maxLamports, recentBlockhash, expiresAt } = result;
|
|
6439
6171
|
if (typeof quoteId !== "string" || typeof feePayer !== "string" || typeof maxLamports !== "string" || typeof recentBlockhash !== "string" || typeof expiresAt !== "number") {
|
|
@@ -6445,15 +6177,15 @@ var defaultGasStationClient = {
|
|
|
6445
6177
|
return { quoteId, feePayer, maxLamports, recentBlockhash, expiresAt };
|
|
6446
6178
|
},
|
|
6447
6179
|
execute: async (args) => {
|
|
6448
|
-
const result = await
|
|
6449
|
-
args.
|
|
6180
|
+
const result = await submitGasStationJob(
|
|
6181
|
+
args.destination,
|
|
6450
6182
|
[
|
|
6451
6183
|
["phase", "execute"],
|
|
6452
6184
|
["transaction", args.transaction],
|
|
6453
6185
|
["quoteId", args.quoteId],
|
|
6454
6186
|
["idempotencyKey", args.idempotencyKey]
|
|
6455
6187
|
],
|
|
6456
|
-
args.
|
|
6188
|
+
args.submit
|
|
6457
6189
|
);
|
|
6458
6190
|
const signature = result["signature"];
|
|
6459
6191
|
if (typeof signature !== "string" || signature.length === 0) {
|
|
@@ -6470,7 +6202,7 @@ var defaultGasStationClient = {
|
|
|
6470
6202
|
};
|
|
6471
6203
|
}
|
|
6472
6204
|
};
|
|
6473
|
-
var
|
|
6205
|
+
var DEVNET_DVM_DESTINATION = "g.toon.ario";
|
|
6474
6206
|
var NAME_USAGE = `Usage: rig name <buy|set|status> <name> [options]
|
|
6475
6207
|
|
|
6476
6208
|
ArNS naming for Arweave-served artifacts. A name registered on the ar.io
|
|
@@ -6483,7 +6215,7 @@ mnemonic that pays for pushes (derived at m/44'/501'/0'/0'). Fund it with
|
|
|
6483
6215
|
registry program \u2014 NOT through TOON ILP payment channels.
|
|
6484
6216
|
|
|
6485
6217
|
Commands:
|
|
6486
|
-
name buy <name> [--years n | --permabuy] [--via <
|
|
6218
|
+
name buy <name> [--years n | --permabuy] [--via <destination>]
|
|
6487
6219
|
quote (mARIO) \u2192 confirm \u2192 register. The spawned ANT is
|
|
6488
6220
|
owned by this identity's Solana key. Default: 1-year
|
|
6489
6221
|
lease. PAID \u2014 spends mARIO from the Solana wallet.
|
|
@@ -6491,7 +6223,7 @@ Commands:
|
|
|
6491
6223
|
the ANT (dust SOL only), then a store DVM executes the
|
|
6492
6224
|
kind:5095 buy job and pays the mARIO from ITS wallet;
|
|
6493
6225
|
the name is owned by your ANT from inception.
|
|
6494
|
-
name set <name> <txId> [--undername <sub>] [--ttl <seconds>] [--via <
|
|
6226
|
+
name set <name> <txId> [--undername <sub>] [--ttl <seconds>] [--via <destination>]
|
|
6495
6227
|
point the name (or an undername) at an Arweave txId
|
|
6496
6228
|
(typically a deployed path manifest). Signs an ANT
|
|
6497
6229
|
record update with the Solana key. With --via: the
|
|
@@ -6523,17 +6255,24 @@ Options:
|
|
|
6523
6255
|
unverified.
|
|
6524
6256
|
--process-id <id> explicit ArNS registry program id \u2014 a Solana program
|
|
6525
6257
|
address (overrides --network; or RIG_ARIO_PROCESS_ID)
|
|
6526
|
-
--via <
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
|
|
6258
|
+
--via <destination> broker buy/set through a store node's DVM, naming its
|
|
6259
|
+
ILP DESTINATION (or RIG_ARNS_DVM_DESTINATION), e.g.
|
|
6260
|
+
--via ${DEVNET_DVM_DESTINATION}. The DVM pays the mARIO;
|
|
6261
|
+
you own the name via your spawned ANT.
|
|
6262
|
+
The job travels as a PAID packet, exactly as a git-object
|
|
6263
|
+
store write does \u2014 the store sits behind the connector's
|
|
6264
|
+
payment termination, so there is no unpaid endpoint to
|
|
6265
|
+
aim at. That node's ingress, route price and payment
|
|
6266
|
+
channel are all discovered from its own announce, so the
|
|
6267
|
+
destination is the only thing you supply.
|
|
6268
|
+
Costs one store-route packet per job (two for set:
|
|
6269
|
+
quote + execute).
|
|
6531
6270
|
DEVNET DEFAULT: with --network devnet and the TOON
|
|
6532
6271
|
network on devnet too, buy/set default to the deployed
|
|
6533
|
-
devnet store DVM (${
|
|
6272
|
+
devnet store DVM (${DEVNET_DVM_DESTINATION})
|
|
6534
6273
|
unless --direct opts out.
|
|
6535
6274
|
--direct force the direct wallet-paid path: never default (or
|
|
6536
|
-
read
|
|
6275
|
+
read RIG_ARNS_DVM_DESTINATION as) a --via DVM. Mutually
|
|
6537
6276
|
exclusive with an explicit --via.
|
|
6538
6277
|
--yes skip the confirmation (required when not a TTY) for
|
|
6539
6278
|
buy/set
|
|
@@ -6543,6 +6282,25 @@ Options:
|
|
|
6543
6282
|
var DEFAULT_TTL_SECONDS = 3600;
|
|
6544
6283
|
var DEFAULT_LEASE_YEARS = 1;
|
|
6545
6284
|
var NETWORKS = ["mainnet", "devnet"];
|
|
6285
|
+
async function openStoreJobSession(deps, destination) {
|
|
6286
|
+
const ctx = await (deps.loadStandalone ?? defaultLoadStandalone)({
|
|
6287
|
+
env: deps.env,
|
|
6288
|
+
cwd: deps.cwd,
|
|
6289
|
+
warn: (line) => deps.io.err(line),
|
|
6290
|
+
storeDestination: destination
|
|
6291
|
+
});
|
|
6292
|
+
const submitStoreJob = ctx.publisher.submitStoreJob;
|
|
6293
|
+
if (!submitStoreJob) {
|
|
6294
|
+
await ctx.stop();
|
|
6295
|
+
throw new Error(
|
|
6296
|
+
"the active publisher cannot submit a store job (submitStoreJob unavailable) \u2014 `rig name --via` requires the standalone publisher"
|
|
6297
|
+
);
|
|
6298
|
+
}
|
|
6299
|
+
return {
|
|
6300
|
+
submit: (request) => submitStoreJob.call(ctx.publisher, request),
|
|
6301
|
+
stop: () => ctx.stop()
|
|
6302
|
+
};
|
|
6303
|
+
}
|
|
6546
6304
|
async function resolveNameContext(deps, network, processId, mode) {
|
|
6547
6305
|
const { io: io2, env } = deps;
|
|
6548
6306
|
const resolved = await resolveIdentity({
|
|
@@ -6556,10 +6314,10 @@ async function resolveNameContext(deps, network, processId, mode) {
|
|
|
6556
6314
|
sourceLabel: resolved.sourceLabel
|
|
6557
6315
|
};
|
|
6558
6316
|
const client = await import("@toon-protocol/client");
|
|
6559
|
-
const derived =
|
|
6560
|
-
resolved.
|
|
6561
|
-
|
|
6562
|
-
);
|
|
6317
|
+
const derived = client.deriveFullIdentity(resolved.mnemonic, {
|
|
6318
|
+
accountIndex: resolved.accountIndex,
|
|
6319
|
+
scheme: "legacy"
|
|
6320
|
+
});
|
|
6563
6321
|
const solanaAddress = derived.solana.publicKey;
|
|
6564
6322
|
if (!solanaAddress) {
|
|
6565
6323
|
throw new Error(
|
|
@@ -6573,7 +6331,7 @@ async function resolveNameContext(deps, network, processId, mode) {
|
|
|
6573
6331
|
network,
|
|
6574
6332
|
...processId !== void 0 ? { processId } : {}
|
|
6575
6333
|
});
|
|
6576
|
-
const nostrSecretKey =
|
|
6334
|
+
const nostrSecretKey = deriveNostrKeyFromMnemonic(
|
|
6577
6335
|
resolved.mnemonic,
|
|
6578
6336
|
resolved.accountIndex
|
|
6579
6337
|
).secretKey;
|
|
@@ -6644,12 +6402,17 @@ function parseNameFlags(args, env) {
|
|
|
6644
6402
|
"--direct and --via are mutually exclusive: --direct forces the wallet-paid path, --via brokers through a DVM"
|
|
6645
6403
|
);
|
|
6646
6404
|
}
|
|
6647
|
-
const viaRaw = values.direct ? void 0 : values.via ?? env["RIG_ARNS_DVM_URL"];
|
|
6405
|
+
const viaRaw = values.direct ? void 0 : values.via ?? env["RIG_ARNS_DVM_DESTINATION"] ?? env["RIG_ARNS_DVM_URL"];
|
|
6648
6406
|
let via;
|
|
6649
6407
|
if (viaRaw !== void 0) {
|
|
6650
|
-
if (
|
|
6408
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(viaRaw)) {
|
|
6651
6409
|
throw new Error(
|
|
6652
|
-
`--via
|
|
6410
|
+
`--via names an ILP destination, not a URL (got ${JSON.stringify(viaRaw)}). Brokered ArNS jobs travel as paid packets to a store node, e.g. --via ${DEVNET_DVM_DESTINATION}. The node's endpoint, price and payment channel are discovered from its own announce.`
|
|
6411
|
+
);
|
|
6412
|
+
}
|
|
6413
|
+
if (!/^g\.[a-z0-9]+(\.[a-z0-9-]+)*$/i.test(viaRaw)) {
|
|
6414
|
+
throw new Error(
|
|
6415
|
+
`--via must be an ILP destination like ${DEVNET_DVM_DESTINATION}, got ${JSON.stringify(viaRaw)}`
|
|
6653
6416
|
);
|
|
6654
6417
|
}
|
|
6655
6418
|
via = viaRaw;
|
|
@@ -6755,14 +6518,20 @@ async function runBuy(name, flags, deps) {
|
|
|
6755
6518
|
io2.out(`Spawned ANT ${spawn3.processId} (tx ${spawn3.signature})`);
|
|
6756
6519
|
}
|
|
6757
6520
|
const submit = deps.submitDvmBuyJob ?? defaultSubmitDvmBuyJob;
|
|
6758
|
-
const
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6521
|
+
const session = await openStoreJobSession(deps, via);
|
|
6522
|
+
let receipt2;
|
|
6523
|
+
try {
|
|
6524
|
+
receipt2 = await submit({
|
|
6525
|
+
destination: via,
|
|
6526
|
+
name,
|
|
6527
|
+
type,
|
|
6528
|
+
years,
|
|
6529
|
+
processId: spawn3.processId,
|
|
6530
|
+
submit: session.submit
|
|
6531
|
+
});
|
|
6532
|
+
} finally {
|
|
6533
|
+
await session.stop();
|
|
6534
|
+
}
|
|
6766
6535
|
const result2 = {
|
|
6767
6536
|
registryTxId: receipt2.registryTxId,
|
|
6768
6537
|
antProcessId: spawn3.processId,
|
|
@@ -6910,25 +6679,32 @@ async function runSet(name, txId, flags, deps) {
|
|
|
6910
6679
|
);
|
|
6911
6680
|
if (via !== null) {
|
|
6912
6681
|
const gas = deps.gasStation ?? defaultGasStationClient;
|
|
6913
|
-
const
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6682
|
+
const session = await openStoreJobSession(deps, via);
|
|
6683
|
+
let quote;
|
|
6684
|
+
let executed;
|
|
6685
|
+
try {
|
|
6686
|
+
quote = await gas.quote({
|
|
6687
|
+
destination: via,
|
|
6688
|
+
submit: session.submit
|
|
6689
|
+
});
|
|
6690
|
+
const wireTx = await signed.sdk.buildSetRecordTransaction({
|
|
6691
|
+
antProcessId,
|
|
6692
|
+
undername: undername ?? "@",
|
|
6693
|
+
transactionId: txId,
|
|
6694
|
+
ttlSeconds: flags.ttl,
|
|
6695
|
+
feePayer: quote.feePayer,
|
|
6696
|
+
recentBlockhash: quote.recentBlockhash
|
|
6697
|
+
});
|
|
6698
|
+
executed = await gas.execute({
|
|
6699
|
+
destination: via,
|
|
6700
|
+
transaction: wireTx,
|
|
6701
|
+
quoteId: quote.quoteId,
|
|
6702
|
+
idempotencyKey: randomUUID(),
|
|
6703
|
+
submit: session.submit
|
|
6704
|
+
});
|
|
6705
|
+
} finally {
|
|
6706
|
+
await session.stop();
|
|
6707
|
+
}
|
|
6932
6708
|
const gasStation = {
|
|
6933
6709
|
quoteId: quote.quoteId,
|
|
6934
6710
|
feePayer: quote.feePayer,
|
|
@@ -7092,9 +6868,9 @@ async function runName(args, deps) {
|
|
|
7092
6868
|
} catch {
|
|
7093
6869
|
}
|
|
7094
6870
|
if (toonDevnet) {
|
|
7095
|
-
flags = { ...flags, via:
|
|
6871
|
+
flags = { ...flags, via: DEVNET_DVM_DESTINATION };
|
|
7096
6872
|
io2.err(
|
|
7097
|
-
`Brokering via the devnet store DVM ${
|
|
6873
|
+
`Brokering via the devnet store DVM ${DEVNET_DVM_DESTINATION} (no --via given; pass --direct for a wallet-paid ${sub}).`
|
|
7098
6874
|
);
|
|
7099
6875
|
}
|
|
7100
6876
|
}
|
|
@@ -7120,8 +6896,285 @@ async function runName(args, deps) {
|
|
|
7120
6896
|
}
|
|
7121
6897
|
}
|
|
7122
6898
|
|
|
7123
|
-
// src/cli/
|
|
6899
|
+
// src/cli/payout.ts
|
|
7124
6900
|
import { parseArgs as parseArgs16 } from "util";
|
|
6901
|
+
import { getAddress } from "viem";
|
|
6902
|
+
var PAYOUT_USAGE = `Usage: rig payout <set|clear|show> [<address>] [options]
|
|
6903
|
+
|
|
6904
|
+
Manage a repo's declared payout pointer (rig#92, part of the payout epic
|
|
6905
|
+
toon-protocol/toon-meta#391). No pointer on the kind:30617 announcement means
|
|
6906
|
+
a serving node keeps 100% of repo-scoped write fees; a pointer opts the repo
|
|
6907
|
+
into that node's declared ownerFeeShare split.
|
|
6908
|
+
|
|
6909
|
+
Subcommands:
|
|
6910
|
+
show show the declared payout pointer \u2014 FREE (relay read)
|
|
6911
|
+
set <address> declare the payout pointer (EVM address, EIP-55
|
|
6912
|
+
checksummed or all-lowercase) \u2014 PAID: republishes the
|
|
6913
|
+
kind:30617 (permanent, non-refundable). v1 accepts evm
|
|
6914
|
+
addresses only.
|
|
6915
|
+
clear remove the payout pointer \u2014 PAID: republishes the
|
|
6916
|
+
kind:30617
|
|
6917
|
+
|
|
6918
|
+
set/clear must run under the repo OWNER's identity (only the owner's
|
|
6919
|
+
announcement is authoritative).
|
|
6920
|
+
|
|
6921
|
+
Options:
|
|
6922
|
+
--repo-id <id> repository id / NIP-34 d-tag (default: git config)
|
|
6923
|
+
--owner <pubkey> repository owner (npub or hex; default: git config)
|
|
6924
|
+
--remote <name> publish/read via this configured git remote (default: origin)
|
|
6925
|
+
--relay <url> ad-hoc relay override (exactly one for set/clear)
|
|
6926
|
+
--yes skip the fee confirmation (required when not a TTY)
|
|
6927
|
+
--json machine-readable envelope
|
|
6928
|
+
-h, --help show this help`;
|
|
6929
|
+
async function runPayout(args, deps) {
|
|
6930
|
+
const { io: io2 } = deps;
|
|
6931
|
+
const [sub, ...rest] = args;
|
|
6932
|
+
switch (sub) {
|
|
6933
|
+
case "show":
|
|
6934
|
+
return runShow2(rest, deps);
|
|
6935
|
+
case "set":
|
|
6936
|
+
return runMutate2("set", rest, deps);
|
|
6937
|
+
case "clear":
|
|
6938
|
+
return runMutate2("clear", rest, deps);
|
|
6939
|
+
case "--help":
|
|
6940
|
+
case "-h":
|
|
6941
|
+
case "help":
|
|
6942
|
+
io2.out(PAYOUT_USAGE);
|
|
6943
|
+
return 0;
|
|
6944
|
+
default:
|
|
6945
|
+
io2.err(
|
|
6946
|
+
sub === void 0 ? "missing subcommand: rig payout <set|clear|show>" : `unknown rig payout subcommand: ${sub}`
|
|
6947
|
+
);
|
|
6948
|
+
io2.err(PAYOUT_USAGE);
|
|
6949
|
+
return 2;
|
|
6950
|
+
}
|
|
6951
|
+
}
|
|
6952
|
+
async function runShow2(args, deps) {
|
|
6953
|
+
const { io: io2 } = deps;
|
|
6954
|
+
let flags;
|
|
6955
|
+
try {
|
|
6956
|
+
const { values, positionals } = parseArgs16({
|
|
6957
|
+
args,
|
|
6958
|
+
options: REPO_COMMAND_OPTIONS,
|
|
6959
|
+
allowPositionals: true
|
|
6960
|
+
});
|
|
6961
|
+
if (positionals.length > 0) {
|
|
6962
|
+
throw new Error("rig payout show takes no positional arguments");
|
|
6963
|
+
}
|
|
6964
|
+
flags = pickRepoCommandFlags(values);
|
|
6965
|
+
} catch (err) {
|
|
6966
|
+
io2.err(err instanceof Error ? err.message : String(err));
|
|
6967
|
+
io2.err(PAYOUT_USAGE);
|
|
6968
|
+
return 2;
|
|
6969
|
+
}
|
|
6970
|
+
if (flags.help) {
|
|
6971
|
+
io2.out(PAYOUT_USAGE);
|
|
6972
|
+
return 0;
|
|
6973
|
+
}
|
|
6974
|
+
try {
|
|
6975
|
+
const ctx = await resolveRepoContext(flags, deps);
|
|
6976
|
+
const wsRelays = ctx.relays.filter((url) => WS_URL_RE4.test(url));
|
|
6977
|
+
if (wsRelays.length === 0) {
|
|
6978
|
+
throw new InvalidRelayUrlError(
|
|
6979
|
+
ctx.relays[0] ?? "",
|
|
6980
|
+
"reads need a ws:// or wss:// relay"
|
|
6981
|
+
);
|
|
6982
|
+
}
|
|
6983
|
+
const remote = await fetchRemoteState({
|
|
6984
|
+
relayUrls: wsRelays,
|
|
6985
|
+
ownerPubkey: ctx.owner,
|
|
6986
|
+
repoId: ctx.repoId,
|
|
6987
|
+
...deps.webSocketFactory ? { webSocketFactory: deps.webSocketFactory } : {}
|
|
6988
|
+
});
|
|
6989
|
+
const payout = remote.payout;
|
|
6990
|
+
if (flags.json) {
|
|
6991
|
+
io2.emitJson({
|
|
6992
|
+
command: "payout show",
|
|
6993
|
+
repoAddr: { ownerPubkey: ctx.owner, repoId: ctx.repoId },
|
|
6994
|
+
announced: remote.announced,
|
|
6995
|
+
payout
|
|
6996
|
+
});
|
|
6997
|
+
return 0;
|
|
6998
|
+
}
|
|
6999
|
+
io2.out(`Repo: 30617:${ctx.owner}:${ctx.repoId}`);
|
|
7000
|
+
if (!remote.announced) {
|
|
7001
|
+
io2.out("No kind:30617 announcement found \u2014 no payout pointer.");
|
|
7002
|
+
return 0;
|
|
7003
|
+
}
|
|
7004
|
+
io2.out(
|
|
7005
|
+
payout === null ? "Payout: none (the serving node keeps 100% of repo-scoped write fees)" : `Payout: ${payout.chain} ${payout.address}`
|
|
7006
|
+
);
|
|
7007
|
+
return 0;
|
|
7008
|
+
} catch (err) {
|
|
7009
|
+
return emitCliError(io2, flags.json, "payout show", err);
|
|
7010
|
+
}
|
|
7011
|
+
}
|
|
7012
|
+
async function runMutate2(op, args, deps) {
|
|
7013
|
+
const { io: io2 } = deps;
|
|
7014
|
+
const command = `payout ${op}`;
|
|
7015
|
+
let flags;
|
|
7016
|
+
let nextPayout = null;
|
|
7017
|
+
try {
|
|
7018
|
+
const { values, positionals } = parseArgs16({
|
|
7019
|
+
args,
|
|
7020
|
+
options: REPO_COMMAND_OPTIONS,
|
|
7021
|
+
allowPositionals: true
|
|
7022
|
+
});
|
|
7023
|
+
flags = pickRepoCommandFlags(values);
|
|
7024
|
+
if (flags.help) {
|
|
7025
|
+
io2.out(PAYOUT_USAGE);
|
|
7026
|
+
return 0;
|
|
7027
|
+
}
|
|
7028
|
+
if (op === "set") {
|
|
7029
|
+
if (positionals.length !== 1) {
|
|
7030
|
+
throw new Error("expected exactly one <address> to set");
|
|
7031
|
+
}
|
|
7032
|
+
const raw = positionals[0];
|
|
7033
|
+
if (!isValidEvmPayoutAddress(raw)) {
|
|
7034
|
+
throw new Error(
|
|
7035
|
+
`<address> must be a valid EVM address (0x + 40 hex chars, correctly EIP-55 checksummed if mixed-case) \u2014 got ${JSON.stringify(raw)}. See toon-meta#391 (payout epic): v1 accepts evm addresses only.`
|
|
7036
|
+
);
|
|
7037
|
+
}
|
|
7038
|
+
nextPayout = { chain: "evm", address: getAddress(raw) };
|
|
7039
|
+
} else if (positionals.length !== 0) {
|
|
7040
|
+
throw new Error("rig payout clear takes no positional arguments");
|
|
7041
|
+
}
|
|
7042
|
+
} catch (err) {
|
|
7043
|
+
io2.err(err instanceof Error ? err.message : String(err));
|
|
7044
|
+
io2.err(PAYOUT_USAGE);
|
|
7045
|
+
return 2;
|
|
7046
|
+
}
|
|
7047
|
+
let standaloneCtx;
|
|
7048
|
+
try {
|
|
7049
|
+
const ctx = await resolveRepoContext(flags, deps);
|
|
7050
|
+
if (ctx.relays.length > 1) {
|
|
7051
|
+
io2.err(singleRelayRefusal(ctx.resolved, "Nothing was published or paid."));
|
|
7052
|
+
return 1;
|
|
7053
|
+
}
|
|
7054
|
+
const relayUrl = ctx.relays[0];
|
|
7055
|
+
if (relayUrl === void 0 || !WS_URL_RE4.test(relayUrl)) {
|
|
7056
|
+
throw new InvalidRelayUrlError(
|
|
7057
|
+
relayUrl ?? "",
|
|
7058
|
+
"a paid publish needs a ws:// or wss:// relay"
|
|
7059
|
+
);
|
|
7060
|
+
}
|
|
7061
|
+
const load = deps.loadStandalone ?? defaultLoadStandalone;
|
|
7062
|
+
standaloneCtx = await load({
|
|
7063
|
+
env: deps.env,
|
|
7064
|
+
cwd: deps.cwd,
|
|
7065
|
+
warn: (line) => io2.err(line),
|
|
7066
|
+
relayUrl
|
|
7067
|
+
});
|
|
7068
|
+
const identity = identityReport(standaloneCtx);
|
|
7069
|
+
if (identity.pubkey.toLowerCase() !== ctx.owner.toLowerCase()) {
|
|
7070
|
+
io2.err(
|
|
7071
|
+
`rig: only the repo owner (${ctx.owner.slice(0, 8)}\u2026) can change the payout pointer \u2014 the active identity is ${identity.pubkey.slice(0, 8)}\u2026. A non-owner republish would write your own (ignored) announcement. Nothing was published or paid.`
|
|
7072
|
+
);
|
|
7073
|
+
return 1;
|
|
7074
|
+
}
|
|
7075
|
+
const remote = await fetchRemoteState({
|
|
7076
|
+
relayUrls: [relayUrl],
|
|
7077
|
+
ownerPubkey: ctx.owner,
|
|
7078
|
+
repoId: ctx.repoId,
|
|
7079
|
+
...deps.webSocketFactory ? { webSocketFactory: deps.webSocketFactory } : {}
|
|
7080
|
+
});
|
|
7081
|
+
if (!remote.announced) {
|
|
7082
|
+
io2.err(
|
|
7083
|
+
`rig: 30617:${ctx.owner.slice(0, 8)}\u2026:${ctx.repoId} has no announcement yet \u2014 run \`rig push\` to publish the repo (with its real name/description) before managing the payout pointer. Nothing was published or paid.`
|
|
7084
|
+
);
|
|
7085
|
+
return 1;
|
|
7086
|
+
}
|
|
7087
|
+
const current = remote.payout;
|
|
7088
|
+
if (nextPayout !== null && current !== null && current.chain === nextPayout.chain && current.address === nextPayout.address) {
|
|
7089
|
+
io2.err(
|
|
7090
|
+
`rig: payout is already set to ${current.chain} ${current.address} \u2014 nothing to do (not published).`
|
|
7091
|
+
);
|
|
7092
|
+
return 0;
|
|
7093
|
+
}
|
|
7094
|
+
if (op === "clear" && current === null) {
|
|
7095
|
+
io2.err("rig: no payout pointer is set \u2014 nothing to do (not published).");
|
|
7096
|
+
return 0;
|
|
7097
|
+
}
|
|
7098
|
+
const name = remote.name ?? ctx.repoId;
|
|
7099
|
+
const description = remote.description ?? "";
|
|
7100
|
+
const event = buildRepoAnnouncement(
|
|
7101
|
+
ctx.repoId,
|
|
7102
|
+
name,
|
|
7103
|
+
description,
|
|
7104
|
+
remote.maintainers,
|
|
7105
|
+
nextPayout
|
|
7106
|
+
);
|
|
7107
|
+
const fee = (await standaloneCtx.publisher.getFeeRates()).eventFee.toString();
|
|
7108
|
+
const action = nextPayout ? `kind:30617 payout set ${nextPayout.chain} ${nextPayout.address}` : "kind:30617 payout clear";
|
|
7109
|
+
if (!flags.json) {
|
|
7110
|
+
io2.out(`Republish ${action}`);
|
|
7111
|
+
io2.out(`Repo: 30617:${ctx.owner}:${ctx.repoId}`);
|
|
7112
|
+
io2.out(
|
|
7113
|
+
`Payout after: ${nextPayout ? `${nextPayout.chain} ${nextPayout.address}` : "(none)"}`
|
|
7114
|
+
);
|
|
7115
|
+
io2.out(`Fee: ${feeLabel(fee)}. Writes are permanent and non-refundable.`);
|
|
7116
|
+
}
|
|
7117
|
+
if (!flags.yes) {
|
|
7118
|
+
if (flags.json) {
|
|
7119
|
+
io2.emitJson({
|
|
7120
|
+
command,
|
|
7121
|
+
repoAddr: { ownerPubkey: ctx.owner, repoId: ctx.repoId },
|
|
7122
|
+
identity,
|
|
7123
|
+
executed: false,
|
|
7124
|
+
feeEstimate: fee,
|
|
7125
|
+
payout: nextPayout,
|
|
7126
|
+
hint: "estimate only \u2014 re-run with --yes to publish (permanent, non-refundable)"
|
|
7127
|
+
});
|
|
7128
|
+
return 0;
|
|
7129
|
+
}
|
|
7130
|
+
if (!io2.isInteractive) {
|
|
7131
|
+
io2.err(
|
|
7132
|
+
"refusing to spend channel funds without confirmation in a non-interactive session \u2014 re-run with --yes (or use --json for an estimate)"
|
|
7133
|
+
);
|
|
7134
|
+
return 1;
|
|
7135
|
+
}
|
|
7136
|
+
const proceed = await io2.confirm(
|
|
7137
|
+
`Proceed with paid republish (${feeLabel(fee)})? [y/N] `
|
|
7138
|
+
);
|
|
7139
|
+
if (!proceed) {
|
|
7140
|
+
io2.err("aborted \u2014 nothing was published.");
|
|
7141
|
+
return 1;
|
|
7142
|
+
}
|
|
7143
|
+
}
|
|
7144
|
+
const receipt = await standaloneCtx.publisher.publishEvent(event, [
|
|
7145
|
+
relayUrl
|
|
7146
|
+
]);
|
|
7147
|
+
const result = serializeEventReceipt(event.kind, receipt);
|
|
7148
|
+
if (flags.json) {
|
|
7149
|
+
io2.emitJson({
|
|
7150
|
+
command,
|
|
7151
|
+
repoAddr: { ownerPubkey: ctx.owner, repoId: ctx.repoId },
|
|
7152
|
+
identity,
|
|
7153
|
+
executed: true,
|
|
7154
|
+
feeEstimate: fee,
|
|
7155
|
+
payout: nextPayout,
|
|
7156
|
+
result
|
|
7157
|
+
});
|
|
7158
|
+
} else {
|
|
7159
|
+
io2.out(
|
|
7160
|
+
`Published ${action}: ${result.eventId} paid ${result.feePaid} base units`
|
|
7161
|
+
);
|
|
7162
|
+
}
|
|
7163
|
+
return 0;
|
|
7164
|
+
} catch (err) {
|
|
7165
|
+
return emitCliError(io2, flags.json, command, err);
|
|
7166
|
+
} finally {
|
|
7167
|
+
if (standaloneCtx) {
|
|
7168
|
+
try {
|
|
7169
|
+
await standaloneCtx.stop();
|
|
7170
|
+
} catch {
|
|
7171
|
+
}
|
|
7172
|
+
}
|
|
7173
|
+
}
|
|
7174
|
+
}
|
|
7175
|
+
|
|
7176
|
+
// src/cli/site.ts
|
|
7177
|
+
import { parseArgs as parseArgs17 } from "util";
|
|
7125
7178
|
|
|
7126
7179
|
// src/arweave-manifest.ts
|
|
7127
7180
|
var DEFAULT_INDEX = "index.html";
|
|
@@ -7140,22 +7193,22 @@ function buildArweaveManifest(entries, indexPath = DEFAULT_INDEX, fallbackTxId)
|
|
|
7140
7193
|
}
|
|
7141
7194
|
|
|
7142
7195
|
// src/cli/site-record.ts
|
|
7143
|
-
import { mkdirSync as mkdirSync5, readFileSync as
|
|
7144
|
-
import { homedir as
|
|
7145
|
-
import { join as
|
|
7196
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
7197
|
+
import { homedir as homedir5 } from "os";
|
|
7198
|
+
import { join as join6 } from "path";
|
|
7146
7199
|
var SITE_MANIFEST_FILENAME = "site-manifests.json";
|
|
7147
7200
|
function storeDir2(env) {
|
|
7148
|
-
return env["TOON_CLIENT_HOME"] ??
|
|
7201
|
+
return env["TOON_CLIENT_HOME"] ?? join6(homedir5(), ".toon-client");
|
|
7149
7202
|
}
|
|
7150
7203
|
function storePath2(env) {
|
|
7151
|
-
return
|
|
7204
|
+
return join6(storeDir2(env), SITE_MANIFEST_FILENAME);
|
|
7152
7205
|
}
|
|
7153
7206
|
function keyOf(repoId, ref) {
|
|
7154
7207
|
return `${repoId}\0${ref}`;
|
|
7155
7208
|
}
|
|
7156
7209
|
function readFile2(env) {
|
|
7157
7210
|
try {
|
|
7158
|
-
const parsed = JSON.parse(
|
|
7211
|
+
const parsed = JSON.parse(readFileSync5(storePath2(env), "utf8"));
|
|
7159
7212
|
if (parsed && typeof parsed === "object") return parsed;
|
|
7160
7213
|
return {};
|
|
7161
7214
|
} catch {
|
|
@@ -7176,7 +7229,7 @@ function writeSiteRecord(env, record) {
|
|
|
7176
7229
|
|
|
7177
7230
|
// src/cli/site.ts
|
|
7178
7231
|
var MANIFEST_CONTENT_TYPE = "application/x.arweave-manifest+json";
|
|
7179
|
-
var DEFAULT_GATEWAY =
|
|
7232
|
+
var DEFAULT_GATEWAY = PREFERRED_GATEWAY;
|
|
7180
7233
|
var SITE_USAGE = `Usage: rig site <publish|url> [ref] [options]
|
|
7181
7234
|
|
|
7182
7235
|
Serve a pushed repo as a permanent, path-routed website. \`rig push\` already
|
|
@@ -7212,7 +7265,7 @@ Options (publish):
|
|
|
7212
7265
|
estimate (nothing uploaded)
|
|
7213
7266
|
-h, --help show this help`;
|
|
7214
7267
|
function parseSiteArgs(args) {
|
|
7215
|
-
const { values, positionals } =
|
|
7268
|
+
const { values, positionals } = parseArgs17({
|
|
7216
7269
|
args,
|
|
7217
7270
|
options: {
|
|
7218
7271
|
index: { type: "string" },
|
|
@@ -7364,7 +7417,6 @@ async function runSitePublish(args, deps) {
|
|
|
7364
7417
|
}
|
|
7365
7418
|
}
|
|
7366
7419
|
const feeRates = await ctx.publisher.getFeeRates();
|
|
7367
|
-
const { uploadFee } = feeRates;
|
|
7368
7420
|
const previewEntries = blobs.map((b) => ({
|
|
7369
7421
|
path: b.path,
|
|
7370
7422
|
txId: known.get(b.sha) ?? PLACEHOLDER_TX
|
|
@@ -7380,9 +7432,12 @@ async function runSitePublish(args, deps) {
|
|
|
7380
7432
|
if (flags.forceReupload) {
|
|
7381
7433
|
const { objects } = await reader.statObjects(uniqueShas);
|
|
7382
7434
|
reuploadBytes = objects.reduce((sum, o) => sum + o.size, 0);
|
|
7383
|
-
reuploadFee =
|
|
7435
|
+
reuploadFee = objects.reduce(
|
|
7436
|
+
(sum, o) => sum + uploadChargeFor(feeRates, o.size),
|
|
7437
|
+
0n
|
|
7438
|
+
);
|
|
7384
7439
|
}
|
|
7385
|
-
const manifestFee =
|
|
7440
|
+
const manifestFee = uploadChargeFor(feeRates, manifestBytes);
|
|
7386
7441
|
const totalFee = manifestFee + reuploadFee;
|
|
7387
7442
|
const gateway = flags.gateway ?? deps.env["RIG_ARWEAVE_GATEWAY"] ?? DEFAULT_GATEWAY;
|
|
7388
7443
|
const baseJson = () => ({
|
|
@@ -7622,6 +7677,10 @@ Commands rig owns:
|
|
|
7622
7677
|
maintainers add <pubkey> remove republish the kind:30617 to change who may
|
|
7623
7678
|
maintainers remove <pubkey> author authoritative issue/PR status (owner is
|
|
7624
7679
|
always an implicit maintainer)
|
|
7680
|
+
payout show show the repo's declared payout pointer (free);
|
|
7681
|
+
payout set <address> set/clear republish the kind:30617 \u2014 no pointer
|
|
7682
|
+
payout clear means the serving node keeps 100% of
|
|
7683
|
+
repo-scoped write fees (v1: evm addresses only)
|
|
7625
7684
|
fund drip devnet faucet funds to this identity's
|
|
7626
7685
|
wallet (free); on other networks prints the
|
|
7627
7686
|
address(es) to fund externally
|
|
@@ -7629,10 +7688,11 @@ Commands rig owns:
|
|
|
7629
7688
|
(free \u2014 chain reads and local state only)
|
|
7630
7689
|
chain [set <c>|unset] choose which chain/USDC settles paid writes
|
|
7631
7690
|
(evm|sol|mina); free \u2014 reads/writes local config
|
|
7632
|
-
entry
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7691
|
+
entry <url> | entry clear choose the connector that prices and settles paid
|
|
7692
|
+
writes \u2014 one URL is the whole configuration, since
|
|
7693
|
+
its GET /ilp describes it; --relay <wss-url>
|
|
7694
|
+
records the free-read relay beside it; free \u2014
|
|
7695
|
+
writes local config
|
|
7636
7696
|
name buy <name> ArNS naming (#367): buy points a human name at an
|
|
7637
7697
|
name set <name> <txId> Arweave txId, owned + paid by this identity's
|
|
7638
7698
|
name status <name> Solana key. buy spends mARIO on Solana via the
|
|
@@ -7715,6 +7775,8 @@ async function dispatch(argv2, deps) {
|
|
|
7715
7775
|
return runPr(rest, deps);
|
|
7716
7776
|
case "maintainers":
|
|
7717
7777
|
return runMaintainers(rest, deps);
|
|
7778
|
+
case "payout":
|
|
7779
|
+
return runPayout(rest, deps);
|
|
7718
7780
|
case "channel":
|
|
7719
7781
|
return runChannel(rest, deps);
|
|
7720
7782
|
case "channels":
|
|
@@ -7806,6 +7868,7 @@ var RIG_OWNED_VERBS = /* @__PURE__ */ new Set([
|
|
|
7806
7868
|
"comment",
|
|
7807
7869
|
"pr",
|
|
7808
7870
|
"maintainers",
|
|
7871
|
+
"payout",
|
|
7809
7872
|
"channel",
|
|
7810
7873
|
"channels",
|
|
7811
7874
|
"fund",
|