@piprail/sdk 2.0.0 → 2.0.2

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.cts CHANGED
@@ -4349,7 +4349,7 @@ interface ResolvedNetwork {
4349
4349
  reason?: RecipientReason;
4350
4350
  }>;
4351
4351
  /**
4352
- * OPTIONAL (EVM + EIP-3009 only) — the BUYER counterpart to {@link settleExactSelf}.
4352
+ * OPTIONAL (EVM EIP-3009/Permit2 + Solana SVM) — the BUYER counterpart to {@link settleExactSelf}.
4353
4353
  * Build + EIP-712-sign an EIP-3009 `transferWithAuthorization` for a standard x402
4354
4354
  * `exact` rail, so a PipRail agent can PAY any standard x402 server (not just PipRail's
4355
4355
  * own `onchain-proof` gates). The client frames the returned `payload` + `accepted` echo
@@ -4881,7 +4881,7 @@ type PipRailEvent = {
4881
4881
  * Wallet for the chosen chain family. **One field, every chain: `{ key }`** — the
4882
4882
  * chain's secret as a string (the `chain` selector routes; each driver validates the
4883
4883
  * format). NEAR also needs `{ accountId }`. What `key` is, per chain:
4884
- * - EVM / Tron → a 0x… hex private key (secp256k1)
4884
+ * - EVM / Tron → a 0x… hex private key (secp256k1; Tron also accepts it without the 0x prefix)
4885
4885
  * - Sui → a `suiprivkey1…` bech32 secret
4886
4886
  * - Aptos → an AIP-80 `ed25519-priv-0x…` (or raw `0x…`) secret
4887
4887
  * - Solana → a base58 secret key (or a `Uint8Array`)
@@ -5226,6 +5226,15 @@ declare class PipRailClient {
5226
5226
  private readonly ledger;
5227
5227
  private bound?;
5228
5228
  constructor(opts: PipRailClientOptions);
5229
+ /**
5230
+ * Fail LOUDLY at construction on a malformed amount cap — a security boundary
5231
+ * must never silently half-arm, and a misconfigured cap is a programmer error
5232
+ * (→ `TypeError`, no new SDK code). Each cap (`maxAmount` / `maxTotal` /
5233
+ * `windowTotal`) must be a non-negative decimal STRING (the same grammar
5234
+ * {@link floorUnits} accepts), so a typo like `'0.01abc'` fails fast here instead
5235
+ * of lazily throwing a raw `floorUnits` error out of the never-throw read methods.
5236
+ */
5237
+ private assertPolicyAmountCaps;
5229
5238
  /**
5230
5239
  * Fail LOUDLY at construction on a misconfigured time policy — a security
5231
5240
  * boundary must never silently half-arm. Two invariants (a misconfiguration is
package/dist/index.d.ts CHANGED
@@ -4349,7 +4349,7 @@ interface ResolvedNetwork {
4349
4349
  reason?: RecipientReason;
4350
4350
  }>;
4351
4351
  /**
4352
- * OPTIONAL (EVM + EIP-3009 only) — the BUYER counterpart to {@link settleExactSelf}.
4352
+ * OPTIONAL (EVM EIP-3009/Permit2 + Solana SVM) — the BUYER counterpart to {@link settleExactSelf}.
4353
4353
  * Build + EIP-712-sign an EIP-3009 `transferWithAuthorization` for a standard x402
4354
4354
  * `exact` rail, so a PipRail agent can PAY any standard x402 server (not just PipRail's
4355
4355
  * own `onchain-proof` gates). The client frames the returned `payload` + `accepted` echo
@@ -4881,7 +4881,7 @@ type PipRailEvent = {
4881
4881
  * Wallet for the chosen chain family. **One field, every chain: `{ key }`** — the
4882
4882
  * chain's secret as a string (the `chain` selector routes; each driver validates the
4883
4883
  * format). NEAR also needs `{ accountId }`. What `key` is, per chain:
4884
- * - EVM / Tron → a 0x… hex private key (secp256k1)
4884
+ * - EVM / Tron → a 0x… hex private key (secp256k1; Tron also accepts it without the 0x prefix)
4885
4885
  * - Sui → a `suiprivkey1…` bech32 secret
4886
4886
  * - Aptos → an AIP-80 `ed25519-priv-0x…` (or raw `0x…`) secret
4887
4887
  * - Solana → a base58 secret key (or a `Uint8Array`)
@@ -5226,6 +5226,15 @@ declare class PipRailClient {
5226
5226
  private readonly ledger;
5227
5227
  private bound?;
5228
5228
  constructor(opts: PipRailClientOptions);
5229
+ /**
5230
+ * Fail LOUDLY at construction on a malformed amount cap — a security boundary
5231
+ * must never silently half-arm, and a misconfigured cap is a programmer error
5232
+ * (→ `TypeError`, no new SDK code). Each cap (`maxAmount` / `maxTotal` /
5233
+ * `windowTotal`) must be a non-negative decimal STRING (the same grammar
5234
+ * {@link floorUnits} accepts), so a typo like `'0.01abc'` fails fast here instead
5235
+ * of lazily throwing a raw `floorUnits` error out of the never-throw read methods.
5236
+ */
5237
+ private assertPolicyAmountCaps;
5229
5238
  /**
5230
5239
  * Fail LOUDLY at construction on a misconfigured time policy — a security
5231
5240
  * boundary must never silently half-arm. Two invariants (a misconfiguration is
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  parseUnits,
25
25
  rejectForeignToken,
26
26
  toInsufficientFundsError
27
- } from "./chunk-47VEOHZN.js";
27
+ } from "./chunk-7XK22JSQ.js";
28
28
 
29
29
  // src/drivers/registry.ts
30
30
  var byFamily = /* @__PURE__ */ new Map();
@@ -322,7 +322,21 @@ import { privateKeyToAccount } from "viem/accounts";
322
322
  function createWalletAdapter(config, resolved) {
323
323
  assertNoLegacyWalletKey(config, "EVM");
324
324
  if ("key" in config) {
325
- const account = privateKeyToAccount(config.key);
325
+ const key = config.key;
326
+ if (typeof key !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(key)) {
327
+ const hint = typeof key === "string" && !key.startsWith("0x") ? " (got a non-0x string \u2014 a base58/seed key belongs to another family; pass { key } as the EVM chain's 0x\u2026 hex secret)." : " (expected 0x followed by 64 hex characters).";
328
+ throw new WrongFamilyError(
329
+ `chain is EVM; the wallet { key } is not a valid 0x\u2026 32-byte hex private key${hint}`
330
+ );
331
+ }
332
+ let account;
333
+ try {
334
+ account = privateKeyToAccount(key);
335
+ } catch (err) {
336
+ throw new WrongFamilyError(
337
+ `chain is EVM; the wallet { key } is not a valid 0x\u2026 32-byte hex private key: ${err instanceof Error ? err.message : String(err)}.`
338
+ );
339
+ }
326
340
  const transport = http(resolved.rpcUrl);
327
341
  const walletClient = createWalletClient({ account, chain: resolved.chain, transport });
328
342
  return { account, walletClient };
@@ -1494,6 +1508,7 @@ function isValidChallenge(value) {
1494
1508
  const v = value;
1495
1509
  if (v.x402Version !== 2) return false;
1496
1510
  if (!Array.isArray(v.accepts) || v.accepts.length === 0) return false;
1511
+ if (!v.accepts.every((a) => a !== null && typeof a === "object")) return false;
1497
1512
  if (!v.resource || typeof v.resource !== "object") return false;
1498
1513
  return true;
1499
1514
  }
@@ -1801,7 +1816,7 @@ var loaders = {
1801
1816
  solana: async () => {
1802
1817
  let mod;
1803
1818
  try {
1804
- mod = await import("./solana-DTO2R3AT.js");
1819
+ mod = await import("./solana-E4MD6JJ6.js");
1805
1820
  } catch (cause) {
1806
1821
  throw new MissingDriverError(
1807
1822
  `Solana selected, but its packages aren't installed. Run: npm install @solana/web3.js @solana/spl-token bs58`,
@@ -1813,7 +1828,7 @@ var loaders = {
1813
1828
  ton: async () => {
1814
1829
  let mod;
1815
1830
  try {
1816
- mod = await import("./ton-CPK57L2O.js");
1831
+ mod = await import("./ton-5ZPT5PSP.js");
1817
1832
  } catch (cause) {
1818
1833
  throw new MissingDriverError(
1819
1834
  `TON selected, but its packages aren't installed. Run: npm install @ton/ton @ton/core @ton/crypto`,
@@ -1825,7 +1840,7 @@ var loaders = {
1825
1840
  stellar: async () => {
1826
1841
  let mod;
1827
1842
  try {
1828
- mod = await import("./stellar-T5VONOEO.js");
1843
+ mod = await import("./stellar-U5NCRIOJ.js");
1829
1844
  } catch (cause) {
1830
1845
  throw new MissingDriverError(
1831
1846
  `Stellar selected, but its package isn't installed. Run: npm install @stellar/stellar-sdk`,
@@ -1837,7 +1852,7 @@ var loaders = {
1837
1852
  xrpl: async () => {
1838
1853
  let mod;
1839
1854
  try {
1840
- mod = await import("./xrpl-AH4FFC2C.js");
1855
+ mod = await import("./xrpl-2MZEOIFY.js");
1841
1856
  } catch (cause) {
1842
1857
  throw new MissingDriverError(
1843
1858
  `XRPL selected, but its package isn't installed. Run: npm install xrpl`,
@@ -1849,7 +1864,7 @@ var loaders = {
1849
1864
  tron: async () => {
1850
1865
  let mod;
1851
1866
  try {
1852
- mod = await import("./tron-LZRCDRZC.js");
1867
+ mod = await import("./tron-WYS4X2I5.js");
1853
1868
  } catch (cause) {
1854
1869
  throw new MissingDriverError(
1855
1870
  `Tron selected, but its package isn't installed. Run: npm install tronweb`,
@@ -1861,7 +1876,7 @@ var loaders = {
1861
1876
  sui: async () => {
1862
1877
  let mod;
1863
1878
  try {
1864
- mod = await import("./sui-J53NYMVL.js");
1879
+ mod = await import("./sui-Y53M4GUM.js");
1865
1880
  } catch (cause) {
1866
1881
  throw new MissingDriverError(
1867
1882
  `Sui selected, but its package isn't installed. Run: npm install @mysten/sui`,
@@ -1873,7 +1888,7 @@ var loaders = {
1873
1888
  near: async () => {
1874
1889
  let mod;
1875
1890
  try {
1876
- mod = await import("./near-CHE7B2CY.js");
1891
+ mod = await import("./near-MTYBCUYM.js");
1877
1892
  } catch (cause) {
1878
1893
  throw new MissingDriverError(
1879
1894
  `NEAR selected, but its package isn't installed. Run: npm install near-api-js`,
@@ -1885,7 +1900,7 @@ var loaders = {
1885
1900
  aptos: async () => {
1886
1901
  let mod;
1887
1902
  try {
1888
- mod = await import("./aptos-SMEQXIYJ.js");
1903
+ mod = await import("./aptos-RIL56C7L.js");
1889
1904
  } catch (cause) {
1890
1905
  throw new MissingDriverError(
1891
1906
  `Aptos selected, but its package isn't installed. Run: npm install @aptos-labs/ts-sdk`,
@@ -1897,7 +1912,7 @@ var loaders = {
1897
1912
  algorand: async () => {
1898
1913
  let mod;
1899
1914
  try {
1900
- mod = await import("./algorand-RJ4DRWHV.js");
1915
+ mod = await import("./algorand-GSFVZTBF.js");
1901
1916
  } catch (cause) {
1902
1917
  throw new MissingDriverError(
1903
1918
  `Algorand selected, but its package isn't installed. Run: npm install algosdk`,
@@ -2585,8 +2600,29 @@ var PipRailClient = class {
2585
2600
  this.maxRetries = Math.max(1, opts.maxPaymentRetries ?? 3);
2586
2601
  this.retryTimeoutMs = opts.retryTimeoutMs ?? 3e4;
2587
2602
  this.onEvent = opts.onEvent ?? (() => void 0);
2603
+ this.assertPolicyAmountCaps(opts.policy);
2588
2604
  this.assertPolicyTimeOptions(opts.policy);
2589
2605
  }
2606
+ /**
2607
+ * Fail LOUDLY at construction on a malformed amount cap — a security boundary
2608
+ * must never silently half-arm, and a misconfigured cap is a programmer error
2609
+ * (→ `TypeError`, no new SDK code). Each cap (`maxAmount` / `maxTotal` /
2610
+ * `windowTotal`) must be a non-negative decimal STRING (the same grammar
2611
+ * {@link floorUnits} accepts), so a typo like `'0.01abc'` fails fast here instead
2612
+ * of lazily throwing a raw `floorUnits` error out of the never-throw read methods.
2613
+ */
2614
+ assertPolicyAmountCaps(policy) {
2615
+ if (!policy) return;
2616
+ for (const field of ["maxAmount", "maxTotal", "windowTotal"]) {
2617
+ const v = policy[field];
2618
+ if (v === void 0) continue;
2619
+ if (typeof v !== "string" || !/^\d+(\.\d+)?$/.test(v)) {
2620
+ throw new TypeError(
2621
+ `policy.${field} must be a non-negative decimal string (e.g. '0.10'); got ${JSON.stringify(v)}.`
2622
+ );
2623
+ }
2624
+ }
2625
+ }
2590
2626
  /**
2591
2627
  * Fail LOUDLY at construction on a misconfigured time policy — a security
2592
2628
  * boundary must never silently half-arm. Two invariants (a misconfiguration is
@@ -3189,20 +3225,25 @@ var PipRailClient = class {
3189
3225
  /** Build the agent-facing quote for an accept: TRUE decimals/symbol (via the
3190
3226
  * driver's describeAsset) + the policy verdict + a symbol-mismatch flag. */
3191
3227
  buildQuote(net, accept, url, description) {
3192
- if (!/^\d+$/.test(accept.amount)) {
3228
+ if (typeof accept.amount !== "string" || !/^\d+$/.test(accept.amount)) {
3229
+ throw new InvalidEnvelopeError(
3230
+ `challenge amount "${String(accept.amount)}" is not a base-unit integer string.`
3231
+ );
3232
+ }
3233
+ if (typeof accept.asset !== "string" || accept.asset.length === 0) {
3193
3234
  throw new InvalidEnvelopeError(
3194
- `challenge amount "${accept.amount}" is not a base-unit integer.`
3235
+ `challenge on ${accept.network} states no (string) asset \u2014 refusing to price it.`
3195
3236
  );
3196
3237
  }
3197
3238
  const amountBase = BigInt(accept.amount);
3198
3239
  const described = net.describeAsset(accept.asset);
3199
- const decimals = described?.decimals ?? accept.extra.decimals;
3200
- if (decimals === void 0) {
3240
+ const decimals = described?.decimals ?? accept.extra?.decimals;
3241
+ if (typeof decimals !== "number" || !Number.isInteger(decimals) || decimals < 0) {
3201
3242
  throw new InvalidEnvelopeError(
3202
- `challenge for ${accept.asset} on ${accept.network} states no decimals and the SDK doesn't recognise the token \u2014 refusing to price it.`
3243
+ `challenge for ${accept.asset} on ${accept.network} states no valid decimals and the SDK doesn't recognise the token \u2014 refusing to price it.`
3203
3244
  );
3204
3245
  }
3205
- const symbol = described?.symbol ?? accept.extra.symbol;
3246
+ const symbol = described?.symbol ?? accept.extra?.symbol;
3206
3247
  const amountFormatted = formatUnits(amountBase, decimals);
3207
3248
  const intent = {
3208
3249
  host: hostOf2(url),
@@ -3234,7 +3275,7 @@ var PipRailClient = class {
3234
3275
  this.ledger.totalFor(accept.network, accept.asset),
3235
3276
  ctx
3236
3277
  );
3237
- const serverSymbol = accept.extra.symbol;
3278
+ const serverSymbol = accept.extra?.symbol;
3238
3279
  const symbolMismatch = intent.recognized && !!serverSymbol && !!symbol && serverSymbol.toUpperCase() !== symbol.toUpperCase();
3239
3280
  return {
3240
3281
  url,
@@ -3310,7 +3351,7 @@ var PipRailClient = class {
3310
3351
  const ref = await net.send(wallet, accept);
3311
3352
  this.safeEmit({ kind: "payment-broadcast", ref });
3312
3353
  try {
3313
- const { height } = await net.confirm(ref, accept.extra.minConfirmations ?? 1);
3354
+ const { height } = await net.confirm(ref, accept.extra?.minConfirmations ?? 1);
3314
3355
  this.safeEmit({
3315
3356
  kind: "payment-confirmed",
3316
3357
  ref,
@@ -3330,7 +3371,7 @@ var PipRailClient = class {
3330
3371
  const signature = {
3331
3372
  x402Version: 2,
3332
3373
  accepted: accept,
3333
- payload: { nonce: accept.extra.nonce, txHash: ref }
3374
+ payload: { nonce: accept.extra?.nonce, txHash: ref }
3334
3375
  };
3335
3376
  const headers = new Headers(originalInit?.headers);
3336
3377
  headers.set(HEADER_SIGNATURE, buildSignatureHeader(signature));
@@ -4023,6 +4064,22 @@ async function readBody(res) {
4023
4064
  return text;
4024
4065
  }
4025
4066
  }
4067
+ function toToolError(err) {
4068
+ if (!(err instanceof PipRailError)) throw err;
4069
+ const out = {
4070
+ ok: false,
4071
+ code: err.code,
4072
+ reason: err.message,
4073
+ explain: explainDecline(err)
4074
+ };
4075
+ if (err instanceof PaymentDeclinedError) {
4076
+ out.declined = true;
4077
+ if (err.reasonCode) out.reasonCode = err.reasonCode;
4078
+ }
4079
+ const ref = err.ref;
4080
+ if (typeof ref === "string") out.ref = ref;
4081
+ return out;
4082
+ }
4026
4083
  function paymentTools(client) {
4027
4084
  return [
4028
4085
  {
@@ -4049,23 +4106,27 @@ function paymentTools(client) {
4049
4106
  additionalProperties: false
4050
4107
  },
4051
4108
  invoke: async (args) => {
4052
- const opts = {};
4053
- if (typeof args.query === "string") opts.query = args.query;
4054
- if (typeof args.network === "string") opts.network = args.network;
4055
- if (typeof args.maxPrice === "number") opts.maxPrice = args.maxPrice;
4056
- if (typeof args.limit === "number") opts.limit = args.limit;
4057
- const found = await client.discover(opts);
4058
- return {
4059
- count: found.length,
4060
- resources: found.map((r) => ({
4061
- resource: r.resource,
4062
- name: r.name,
4063
- description: r.description,
4064
- source: r.source,
4065
- priceUsd: r.priceUsd,
4066
- networks: [...new Set(r.rails.map((rail) => rail.network))]
4067
- }))
4068
- };
4109
+ try {
4110
+ const opts = {};
4111
+ if (typeof args.query === "string") opts.query = args.query;
4112
+ if (typeof args.network === "string") opts.network = args.network;
4113
+ if (typeof args.maxPrice === "number") opts.maxPrice = args.maxPrice;
4114
+ if (typeof args.limit === "number") opts.limit = args.limit;
4115
+ const found = await client.discover(opts);
4116
+ return {
4117
+ count: found.length,
4118
+ resources: found.map((r) => ({
4119
+ resource: r.resource,
4120
+ name: r.name,
4121
+ description: r.description,
4122
+ source: r.source,
4123
+ priceUsd: r.priceUsd,
4124
+ networks: [...new Set(r.rails.map((rail) => rail.network))]
4125
+ }))
4126
+ };
4127
+ } catch (err) {
4128
+ return toToolError(err);
4129
+ }
4069
4130
  }
4070
4131
  },
4071
4132
  {
@@ -4088,8 +4149,12 @@ function paymentTools(client) {
4088
4149
  },
4089
4150
  outputSchema: OPEN_OBJECT,
4090
4151
  invoke: async (args) => {
4091
- const quote = await client.quote(String(args.url));
4092
- return quote ? { gated: true, ...quote } : { gated: false, url: String(args.url) };
4152
+ try {
4153
+ const quote = await client.quote(String(args.url));
4154
+ return quote ? { gated: true, ...quote } : { gated: false, url: String(args.url) };
4155
+ } catch (err) {
4156
+ return toToolError(err);
4157
+ }
4093
4158
  }
4094
4159
  },
4095
4160
  {
@@ -4112,34 +4177,38 @@ function paymentTools(client) {
4112
4177
  },
4113
4178
  outputSchema: OPEN_OBJECT,
4114
4179
  invoke: async (args) => {
4115
- const plan = await client.planPayment(String(args.url));
4116
- if (plan == null) return { gated: false, url: String(args.url) };
4117
- return {
4118
- gated: true,
4119
- payable: plan.payable,
4120
- status: plan.status,
4121
- fundingHint: plan.fundingHint,
4122
- // One model-readable line distilling the whole plan.
4123
- summary: summarizePlan(plan),
4124
- best: plan.best ? {
4125
- network: plan.best.accept.network,
4126
- symbol: plan.best.quote.symbol,
4127
- amount: plan.best.quote.amountFormatted,
4128
- gasCoin: plan.best.cost.feeSymbol,
4129
- gas: plan.best.cost.feeFormatted
4130
- } : null,
4131
- options: plan.options.map((o) => ({
4132
- network: o.accept.network,
4133
- symbol: o.quote.symbol,
4134
- amount: o.quote.amountFormatted,
4135
- state: o.state,
4136
- blockers: o.blockers,
4137
- warnings: o.warnings,
4138
- recipientReady: o.recipient.ready
4139
- })),
4140
- // The session's time leash, present only when a time policy is configured.
4141
- ...plan.session ? { session: plan.session } : {}
4142
- };
4180
+ try {
4181
+ const plan = await client.planPayment(String(args.url));
4182
+ if (plan == null) return { gated: false, url: String(args.url) };
4183
+ return {
4184
+ gated: true,
4185
+ payable: plan.payable,
4186
+ status: plan.status,
4187
+ fundingHint: plan.fundingHint,
4188
+ // One model-readable line distilling the whole plan.
4189
+ summary: summarizePlan(plan),
4190
+ best: plan.best ? {
4191
+ network: plan.best.accept.network,
4192
+ symbol: plan.best.quote.symbol,
4193
+ amount: plan.best.quote.amountFormatted,
4194
+ gasCoin: plan.best.cost.feeSymbol,
4195
+ gas: plan.best.cost.feeFormatted
4196
+ } : null,
4197
+ options: plan.options.map((o) => ({
4198
+ network: o.accept.network,
4199
+ symbol: o.quote.symbol,
4200
+ amount: o.quote.amountFormatted,
4201
+ state: o.state,
4202
+ blockers: o.blockers,
4203
+ warnings: o.warnings,
4204
+ recipientReady: o.recipient.ready
4205
+ })),
4206
+ // The session's time leash, present only when a time policy is configured.
4207
+ ...plan.session ? { session: plan.session } : {}
4208
+ };
4209
+ } catch (err) {
4210
+ return toToolError(err);
4211
+ }
4143
4212
  }
4144
4213
  },
4145
4214
  {
@@ -4245,14 +4314,18 @@ function paymentTools(client) {
4245
4314
  additionalProperties: false
4246
4315
  },
4247
4316
  invoke: async (args) => {
4248
- const opts = {};
4249
- if (typeof args.name === "string") opts.name = args.name;
4250
- if (typeof args.description === "string") opts.description = args.description;
4251
- if (typeof args.priceUsd === "number") opts.priceUsd = args.priceUsd;
4252
- if (typeof args.network === "string") opts.network = args.network;
4253
- if (typeof args.asset === "string") opts.asset = args.asset;
4254
- const outcomes = await client.register(String(args.url), opts);
4255
- return { outcomes };
4317
+ try {
4318
+ const opts = {};
4319
+ if (typeof args.name === "string") opts.name = args.name;
4320
+ if (typeof args.description === "string") opts.description = args.description;
4321
+ if (typeof args.priceUsd === "number") opts.priceUsd = args.priceUsd;
4322
+ if (typeof args.network === "string") opts.network = args.network;
4323
+ if (typeof args.asset === "string") opts.asset = args.asset;
4324
+ const outcomes = await client.register(String(args.url), opts);
4325
+ return { outcomes };
4326
+ } catch (err) {
4327
+ return toToolError(err);
4328
+ }
4256
4329
  }
4257
4330
  },
4258
4331
  {
@@ -4268,14 +4341,18 @@ function paymentTools(client) {
4268
4341
  parameters: { type: "object", properties: {}, additionalProperties: false },
4269
4342
  outputSchema: OPEN_OBJECT,
4270
4343
  invoke: async () => {
4271
- const spent = client.spent();
4272
- const budget = client.budget();
4273
- return {
4274
- spent,
4275
- remaining: budget.byAsset,
4276
- session: budget.session,
4277
- report: formatSpendReport(spent)
4278
- };
4344
+ try {
4345
+ const spent = client.spent();
4346
+ const budget = client.budget();
4347
+ return {
4348
+ spent,
4349
+ remaining: budget.byAsset,
4350
+ session: budget.session,
4351
+ report: formatSpendReport(spent)
4352
+ };
4353
+ } catch (err) {
4354
+ return toToolError(err);
4355
+ }
4279
4356
  }
4280
4357
  },
4281
4358
  {
@@ -8,7 +8,7 @@
8
8
 
9
9
 
10
10
 
11
- var _chunkDKQXW454cjs = require('./chunk-DKQXW454.cjs');
11
+ var _chunkJG6KRAW6cjs = require('./chunk-JG6KRAW6.cjs');
12
12
 
13
13
  // src/drivers/near/index.ts
14
14
  var _nearapijs = require('near-api-js');
@@ -54,18 +54,18 @@ async function payNear(params) {
54
54
  return res.hash;
55
55
  } catch (err) {
56
56
  if (isNearRegistrationError(err)) {
57
- throw new (0, _chunkDKQXW454cjs.RecipientNotReadyError)(
57
+ throw new (0, _chunkJG6KRAW6cjs.RecipientNotReadyError)(
58
58
  `NEAR recipient ${accept.payTo} isn't registered on token ${accept.asset} (NEP-145 storage_deposit) \u2014 register it once (\u22480.00125 NEAR) before it can receive. (NEAR: not registered)`,
59
59
  { cause: err }
60
60
  );
61
61
  }
62
62
  if (isNearAffordability(err)) {
63
- throw new (0, _chunkDKQXW454cjs.InsufficientFundsError)(
63
+ throw new (0, _chunkJG6KRAW6cjs.InsufficientFundsError)(
64
64
  err instanceof Error ? err.message : "Insufficient NEAR balance for the payment.",
65
65
  { cause: err }
66
66
  );
67
67
  }
68
- throw _nullishCoalesce(_chunkDKQXW454cjs.toInsufficientFundsError.call(void 0, err), () => ( err));
68
+ throw _nullishCoalesce(_chunkJG6KRAW6cjs.toInsufficientFundsError.call(void 0, err), () => ( err));
69
69
  }
70
70
  }
71
71
  async function payNearNative(params) {
@@ -75,12 +75,12 @@ async function payNearNative(params) {
75
75
  return res.hash;
76
76
  } catch (err) {
77
77
  if (isNearAffordability(err)) {
78
- throw new (0, _chunkDKQXW454cjs.InsufficientFundsError)(
78
+ throw new (0, _chunkJG6KRAW6cjs.InsufficientFundsError)(
79
79
  err instanceof Error ? err.message : "Insufficient NEAR balance for the payment.",
80
80
  { cause: err }
81
81
  );
82
82
  }
83
- throw _nullishCoalesce(_chunkDKQXW454cjs.toInsufficientFundsError.call(void 0, err), () => ( err));
83
+ throw _nullishCoalesce(_chunkJG6KRAW6cjs.toInsufficientFundsError.call(void 0, err), () => ( err));
84
84
  }
85
85
  }
86
86
  function isNearRegistrationError(err) {
@@ -217,13 +217,13 @@ function txNotFound(hash) {
217
217
 
218
218
  function assertNearWallet(wallet, network) {
219
219
  if (typeof wallet !== "object" || wallet === null) {
220
- throw new (0, _chunkDKQXW454cjs.WrongFamilyError)(
220
+ throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
221
221
  `chain ${network} is NEAR; wallet must be { accountId, key } (key = ed25519:\u2026).`
222
222
  );
223
223
  }
224
- _chunkDKQXW454cjs.assertNoLegacyWalletKey.call(void 0, wallet, "NEAR");
224
+ _chunkJG6KRAW6cjs.assertNoLegacyWalletKey.call(void 0, wallet, "NEAR");
225
225
  if (!("accountId" in wallet) || !("key" in wallet)) {
226
- throw new (0, _chunkDKQXW454cjs.WrongFamilyError)(
226
+ throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
227
227
  `chain ${network} is NEAR; wallet must be { accountId, key } (key = ed25519:\u2026).`
228
228
  );
229
229
  }
@@ -231,13 +231,13 @@ function assertNearWallet(wallet, network) {
231
231
  }
232
232
  function resolveNearWallet(config) {
233
233
  if (!config.accountId || !config.key) {
234
- throw new (0, _chunkDKQXW454cjs.WrongFamilyError)("NEAR wallet needs { accountId, key } (key = ed25519:\u2026).");
234
+ throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)("NEAR wallet needs { accountId, key } (key = ed25519:\u2026).");
235
235
  }
236
236
  let signer;
237
237
  try {
238
238
  signer = _nearapijs.KeyPairSigner.fromSecretKey(config.key);
239
239
  } catch (cause) {
240
- throw new (0, _chunkDKQXW454cjs.WrongFamilyError)("NEAR wallet { key } is not a valid ed25519:\u2026 secret key.", {
240
+ throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)("NEAR wallet { key } is not a valid ed25519:\u2026 secret key.", {
241
241
  cause
242
242
  });
243
243
  }
@@ -304,16 +304,16 @@ function makeNearNetwork(preset, rpcUrl) {
304
304
  const info = preset.tokens[token.toUpperCase()];
305
305
  if (!info) {
306
306
  const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
307
- throw new (0, _chunkDKQXW454cjs.UnknownTokenError)(
307
+ throw new (0, _chunkJG6KRAW6cjs.UnknownTokenError)(
308
308
  `token "${token}" isn't built in for NEAR (known: ${known}). Pass { contractId, decimals } for a custom NEP-141.`
309
309
  );
310
310
  }
311
311
  return { asset: info.contractId, decimals: info.decimals, symbol: info.symbol };
312
312
  }
313
- _chunkDKQXW454cjs.rejectForeignToken.call(void 0, token, "near", network);
313
+ _chunkJG6KRAW6cjs.rejectForeignToken.call(void 0, token, "near", network);
314
314
  const t = token;
315
315
  if (!t.contractId || typeof t.decimals !== "number") {
316
- throw new (0, _chunkDKQXW454cjs.WrongFamilyError)(
316
+ throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
317
317
  `chain ${network} is NEAR; a custom token must be { contractId, decimals }.`
318
318
  );
319
319
  }
@@ -332,12 +332,12 @@ function makeNearNetwork(preset, rpcUrl) {
332
332
  },
333
333
  assertValidPayTo(payTo) {
334
334
  if (payTo.startsWith("0x")) {
335
- throw new (0, _chunkDKQXW454cjs.WrongFamilyError)(
335
+ throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
336
336
  `chain ${network} is NEAR, but payTo "${payTo}" looks like an EVM/Sui 0x address.`
337
337
  );
338
338
  }
339
339
  if (!isValidNearAccountId(payTo)) {
340
- throw new (0, _chunkDKQXW454cjs.WrongFamilyError)(
340
+ throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
341
341
  `chain ${network} is NEAR, but payTo "${payTo}" is not a valid NEAR account id.`
342
342
  );
343
343
  }
@@ -381,10 +381,10 @@ function makeNearNetwork(preset, rpcUrl) {
381
381
  if (tx && tx.success) return { height: "0" };
382
382
  } catch (e7) {
383
383
  }
384
- throw new (0, _chunkDKQXW454cjs.ConfirmationTimeoutError)(`NEAR tx ${hash} not confirmed in time.`);
384
+ throw new (0, _chunkJG6KRAW6cjs.ConfirmationTimeoutError)(`NEAR tx ${hash} not confirmed in time.`);
385
385
  },
386
386
  async estimateCost() {
387
- return _chunkDKQXW454cjs.nativeCost.call(void 0, {
387
+ return _chunkJG6KRAW6cjs.nativeCost.call(void 0, {
388
388
  symbol: "NEAR",
389
389
  decimals: NEAR_DECIMALS,
390
390
  fee: 1500000000000000000000n,
@@ -8,7 +8,7 @@ import {
8
8
  nativeCost,
9
9
  rejectForeignToken,
10
10
  toInsufficientFundsError
11
- } from "./chunk-47VEOHZN.js";
11
+ } from "./chunk-7XK22JSQ.js";
12
12
 
13
13
  // src/drivers/near/index.ts
14
14
  import { JsonRpcProvider, Account, actions } from "near-api-js";
@@ -8,7 +8,7 @@ import {
8
8
  nativeCost,
9
9
  rejectForeignToken,
10
10
  toInsufficientFundsError
11
- } from "./chunk-47VEOHZN.js";
11
+ } from "./chunk-7XK22JSQ.js";
12
12
 
13
13
  // src/drivers/solana/index.ts
14
14
  import { Connection, PublicKey as PublicKey3 } from "@solana/web3.js";
@@ -521,8 +521,19 @@ function toKeypair(wallet, network) {
521
521
  }
522
522
  if ("key" in wallet) {
523
523
  const sk = wallet.key;
524
- const bytes = typeof sk === "string" ? bs582.decode(sk) : sk;
525
- return Keypair3.fromSecretKey(bytes);
524
+ if (typeof sk === "string" && sk.startsWith("0x")) {
525
+ throw new WrongFamilyError(
526
+ `chain ${network} is Solana, but the wallet { key } is a 0x\u2026 hex key \u2014 that's an EVM key. A Solana key is a base58 secret string (or a 64-byte Uint8Array).`
527
+ );
528
+ }
529
+ try {
530
+ const bytes = typeof sk === "string" ? bs582.decode(sk) : sk;
531
+ return Keypair3.fromSecretKey(bytes);
532
+ } catch (err) {
533
+ throw new WrongFamilyError(
534
+ `chain ${network} is Solana; the wallet { key } isn't a valid Solana secret (expected a base58 secret string or a 64-byte Uint8Array): ${err instanceof Error ? err.message : String(err)}.`
535
+ );
536
+ }
526
537
  }
527
538
  throw new WrongFamilyError(
528
539
  `chain ${network} is Solana; wallet must be { key } (base58 secret) or { signer }.`