@toon-protocol/rig 2.4.1 → 2.6.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 +18 -5
- package/dist/{chunk-OIJNRACA.js → chunk-6SQ7723I.js} +11 -11
- package/dist/chunk-6SQ7723I.js.map +1 -0
- package/dist/chunk-AFJNFDUQ.js +281 -0
- package/dist/chunk-AFJNFDUQ.js.map +1 -0
- package/dist/{chunk-X2CZPPDM.js → chunk-B5ISARMU.js} +3 -1
- package/dist/chunk-B5ISARMU.js.map +1 -0
- package/dist/{chunk-W2SDL2PE.js → chunk-NIRC5LFS.js} +31 -11
- package/dist/chunk-NIRC5LFS.js.map +1 -0
- package/dist/cli/rig.js +376 -73
- package/dist/cli/rig.js.map +1 -1
- package/dist/index.d.ts +21 -0
- package/dist/index.js +9 -9
- package/dist/network-bootstrap-WNSHRC5P.js +34 -0
- package/dist/network-bootstrap-WNSHRC5P.js.map +1 -0
- package/dist/standalone/index.d.ts +48 -23
- package/dist/standalone/index.js +2 -2
- package/dist/{standalone-mode-VH2XPOPK.js → standalone-mode-WEMJBHME.js} +20 -270
- package/dist/standalone-mode-WEMJBHME.js.map +1 -0
- package/package.json +2 -2
- package/dist/chunk-OIJNRACA.js.map +0 -1
- package/dist/chunk-W2SDL2PE.js.map +0 -1
- package/dist/chunk-X2CZPPDM.js.map +0 -1
- package/dist/standalone-mode-VH2XPOPK.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -656,6 +656,13 @@ interface PushFeeEstimate {
|
|
|
656
656
|
eventFees: bigint;
|
|
657
657
|
/** uploadFee + eventFees. */
|
|
658
658
|
totalFee: bigint;
|
|
659
|
+
/**
|
|
660
|
+
* Objects excluded from the upload because their body is zero bytes — the
|
|
661
|
+
* git empty blob, which the store rejects as malformed (F00). Reconstructed
|
|
662
|
+
* locally on clone/fetch, so nothing is lost; surfaced here so the fee table
|
|
663
|
+
* can report the skip honestly.
|
|
664
|
+
*/
|
|
665
|
+
skippedEmptyCount: number;
|
|
659
666
|
}
|
|
660
667
|
/** Everything `executePush` (and a confirm UI) needs. */
|
|
661
668
|
interface PushPlan {
|
|
@@ -676,6 +683,13 @@ interface PushPlan {
|
|
|
676
683
|
* crashed push never uploads a tip whose history is missing.
|
|
677
684
|
*/
|
|
678
685
|
objects: PlannedObject[];
|
|
686
|
+
/**
|
|
687
|
+
* Zero-byte objects (the git empty blob) excluded from {@link objects}: the
|
|
688
|
+
* store rejects a zero-byte kind:5094 upload as malformed (F00), so `rig`
|
|
689
|
+
* never uploads it — the commit/tree still references it and clone/fetch
|
|
690
|
+
* synthesizes it locally. Kept for honest receipts, never uploaded.
|
|
691
|
+
*/
|
|
692
|
+
skippedEmptyObjects: PlannedObject[];
|
|
679
693
|
/**
|
|
680
694
|
* sha→txId hints known WITHOUT uploading: the remote's `arweave` tags
|
|
681
695
|
* plus anything `resolveMissing` found. Merged into the published
|
|
@@ -836,6 +850,13 @@ interface GitFeeEstimate {
|
|
|
836
850
|
eventFees: string;
|
|
837
851
|
/** uploadFee + eventFees. */
|
|
838
852
|
totalFee: string;
|
|
853
|
+
/**
|
|
854
|
+
* Zero-byte objects (the git empty blob) excluded from the upload — the
|
|
855
|
+
* store rejects zero-byte content as malformed, so they are skipped on push
|
|
856
|
+
* and reconstructed on clone/fetch. Optional for wire compatibility with
|
|
857
|
+
* daemons predating the empty-blob handling. Default 0.
|
|
858
|
+
*/
|
|
859
|
+
skippedEmptyCount?: number;
|
|
839
860
|
}
|
|
840
861
|
/** Serialized `PushPlan` — everything a confirm UI needs. */
|
|
841
862
|
interface GitEstimateResponse {
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,15 @@ import {
|
|
|
27
27
|
walkClosure,
|
|
28
28
|
writeGitObject,
|
|
29
29
|
writeGitObjects
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-NIRC5LFS.js";
|
|
31
|
+
import {
|
|
32
|
+
MAX_OBJECT_SIZE,
|
|
33
|
+
createGitBlob,
|
|
34
|
+
createGitCommit,
|
|
35
|
+
createGitTag,
|
|
36
|
+
createGitTree,
|
|
37
|
+
hashGitObject
|
|
38
|
+
} from "./chunk-B5ISARMU.js";
|
|
31
39
|
import {
|
|
32
40
|
COMMENT_KIND,
|
|
33
41
|
MAINTAINERS_TAG,
|
|
@@ -43,14 +51,6 @@ import {
|
|
|
43
51
|
parseMaintainers,
|
|
44
52
|
queryRelay
|
|
45
53
|
} from "./chunk-3HRFDH7H.js";
|
|
46
|
-
import {
|
|
47
|
-
MAX_OBJECT_SIZE,
|
|
48
|
-
createGitBlob,
|
|
49
|
-
createGitCommit,
|
|
50
|
-
createGitTag,
|
|
51
|
-
createGitTree,
|
|
52
|
-
hashGitObject
|
|
53
|
-
} from "./chunk-X2CZPPDM.js";
|
|
54
54
|
export {
|
|
55
55
|
COMMENT_KIND,
|
|
56
56
|
DEFAULT_CONCURRENCY,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEVNET_CHAIN_RPC_URLS,
|
|
3
|
+
DEVNET_ZONE,
|
|
4
|
+
DISCOVERY_TIMEOUT_MS,
|
|
5
|
+
ILP_PEER_INFO_KIND,
|
|
6
|
+
TokenNetworkUnderivableError,
|
|
7
|
+
discoverAnnouncedPeers,
|
|
8
|
+
evmPresetForChain,
|
|
9
|
+
evmTokenBalance,
|
|
10
|
+
genesisSeedPubkeys,
|
|
11
|
+
isDevnetZonePeer,
|
|
12
|
+
loadGenesisSeed,
|
|
13
|
+
pickPaymentPeer,
|
|
14
|
+
resolveChainSettlement,
|
|
15
|
+
selectSettlementChain
|
|
16
|
+
} from "./chunk-AFJNFDUQ.js";
|
|
17
|
+
import "./chunk-3HRFDH7H.js";
|
|
18
|
+
export {
|
|
19
|
+
DEVNET_CHAIN_RPC_URLS,
|
|
20
|
+
DEVNET_ZONE,
|
|
21
|
+
DISCOVERY_TIMEOUT_MS,
|
|
22
|
+
ILP_PEER_INFO_KIND,
|
|
23
|
+
TokenNetworkUnderivableError,
|
|
24
|
+
discoverAnnouncedPeers,
|
|
25
|
+
evmPresetForChain,
|
|
26
|
+
evmTokenBalance,
|
|
27
|
+
genesisSeedPubkeys,
|
|
28
|
+
isDevnetZonePeer,
|
|
29
|
+
loadGenesisSeed,
|
|
30
|
+
pickPaymentPeer,
|
|
31
|
+
resolveChainSettlement,
|
|
32
|
+
selectSettlementChain
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=network-bootstrap-WNSHRC5P.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -189,19 +189,38 @@ declare function channelStatus(entry: WatermarkEntry | undefined, nowSec?: numbe
|
|
|
189
189
|
*/
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
|
-
* One
|
|
193
|
-
* `@toon-protocol/client`'s `
|
|
194
|
-
* not exported from the package root); keep in sync.
|
|
192
|
+
* One asset amount within a chain's wallet view — structural twin of
|
|
193
|
+
* `@toon-protocol/client`'s `WalletTokenAmount`; keep in sync.
|
|
195
194
|
*/
|
|
196
|
-
interface
|
|
197
|
-
|
|
198
|
-
|
|
195
|
+
interface WalletTokenAmountInfo {
|
|
196
|
+
/** Asset symbol (e.g. `'ETH'`, `'SOL'`, `'MINA'`, `'USDC'`), when known. */
|
|
197
|
+
symbol?: string;
|
|
199
198
|
/** Base-unit integer, decimal string. */
|
|
200
199
|
amount: string;
|
|
201
|
-
/**
|
|
202
|
-
|
|
203
|
-
/** Token
|
|
204
|
-
|
|
200
|
+
/** Decimals for formatting (ETH 18, SOL 9, MINA 9, USDC 6). */
|
|
201
|
+
decimals?: number;
|
|
202
|
+
/** Token contract / SPL mint address. Absent for the native coin. */
|
|
203
|
+
address?: string;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The full wallet view for ONE chain — native coin + configured tokens —
|
|
207
|
+
* structural twin of `@toon-protocol/client`'s `WalletChainBalances`
|
|
208
|
+
* (`balance/WalletBalanceReader.ts`, exported from the package root); keep in
|
|
209
|
+
* sync.
|
|
210
|
+
*/
|
|
211
|
+
interface WalletChainBalanceInfo {
|
|
212
|
+
chain: 'evm' | 'solana' | 'mina';
|
|
213
|
+
/** Full chain key, e.g. `'evm:31337'`, `'solana'`, `'mina'`. */
|
|
214
|
+
chainKey: string;
|
|
215
|
+
address: string;
|
|
216
|
+
/** Native-coin balance, when readable. */
|
|
217
|
+
native?: WalletTokenAmountInfo;
|
|
218
|
+
/** Configured token balances (e.g. USDC). */
|
|
219
|
+
tokens: WalletTokenAmountInfo[];
|
|
220
|
+
/** True when nothing on this chain could be read (RPC unreachable). */
|
|
221
|
+
unreadable?: boolean;
|
|
222
|
+
/** First read error, when any read failed. */
|
|
223
|
+
error?: string;
|
|
205
224
|
}
|
|
206
225
|
/** Receipt of an explicit `rig channel open` (fresh open OR resume). */
|
|
207
226
|
interface ChannelOpenOutcome {
|
|
@@ -255,10 +274,12 @@ interface StandaloneMoneyOps {
|
|
|
255
274
|
/** Settle a closed channel after its challenge window — releases funds. */
|
|
256
275
|
settleChannel(record: ChannelMapRecord): Promise<ChannelSettleOutcome>;
|
|
257
276
|
/**
|
|
258
|
-
*
|
|
259
|
-
*
|
|
277
|
+
* The full multi-chain wallet view (#299) for the identity's configured
|
|
278
|
+
* chains — native coin + configured tokens (USDC) grouped per chain — a FREE
|
|
279
|
+
* read (no client start, no nonce guard, no uplink). Best-effort per chain:
|
|
280
|
+
* an unreachable RPC yields an `unreadable` chain rather than failing others.
|
|
260
281
|
*/
|
|
261
|
-
|
|
282
|
+
walletChainBalances(): Promise<WalletChainBalanceInfo[]>;
|
|
262
283
|
}
|
|
263
284
|
|
|
264
285
|
/**
|
|
@@ -344,8 +365,12 @@ interface ToonClientLike {
|
|
|
344
365
|
channelId: string;
|
|
345
366
|
txHash?: string;
|
|
346
367
|
}>;
|
|
347
|
-
/**
|
|
348
|
-
|
|
368
|
+
/**
|
|
369
|
+
* Free FULL multi-chain wallet view (#299) — native coin + configured tokens
|
|
370
|
+
* per chain — works on an UNSTARTED client (Solana/Mina addresses are derived
|
|
371
|
+
* from the mnemonic on demand).
|
|
372
|
+
*/
|
|
373
|
+
getWalletBalances?(): Promise<WalletChainBalanceInfo[]>;
|
|
349
374
|
}
|
|
350
375
|
interface StandalonePublisherOptions {
|
|
351
376
|
/**
|
|
@@ -532,14 +557,14 @@ declare class StandalonePublisher implements Publisher {
|
|
|
532
557
|
*/
|
|
533
558
|
settleRecordedChannel(record: ChannelMapRecord): Promise<ChannelSettleOutcome>;
|
|
534
559
|
/**
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
560
|
+
* The full multi-chain wallet view (#299) for the embedded identity — native
|
|
561
|
+
* coin + configured tokens (USDC) per chain — a FREE read on the UNSTARTED
|
|
562
|
+
* client (no nonce guard, no uplink, no channel). The client derives the
|
|
563
|
+
* Solana/Mina addresses from the mnemonic on demand, so ALL configured chains
|
|
564
|
+
* appear even before a start. Best-effort per chain (an unreachable RPC yields
|
|
565
|
+
* an `unreadable` chain, not a failure).
|
|
541
566
|
*/
|
|
542
|
-
|
|
567
|
+
readWalletChainBalances(): Promise<WalletChainBalanceInfo[]>;
|
|
543
568
|
/**
|
|
544
569
|
* Fee rates for `planPush` estimation: the flat per-event fee and the
|
|
545
570
|
* per-byte upload rate this publisher pays (daemon `feePerEvent` and seed
|
|
@@ -676,4 +701,4 @@ declare class NonceLock {
|
|
|
676
701
|
release(): void;
|
|
677
702
|
}
|
|
678
703
|
|
|
679
|
-
export { type AcquireLockOptions, type ChannelCloseOutcome, ChannelMapCorruptError, type ChannelMapKey, type ChannelMapRecord, ChannelMapStore, type ChannelMapStoreOptions, type ChannelOpenOutcome, type ChannelSettleOutcome, type CheckDaemonOptions, DEFAULT_DAEMON_PORT, DaemonIdentityConflictError, NonceLock, type PersistedChannelContext, RIG_CHANNEL_MAP_FILENAME, type SignedNostrEvent, StandaloneLockError, type StandaloneMoneyOps, StandalonePublishError, StandalonePublisher, type StandalonePublisherOptions, type ToonClientLike, type
|
|
704
|
+
export { type AcquireLockOptions, type ChannelCloseOutcome, ChannelMapCorruptError, type ChannelMapKey, type ChannelMapRecord, ChannelMapStore, type ChannelMapStoreOptions, type ChannelOpenOutcome, type ChannelSettleOutcome, type CheckDaemonOptions, DEFAULT_DAEMON_PORT, DaemonIdentityConflictError, NonceLock, type PersistedChannelContext, RIG_CHANNEL_MAP_FILENAME, type SignedNostrEvent, StandaloneLockError, type StandaloneMoneyOps, StandalonePublishError, StandalonePublisher, type StandalonePublisherOptions, type ToonClientLike, type WalletChainBalanceInfo, type WalletTokenAmountInfo, type WatermarkEntry, channelStatus, checkDaemonIdentity, defaultDaemonPort, defaultLockDir, deriveRouteDestinations, extractArweaveTxId, recordKey, resolveChannelPaths };
|
package/dist/standalone/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
StandalonePublisher,
|
|
4
4
|
deriveRouteDestinations,
|
|
5
5
|
extractArweaveTxId
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-6SQ7723I.js";
|
|
7
7
|
import {
|
|
8
8
|
ChannelMapCorruptError,
|
|
9
9
|
ChannelMapStore,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
recordKey,
|
|
20
20
|
resolveChannelPaths
|
|
21
21
|
} from "../chunk-SW7ZHMGS.js";
|
|
22
|
-
import "../chunk-
|
|
22
|
+
import "../chunk-B5ISARMU.js";
|
|
23
23
|
export {
|
|
24
24
|
ChannelMapCorruptError,
|
|
25
25
|
ChannelMapStore,
|
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveIdentity
|
|
3
3
|
} from "./chunk-XGFBDUQX.js";
|
|
4
|
-
import {
|
|
5
|
-
fetchRemoteState,
|
|
6
|
-
queryRelay
|
|
7
|
-
} from "./chunk-3HRFDH7H.js";
|
|
8
4
|
import {
|
|
9
5
|
StandalonePublisher
|
|
10
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6SQ7723I.js";
|
|
11
7
|
import {
|
|
12
8
|
ChannelMapStore,
|
|
13
9
|
RIG_CHANNEL_MAP_FILENAME
|
|
14
10
|
} from "./chunk-SW7ZHMGS.js";
|
|
15
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-B5ISARMU.js";
|
|
12
|
+
import {
|
|
13
|
+
DISCOVERY_TIMEOUT_MS,
|
|
14
|
+
TokenNetworkUnderivableError,
|
|
15
|
+
discoverAnnouncedPeers,
|
|
16
|
+
evmTokenBalance,
|
|
17
|
+
genesisSeedPubkeys,
|
|
18
|
+
loadGenesisSeed,
|
|
19
|
+
pickPaymentPeer,
|
|
20
|
+
resolveChainSettlement,
|
|
21
|
+
selectSettlementChain
|
|
22
|
+
} from "./chunk-AFJNFDUQ.js";
|
|
23
|
+
import {
|
|
24
|
+
fetchRemoteState
|
|
25
|
+
} from "./chunk-3HRFDH7H.js";
|
|
16
26
|
|
|
17
27
|
// src/cli/standalone-mode.ts
|
|
18
28
|
import { readFileSync as readFileSync2 } from "fs";
|
|
@@ -179,266 +189,6 @@ var TopologyCache = class {
|
|
|
179
189
|
}
|
|
180
190
|
};
|
|
181
191
|
|
|
182
|
-
// src/standalone/network-bootstrap.ts
|
|
183
|
-
import {
|
|
184
|
-
CHAIN_PRESETS,
|
|
185
|
-
GenesisPeerLoader,
|
|
186
|
-
isEventExpired,
|
|
187
|
-
parseIlpPeerInfo
|
|
188
|
-
} from "@toon-protocol/core";
|
|
189
|
-
var ILP_PEER_INFO_KIND = 10032;
|
|
190
|
-
var DISCOVERY_TIMEOUT_MS = 5e3;
|
|
191
|
-
function parseRoutes(content) {
|
|
192
|
-
try {
|
|
193
|
-
const parsed = JSON.parse(content);
|
|
194
|
-
const routes = parsed.routes;
|
|
195
|
-
if (typeof routes !== "object" || routes === null) return void 0;
|
|
196
|
-
const { publish, store } = routes;
|
|
197
|
-
const out = {
|
|
198
|
-
...typeof publish === "string" && publish.length > 0 ? { publish } : {},
|
|
199
|
-
...typeof store === "string" && store.length > 0 ? { store } : {}
|
|
200
|
-
};
|
|
201
|
-
return out.publish || out.store ? out : void 0;
|
|
202
|
-
} catch {
|
|
203
|
-
return void 0;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
async function discoverAnnouncedPeers(relayUrl, options = {}) {
|
|
207
|
-
const factory = options.webSocketFactory ?? defaultDiscoveryWebSocketFactory();
|
|
208
|
-
const events = await queryRelay(
|
|
209
|
-
relayUrl,
|
|
210
|
-
{ kinds: [ILP_PEER_INFO_KIND], limit: 100 },
|
|
211
|
-
options.timeoutMs ?? DISCOVERY_TIMEOUT_MS,
|
|
212
|
-
factory
|
|
213
|
-
);
|
|
214
|
-
const latestByAuthor = /* @__PURE__ */ new Map();
|
|
215
|
-
for (const event of events) {
|
|
216
|
-
if (event.kind !== ILP_PEER_INFO_KIND) continue;
|
|
217
|
-
const prev = latestByAuthor.get(event.pubkey);
|
|
218
|
-
if (!prev || event.created_at > prev.created_at) {
|
|
219
|
-
latestByAuthor.set(event.pubkey, event);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
const peers = [];
|
|
223
|
-
for (const event of latestByAuthor.values()) {
|
|
224
|
-
if (isEventExpired(event)) {
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
let info;
|
|
228
|
-
try {
|
|
229
|
-
info = parseIlpPeerInfo(event);
|
|
230
|
-
} catch {
|
|
231
|
-
continue;
|
|
232
|
-
}
|
|
233
|
-
const routes = parseRoutes(event.content);
|
|
234
|
-
peers.push({
|
|
235
|
-
pubkey: event.pubkey,
|
|
236
|
-
info,
|
|
237
|
-
...routes ? { routes } : {},
|
|
238
|
-
createdAt: event.created_at
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
return peers;
|
|
242
|
-
}
|
|
243
|
-
function defaultDiscoveryWebSocketFactory() {
|
|
244
|
-
return (url) => {
|
|
245
|
-
const ctor = globalThis.WebSocket;
|
|
246
|
-
if (!ctor) {
|
|
247
|
-
throw new Error(
|
|
248
|
-
"No global WebSocket constructor (Node >= 22 required) for announce discovery"
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
return new ctor(url);
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
function pickPaymentPeer(peers, seedPubkeys) {
|
|
255
|
-
const seeded = peers.filter((p) => seedPubkeys.includes(p.pubkey));
|
|
256
|
-
if (seeded.length > 0) {
|
|
257
|
-
return seeded.sort((a, b) => b.createdAt - a.createdAt)[0];
|
|
258
|
-
}
|
|
259
|
-
const payable = peers.filter(
|
|
260
|
-
(p) => (p.info.httpEndpoint || p.info.btpEndpoint) && p.info.settlementAddresses && Object.keys(p.info.settlementAddresses).length > 0
|
|
261
|
-
);
|
|
262
|
-
if (payable.length === 0) return void 0;
|
|
263
|
-
const publishEdges = payable.filter(
|
|
264
|
-
(p) => p.routes?.publish !== void 0 && p.routes.publish === p.info.ilpAddress
|
|
265
|
-
);
|
|
266
|
-
const pool = publishEdges.length > 0 ? publishEdges : payable;
|
|
267
|
-
return pool.sort((a, b) => b.createdAt - a.createdAt)[0];
|
|
268
|
-
}
|
|
269
|
-
var DEVNET_ZONE = "devnet.toonprotocol.dev";
|
|
270
|
-
var DEVNET_CHAIN_RPC_URLS = {
|
|
271
|
-
"evm:31337": "https://evm-rpc.devnet.toonprotocol.dev",
|
|
272
|
-
"solana:devnet": "https://solana-rpc.devnet.toonprotocol.dev"
|
|
273
|
-
};
|
|
274
|
-
function hostOf(url) {
|
|
275
|
-
if (!url) return void 0;
|
|
276
|
-
try {
|
|
277
|
-
return new URL(url).hostname;
|
|
278
|
-
} catch {
|
|
279
|
-
return void 0;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
function isDevnetZonePeer(peer) {
|
|
283
|
-
if (!peer) return false;
|
|
284
|
-
return [
|
|
285
|
-
hostOf(peer.info.httpEndpoint),
|
|
286
|
-
hostOf(peer.info.btpEndpoint),
|
|
287
|
-
hostOf(peer.info.relayUrl)
|
|
288
|
-
].some((h) => h !== void 0 && (h === DEVNET_ZONE || h.endsWith(`.${DEVNET_ZONE}`)));
|
|
289
|
-
}
|
|
290
|
-
function evmChainIdOf(chain) {
|
|
291
|
-
const parts = chain.split(":");
|
|
292
|
-
if (parts[0] !== "evm") return void 0;
|
|
293
|
-
const raw = parts.length >= 3 ? parts[2] : parts[1];
|
|
294
|
-
const id = Number.parseInt(raw ?? "", 10);
|
|
295
|
-
return Number.isNaN(id) ? void 0 : id;
|
|
296
|
-
}
|
|
297
|
-
function evmPresetForChain(chain) {
|
|
298
|
-
const id = evmChainIdOf(chain);
|
|
299
|
-
if (id === void 0) return void 0;
|
|
300
|
-
for (const preset of Object.values(CHAIN_PRESETS)) {
|
|
301
|
-
if (preset.chainId === id) {
|
|
302
|
-
return {
|
|
303
|
-
rpcUrl: preset.rpcUrl,
|
|
304
|
-
usdcAddress: preset.usdcAddress,
|
|
305
|
-
tokenNetworkAddress: preset.tokenNetworkAddress
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
return void 0;
|
|
310
|
-
}
|
|
311
|
-
function resolveChainSettlement(chain, explicit, announce) {
|
|
312
|
-
const family = chain.split(":")[0] ?? chain;
|
|
313
|
-
const preset = evmPresetForChain(chain);
|
|
314
|
-
const devnetRpc = isDevnetZonePeer(announce) ? DEVNET_CHAIN_RPC_URLS[chain] : void 0;
|
|
315
|
-
const rpcUrl = explicit.chainRpcUrls?.[chain] ?? devnetRpc ?? preset?.rpcUrl;
|
|
316
|
-
const tokenAddress = explicit.preferredTokens?.[chain] ?? announce?.info.preferredTokens?.[chain] ?? (preset?.usdcAddress || void 0);
|
|
317
|
-
const tokenNetwork = explicit.tokenNetworks?.[chain] ?? announce?.info.tokenNetworks?.[chain] ?? (preset?.tokenNetworkAddress || void 0);
|
|
318
|
-
return {
|
|
319
|
-
chain,
|
|
320
|
-
family,
|
|
321
|
-
...rpcUrl ? { rpcUrl } : {},
|
|
322
|
-
...tokenAddress ? { tokenAddress } : {},
|
|
323
|
-
...tokenNetwork ? { tokenNetwork } : {}
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
var TokenNetworkUnderivableError = class extends Error {
|
|
327
|
-
constructor(chain, announce, relayUrl) {
|
|
328
|
-
const announceRef = announce ? `the kind:10032 announce from ${announce.pubkey.slice(0, 16)}\u2026 on ${relayUrl}` : `no kind:10032 announce was found on ${relayUrl}`;
|
|
329
|
-
super(
|
|
330
|
-
`cannot derive the TokenNetwork contract for settlement chain "${chain}": ${announceRef} carries no tokenNetworks["${chain}"], and no built-in chain preset matches its chain id \u2014 add tokenNetworks["${chain}"] to the client config (or pick another chain via TOON_CLIENT_CHAIN / the chain config field)`
|
|
331
|
-
);
|
|
332
|
-
this.name = "TokenNetworkUnderivableError";
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
async function selectSettlementChain(options) {
|
|
336
|
-
const { explicitChain, announcedChains } = options;
|
|
337
|
-
if (explicitChain) {
|
|
338
|
-
if (explicitChain.includes(":")) {
|
|
339
|
-
return {
|
|
340
|
-
chain: explicitChain,
|
|
341
|
-
reason: "explicit",
|
|
342
|
-
detail: `chain ${explicitChain} set by config`
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
const familyMatch = announcedChains.find(
|
|
346
|
-
(c) => (c.split(":")[0] ?? c) === explicitChain
|
|
347
|
-
);
|
|
348
|
-
if (!familyMatch) {
|
|
349
|
-
throw new Error(
|
|
350
|
-
`configured chain family "${explicitChain}" is not announced by the payment peer (announced: ${announcedChains.join(", ") || "none"}) \u2014 set a full chain id (e.g. "evm:31337") to force it`
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
return {
|
|
354
|
-
chain: familyMatch,
|
|
355
|
-
reason: "explicit",
|
|
356
|
-
detail: `chain family "${explicitChain}" set by config \u2192 ${familyMatch}`
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
const live = (options.records ?? []).filter((r) => !r.closed && announcedChains.includes(r.chain)).sort((a, b) => b.lastUsedAt.localeCompare(a.lastUsedAt));
|
|
360
|
-
const persisted = live[0];
|
|
361
|
-
if (persisted) {
|
|
362
|
-
return {
|
|
363
|
-
chain: persisted.chain,
|
|
364
|
-
reason: "persisted-channel",
|
|
365
|
-
detail: `existing payment channel on ${persisted.chain} (rig channel map)`
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
const evmChains = announcedChains.filter((c) => c.startsWith("evm:"));
|
|
369
|
-
if (options.evmAddress && options.probeBalance) {
|
|
370
|
-
for (const chain of evmChains) {
|
|
371
|
-
const settlement = options.resolveSettlement(chain);
|
|
372
|
-
if (!settlement.rpcUrl || !settlement.tokenAddress) continue;
|
|
373
|
-
try {
|
|
374
|
-
const balance = await options.probeBalance({
|
|
375
|
-
rpcUrl: settlement.rpcUrl,
|
|
376
|
-
tokenAddress: settlement.tokenAddress,
|
|
377
|
-
owner: options.evmAddress
|
|
378
|
-
});
|
|
379
|
-
if (balance > 0n) {
|
|
380
|
-
return {
|
|
381
|
-
chain,
|
|
382
|
-
reason: "funded",
|
|
383
|
-
detail: `wallet holds ${balance} token base units on ${chain}`
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
} catch {
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
const fallback = evmChains[0] ?? announcedChains[0];
|
|
391
|
-
if (!fallback) {
|
|
392
|
-
throw new Error(
|
|
393
|
-
"the payment peer announces no settlement chains \u2014 cannot select a chain for paid writes (set supportedChains/chain in the client config)"
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
return {
|
|
397
|
-
chain: fallback,
|
|
398
|
-
reason: "default",
|
|
399
|
-
detail: evmChains[0] ? `first EVM chain announced by the payment peer` : `first chain announced by the payment peer (no EVM chain announced)`
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
var BALANCE_OF_SELECTOR = "0x70a08231";
|
|
403
|
-
async function evmTokenBalance(args) {
|
|
404
|
-
const fetchImpl = args.fetchImpl ?? fetch;
|
|
405
|
-
const owner = args.owner.replace(/^0x/, "").toLowerCase().padStart(64, "0");
|
|
406
|
-
const controller = new AbortController();
|
|
407
|
-
const timer = setTimeout(() => controller.abort(), args.timeoutMs ?? 5e3);
|
|
408
|
-
try {
|
|
409
|
-
const res = await fetchImpl(args.rpcUrl, {
|
|
410
|
-
method: "POST",
|
|
411
|
-
headers: { "content-type": "application/json" },
|
|
412
|
-
body: JSON.stringify({
|
|
413
|
-
jsonrpc: "2.0",
|
|
414
|
-
id: 1,
|
|
415
|
-
method: "eth_call",
|
|
416
|
-
params: [
|
|
417
|
-
{ to: args.tokenAddress, data: `${BALANCE_OF_SELECTOR}${owner}` },
|
|
418
|
-
"latest"
|
|
419
|
-
]
|
|
420
|
-
}),
|
|
421
|
-
signal: controller.signal
|
|
422
|
-
});
|
|
423
|
-
if (!res.ok) {
|
|
424
|
-
throw new Error(`eth_call failed: HTTP ${res.status}`);
|
|
425
|
-
}
|
|
426
|
-
const body = await res.json();
|
|
427
|
-
if (typeof body.result !== "string") {
|
|
428
|
-
throw new Error(`eth_call failed: ${body.error?.message ?? "no result"}`);
|
|
429
|
-
}
|
|
430
|
-
return BigInt(body.result === "0x" ? "0x0" : body.result);
|
|
431
|
-
} finally {
|
|
432
|
-
clearTimeout(timer);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
function loadGenesisSeed() {
|
|
436
|
-
return GenesisPeerLoader.loadGenesisPeers()[0];
|
|
437
|
-
}
|
|
438
|
-
function genesisSeedPubkeys() {
|
|
439
|
-
return GenesisPeerLoader.loadGenesisPeers().map((p) => p.pubkey);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
192
|
// src/cli/standalone-mode.ts
|
|
443
193
|
var MissingUplinkError = class extends Error {
|
|
444
194
|
constructor(configPath, relayUrl) {
|
|
@@ -683,8 +433,8 @@ var TopologyRecoveringPublisher = class {
|
|
|
683
433
|
return p.settleRecordedChannel(record);
|
|
684
434
|
}
|
|
685
435
|
/** Free read on the unstarted client — no bootstrap, no recovery needed. */
|
|
686
|
-
|
|
687
|
-
return this.inner.
|
|
436
|
+
readWalletChainBalances() {
|
|
437
|
+
return this.inner.readWalletChainBalances();
|
|
688
438
|
}
|
|
689
439
|
async stop() {
|
|
690
440
|
await this.inner.stop();
|
|
@@ -852,7 +602,7 @@ async function createStandaloneContext(options) {
|
|
|
852
602
|
openChannel: (opts) => publisher.openChannelExplicit(opts),
|
|
853
603
|
closeChannel: (record) => publisher.closeRecordedChannel(record),
|
|
854
604
|
settleChannel: (record) => publisher.settleRecordedChannel(record),
|
|
855
|
-
|
|
605
|
+
walletChainBalances: () => publisher.readWalletChainBalances()
|
|
856
606
|
},
|
|
857
607
|
stop: () => publisher.stop()
|
|
858
608
|
};
|
|
@@ -862,4 +612,4 @@ export {
|
|
|
862
612
|
createStandaloneContext,
|
|
863
613
|
resolveNetworkTopology
|
|
864
614
|
};
|
|
865
|
-
//# sourceMappingURL=standalone-mode-
|
|
615
|
+
//# sourceMappingURL=standalone-mode-WEMJBHME.js.map
|