@toon-protocol/client-mcp 0.9.0 → 0.10.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.
@@ -1173,7 +1173,7 @@ var BootstrapService = class {
1173
1173
  };
1174
1174
  console.log(`[Bootstrap] Query filter:`, JSON.stringify(filter));
1175
1175
  console.log(`[Bootstrap] Connecting to ${knownPeer.relayUrl}...`);
1176
- return new Promise((resolve, reject) => {
1176
+ return new Promise((resolve2, reject) => {
1177
1177
  const events = [];
1178
1178
  const timeout = this.config.queryTimeout ?? 5e3;
1179
1179
  const ws = new WebSocket22(knownPeer.relayUrl);
@@ -1267,7 +1267,7 @@ var BootstrapService = class {
1267
1267
  const peerInfo = parseIlpPeerInfo(
1268
1268
  mostRecent
1269
1269
  );
1270
- resolve(peerInfo);
1270
+ resolve2(peerInfo);
1271
1271
  } catch (error) {
1272
1272
  reject(
1273
1273
  new BootstrapError(
@@ -1314,7 +1314,7 @@ var BootstrapService = class {
1314
1314
  const peerInfo = parseIlpPeerInfo(
1315
1315
  mostRecent
1316
1316
  );
1317
- resolve(peerInfo);
1317
+ resolve2(peerInfo);
1318
1318
  } catch (error) {
1319
1319
  reject(
1320
1320
  new BootstrapError(
@@ -7021,7 +7021,7 @@ async function withRetry(operation, options) {
7021
7021
  throw lastError;
7022
7022
  }
7023
7023
  const currentDelay = exponentialBackoff ? Math.min(retryDelay * Math.pow(2, attempt), maxDelay) : retryDelay;
7024
- await new Promise((resolve) => setTimeout(resolve, currentDelay));
7024
+ await new Promise((resolve2) => setTimeout(resolve2, currentDelay));
7025
7025
  }
7026
7026
  }
7027
7027
  throw lastError ?? new Error("Unknown error during retry");
@@ -7429,7 +7429,7 @@ var IsomorphicBtpClient = class {
7429
7429
  }
7430
7430
  async connect() {
7431
7431
  if (this._isConnected) return;
7432
- return new Promise((resolve, reject) => {
7432
+ return new Promise((resolve2, reject) => {
7433
7433
  try {
7434
7434
  this.ws = this.config.createWebSocket ? this.config.createWebSocket(this.config.url) : new WebSocket(this.config.url);
7435
7435
  this.ws.binaryType = "arraybuffer";
@@ -7445,7 +7445,7 @@ var IsomorphicBtpClient = class {
7445
7445
  try {
7446
7446
  await this.authenticate();
7447
7447
  this._isConnected = true;
7448
- resolve();
7448
+ resolve2();
7449
7449
  } catch (err) {
7450
7450
  this._isConnected = false;
7451
7451
  this.ws?.close();
@@ -7510,12 +7510,12 @@ var IsomorphicBtpClient = class {
7510
7510
  const remaining = packet.expiresAt.getTime() - Date.now();
7511
7511
  timeoutMs = Math.max(remaining - 500, 1e3);
7512
7512
  }
7513
- return new Promise((resolve, reject) => {
7513
+ return new Promise((resolve2, reject) => {
7514
7514
  const timeoutId = setTimeout(() => {
7515
7515
  this.pendingRequests.delete(requestId);
7516
7516
  reject(new BtpConnectionError(`Packet send timeout (${timeoutMs}ms)`));
7517
7517
  }, timeoutMs);
7518
- this.pendingRequests.set(requestId, { resolve, reject, timeoutId });
7518
+ this.pendingRequests.set(requestId, { resolve: resolve2, reject, timeoutId });
7519
7519
  });
7520
7520
  }
7521
7521
  /**
@@ -7564,7 +7564,7 @@ var IsomorphicBtpClient = class {
7564
7564
  ilpPacket: new Uint8Array(0)
7565
7565
  }
7566
7566
  });
7567
- return new Promise((resolve, reject) => {
7567
+ return new Promise((resolve2, reject) => {
7568
7568
  const timeout = setTimeout(() => {
7569
7569
  reject(new BtpAuthError("Authentication timeout"));
7570
7570
  }, this.config.authTimeoutMs);
@@ -7590,7 +7590,7 @@ var IsomorphicBtpClient = class {
7590
7590
  )
7591
7591
  );
7592
7592
  } else if (message.type === BTPMessageType.RESPONSE) {
7593
- resolve();
7593
+ resolve2();
7594
7594
  }
7595
7595
  }
7596
7596
  } catch (err) {
@@ -8445,29 +8445,44 @@ async function openSolanaChannel(params) {
8445
8445
  ]);
8446
8446
  let depositTxSignature;
8447
8447
  if (params.deposit && params.deposit.amount > 0n) {
8448
- const depositData = new Uint8Array(16);
8449
- depositData.set(IX_DEPOSIT, 0);
8450
- writeU64LE(depositData, 8, params.deposit.amount);
8451
- depositTxSignature = await buildAndSendTransaction(rpcUrl, payer, [
8452
- {
8453
- programId,
8454
- keys: [
8455
- { pubkey: payerPubkey, isSigner: true, isWritable: false },
8456
- {
8457
- pubkey: params.deposit.payerTokenAccount,
8458
- isSigner: false,
8459
- isWritable: true
8460
- },
8461
- { pubkey: vaultPDA, isSigner: false, isWritable: true },
8462
- { pubkey: channelPDA, isSigner: false, isWritable: true },
8463
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }
8464
- ],
8465
- data: depositData
8466
- }
8467
- ]);
8448
+ ({ depositTxSignature } = await depositSolanaChannel({
8449
+ rpcUrl,
8450
+ programId,
8451
+ channelPDA,
8452
+ payerSeed,
8453
+ payerPubkey,
8454
+ payerTokenAccount: params.deposit.payerTokenAccount,
8455
+ amount: params.deposit.amount
8456
+ }));
8468
8457
  }
8469
8458
  return { channelPDA, opened: true, initTxSignature, depositTxSignature };
8470
8459
  }
8460
+ async function depositSolanaChannel(params) {
8461
+ const { rpcUrl, programId, channelPDA, payerSeed, payerPubkey, payerTokenAccount, amount } = params;
8462
+ if (amount <= 0n) throw new Error("Solana deposit amount must be positive.");
8463
+ const payer = {
8464
+ publicKey: padTo32(base58Decode(payerPubkey)),
8465
+ privateKey: payerSeed
8466
+ };
8467
+ const { pda: vaultPDA } = deriveVaultPDA(channelPDA, programId);
8468
+ const depositData = new Uint8Array(16);
8469
+ depositData.set(IX_DEPOSIT, 0);
8470
+ writeU64LE(depositData, 8, amount);
8471
+ const depositTxSignature = await buildAndSendTransaction(rpcUrl, payer, [
8472
+ {
8473
+ programId,
8474
+ keys: [
8475
+ { pubkey: payerPubkey, isSigner: true, isWritable: false },
8476
+ { pubkey: payerTokenAccount, isSigner: false, isWritable: true },
8477
+ { pubkey: vaultPDA, isSigner: false, isWritable: true },
8478
+ { pubkey: channelPDA, isSigner: false, isWritable: true },
8479
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }
8480
+ ],
8481
+ data: depositData
8482
+ }
8483
+ ]);
8484
+ return { depositTxSignature };
8485
+ }
8471
8486
  var cachedO1js = null;
8472
8487
  var cachedPaymentChannel = null;
8473
8488
  var compiledContract = null;
@@ -8815,6 +8830,101 @@ var OnChainChannelClient = class {
8815
8830
  if (chainPrefix === "mina") return this.openMinaChannel(params);
8816
8831
  return this.openEvmChannel(params);
8817
8832
  }
8833
+ /**
8834
+ * Deposit additional collateral into an already-open channel. `amount` is the
8835
+ * DELTA to add (base units). Dispatches by the channel's cached chain context;
8836
+ * `currentDeposit` is the channel's current locked total (tracked off-chain by
8837
+ * the caller) — required for EVM, whose `setTotalDeposit` takes the new
8838
+ * cumulative total, not a delta. Returns the new on-chain deposit total.
8839
+ *
8840
+ * Non-custodial: the client deposits its OWN funds and signs its OWN tx.
8841
+ * EVM is live; Solana/Mina deposit extraction is a follow-up (PR B.1).
8842
+ */
8843
+ async depositToChannel(channelId, amount, opts) {
8844
+ if (amount <= 0n) throw new Error("Deposit amount must be positive.");
8845
+ const ctx = this.channelContext.get(channelId);
8846
+ if (!ctx) {
8847
+ throw new Error(
8848
+ `No on-chain context for channel "${channelId}" \u2014 it must be opened by this client first.`
8849
+ );
8850
+ }
8851
+ const chainPrefix = ctx.chain.split(":")[0];
8852
+ if (chainPrefix === "solana") {
8853
+ return this.depositSolana(channelId, amount, opts.currentDeposit);
8854
+ }
8855
+ if (chainPrefix === "mina") {
8856
+ throw new Error("Deposit on mina is not yet supported (EVM + Solana today; Mina follow-up).");
8857
+ }
8858
+ return this.depositEvm(channelId, amount, opts.currentDeposit, ctx);
8859
+ }
8860
+ /**
8861
+ * Solana deposit: fire the standalone `deposit` instruction against the channel
8862
+ * vault. Incremental on-chain (the program adds `amount`), so the new total is
8863
+ * the caller-tracked current plus the delta. Requires the funded payer token
8864
+ * account (the funded ATA) from the Solana channel config.
8865
+ */
8866
+ async depositSolana(channelId, amount, currentDeposit) {
8867
+ if (!this.solanaConfig) {
8868
+ throw new Error("Solana channel config not set \u2014 cannot deposit.");
8869
+ }
8870
+ const cfg = this.solanaConfig;
8871
+ const payerTokenAccount = cfg.deposit?.payerTokenAccount;
8872
+ if (!payerTokenAccount) {
8873
+ throw new Error(
8874
+ "Solana deposit requires solanaConfig.deposit.payerTokenAccount (the funded SPL token account)."
8875
+ );
8876
+ }
8877
+ const payerSeed = cfg.keypair.slice(0, 32);
8878
+ const payerPubkey = base58Encode(new Uint8Array(ed25519.getPublicKey(payerSeed)));
8879
+ const { depositTxSignature } = await depositSolanaChannel({
8880
+ rpcUrl: cfg.rpcUrl,
8881
+ programId: cfg.programId,
8882
+ channelPDA: channelId,
8883
+ payerSeed,
8884
+ payerPubkey,
8885
+ payerTokenAccount,
8886
+ amount
8887
+ });
8888
+ return { txHash: depositTxSignature, depositTotal: currentDeposit + amount };
8889
+ }
8890
+ /**
8891
+ * EVM deposit: approve the token-network for the delta if the allowance is
8892
+ * short, then `setTotalDeposit(channelId, participant, current + delta)` —
8893
+ * the contract takes the new cumulative total, so we add the delta to the
8894
+ * caller-supplied current locked amount.
8895
+ */
8896
+ async depositEvm(channelId, amount, currentDeposit, ctx) {
8897
+ const { publicClient, walletClient } = this.createClients(ctx.chain);
8898
+ const tokenNetworkAddr = ctx.tokenNetworkAddress;
8899
+ const myAddress = this.evmSigner.address;
8900
+ const newTotal = currentDeposit + amount;
8901
+ if (ctx.tokenAddress) {
8902
+ const tokenAddr = ctx.tokenAddress;
8903
+ const allowance = await publicClient.readContract({
8904
+ address: tokenAddr,
8905
+ abi: ERC20_ABI,
8906
+ functionName: "allowance",
8907
+ args: [myAddress, tokenNetworkAddr]
8908
+ });
8909
+ if (allowance < amount) {
8910
+ const approveHash = await walletClient.writeContract({
8911
+ address: tokenAddr,
8912
+ abi: ERC20_ABI,
8913
+ functionName: "approve",
8914
+ args: [tokenNetworkAddr, maxUint256]
8915
+ });
8916
+ await publicClient.waitForTransactionReceipt({ hash: approveHash });
8917
+ }
8918
+ }
8919
+ const depositHash = await walletClient.writeContract({
8920
+ address: tokenNetworkAddr,
8921
+ abi: TOKEN_NETWORK_ABI,
8922
+ functionName: "setTotalDeposit",
8923
+ args: [channelId, myAddress, newTotal]
8924
+ });
8925
+ await publicClient.waitForTransactionReceipt({ hash: depositHash });
8926
+ return { txHash: depositHash, depositTotal: newTotal };
8927
+ }
8818
8928
  /**
8819
8929
  * Opens a REAL on-chain Solana payment channel.
8820
8930
  *
@@ -9016,7 +9126,8 @@ var OnChainChannelClient = class {
9016
9126
  }
9017
9127
  this.channelContext.set(channelId, {
9018
9128
  chain: chain2,
9019
- tokenNetworkAddress: tokenNetwork
9129
+ tokenNetworkAddress: tokenNetwork,
9130
+ ...params.token ? { tokenAddress: params.token } : {}
9020
9131
  });
9021
9132
  if (deposit > 0n) {
9022
9133
  const depositHash = await walletClient.writeContract({
@@ -9883,6 +9994,18 @@ var ChannelManager = class {
9883
9994
  }
9884
9995
  return tracking.depositTotal ?? 0n;
9885
9996
  }
9997
+ /**
9998
+ * Update the tracked on-chain deposit total after a successful deposit, so the
9999
+ * available balance (`depositTotal - cumulativeAmount`) reflects the new
10000
+ * collateral on the next read.
10001
+ */
10002
+ setDepositTotal(channelId, total) {
10003
+ const tracking = this.channels.get(channelId);
10004
+ if (!tracking) {
10005
+ throw new Error(`Channel "${channelId}" is not being tracked.`);
10006
+ }
10007
+ tracking.depositTotal = total;
10008
+ }
9886
10009
  /**
9887
10010
  * Gets all tracked channel IDs.
9888
10011
  */
@@ -10398,6 +10521,8 @@ var ToonClient = class {
10398
10521
  */
10399
10522
  minaPrivateKey;
10400
10523
  channelManager;
10524
+ /** Concrete on-chain client, kept so deposit/withdraw can reach chain methods. */
10525
+ onChainChannelClient;
10401
10526
  peerNegotiations = /* @__PURE__ */ new Map();
10402
10527
  /**
10403
10528
  * Creates a new ToonClient instance.
@@ -10591,6 +10716,7 @@ var ToonClient = class {
10591
10716
  }
10592
10717
  }
10593
10718
  if (this.channelManager && initialization.onChainChannelClient) {
10719
+ this.onChainChannelClient = initialization.onChainChannelClient;
10594
10720
  this.channelManager.setChannelClient(
10595
10721
  initialization.onChainChannelClient
10596
10722
  );
@@ -11007,6 +11133,31 @@ var ToonClient = class {
11007
11133
  if (!this.channelManager) throw new Error("ChannelManager not initialized");
11008
11134
  return this.channelManager.getDepositTotal(channelId);
11009
11135
  }
11136
+ /**
11137
+ * Deposit additional collateral into an open channel. `amount` is the delta to
11138
+ * add (base units, decimal string or bigint). The daemon signs its own tx; no
11139
+ * key material leaves the client. Reads the current tracked deposit, performs
11140
+ * the on-chain deposit, updates the tracked total, and returns the new total.
11141
+ * EVM is live; Solana/Mina deposit lands in a follow-up.
11142
+ */
11143
+ async depositToChannel(channelId, amount) {
11144
+ if (!this.channelManager) throw new Error("ChannelManager not initialized");
11145
+ if (!this.onChainChannelClient) {
11146
+ throw new Error("On-chain channel client not configured (no chainRpcUrls).");
11147
+ }
11148
+ const delta = BigInt(amount);
11149
+ if (delta <= 0n) throw new Error("Deposit amount must be positive.");
11150
+ const currentDeposit = this.channelManager.getDepositTotal(channelId);
11151
+ const result = await this.onChainChannelClient.depositToChannel(channelId, delta, {
11152
+ currentDeposit
11153
+ });
11154
+ this.channelManager.setDepositTotal(channelId, result.depositTotal);
11155
+ return {
11156
+ channelId,
11157
+ ...result.txHash ? { txHash: result.txHash } : {},
11158
+ depositTotal: result.depositTotal.toString()
11159
+ };
11160
+ }
11010
11161
  /**
11011
11162
  * Read the on-chain settlement-token balance of this client's OWN wallet on
11012
11163
  * each configured chain (EVM token, Solana SPL, native MINA). A free read — no
@@ -11377,7 +11528,7 @@ function writeKeystoreFile(path, keystore) {
11377
11528
  // src/daemon/config.ts
11378
11529
  import { readFileSync as readFileSync3 } from "fs";
11379
11530
  import { homedir } from "os";
11380
- import { join as join2 } from "path";
11531
+ import { join as join2, resolve } from "path";
11381
11532
 
11382
11533
  // ../../node_modules/.pnpm/@toon-protocol+core@1.4.2_@toon-protocol+connector@3.13.0_typescript@5.9.3/node_modules/@toon-protocol/core/dist/chunk-5WT7ISKC.js
11383
11534
  import { encode as encode2 } from "@toon-format/toon";
@@ -12008,6 +12159,8 @@ function resolveConfig(file) {
12008
12159
  const storeDestination = process.env["TOON_CLIENT_STORE_DESTINATION"] ?? file.storeDestination ?? routes.store;
12009
12160
  const feePerEvent = BigInt(file.feePerEvent ?? "1");
12010
12161
  const arweaveGateways = parseCsvEnv(process.env["TOON_CLIENT_ARWEAVE_GATEWAYS"]) ?? file.arweaveGateways ?? [...ARWEAVE_GATEWAYS];
12162
+ const uploadRoot = process.env["TOON_CLIENT_UPLOAD_ROOT"] ?? file.uploadAllowedRoot;
12163
+ const uploadAllowedRoot = uploadRoot ? resolve(uploadRoot) : void 0;
12011
12164
  const network = process.env["TOON_CLIENT_NETWORK"] ?? file.network;
12012
12165
  const chain2 = process.env["TOON_CLIENT_CHAIN"] ?? file.chain ?? "evm";
12013
12166
  const apex = file.apexChains?.[chain2] ?? file.apex ?? buildProxyApexNegotiation(file, chain2, destination);
@@ -12063,7 +12216,8 @@ function resolveConfig(file) {
12063
12216
  apexChannelStorePath,
12064
12217
  toonClientConfig,
12065
12218
  network,
12066
- arweaveGateways
12219
+ arweaveGateways,
12220
+ ...uploadAllowedRoot ? { uploadAllowedRoot } : {}
12067
12221
  };
12068
12222
  }
12069
12223
  function defaultChainKey(chain2, chainId) {
@@ -12178,6 +12332,9 @@ var ControlClient = class {
12178
12332
  balances() {
12179
12333
  return this.request("GET", "/balances");
12180
12334
  }
12335
+ depositToChannel(body) {
12336
+ return this.request("POST", "/channels/deposit", body);
12337
+ }
12181
12338
  swap(body) {
12182
12339
  return this.request("POST", "/swap", body);
12183
12340
  }
@@ -12383,4 +12540,4 @@ export {
12383
12540
  @scure/bip32/lib/esm/index.js:
12384
12541
  (*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
12385
12542
  */
12386
- //# sourceMappingURL=chunk-ZVFLRFXS.js.map
12543
+ //# sourceMappingURL=chunk-5Z74D23J.js.map