@toon-protocol/client 0.20.1 → 0.20.3

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/dist/index.d.ts CHANGED
@@ -107,6 +107,8 @@ interface WalletBalanceSources {
107
107
  chainKey?: string;
108
108
  graphqlUrl: string;
109
109
  owner: string;
110
+ /** Settlement-token Field id (decimal). Reads the token balance when set. */
111
+ tokenId?: string;
110
112
  };
111
113
  /** Injectable fetch (Solana/Mina JSON-RPC & GraphQL) for tests. */
112
114
  fetchImpl?: typeof fetch;
@@ -427,7 +429,7 @@ interface ToonClientConfig {
427
429
  }>;
428
430
  /** File path for persisting payment channel nonce/amount state across restarts */
429
431
  channelStorePath?: string;
430
- /** Nostr relay URL for peer discovery. Default: 'ws://localhost:7100' */
432
+ /** Nostr relay URL for peer discovery. Default: 'wss://relay-ws.devnet.toonprotocol.dev' */
431
433
  relayUrl?: string;
432
434
  /**
433
435
  * Known peers to bootstrap with.
@@ -3932,17 +3934,21 @@ declare function buildSettlementInfo(rawConfig: ToonClientConfig): ClientSettlem
3932
3934
  /**
3933
3935
  * Devnet faucet helper.
3934
3936
  *
3935
- * The deployed TOON devnet exposes a faucet that drips test funds to a given
3936
- * chain address so a client can open payment channels and pay for writes:
3937
+ * The deployed TOON devnet exposes a faucet that drips the settlement token
3938
+ * (USDC) to a given chain address so a client can open payment channels and pay
3939
+ * for writes. This helper hits the USDC-ONLY faucet legs — it funds USDC and
3940
+ * assumes the wallet already holds enough native gas to transact:
3937
3941
  *
3938
- * EVM `POST {faucetUrl}/api/request` body `{ address }` → 100 ETH + 10k USDC
3939
- * Solana `POST {faucetUrl}/api/solana/request` body `{ address }` → SOL + USDC
3940
- * Mina `POST {faucetUrl}/api/mina/request` body `{ address }` → native MINA + USDC
3942
+ * EVM `POST {faucetUrl}/api/base-sepolia/request` body `{ address }` → USDC (Base Sepolia mint)
3943
+ * Solana `POST {faucetUrl}/api/solana/usdc-request` body `{ address }` → USDC (no SOL leg)
3944
+ * Mina `POST {faucetUrl}/api/mina/usdc-request` body `{ address }` → USDC (no MINA leg)
3941
3945
  *
3942
3946
  * Devnet edge (today): `https://faucet.devnet.toonprotocol.dev`.
3943
3947
  *
3944
3948
  * All three chains are live on the deployed faucet — the request shape is
3945
- * identical (`{ address }`); only the path differs.
3949
+ * identical (`{ address }`); only the path differs. (The EVM leg mints the
3950
+ * ungated mock USDC on Base Sepolia and best-effort tops up gas; the Solana and
3951
+ * Mina legs are strictly USDC-only and expect the address to already hold gas.)
3946
3952
  */
3947
3953
  /** Supported faucet chains. */
3948
3954
  type FaucetChain = 'evm' | 'solana' | 'mina';
@@ -3969,12 +3975,12 @@ interface FundWalletOptions {
3969
3975
  /**
3970
3976
  * Default faucet request timeout (ms) for a chain.
3971
3977
  *
3972
- * EVM and Solana faucets respond in a few seconds, so 30s is plenty. The Mina
3973
- * faucet sends native MINA *and* mints USDC on a chain that settles much more
3974
- * slowly: the drip routinely succeeds server-side (the faucet logs
3975
- * `✅ Mina faucet request completed`) but takes well over 30s to answer the
3976
- * HTTP request, so a flat 30s budget makes the client give up on a request that
3977
- * actually worked. Give mina a much longer budget.
3978
+ * The EVM (Base Sepolia mint) and Solana USDC legs respond in a few seconds, so
3979
+ * 30s is plenty. The Mina USDC leg TRANSFERS the token via an o1js-proven
3980
+ * transaction on a chain that settles much more slowly: the drip routinely
3981
+ * succeeds server-side but takes well over 30s to answer the HTTP request, so a
3982
+ * flat 30s budget makes the client give up on a request that actually worked.
3983
+ * Give mina a much longer budget.
3978
3984
  */
3979
3985
  declare function defaultFaucetTimeout(chain: FaucetChain): number;
3980
3986
  /**
package/dist/index.js CHANGED
@@ -470,7 +470,10 @@ function applyDefaults(rawConfig) {
470
470
  connectorUrl,
471
471
  // Surface the derived `POST /ilp` endpoint so HTTP mode selects HttpIlpClient.
472
472
  ...connectorHttpEndpoint ? { connectorHttpEndpoint } : {},
473
- relayUrl: config.relayUrl ?? "ws://localhost:7100",
473
+ // Last-resort relay default. An explicit `config.relayUrl` always wins;
474
+ // `applyNetworkPresets` does not set a per-network relay, so this fallback
475
+ // points at the public devnet relay rather than a dead localhost socket.
476
+ relayUrl: config.relayUrl ?? "wss://relay-ws.devnet.toonprotocol.dev",
474
477
  queryTimeout: config.queryTimeout ?? 3e4,
475
478
  maxRetries: config.maxRetries ?? 3,
476
479
  retryDelay: config.retryDelay ?? 1e3,
@@ -4056,6 +4059,7 @@ var JsonFileChannelStore = class {
4056
4059
 
4057
4060
  // src/balance/WalletBalanceReader.ts
4058
4061
  import { createPublicClient as createPublicClient2, http as http2, defineChain as defineChain2 } from "viem";
4062
+ import { sha256 as sha2564 } from "@noble/hashes/sha2.js";
4059
4063
  var ERC20_READ_ABI = [
4060
4064
  { name: "balanceOf", type: "function", stateMutability: "view", inputs: [{ name: "account", type: "address" }], outputs: [{ type: "uint256" }] },
4061
4065
  { name: "decimals", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
@@ -4170,6 +4174,62 @@ async function readMinaBalance(opts) {
4170
4174
  assetScale: 9
4171
4175
  };
4172
4176
  }
4177
+ var BASE58_ALPHABET2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
4178
+ function base58encode(bytes) {
4179
+ let num = 0n;
4180
+ for (const b of bytes) num = num * 256n + BigInt(b);
4181
+ let out = "";
4182
+ while (num > 0n) {
4183
+ out = BASE58_ALPHABET2[Number(num % 58n)] + out;
4184
+ num /= 58n;
4185
+ }
4186
+ for (const b of bytes) {
4187
+ if (b === 0) out = "1" + out;
4188
+ else break;
4189
+ }
4190
+ return out;
4191
+ }
4192
+ function minaTokenIdToBase58(tokenId) {
4193
+ if (!/^\d+$/.test(tokenId)) {
4194
+ throw new Error(`Mina tokenId must be a decimal Field string: "${tokenId}"`);
4195
+ }
4196
+ let field = BigInt(tokenId);
4197
+ const le = new Uint8Array(32);
4198
+ for (let i = 0; i < 32; i++) {
4199
+ le[i] = Number(field & 0xffn);
4200
+ field >>= 8n;
4201
+ }
4202
+ const body = new Uint8Array(1 + 32);
4203
+ body[0] = 28;
4204
+ body.set(le, 1);
4205
+ const checksum = sha2564(sha2564(body)).slice(0, 4);
4206
+ const raw = new Uint8Array(body.length + 4);
4207
+ raw.set(body, 0);
4208
+ raw.set(checksum, body.length);
4209
+ return base58encode(raw);
4210
+ }
4211
+ async function readMinaTokenBalance(opts) {
4212
+ const fetchImpl = opts.fetchImpl ?? fetch;
4213
+ const token = minaTokenIdToBase58(opts.tokenId);
4214
+ const query = "query($pk:PublicKey!,$t:TokenId){account(publicKey:$pk,token:$t){balance{total}}}";
4215
+ const res = await fetchImpl(opts.graphqlUrl, {
4216
+ method: "POST",
4217
+ headers: { "content-type": "application/json" },
4218
+ body: JSON.stringify({ query, variables: { pk: opts.owner, t: token } })
4219
+ });
4220
+ if (!res.ok) throw new Error(`Mina GraphQL request failed: HTTP ${res.status}`);
4221
+ const json = await res.json();
4222
+ if (json.errors && json.errors.length > 0) {
4223
+ throw new Error(`Mina GraphQL error: ${json.errors[0]?.message ?? "unknown"}`);
4224
+ }
4225
+ return {
4226
+ chain: "mina",
4227
+ address: opts.owner,
4228
+ amount: String(json.data?.account?.balance?.total ?? "0"),
4229
+ asset: "USDC",
4230
+ assetScale: 9
4231
+ };
4232
+ }
4173
4233
  var errText = (e) => e instanceof Error ? e.message : String(e);
4174
4234
  function foldNative(out, settled, errors) {
4175
4235
  if (settled.status === "fulfilled") out.native = settled.value;
@@ -4234,24 +4294,28 @@ async function readWalletBalances(sources) {
4234
4294
  );
4235
4295
  }
4236
4296
  if (sources.mina) {
4237
- const { chainKey = "mina", graphqlUrl, owner } = sources.mina;
4297
+ const { chainKey = "mina", graphqlUrl, owner, tokenId } = sources.mina;
4238
4298
  tasks.push(
4239
4299
  (async () => {
4240
4300
  const out = { chain: "mina", chainKey, address: owner, tokens: [] };
4241
4301
  const errors = [];
4242
- const nativeR = await Promise.allSettled([readMinaBalance({ graphqlUrl, owner, fetchImpl })]);
4302
+ const [nativeR, tokenR] = await Promise.allSettled([
4303
+ readMinaBalance({ graphqlUrl, owner, fetchImpl }),
4304
+ tokenId ? readMinaTokenBalance({ graphqlUrl, owner, tokenId, fetchImpl }) : Promise.resolve(void 0)
4305
+ ]);
4243
4306
  foldNative(
4244
4307
  out,
4245
- nativeR[0].status === "fulfilled" ? {
4308
+ nativeR.status === "fulfilled" ? {
4246
4309
  status: "fulfilled",
4247
4310
  value: {
4248
- symbol: nativeR[0].value.asset,
4249
- amount: nativeR[0].value.amount,
4250
- decimals: nativeR[0].value.assetScale
4311
+ symbol: nativeR.value.asset,
4312
+ amount: nativeR.value.amount,
4313
+ decimals: nativeR.value.assetScale
4251
4314
  }
4252
- } : nativeR[0],
4315
+ } : nativeR,
4253
4316
  errors
4254
4317
  );
4318
+ foldToken(out, tokenR, void 0, errors);
4255
4319
  finalizeChain(out, errors);
4256
4320
  return out;
4257
4321
  })()
@@ -5935,7 +5999,12 @@ var ToonClient = class {
5935
5999
  if (mina?.graphqlUrl) {
5936
6000
  const minaAddress = this.getMinaAddress() ?? (await ensureDerived())?.mina.publicKey;
5937
6001
  if (minaAddress) {
5938
- sources.mina = { chainKey: "mina", graphqlUrl: mina.graphqlUrl, owner: minaAddress };
6002
+ sources.mina = {
6003
+ chainKey: "mina",
6004
+ graphqlUrl: mina.graphqlUrl,
6005
+ owner: minaAddress,
6006
+ ...mina.tokenId ? { tokenId: mina.tokenId } : {}
6007
+ };
5939
6008
  }
5940
6009
  }
5941
6010
  return readWalletBalances(sources);
@@ -6868,11 +6937,11 @@ function defaultFaucetTimeout(chain) {
6868
6937
  function faucetPath(chain) {
6869
6938
  switch (chain) {
6870
6939
  case "evm":
6871
- return "/api/request";
6940
+ return "/api/base-sepolia/request";
6872
6941
  case "solana":
6873
- return "/api/solana/request";
6942
+ return "/api/solana/usdc-request";
6874
6943
  case "mina":
6875
- return "/api/mina/request";
6944
+ return "/api/mina/usdc-request";
6876
6945
  }
6877
6946
  }
6878
6947
  async function fundWallet(faucetUrl, address, chain, options = {}) {