@toon-protocol/client-mcp 0.2.0 → 0.3.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 -37
- package/dist/app/index.html +31 -31
- package/dist/{chunk-NP35YO5O.js → chunk-CQ2QIZ6Z.js} +162 -211
- package/dist/chunk-CQ2QIZ6Z.js.map +1 -0
- package/dist/{chunk-L6F2B3GX.js → chunk-QFHCXJ2V.js} +96 -99
- package/dist/chunk-QFHCXJ2V.js.map +1 -0
- package/dist/{chunk-KNQ2DKNN.js → chunk-XV52IHVR.js} +123 -7
- package/dist/chunk-XV52IHVR.js.map +1 -0
- package/dist/daemon.js +2 -3
- package/dist/daemon.js.map +1 -1
- package/dist/e2e/run-journey.d.ts +1 -0
- package/dist/e2e/run-journey.js +19953 -0
- package/dist/e2e/run-journey.js.map +1 -0
- package/dist/index.d.ts +61 -67
- package/dist/index.js +344 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +2 -3
- package/dist/mcp.js.map +1 -1
- package/package.json +9 -6
- package/dist/anon-proxy-W3KMM7GU-FN7ZJY7P.js +0 -25
- package/dist/anon-proxy-W3KMM7GU-FN7ZJY7P.js.map +0 -1
- package/dist/chunk-KNQ2DKNN.js.map +0 -1
- package/dist/chunk-L6F2B3GX.js.map +0 -1
- package/dist/chunk-NP35YO5O.js.map +0 -1
- package/dist/chunk-SKQTKZIH.js +0 -278
- package/dist/chunk-SKQTKZIH.js.map +0 -1
- package/dist/gateway-QOK47RKS-SEGTXBR3.js +0 -16
- package/dist/gateway-QOK47RKS-SEGTXBR3.js.map +0 -1
- package/dist/socks5-WTJBYGME-6COK4LXW.js +0 -139
- package/dist/socks5-WTJBYGME-6COK4LXW.js.map +0 -1
|
@@ -6831,26 +6831,49 @@ function getNetworkStatus(config) {
|
|
|
6831
6831
|
if (!network || network === "custom") return void 0;
|
|
6832
6832
|
return resolveClientNetwork(network).status;
|
|
6833
6833
|
}
|
|
6834
|
+
function proxyIlpEndpoint(proxyUrl) {
|
|
6835
|
+
if (!proxyUrl) return void 0;
|
|
6836
|
+
const trimmed = proxyUrl.replace(/\/+$/, "");
|
|
6837
|
+
return /\/ilp$/i.test(trimmed) ? trimmed : `${trimmed}/ilp`;
|
|
6838
|
+
}
|
|
6834
6839
|
function validateConfig(config) {
|
|
6835
6840
|
if (config.connector !== void 0) {
|
|
6836
6841
|
throw new ValidationError(
|
|
6837
6842
|
"Embedded mode not yet implemented in ToonClient. Use connectorUrl for HTTP mode."
|
|
6838
6843
|
);
|
|
6839
6844
|
}
|
|
6840
|
-
if (!config.connectorUrl) {
|
|
6845
|
+
if (!config.connectorUrl && !config.proxyUrl) {
|
|
6841
6846
|
throw new ValidationError(
|
|
6842
|
-
'connectorUrl is required for HTTP mode. Example: "http://localhost:8080"'
|
|
6847
|
+
'connectorUrl (or proxyUrl) is required for HTTP mode. Example: "http://localhost:8080"'
|
|
6843
6848
|
);
|
|
6844
6849
|
}
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6850
|
+
if (config.connectorUrl) {
|
|
6851
|
+
try {
|
|
6852
|
+
const url = new URL(config.connectorUrl);
|
|
6853
|
+
if (!url.protocol.startsWith("http")) {
|
|
6854
|
+
throw new Error("Must be HTTP or HTTPS");
|
|
6855
|
+
}
|
|
6856
|
+
} catch (error) {
|
|
6857
|
+
throw new ValidationError(
|
|
6858
|
+
`Invalid connectorUrl: must be a valid HTTP/HTTPS URL (e.g., "http://localhost:8080"). Error: ${error instanceof Error ? error.message : String(error)}`
|
|
6859
|
+
);
|
|
6860
|
+
}
|
|
6861
|
+
}
|
|
6862
|
+
for (const [field, value] of [
|
|
6863
|
+
["proxyUrl", config.proxyUrl],
|
|
6864
|
+
["faucetUrl", config.faucetUrl]
|
|
6865
|
+
]) {
|
|
6866
|
+
if (value === void 0) continue;
|
|
6867
|
+
try {
|
|
6868
|
+
const url = new URL(value);
|
|
6869
|
+
if (!url.protocol.startsWith("http")) {
|
|
6870
|
+
throw new Error("Must be HTTP or HTTPS");
|
|
6871
|
+
}
|
|
6872
|
+
} catch (error) {
|
|
6873
|
+
throw new ValidationError(
|
|
6874
|
+
`Invalid ${field}: must be a valid HTTP/HTTPS URL. Error: ${error instanceof Error ? error.message : String(error)}`
|
|
6875
|
+
);
|
|
6849
6876
|
}
|
|
6850
|
-
} catch (error) {
|
|
6851
|
-
throw new ValidationError(
|
|
6852
|
-
`Invalid connectorUrl: must be a valid HTTP/HTTPS URL (e.g., "http://localhost:8080"). Error: ${error instanceof Error ? error.message : String(error)}`
|
|
6853
|
-
);
|
|
6854
6877
|
}
|
|
6855
6878
|
if (config.secretKey !== void 0) {
|
|
6856
6879
|
if (!config.secretKey || config.secretKey.length !== 32) {
|
|
@@ -6914,25 +6937,6 @@ function validateConfig(config) {
|
|
|
6914
6937
|
);
|
|
6915
6938
|
}
|
|
6916
6939
|
}
|
|
6917
|
-
if (config.transport) {
|
|
6918
|
-
if (config.transport.type === "socks5") {
|
|
6919
|
-
if (!config.transport.socksProxy?.startsWith("socks5h://")) {
|
|
6920
|
-
throw new ValidationError(
|
|
6921
|
-
'transport.socksProxy must use socks5h:// scheme to prevent DNS leaks. The "h" suffix ensures .anyone hostnames are resolved by the proxy, not locally.'
|
|
6922
|
-
);
|
|
6923
|
-
}
|
|
6924
|
-
} else if (config.transport.type === "gateway") {
|
|
6925
|
-
if (!config.transport.gatewayUrl) {
|
|
6926
|
-
throw new ValidationError(
|
|
6927
|
-
"transport.gatewayUrl is required for gateway transport"
|
|
6928
|
-
);
|
|
6929
|
-
}
|
|
6930
|
-
} else if (config.transport.type !== "direct") {
|
|
6931
|
-
throw new ValidationError(
|
|
6932
|
-
`Unknown transport type: "${config.transport.type}"`
|
|
6933
|
-
);
|
|
6934
|
-
}
|
|
6935
|
-
}
|
|
6936
6940
|
if (config.chainRpcUrls && config.supportedChains) {
|
|
6937
6941
|
for (const chain2 of Object.keys(config.chainRpcUrls)) {
|
|
6938
6942
|
if (!config.supportedChains.includes(chain2)) {
|
|
@@ -6949,19 +6953,21 @@ function applyDefaults(rawConfig) {
|
|
|
6949
6953
|
config.mnemonic,
|
|
6950
6954
|
config.mnemonicAccountIndex ?? 0
|
|
6951
6955
|
).secretKey : generateSecretKey2());
|
|
6956
|
+
const connectorHttpEndpoint = config.connectorHttpEndpoint ?? proxyIlpEndpoint(config.proxyUrl);
|
|
6957
|
+
const connectorUrl = config.connectorUrl ?? config.proxyUrl?.replace(/\/+$/, "");
|
|
6952
6958
|
let btpUrl = config.btpUrl;
|
|
6953
|
-
if (!btpUrl &&
|
|
6959
|
+
if (!btpUrl && connectorUrl && !connectorHttpEndpoint) {
|
|
6954
6960
|
try {
|
|
6955
|
-
const url = new URL(
|
|
6961
|
+
const url = new URL(connectorUrl);
|
|
6956
6962
|
const wsProtocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
6957
6963
|
btpUrl = `${wsProtocol}//${url.hostname}:3000`;
|
|
6958
6964
|
} catch {
|
|
6959
6965
|
}
|
|
6960
6966
|
}
|
|
6961
6967
|
let destinationAddress = config.destinationAddress;
|
|
6962
|
-
if (!destinationAddress &&
|
|
6968
|
+
if (!destinationAddress && connectorUrl) {
|
|
6963
6969
|
try {
|
|
6964
|
-
const url = new URL(
|
|
6970
|
+
const url = new URL(connectorUrl);
|
|
6965
6971
|
if (url.hostname === "localhost" || url.hostname === "127.0.0.1") {
|
|
6966
6972
|
if (url.port === "8080") {
|
|
6967
6973
|
destinationAddress = "g.toon.genesis";
|
|
@@ -6984,8 +6990,10 @@ function applyDefaults(rawConfig) {
|
|
|
6984
6990
|
...config,
|
|
6985
6991
|
secretKey,
|
|
6986
6992
|
evmPrivateKey,
|
|
6987
|
-
connectorUrl
|
|
6988
|
-
|
|
6993
|
+
// Satisfied by connectorUrl OR proxyUrl (validateConfig enforced one of them).
|
|
6994
|
+
connectorUrl,
|
|
6995
|
+
// Surface the derived `POST /ilp` endpoint so HTTP mode selects HttpIlpClient.
|
|
6996
|
+
...connectorHttpEndpoint ? { connectorHttpEndpoint } : {},
|
|
6989
6997
|
relayUrl: config.relayUrl ?? "ws://localhost:7100",
|
|
6990
6998
|
queryTimeout: config.queryTimeout ?? 3e4,
|
|
6991
6999
|
maxRetries: config.maxRetries ?? 3,
|
|
@@ -7045,6 +7053,13 @@ function decodeUtf8(bytes) {
|
|
|
7045
7053
|
function isBase64(str) {
|
|
7046
7054
|
return /^[A-Za-z0-9+/]*={0,2}$/.test(str);
|
|
7047
7055
|
}
|
|
7056
|
+
var REQUEST_LINE = "POST /write HTTP/1.1";
|
|
7057
|
+
var HEADERS = ["Host: relay", "Content-Type: application/json"];
|
|
7058
|
+
function buildStoreWriteEnvelope(event) {
|
|
7059
|
+
const body = JSON.stringify({ event });
|
|
7060
|
+
const head = [REQUEST_LINE, ...HEADERS].join("\r\n");
|
|
7061
|
+
return encodeUtf8(head + "\r\n\r\n" + body);
|
|
7062
|
+
}
|
|
7048
7063
|
async function withRetry(operation, options) {
|
|
7049
7064
|
const {
|
|
7050
7065
|
maxRetries,
|
|
@@ -9219,79 +9234,9 @@ var EvmSigner = class {
|
|
|
9219
9234
|
};
|
|
9220
9235
|
}
|
|
9221
9236
|
};
|
|
9222
|
-
function isAnyoneHost(url) {
|
|
9223
|
-
if (!url) return false;
|
|
9224
|
-
try {
|
|
9225
|
-
const withScheme = /:\/\//.test(url) ? url : `ws://${url}`;
|
|
9226
|
-
const host = new URL(withScheme).hostname.toLowerCase();
|
|
9227
|
-
return host.endsWith(".anyone");
|
|
9228
|
-
} catch {
|
|
9229
|
-
return false;
|
|
9230
|
-
}
|
|
9231
|
-
}
|
|
9232
|
-
async function resolveTransport(transport, originalBtpUrl, originalConnectorUrl, managedProxyOptions) {
|
|
9233
|
-
const hasExplicitProxy = !!transport && (transport.type === "socks5" || transport.type === "gateway");
|
|
9234
|
-
const envProxy = process.env["ANYONE_PROXY_URLS"];
|
|
9235
|
-
if (!hasExplicitProxy && managedProxyOptions?.managedAnonProxy !== false && !envProxy && isAnyoneHost(originalBtpUrl)) {
|
|
9236
|
-
const { startManagedAnonProxy: startManagedAnonProxy2 } = await import("./anon-proxy-W3KMM7GU-FN7ZJY7P.js");
|
|
9237
|
-
const { createSocks5WebSocketFactory, createSocks5Fetch } = await import("./socks5-WTJBYGME-6COK4LXW.js");
|
|
9238
|
-
const proxy = await startManagedAnonProxy2({
|
|
9239
|
-
...managedProxyOptions?.managedAnonSocksPort !== void 0 ? { socksPort: managedProxyOptions.managedAnonSocksPort } : {}
|
|
9240
|
-
});
|
|
9241
|
-
try {
|
|
9242
|
-
return {
|
|
9243
|
-
createWebSocket: createSocks5WebSocketFactory(proxy.socksProxy),
|
|
9244
|
-
httpClient: createSocks5Fetch(proxy.socksProxy),
|
|
9245
|
-
stopManagedProxy: proxy.stop
|
|
9246
|
-
};
|
|
9247
|
-
} catch (err) {
|
|
9248
|
-
await proxy.stop();
|
|
9249
|
-
throw err;
|
|
9250
|
-
}
|
|
9251
|
-
}
|
|
9252
|
-
if (!transport || transport.type === "direct") {
|
|
9253
|
-
return {};
|
|
9254
|
-
}
|
|
9255
|
-
if (transport.type === "socks5") {
|
|
9256
|
-
const {
|
|
9257
|
-
createSocks5WebSocketFactory,
|
|
9258
|
-
createSocks5Fetch,
|
|
9259
|
-
probeSocks5Proxy
|
|
9260
|
-
} = await import("./socks5-WTJBYGME-6COK4LXW.js");
|
|
9261
|
-
await probeSocks5Proxy(transport.socksProxy);
|
|
9262
|
-
return {
|
|
9263
|
-
createWebSocket: createSocks5WebSocketFactory(transport.socksProxy),
|
|
9264
|
-
httpClient: createSocks5Fetch(transport.socksProxy)
|
|
9265
|
-
};
|
|
9266
|
-
}
|
|
9267
|
-
if (transport.type === "gateway") {
|
|
9268
|
-
const { rewriteUrlsForGateway } = await import("./gateway-QOK47RKS-SEGTXBR3.js");
|
|
9269
|
-
const rewritten = rewriteUrlsForGateway(
|
|
9270
|
-
transport.gatewayUrl,
|
|
9271
|
-
originalBtpUrl,
|
|
9272
|
-
originalConnectorUrl
|
|
9273
|
-
);
|
|
9274
|
-
return {
|
|
9275
|
-
btpUrl: rewritten.btpUrl,
|
|
9276
|
-
connectorUrl: rewritten.connectorUrl
|
|
9277
|
-
};
|
|
9278
|
-
}
|
|
9279
|
-
throw new Error(
|
|
9280
|
-
`Unknown transport type: "${transport.type}"`
|
|
9281
|
-
);
|
|
9282
|
-
}
|
|
9283
9237
|
async function initializeHttpMode(config) {
|
|
9284
|
-
const
|
|
9285
|
-
|
|
9286
|
-
config.btpUrl,
|
|
9287
|
-
config.connectorUrl,
|
|
9288
|
-
{
|
|
9289
|
-
...config.managedAnonProxy !== void 0 ? { managedAnonProxy: config.managedAnonProxy } : {},
|
|
9290
|
-
...config.managedAnonSocksPort !== void 0 ? { managedAnonSocksPort: config.managedAnonSocksPort } : {}
|
|
9291
|
-
}
|
|
9292
|
-
);
|
|
9293
|
-
const effectiveBtpUrl = transport.btpUrl ?? config.btpUrl;
|
|
9294
|
-
const effectiveConnectorUrl = transport.connectorUrl ?? config.connectorUrl;
|
|
9238
|
+
const effectiveBtpUrl = config.btpUrl;
|
|
9239
|
+
const effectiveConnectorUrl = config.connectorUrl;
|
|
9295
9240
|
const settlementInfo = buildSettlementInfo(config);
|
|
9296
9241
|
const discoveredPeer = readDiscoveredIlpPeer({
|
|
9297
9242
|
btpEndpoint: effectiveBtpUrl,
|
|
@@ -9304,8 +9249,7 @@ async function initializeHttpMode(config) {
|
|
|
9304
9249
|
btpClient = new BtpRuntimeClient({
|
|
9305
9250
|
btpUrl: effectiveBtpUrl,
|
|
9306
9251
|
peerId: config.btpPeerId ?? `client`,
|
|
9307
|
-
authToken: config.btpAuthToken ?? ""
|
|
9308
|
-
createWebSocket: transport.createWebSocket
|
|
9252
|
+
authToken: config.btpAuthToken ?? ""
|
|
9309
9253
|
});
|
|
9310
9254
|
await btpClient.connect();
|
|
9311
9255
|
}
|
|
@@ -9317,17 +9261,14 @@ async function initializeHttpMode(config) {
|
|
|
9317
9261
|
...config.btpAuthToken !== void 0 ? { authToken: config.btpAuthToken } : {},
|
|
9318
9262
|
timeout: config.queryTimeout,
|
|
9319
9263
|
maxRetries: config.maxRetries,
|
|
9320
|
-
retryDelay: config.retryDelay
|
|
9321
|
-
...transport.httpClient !== void 0 ? { httpClient: transport.httpClient } : {},
|
|
9322
|
-
...transport.createWebSocket !== void 0 ? { createWebSocket: transport.createWebSocket } : {}
|
|
9264
|
+
retryDelay: config.retryDelay
|
|
9323
9265
|
});
|
|
9324
9266
|
}
|
|
9325
9267
|
const runtimeClient = httpIlpClient ?? btpClient ?? new HttpRuntimeClient({
|
|
9326
9268
|
connectorUrl: effectiveConnectorUrl,
|
|
9327
9269
|
timeout: config.queryTimeout,
|
|
9328
9270
|
maxRetries: config.maxRetries,
|
|
9329
|
-
retryDelay: config.retryDelay
|
|
9330
|
-
httpClient: transport.httpClient
|
|
9271
|
+
retryDelay: config.retryDelay
|
|
9331
9272
|
});
|
|
9332
9273
|
let onChainChannelClient = null;
|
|
9333
9274
|
if (config.chainRpcUrls) {
|
|
@@ -9372,10 +9313,7 @@ async function initializeHttpMode(config) {
|
|
|
9372
9313
|
runtimeClient,
|
|
9373
9314
|
adminClient: null,
|
|
9374
9315
|
btpClient,
|
|
9375
|
-
onChainChannelClient
|
|
9376
|
-
// Teardown handle for a managed `anon` proxy this init STARTED (undefined
|
|
9377
|
-
// for explicit-proxy/direct/gateway). ToonClient.stop() invokes it.
|
|
9378
|
-
stopManagedProxy: transport.stopManagedProxy
|
|
9316
|
+
onChainChannelClient
|
|
9379
9317
|
};
|
|
9380
9318
|
}
|
|
9381
9319
|
var SolanaSigner = class {
|
|
@@ -10514,13 +10452,7 @@ var ToonClient = class {
|
|
|
10514
10452
|
}
|
|
10515
10453
|
}
|
|
10516
10454
|
const initialization = await initializeHttpMode(this.config);
|
|
10517
|
-
const {
|
|
10518
|
-
bootstrapService,
|
|
10519
|
-
discoveryTracker,
|
|
10520
|
-
runtimeClient,
|
|
10521
|
-
btpClient,
|
|
10522
|
-
stopManagedProxy
|
|
10523
|
-
} = initialization;
|
|
10455
|
+
const { bootstrapService, discoveryTracker, runtimeClient, btpClient } = initialization;
|
|
10524
10456
|
if (this.channelManager) {
|
|
10525
10457
|
const cm = this.channelManager;
|
|
10526
10458
|
const nostrPubkey = this.getPublicKey();
|
|
@@ -10608,8 +10540,7 @@ var ToonClient = class {
|
|
|
10608
10540
|
discoveryTracker,
|
|
10609
10541
|
runtimeClient,
|
|
10610
10542
|
peersDiscovered: bootstrapResults.length,
|
|
10611
|
-
btpClient: btpClient ?? void 0
|
|
10612
|
-
...stopManagedProxy ? { stopManagedProxy } : {}
|
|
10543
|
+
btpClient: btpClient ?? void 0
|
|
10613
10544
|
};
|
|
10614
10545
|
return {
|
|
10615
10546
|
peersDiscovered: bootstrapResults.length,
|
|
@@ -10645,13 +10576,9 @@ var ToonClient = class {
|
|
|
10645
10576
|
const toonData = this.config.toonEncoder(event);
|
|
10646
10577
|
const basePricePerByte = 10n;
|
|
10647
10578
|
const amount = options?.ilpAmount !== void 0 ? String(options.ilpAmount) : String(BigInt(toonData.length) * basePricePerByte);
|
|
10579
|
+
const writeData = buildStoreWriteEnvelope(event);
|
|
10648
10580
|
const destination = options?.destination ?? this.config.destinationAddress;
|
|
10649
|
-
|
|
10650
|
-
throw new ToonClientError(
|
|
10651
|
-
"BTP client required for publishing. Configure btpUrl.",
|
|
10652
|
-
"NO_BTP_CLIENT"
|
|
10653
|
-
);
|
|
10654
|
-
}
|
|
10581
|
+
const transport = this.getClaimTransport();
|
|
10655
10582
|
let claimMessage;
|
|
10656
10583
|
if (options?.claim) {
|
|
10657
10584
|
claimMessage = this.buildClaimMessageForProof(options.claim);
|
|
@@ -10680,13 +10607,11 @@ var ToonClient = class {
|
|
|
10680
10607
|
"MISSING_CLAIM"
|
|
10681
10608
|
);
|
|
10682
10609
|
}
|
|
10683
|
-
const response = await
|
|
10610
|
+
const response = await transport.sendIlpPacketWithClaim(
|
|
10684
10611
|
{
|
|
10685
10612
|
destination,
|
|
10686
10613
|
amount,
|
|
10687
|
-
data: toBase64(
|
|
10688
|
-
toonData instanceof Uint8Array ? toonData : new Uint8Array(toonData)
|
|
10689
|
-
)
|
|
10614
|
+
data: toBase64(writeData)
|
|
10690
10615
|
},
|
|
10691
10616
|
claimMessage
|
|
10692
10617
|
);
|
|
@@ -10766,7 +10691,7 @@ var ToonClient = class {
|
|
|
10766
10691
|
* matching `destination`,
|
|
10767
10692
|
* (c) neither -> throw MISSING_CLAIM.
|
|
10768
10693
|
*
|
|
10769
|
-
* @throws {ToonClientError} INVALID_STATE /
|
|
10694
|
+
* @throws {ToonClientError} INVALID_STATE / NO_ILP_TRANSPORT / MISSING_CLAIM
|
|
10770
10695
|
*/
|
|
10771
10696
|
async sendSwapPacket(params) {
|
|
10772
10697
|
if (!this.state) {
|
|
@@ -10775,18 +10700,13 @@ var ToonClient = class {
|
|
|
10775
10700
|
"INVALID_STATE"
|
|
10776
10701
|
);
|
|
10777
10702
|
}
|
|
10778
|
-
|
|
10779
|
-
throw new ToonClientError(
|
|
10780
|
-
"BTP client required for sending swap packets. Configure btpUrl.",
|
|
10781
|
-
"NO_BTP_CLIENT"
|
|
10782
|
-
);
|
|
10783
|
-
}
|
|
10703
|
+
const transport = this.getClaimTransport();
|
|
10784
10704
|
const claimMessage = await this.resolveClaimForDestination(
|
|
10785
10705
|
params.destination,
|
|
10786
10706
|
params.amount,
|
|
10787
10707
|
params.claim
|
|
10788
10708
|
);
|
|
10789
|
-
return
|
|
10709
|
+
return transport.sendIlpPacketWithClaim(
|
|
10790
10710
|
{
|
|
10791
10711
|
destination: params.destination,
|
|
10792
10712
|
amount: String(params.amount),
|
|
@@ -10826,6 +10746,51 @@ var ToonClient = class {
|
|
|
10826
10746
|
}
|
|
10827
10747
|
return EvmSigner.buildClaimMessage(claim, this.getPublicKey());
|
|
10828
10748
|
}
|
|
10749
|
+
/**
|
|
10750
|
+
* Resolve the ILP transport for a paid (claim-bearing) write.
|
|
10751
|
+
*
|
|
10752
|
+
* The connector is a payment-proxy: paid writes carry an ILP PREPARE plus the
|
|
10753
|
+
* signed payment-channel claim. Either transport speaks the SAME claim
|
|
10754
|
+
* contract — the BTP `payment-channel-claim` protocolData entry and the
|
|
10755
|
+
* ILP-over-HTTP `ILP-Payment-Channel-Claim` header serialize the same claim
|
|
10756
|
+
* JSON — so we route through whichever transport is ACTIVE rather than
|
|
10757
|
+
* hard-requiring BTP.
|
|
10758
|
+
*
|
|
10759
|
+
* Selection (mirrors `modes/http.ts` runtime-client precedence):
|
|
10760
|
+
* 1. `runtimeClient` when it implements `sendIlpPacketWithClaim` — this is
|
|
10761
|
+
* the HttpIlpClient (proxy `POST /ilp`) when a `proxyUrl`/
|
|
10762
|
+
* `connectorHttpEndpoint` is configured, else the BtpRuntimeClient.
|
|
10763
|
+
* 2. `btpClient` as an explicit fallback (always present when `btpUrl` is set).
|
|
10764
|
+
*
|
|
10765
|
+
* The level-3 `HttpRuntimeClient` (connector-admin HTTP, no `btpUrl` AND no
|
|
10766
|
+
* proxy) does NOT implement `sendIlpPacketWithClaim`; in that case there is no
|
|
10767
|
+
* paid-write transport and we throw a clear, actionable error.
|
|
10768
|
+
*
|
|
10769
|
+
* @throws {ToonClientError} NO_ILP_TRANSPORT when no active transport can send
|
|
10770
|
+
* a packet+claim.
|
|
10771
|
+
*/
|
|
10772
|
+
getClaimTransport() {
|
|
10773
|
+
const state = this.state;
|
|
10774
|
+
if (!state) {
|
|
10775
|
+
throw new ToonClientError(
|
|
10776
|
+
"Client not started. Call start() first.",
|
|
10777
|
+
"INVALID_STATE"
|
|
10778
|
+
);
|
|
10779
|
+
}
|
|
10780
|
+
const candidates = [
|
|
10781
|
+
state.runtimeClient,
|
|
10782
|
+
state.btpClient
|
|
10783
|
+
];
|
|
10784
|
+
for (const candidate of candidates) {
|
|
10785
|
+
if (candidate && typeof candidate.sendIlpPacketWithClaim === "function") {
|
|
10786
|
+
return candidate;
|
|
10787
|
+
}
|
|
10788
|
+
}
|
|
10789
|
+
throw new ToonClientError(
|
|
10790
|
+
"No ILP transport for paid writes. Configure `proxyUrl`/`connectorHttpEndpoint` (route through the connector proxy over ILP-over-HTTP) or `btpUrl` (BTP socket).",
|
|
10791
|
+
"NO_ILP_TRANSPORT"
|
|
10792
|
+
);
|
|
10793
|
+
}
|
|
10829
10794
|
/**
|
|
10830
10795
|
* Shared claim-resolution logic used by `publishEvent` and `sendSwapPacket`.
|
|
10831
10796
|
* TODO(12.5 followup): also factor `publishEvent`'s inline claim resolution
|
|
@@ -11014,14 +10979,9 @@ var ToonClient = class {
|
|
|
11014
10979
|
"MISSING_CLAIM"
|
|
11015
10980
|
);
|
|
11016
10981
|
}
|
|
11017
|
-
|
|
11018
|
-
throw new ToonClientError(
|
|
11019
|
-
"BTP client required for sending payments. Configure btpUrl.",
|
|
11020
|
-
"NO_BTP_CLIENT"
|
|
11021
|
-
);
|
|
11022
|
-
}
|
|
10982
|
+
const transport = this.getClaimTransport();
|
|
11023
10983
|
const claimMessage = this.buildClaimMessageForProof(params.claim);
|
|
11024
|
-
return
|
|
10984
|
+
return transport.sendIlpPacketWithClaim(
|
|
11025
10985
|
ilpParams,
|
|
11026
10986
|
claimMessage
|
|
11027
10987
|
);
|
|
@@ -11039,14 +10999,10 @@ var ToonClient = class {
|
|
|
11039
10999
|
if (!this.state) {
|
|
11040
11000
|
throw new ToonClientError("Client not started", "INVALID_STATE");
|
|
11041
11001
|
}
|
|
11042
|
-
const stopManagedProxy = this.state.stopManagedProxy;
|
|
11043
11002
|
try {
|
|
11044
11003
|
if (this.state.btpClient) {
|
|
11045
11004
|
await this.state.btpClient.disconnect();
|
|
11046
11005
|
}
|
|
11047
|
-
if (stopManagedProxy) {
|
|
11048
|
-
await stopManagedProxy();
|
|
11049
|
-
}
|
|
11050
11006
|
this.state = null;
|
|
11051
11007
|
} catch (error) {
|
|
11052
11008
|
throw new ToonClientError(
|
|
@@ -11249,71 +11205,40 @@ function resolveMnemonic(file) {
|
|
|
11249
11205
|
}
|
|
11250
11206
|
function resolveConfig(file) {
|
|
11251
11207
|
const mnemonic = resolveMnemonic(file);
|
|
11208
|
+
const proxyUrl = process.env["TOON_CLIENT_PROXY_URL"] ?? file.proxyUrl;
|
|
11209
|
+
const faucetUrl = process.env["TOON_CLIENT_FAUCET_URL"] ?? file.faucetUrl;
|
|
11252
11210
|
const btpUrl = process.env["TOON_CLIENT_BTP_URL"] ?? file.btpUrl;
|
|
11253
|
-
|
|
11254
|
-
throw new Error(
|
|
11255
|
-
"No btpUrl configured. Set TOON_CLIENT_BTP_URL or add `btpUrl` to the config file."
|
|
11256
|
-
);
|
|
11257
|
-
}
|
|
11211
|
+
const hasUplink = Boolean(btpUrl || proxyUrl);
|
|
11258
11212
|
const relayUrl = process.env["TOON_CLIENT_RELAY_URL"] ?? file.relayUrl ?? "ws://localhost:7100";
|
|
11259
|
-
const explicitSocks = process.env["TOON_CLIENT_SOCKS"] ?? file.socksProxy;
|
|
11260
11213
|
const httpPort = Number(
|
|
11261
11214
|
process.env["TOON_CLIENT_HTTP_PORT"] ?? file.httpPort ?? 8787
|
|
11262
11215
|
);
|
|
11263
|
-
const destination = file.destination ?? "g.townhouse.town";
|
|
11216
|
+
const destination = process.env["TOON_CLIENT_DESTINATION"] ?? file.destination ?? "g.townhouse.town";
|
|
11264
11217
|
const feePerEvent = BigInt(file.feePerEvent ?? "1");
|
|
11265
11218
|
const network = process.env["TOON_CLIENT_NETWORK"] ?? file.network;
|
|
11266
11219
|
const chain2 = process.env["TOON_CLIENT_CHAIN"] ?? file.chain ?? "evm";
|
|
11267
|
-
const apex = file.apexChains?.[chain2] ?? file.apex;
|
|
11268
|
-
const managedPort = Number(file.managedAnonSocksPort ?? 9050);
|
|
11269
|
-
const allowManaged = file.managedAnonProxy ?? true;
|
|
11270
|
-
const btpIsAnyone = isAnyoneHost2(btpUrl);
|
|
11271
|
-
const relayIsAnyone = isAnyoneHost2(relayUrl);
|
|
11272
|
-
let transport;
|
|
11273
|
-
let managedAnonProxy;
|
|
11274
|
-
let managedAnonSocksPort;
|
|
11275
|
-
let readsSocksProxy;
|
|
11276
|
-
let manageReadProxy = false;
|
|
11277
|
-
if (explicitSocks) {
|
|
11278
|
-
transport = { type: "socks5", socksProxy: explicitSocks };
|
|
11279
|
-
managedAnonProxy = false;
|
|
11280
|
-
readsSocksProxy = explicitSocks;
|
|
11281
|
-
} else if (allowManaged && btpIsAnyone) {
|
|
11282
|
-
transport = { type: "direct" };
|
|
11283
|
-
managedAnonProxy = true;
|
|
11284
|
-
managedAnonSocksPort = managedPort;
|
|
11285
|
-
readsSocksProxy = `socks5h://127.0.0.1:${managedPort}`;
|
|
11286
|
-
} else if (allowManaged && relayIsAnyone) {
|
|
11287
|
-
transport = { type: "direct" };
|
|
11288
|
-
managedAnonProxy = false;
|
|
11289
|
-
manageReadProxy = true;
|
|
11290
|
-
managedAnonSocksPort = managedPort;
|
|
11291
|
-
readsSocksProxy = `socks5h://127.0.0.1:${managedPort}`;
|
|
11292
|
-
} else {
|
|
11293
|
-
transport = { type: "direct" };
|
|
11294
|
-
managedAnonProxy = false;
|
|
11295
|
-
}
|
|
11220
|
+
const apex = file.apexChains?.[chain2] ?? file.apex ?? buildProxyApexNegotiation(file, chain2, destination);
|
|
11296
11221
|
const channelStorePath = file.channelStorePath ?? join2(configDir(), "channels.json");
|
|
11297
11222
|
const apexChannelStorePath = join2(configDir(), "apex-channels.json");
|
|
11298
11223
|
const toonClientConfig = {
|
|
11299
|
-
//
|
|
11300
|
-
connectorUrl
|
|
11224
|
+
// validateConfig requires connectorUrl OR proxyUrl. When only BTP is set
|
|
11225
|
+
// we pass a dummy connectorUrl (unused at runtime — BTP transport is used);
|
|
11226
|
+
// when a proxy is configured, `proxyUrl` satisfies the requirement and the
|
|
11227
|
+
// client derives the `POST /ilp` endpoint + routes writes over HTTP.
|
|
11228
|
+
...proxyUrl ? { proxyUrl } : { connectorUrl: "http://127.0.0.1:1" },
|
|
11229
|
+
...faucetUrl ? { faucetUrl } : {},
|
|
11301
11230
|
mnemonic,
|
|
11302
11231
|
mnemonicAccountIndex: file.mnemonicAccountIndex ?? 0,
|
|
11303
11232
|
ilpInfo: {
|
|
11304
11233
|
pubkey: "00".repeat(32),
|
|
11305
11234
|
ilpAddress: "g.toon.client",
|
|
11306
|
-
btpEndpoint: btpUrl,
|
|
11235
|
+
btpEndpoint: btpUrl ?? "",
|
|
11307
11236
|
assetCode: "USD",
|
|
11308
11237
|
assetScale: 6
|
|
11309
11238
|
},
|
|
11310
11239
|
toonEncoder: encodeEventToToon,
|
|
11311
11240
|
toonDecoder: decodeEventFromToon,
|
|
11312
|
-
btpUrl,
|
|
11313
|
-
btpAuthToken: "",
|
|
11314
|
-
transport,
|
|
11315
|
-
managedAnonProxy,
|
|
11316
|
-
...managedAnonSocksPort !== void 0 ? { managedAnonSocksPort } : {},
|
|
11241
|
+
...btpUrl ? { btpUrl, btpAuthToken: "" } : {},
|
|
11317
11242
|
destinationAddress: destination,
|
|
11318
11243
|
relayUrl: "",
|
|
11319
11244
|
// reads use our own RelaySubscription, not bootstrap discovery
|
|
@@ -11331,12 +11256,12 @@ function resolveConfig(file) {
|
|
|
11331
11256
|
return {
|
|
11332
11257
|
httpPort,
|
|
11333
11258
|
relayUrl,
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
...
|
|
11259
|
+
hasUplink,
|
|
11260
|
+
...proxyUrl ? { proxyUrl } : {},
|
|
11261
|
+
...faucetUrl ? { faucetUrl } : {},
|
|
11337
11262
|
destination,
|
|
11338
11263
|
feePerEvent,
|
|
11339
|
-
apex,
|
|
11264
|
+
...apex ? { apex } : {},
|
|
11340
11265
|
...file.apexChildPeers ? { apexChildPeers: file.apexChildPeers } : {},
|
|
11341
11266
|
chain: chain2,
|
|
11342
11267
|
apexChannelStorePath,
|
|
@@ -11344,12 +11269,38 @@ function resolveConfig(file) {
|
|
|
11344
11269
|
network
|
|
11345
11270
|
};
|
|
11346
11271
|
}
|
|
11347
|
-
function
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11272
|
+
function defaultChainKey(chain2, chainId) {
|
|
11273
|
+
switch (chain2) {
|
|
11274
|
+
case "evm":
|
|
11275
|
+
return `evm:devnet:${chainId}`;
|
|
11276
|
+
case "solana":
|
|
11277
|
+
return "solana:devnet";
|
|
11278
|
+
case "mina":
|
|
11279
|
+
return "mina:devnet";
|
|
11280
|
+
}
|
|
11281
|
+
}
|
|
11282
|
+
function buildProxyApexNegotiation(file, chain2, destination) {
|
|
11283
|
+
const proxyUrl = process.env["TOON_CLIENT_PROXY_URL"] ?? file.proxyUrl;
|
|
11284
|
+
if (!proxyUrl) return void 0;
|
|
11285
|
+
const settlementAddresses = file.settlementAddresses ?? {};
|
|
11286
|
+
const familyKeys = (rec) => Object.keys(rec).filter((k) => k.split(":")[0] === chain2);
|
|
11287
|
+
const chainKey = familyKeys(settlementAddresses)[0] ?? familyKeys(file.tokenNetworks ?? {})[0] ?? familyKeys(file.preferredTokens ?? {})[0];
|
|
11288
|
+
if (!chainKey) return void 0;
|
|
11289
|
+
const settlementAddress = settlementAddresses[chainKey];
|
|
11290
|
+
if (!settlementAddress) return void 0;
|
|
11291
|
+
const parts = chainKey.split(":");
|
|
11292
|
+
const chainId = chain2 === "evm" && parts.length >= 3 ? Number(parts[2] ?? 0) : 0;
|
|
11293
|
+
const peerId = destination.split(".").at(-1) ?? destination;
|
|
11294
|
+
return {
|
|
11295
|
+
destination,
|
|
11296
|
+
peerId,
|
|
11297
|
+
chain: chain2,
|
|
11298
|
+
chainKey: chainKey || defaultChainKey(chain2, chainId),
|
|
11299
|
+
chainId,
|
|
11300
|
+
settlementAddress,
|
|
11301
|
+
...file.preferredTokens?.[chainKey] ? { tokenAddress: file.preferredTokens[chainKey] } : {},
|
|
11302
|
+
...file.tokenNetworks?.[chainKey] ? { tokenNetwork: file.tokenNetworks[chainKey] } : {}
|
|
11303
|
+
};
|
|
11353
11304
|
}
|
|
11354
11305
|
|
|
11355
11306
|
// src/control-client.ts
|
|
@@ -11627,4 +11578,4 @@ export {
|
|
|
11627
11578
|
@scure/bip32/lib/esm/index.js:
|
|
11628
11579
|
(*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
11629
11580
|
*/
|
|
11630
|
-
//# sourceMappingURL=chunk-
|
|
11581
|
+
//# sourceMappingURL=chunk-CQ2QIZ6Z.js.map
|