@xona-labs/xpay 0.2.24 → 0.2.26

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.
Files changed (118) hide show
  1. package/CHANGELOG.md +101 -78
  2. package/README.md +71 -69
  3. package/SKILL.md +22 -22
  4. package/dist/agenc/api.d.ts +8 -8
  5. package/dist/agenc/api.js +11 -11
  6. package/dist/agenc/hire.d.ts +4 -4
  7. package/dist/agenc/hire.js +17 -17
  8. package/dist/agenc/price.d.ts +1 -1
  9. package/dist/agenc/price.js +1 -1
  10. package/dist/biometric/index.d.ts +3 -3
  11. package/dist/biometric/index.js +6 -6
  12. package/dist/cli/accounts.d.ts +1 -1
  13. package/dist/cli/accounts.js +1 -1
  14. package/dist/cli/agenc.d.ts +2 -2
  15. package/dist/cli/agenc.js +4 -4
  16. package/dist/cli/balance.d.ts +1 -1
  17. package/dist/cli/balance.js +4 -4
  18. package/dist/cli/bento.d.ts +3 -3
  19. package/dist/cli/bento.js +8 -8
  20. package/dist/cli/bento.js.map +1 -1
  21. package/dist/cli/biometric.d.ts +1 -1
  22. package/dist/cli/biometric.js +8 -8
  23. package/dist/cli/common.js +6 -6
  24. package/dist/cli/common.js.map +1 -1
  25. package/dist/cli/discover.d.ts +2 -2
  26. package/dist/cli/discover.js +4 -4
  27. package/dist/cli/guardrail.d.ts +1 -1
  28. package/dist/cli/guardrail.js +3 -3
  29. package/dist/cli/index.d.ts +2 -2
  30. package/dist/cli/index.js +12 -12
  31. package/dist/cli/init.d.ts +1 -1
  32. package/dist/cli/init.js +2 -2
  33. package/dist/cli/magicblock.d.ts +1 -1
  34. package/dist/cli/magicblock.js +4 -4
  35. package/dist/cli/mcp-server.d.ts +2 -2
  36. package/dist/cli/mcp-server.d.ts.map +1 -1
  37. package/dist/cli/mcp-server.js +25 -22
  38. package/dist/cli/mcp-server.js.map +1 -1
  39. package/dist/cli/pay.d.ts +1 -1
  40. package/dist/cli/pay.js +1 -1
  41. package/dist/cli/report.d.ts +2 -2
  42. package/dist/cli/report.js +4 -4
  43. package/dist/cli/report.js.map +1 -1
  44. package/dist/cli/sana.d.ts +1 -1
  45. package/dist/cli/sana.js +3 -3
  46. package/dist/cli/shop.d.ts +1 -1
  47. package/dist/cli/shop.js +1 -1
  48. package/dist/cli/swap.d.ts +1 -1
  49. package/dist/cli/swap.js +3 -3
  50. package/dist/cli/token.d.ts +2 -2
  51. package/dist/cli/token.js +2 -2
  52. package/dist/cli/trade.d.ts +2 -2
  53. package/dist/cli/trade.js +8 -8
  54. package/dist/cli/trade.js.map +1 -1
  55. package/dist/cli/transfer.d.ts +1 -1
  56. package/dist/cli/transfer.js +1 -1
  57. package/dist/cli/x.d.ts +1 -1
  58. package/dist/cli/x.js +1 -1
  59. package/dist/cli/zauth.d.ts +1 -1
  60. package/dist/cli/zauth.js +5 -5
  61. package/dist/discover/cache.js +1 -1
  62. package/dist/discover/index.d.ts +2 -2
  63. package/dist/discover/index.js +6 -6
  64. package/dist/discover/orbitx402.d.ts +2 -2
  65. package/dist/discover/orbitx402.js +1 -1
  66. package/dist/discover/payai.js +1 -1
  67. package/dist/do/index.d.ts +2 -2
  68. package/dist/do/index.js +1 -1
  69. package/dist/guardrail/index.d.ts +4 -4
  70. package/dist/guardrail/index.js +14 -14
  71. package/dist/guardrail/index.js.map +1 -1
  72. package/dist/index.d.ts +7 -7
  73. package/dist/index.js +2 -2
  74. package/dist/magicblock/client.d.ts +2 -2
  75. package/dist/magicblock/client.js +4 -4
  76. package/dist/profile/index.d.ts +3 -3
  77. package/dist/profile/index.js +3 -3
  78. package/dist/profile/storage.d.ts +1 -1
  79. package/dist/profile/storage.js +4 -4
  80. package/dist/profile/types.d.ts +6 -6
  81. package/dist/profile/types.js +1 -1
  82. package/dist/report/index.d.ts +1 -1
  83. package/dist/report/index.js +2 -2
  84. package/dist/sana/tools.js +8 -8
  85. package/dist/signers/raw-evm.d.ts +1 -1
  86. package/dist/signers/raw-evm.js +5 -5
  87. package/dist/signers/raw-solana.d.ts +1 -1
  88. package/dist/signers/raw-solana.js +4 -4
  89. package/dist/swap/index.d.ts +6 -6
  90. package/dist/swap/index.js +12 -12
  91. package/dist/token/index.d.ts +8 -8
  92. package/dist/token/index.js +14 -14
  93. package/dist/token/rwa.d.ts +3 -3
  94. package/dist/token/rwa.js +3 -3
  95. package/dist/tools/index.d.ts +15 -1
  96. package/dist/tools/index.d.ts.map +1 -1
  97. package/dist/tools/index.js +71 -31
  98. package/dist/tools/index.js.map +1 -1
  99. package/dist/trading/discovery.d.ts +6 -6
  100. package/dist/trading/discovery.js +7 -7
  101. package/dist/trading/index.d.ts +6 -6
  102. package/dist/trading/index.js +13 -13
  103. package/dist/transfer/index.d.ts +4 -4
  104. package/dist/transfer/index.js +8 -8
  105. package/dist/types.d.ts +7 -7
  106. package/dist/use/index.d.ts +5 -5
  107. package/dist/use/index.js +20 -20
  108. package/dist/wallet/index.d.ts +2 -2
  109. package/dist/wallet/index.js +3 -3
  110. package/dist/x402/evm-payment.d.ts +4 -4
  111. package/dist/x402/evm-payment.js +6 -6
  112. package/dist/x402/extract.d.ts +1 -1
  113. package/dist/x402/extract.js +1 -1
  114. package/dist/x402/svm-payment.d.ts +2 -2
  115. package/dist/x402/svm-payment.js +2 -2
  116. package/dist/zauth/index.d.ts +4 -4
  117. package/dist/zauth/index.js +5 -5
  118. package/package.json +4 -3
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Robinhood Chain token discovery GeckoTerminal public API.
2
+ * Robinhood Chain token discovery - GeckoTerminal public API.
3
3
  *
4
4
  * GeckoTerminal indexes Robinhood Chain under the network id "robinhood"
5
5
  * (keyless, ~30 req/min). Used for the trending/new token tools and for the
6
- * USD pricing attached to trade quotes. Discovery is read-only market data
6
+ * USD pricing attached to trade quotes. Discovery is read-only market data -
7
7
  * the trade path itself never depends on it.
8
8
  */
9
9
  export interface DiscoveredToken {
@@ -18,7 +18,7 @@ export interface DiscoveredToken {
18
18
  priceChange24hPct?: number;
19
19
  /** Liquidity pool: 20-byte address (Uniswap v3) or 32-byte id (v4). */
20
20
  pool: string;
21
- /** True for v4 pool ids xpay_trade only routes v3 pools today. */
21
+ /** True for v4 pool ids - xpay_trade only routes v3 pools today. */
22
22
  poolIsV4: boolean;
23
23
  dex?: string;
24
24
  poolCreatedAt?: string;
@@ -27,7 +27,7 @@ export interface DiscoveredToken {
27
27
  export declare function trendingTokens(opts?: {
28
28
  limit?: number;
29
29
  }): Promise<DiscoveredToken[]>;
30
- /** Tokens from the most recently created pools (fresh launches high risk). */
30
+ /** Tokens from the most recently created pools (fresh launches - high risk). */
31
31
  export declare function newTokens(opts?: {
32
32
  limit?: number;
33
33
  }): Promise<DiscoveredToken[]>;
@@ -44,14 +44,14 @@ export interface TokenHolding {
44
44
  /**
45
45
  * All ERC-20 balances a wallet holds on Robinhood Chain, via the chain's
46
46
  * Blockscout explorer API (keyless). This is what surfaces memecoins bought
47
- * through `xpay trade` the on-chain signer only knows a hardcoded token list.
47
+ * through `xpay trade` - the on-chain signer only knows a hardcoded token list.
48
48
  * Best-effort: returns [] if the explorer is unreachable.
49
49
  */
50
50
  export declare function robinhoodHoldings(address: string): Promise<TokenHolding[]>;
51
51
  /**
52
52
  * Resolve a token symbol to its contract address via trending + new pools.
53
53
  * Throws when the symbol is unknown or matches several distinct contracts
54
- * (memecoin symbols are not unique pass the address instead).
54
+ * (memecoin symbols are not unique - pass the address instead).
55
55
  */
56
56
  export declare function resolveTokenBySymbol(symbol: string): Promise<DiscoveredToken>;
57
57
  //# sourceMappingURL=discovery.d.ts.map
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Robinhood Chain token discovery GeckoTerminal public API.
2
+ * Robinhood Chain token discovery - GeckoTerminal public API.
3
3
  *
4
4
  * GeckoTerminal indexes Robinhood Chain under the network id "robinhood"
5
5
  * (keyless, ~30 req/min). Used for the trending/new token tools and for the
6
- * USD pricing attached to trade quotes. Discovery is read-only market data
6
+ * USD pricing attached to trade quotes. Discovery is read-only market data -
7
7
  * the trade path itself never depends on it.
8
8
  */
9
9
  const DEFAULT_ENDPOINT = "https://api.geckoterminal.com/api/v2";
@@ -31,7 +31,7 @@ function poolsToTokens(payload, limit) {
31
31
  const out = [];
32
32
  for (const pool of data) {
33
33
  const attrs = pool.attributes ?? {};
34
- // base_token id looks like "robinhood_0x020b…" address after the prefix.
34
+ // base_token id looks like "robinhood_0x020b…" - address after the prefix.
35
35
  const baseId = pool.relationships?.base_token?.data?.id ?? "";
36
36
  const address = baseId.includes("_") ? baseId.slice(baseId.indexOf("_") + 1) : "";
37
37
  if (!address.startsWith("0x"))
@@ -64,7 +64,7 @@ export async function trendingTokens(opts = {}) {
64
64
  const payload = await gtFetch(`/networks/${GT_NETWORK}/trending_pools?page=1`);
65
65
  return poolsToTokens(payload, opts.limit ?? 10);
66
66
  }
67
- /** Tokens from the most recently created pools (fresh launches high risk). */
67
+ /** Tokens from the most recently created pools (fresh launches - high risk). */
68
68
  export async function newTokens(opts = {}) {
69
69
  const payload = await gtFetch(`/networks/${GT_NETWORK}/new_pools?page=1`);
70
70
  return poolsToTokens(payload, opts.limit ?? 10);
@@ -83,7 +83,7 @@ export async function tokenPriceUsd(address) {
83
83
  /**
84
84
  * All ERC-20 balances a wallet holds on Robinhood Chain, via the chain's
85
85
  * Blockscout explorer API (keyless). This is what surfaces memecoins bought
86
- * through `xpay trade` the on-chain signer only knows a hardcoded token list.
86
+ * through `xpay trade` - the on-chain signer only knows a hardcoded token list.
87
87
  * Best-effort: returns [] if the explorer is unreachable.
88
88
  */
89
89
  export async function robinhoodHoldings(address) {
@@ -132,7 +132,7 @@ function atomsToHuman(atoms, decimals) {
132
132
  /**
133
133
  * Resolve a token symbol to its contract address via trending + new pools.
134
134
  * Throws when the symbol is unknown or matches several distinct contracts
135
- * (memecoin symbols are not unique pass the address instead).
135
+ * (memecoin symbols are not unique - pass the address instead).
136
136
  */
137
137
  export async function resolveTokenBySymbol(symbol) {
138
138
  const wanted = symbol.trim().toUpperCase();
@@ -146,7 +146,7 @@ export async function resolveTokenBySymbol(symbol) {
146
146
  matches.set(t.address.toLowerCase(), t);
147
147
  }
148
148
  if (matches.size === 0) {
149
- throw new Error(`xpay.trade: unknown token "${symbol}" not in Robinhood Chain trending/new pools. ` +
149
+ throw new Error(`xpay.trade: unknown token "${symbol}" - not in Robinhood Chain trending/new pools. ` +
150
150
  "Pass the token's contract address instead.");
151
151
  }
152
152
  if (matches.size > 1) {
@@ -1,15 +1,15 @@
1
1
  /**
2
- * Robinhood Chain token trading direct Uniswap V3 (NOXA Fun launchpad).
2
+ * Robinhood Chain token trading - direct Uniswap V3 (NOXA Fun launchpad).
3
3
  *
4
4
  * NOXA Fun tokens (fun.noxa.fi) launch straight into Uniswap V3 pools quoted
5
5
  * in WETH, so trading them is plain V3: quote via QuoterV2, execute via
6
- * SwapRouter02. No third-party API or key everything is on-chain against the
6
+ * SwapRouter02. No third-party API or key - everything is on-chain against the
7
7
  * chain's own RPC. GMGN was ruled out (no chain-4663 support, gated API).
8
8
  *
9
9
  * Scope v1: ETH ⇄ token only (buy with native ETH, sell back to native ETH).
10
10
  * The router auto-wraps ETH on buys; sells unwrap WETH → ETH via multicall.
11
11
  *
12
- * A trade is irreversible and risks wallet value, so exactly like `swap` —
12
+ * A trade is irreversible and risks wallet value, so, exactly like `swap`,
13
13
  * it runs through the guardrail *before* signing.
14
14
  */
15
15
  import type { Network } from "../types.js";
@@ -24,7 +24,7 @@ export declare const RH_CONTRACTS: {
24
24
  readonly weth: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73";
25
25
  readonly noxaLauncher: "0xD9eC2db5f3D1b236843925949fe5bd8a3836FCcB";
26
26
  };
27
- /** Trading settings profile `config.trading`, overridable per call. */
27
+ /** Trading settings - profile `config.trading`, overridable per call. */
28
28
  export interface TradeConfig {
29
29
  /** Default max slippage in bps (100 = 1%). */
30
30
  slippageBps?: number;
@@ -75,7 +75,7 @@ export interface TradeQuote {
75
75
  /** Input-side USD estimate (GeckoTerminal spot). Best-effort. */
76
76
  usdValue?: number;
77
77
  /**
78
- * True when the counterparty token was NOT confirmed as a NOXA Fun launch
78
+ * True when the counterparty token was NOT confirmed as a NOXA Fun launch -
79
79
  * it may still be tradeable, but treat the pool/price with more suspicion.
80
80
  */
81
81
  unverified: boolean;
@@ -86,7 +86,7 @@ export interface TradeResult extends TradeQuote {
86
86
  /** Transaction hash on Robinhood Chain. */
87
87
  txHash: string;
88
88
  }
89
- /** Quote a trade without executing no guardrail, no signing, no funds moved. */
89
+ /** Quote a trade without executing - no guardrail, no signing, no funds moved. */
90
90
  export declare function tradeQuote(args: Omit<TradeArgs, "guardrail">): Promise<TradeQuote>;
91
91
  /** Execute a trade on Robinhood Chain. Guardrail runs before signing. */
92
92
  export declare function trade(args: TradeArgs): Promise<TradeResult>;
@@ -1,15 +1,15 @@
1
1
  /**
2
- * Robinhood Chain token trading direct Uniswap V3 (NOXA Fun launchpad).
2
+ * Robinhood Chain token trading - direct Uniswap V3 (NOXA Fun launchpad).
3
3
  *
4
4
  * NOXA Fun tokens (fun.noxa.fi) launch straight into Uniswap V3 pools quoted
5
5
  * in WETH, so trading them is plain V3: quote via QuoterV2, execute via
6
- * SwapRouter02. No third-party API or key everything is on-chain against the
6
+ * SwapRouter02. No third-party API or key - everything is on-chain against the
7
7
  * chain's own RPC. GMGN was ruled out (no chain-4663 support, gated API).
8
8
  *
9
9
  * Scope v1: ETH ⇄ token only (buy with native ETH, sell back to native ETH).
10
10
  * The router auto-wraps ETH on buys; sells unwrap WETH → ETH via multicall.
11
11
  *
12
- * A trade is irreversible and risks wallet value, so exactly like `swap` —
12
+ * A trade is irreversible and risks wallet value, so, exactly like `swap`,
13
13
  * it runs through the guardrail *before* signing.
14
14
  */
15
15
  import { Contract, MaxUint256, getAddress, isAddress } from "ethers";
@@ -25,7 +25,7 @@ export const RH_CONTRACTS = {
25
25
  };
26
26
  /** Fee tiers probed (in bps*100) when the pool fee isn't known up front. NOXA uses 10000 (1%). */
27
27
  const FEE_TIERS = [10000, 3000, 500, 100];
28
- const DEFAULT_SLIPPAGE_BPS = 100; // 1% memecoin pools with a 1% fee move fast.
28
+ const DEFAULT_SLIPPAGE_BPS = 100; // 1% - memecoin pools with a 1% fee move fast.
29
29
  const MAX_SLIPPAGE_BPS = 5000; // 50% hard ceiling.
30
30
  const QUOTER_ABI = [
31
31
  "function quoteExactInputSingle((address tokenIn,address tokenOut,uint256 amountIn,uint24 fee,uint160 sqrtPriceLimitX96)) returns (uint256 amountOut,uint160 sqrtPriceX96After,uint32 initializedTicksCrossed,uint256 gasEstimate)",
@@ -42,7 +42,7 @@ const ERC20_ABI = [
42
42
  "function allowance(address owner,address spender) view returns (uint256)",
43
43
  "function approve(address spender,uint256 amount) returns (bool)",
44
44
  ];
45
- // NOXA Fun token surface non-standard getters a plain ERC-20 lacks.
45
+ // NOXA Fun token surface - non-standard getters a plain ERC-20 lacks.
46
46
  const NOXA_TOKEN_ABI = [
47
47
  "function liquidityPool() view returns (address)",
48
48
  "function pairToken() view returns (address)",
@@ -54,14 +54,14 @@ const NOXA_TOKEN_ABI = [
54
54
  // SwapRouter02 recipient constant: keep output in the router for a follow-up unwrap.
55
55
  const ROUTER_ADDRESS_THIS = "0x0000000000000000000000000000000000000002";
56
56
  const NATIVE_ETH = { symbol: "ETH", decimals: 18 };
57
- /** Quote a trade without executing no guardrail, no signing, no funds moved. */
57
+ /** Quote a trade without executing - no guardrail, no signing, no funds moved. */
58
58
  export async function tradeQuote(args) {
59
59
  return (await prepare(args)).quote;
60
60
  }
61
61
  /** Execute a trade on Robinhood Chain. Guardrail runs before signing. */
62
62
  export async function trade(args) {
63
63
  const { quote, ethersWallet, side, token } = await prepare(args);
64
- // Guardrail *before* signing same security boundary as swap/pay/transfer.
64
+ // Guardrail *before* signing - same security boundary as swap/pay/transfer.
65
65
  // Reuse the "swap" scheme so host-whitelist is skipped and the USD estimate
66
66
  // is priced from `extra.usdEstimate` (see Guardrail.estimateUsd).
67
67
  await args.guardrail.check({
@@ -140,7 +140,7 @@ async function prepare(args) {
140
140
  throw new Error(`xpay.trade: only Robinhood Chain ("robinhood") is supported (got "${network}")`);
141
141
  }
142
142
  if (!args.wallet.has(ROBINHOOD_NETWORK)) {
143
- throw new Error('xpay.trade: no "robinhood" signer configured add it to your profile networks');
143
+ throw new Error('xpay.trade: no "robinhood" signer configured - add it to your profile networks');
144
144
  }
145
145
  if (!Number.isFinite(args.amount) || args.amount <= 0) {
146
146
  throw new Error("xpay.trade: amount must be a positive number");
@@ -180,7 +180,7 @@ async function prepare(args) {
180
180
  // A buy that would breach a cap is failed up front with a clear message
181
181
  // rather than reverting opaquely on-chain. The cap info is surfaced on the
182
182
  // quote only when this trade is actually within striking distance of a cap
183
- // (>25% of it) established tokens leave a far-future endBlock set with wide
183
+ // (>25% of it) - established tokens leave a far-future endBlock set with wide
184
184
  // caps, so reporting it unconditionally would be misleading noise.
185
185
  let boundRestriction;
186
186
  if (restriction && side === "buy") {
@@ -232,7 +232,7 @@ function isEth(ref) {
232
232
  async function resolveToken(wallet, ref) {
233
233
  let address = ref.trim();
234
234
  if (!isAddress(address)) {
235
- // Treat as a symbol resolve via GeckoTerminal trending/new pools.
235
+ // Treat as a symbol - resolve via GeckoTerminal trending/new pools.
236
236
  const found = await resolveTokenBySymbol(address);
237
237
  address = found.address;
238
238
  }
@@ -244,7 +244,7 @@ async function resolveToken(wallet, ref) {
244
244
  ]);
245
245
  return { address, symbol, decimals };
246
246
  }
247
- /** Probe a token's NOXA Fun surface pool, fee tier, launch restrictions. */
247
+ /** Probe a token's NOXA Fun surface - pool, fee tier, launch restrictions. */
248
248
  async function inspectToken(wallet, address) {
249
249
  const t = new Contract(address, NOXA_TOKEN_ABI, wallet);
250
250
  try {
@@ -277,7 +277,7 @@ async function inspectToken(wallet, address) {
277
277
  return meta;
278
278
  }
279
279
  catch {
280
- // Not a NOXA token (getters reverted) still tradeable if a V3 pool exists.
280
+ // Not a NOXA token (getters reverted) - still tradeable if a V3 pool exists.
281
281
  return { isNoxa: false };
282
282
  }
283
283
  }
@@ -287,7 +287,7 @@ async function quoteBestFee(wallet, tokenIn, tokenOut, amountIn, fees) {
287
287
  let lastErr;
288
288
  for (const fee of fees) {
289
289
  try {
290
- // QuoterV2 quote fns are non-view (revert-to-return) must use staticCall.
290
+ // QuoterV2 quote fns are non-view (revert-to-return) - must use staticCall.
291
291
  const res = await quoter.quoteExactInputSingle.staticCall({
292
292
  tokenIn,
293
293
  tokenOut,
@@ -1,11 +1,11 @@
1
1
  /**
2
- * Direct SPL / ERC-20 transfer no x402, no provider, just send funds.
2
+ * Direct SPL / ERC-20 transfer - no x402, no provider, just send funds.
3
3
  *
4
4
  * Goes through the same guardrail as `use()` so a compromised CLI / agent
5
5
  * can't drain the wallet past the configured caps.
6
6
  *
7
7
  * Solana: any SPL token by symbol (USDC, BONK, JUP, …) or raw mint address.
8
- * EVM: the network's stablecoin only USDC, or USDT0 on Stable (other
8
+ * EVM: the network's stablecoin only - USDC, or USDT0 on Stable (other
9
9
  * ERC-20 addresses can be added to EVM_STABLECOIN as needed).
10
10
  */
11
11
  import type { Network } from "../types.js";
@@ -17,7 +17,7 @@ export interface SplTokenInfo {
17
17
  decimals: number;
18
18
  symbol: string;
19
19
  }
20
- /** Well-known Solana SPL tokens symbol (uppercase) → info. */
20
+ /** Well-known Solana SPL tokens - symbol (uppercase) → info. */
21
21
  export declare const SOLANA_TOKENS: Record<string, SplTokenInfo>;
22
22
  /** Symbols users can name in CLI / MCP. */
23
23
  export declare const KNOWN_SOLANA_SYMBOLS: string[];
@@ -31,7 +31,7 @@ export interface TransferArgs {
31
31
  /**
32
32
  * Token to transfer.
33
33
  * - Solana: symbol ("USDC", "BONK", "JUP", …) or raw mint address.
34
- * - EVM: only the network's stablecoin "USDC", or "USDT0" on Stable.
34
+ * - EVM: only the network's stablecoin - "USDC", or "USDT0" on Stable.
35
35
  * Defaults to the network's stablecoin.
36
36
  */
37
37
  token?: string;
@@ -1,17 +1,17 @@
1
1
  /**
2
- * Direct SPL / ERC-20 transfer no x402, no provider, just send funds.
2
+ * Direct SPL / ERC-20 transfer - no x402, no provider, just send funds.
3
3
  *
4
4
  * Goes through the same guardrail as `use()` so a compromised CLI / agent
5
5
  * can't drain the wallet past the configured caps.
6
6
  *
7
7
  * Solana: any SPL token by symbol (USDC, BONK, JUP, …) or raw mint address.
8
- * EVM: the network's stablecoin only USDC, or USDT0 on Stable (other
8
+ * EVM: the network's stablecoin only - USDC, or USDT0 on Stable (other
9
9
  * ERC-20 addresses can be added to EVM_STABLECOIN as needed).
10
10
  */
11
11
  import { Connection, PublicKey, SystemProgram, Transaction, LAMPORTS_PER_SOL, } from "@solana/web3.js";
12
12
  import { getMint } from "@solana/spl-token";
13
13
  import { magicBlockPrivateTransfer } from "../magicblock/client.js";
14
- /** Well-known Solana SPL tokens symbol (uppercase) → info. */
14
+ /** Well-known Solana SPL tokens - symbol (uppercase) → info. */
15
15
  export const SOLANA_TOKENS = {
16
16
  USDC: { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", decimals: 6, symbol: "USDC" },
17
17
  USDT: { mint: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", decimals: 6, symbol: "USDT" },
@@ -58,7 +58,7 @@ export async function transfer(args) {
58
58
  throw new Error(`transfer: no stablecoin registered for EVM network "${network}"`);
59
59
  }
60
60
  // Accept the network's own symbol, plus the generic "USDC"/"USDT" the
61
- // caller may default to on Stable they all mean USDT0.
61
+ // caller may default to - on Stable they all mean USDT0.
62
62
  const tokenSymbol = (args.token ?? stablecoin.symbol).toUpperCase();
63
63
  const aliases = network === "stable" ? ["USDT0", "USDT", "USDC"] : ["USDC"];
64
64
  if (!aliases.includes(tokenSymbol)) {
@@ -83,7 +83,7 @@ export async function transfer(args) {
83
83
  if (tokenKey === "SOL") {
84
84
  if (args.private) {
85
85
  throw new Error(`transfer: native SOL is not supported by MagicBlock PER (SPL tokens only). ` +
86
- `Use "wSOL" instead it goes through the PER and settles as wrapped SOL on the other end.`);
86
+ `Use "wSOL" instead - it goes through the PER and settles as wrapped SOL on the other end.`);
87
87
  }
88
88
  return transferNativeSol(args);
89
89
  }
@@ -134,7 +134,7 @@ async function transferNativeSol(args) {
134
134
  const rpc = process.env.XPAY_SOLANA_RPC ?? "https://solana-mainnet.g.alchemy.com/v2/Ug5mqBVIbSHoa8ZHgTUSJ";
135
135
  const connection = new Connection(rpc, "confirmed");
136
136
  // Reconstruct keypair from the signer's signMessage so we can sign the tx.
137
- // rawSolanaSigner keeps the keypair internally we access it by signing a
137
+ // rawSolanaSigner keeps the keypair internally - we access it by signing a
138
138
  // known message and rebuilding. Instead, we use a lower-level approach:
139
139
  // delegate to signer.pay() with a synthetic SOL "requirement" if it supports
140
140
  // it, otherwise build the SystemProgram.transfer tx ourselves.
@@ -173,7 +173,7 @@ async function resolveSolanaToken(token) {
173
173
  // Reverse lookup by mint address.
174
174
  if (BY_MINT[token])
175
175
  return BY_MINT[token];
176
- // Looks like a base58 mint address fetch from chain.
176
+ // Looks like a base58 mint address - fetch from chain.
177
177
  if (/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(token)) {
178
178
  const rpc = process.env.XPAY_SOLANA_RPC ?? "https://solana-mainnet.g.alchemy.com/v2/Ug5mqBVIbSHoa8ZHgTUSJ";
179
179
  try {
@@ -203,7 +203,7 @@ function resolveNetwork(args) {
203
203
  // Auto-detect only across networks the profile actually opted into.
204
204
  // Robinhood and Stable signers are always registered (see
205
205
  // signersFromProfile), so keying off `wallet.has()` alone would make every
206
- // EVM transfer ambiguous reach those two with an explicit --network
206
+ // EVM transfer ambiguous - reach those two with an explicit --network
207
207
  // unless they're in the profile's `networks`.
208
208
  const evm = args.wallet.networks.filter((n) => EVM_NETWORKS.includes(n) && args.wallet.has(n));
209
209
  if (evm.length === 0)
package/dist/types.d.ts CHANGED
@@ -8,9 +8,9 @@
8
8
  import { z } from "zod";
9
9
  /** A network slug. Keep this open-ended so new chains can be added without an SDK release. */
10
10
  export type Network = "solana" | "base" | "ethereum" | "arbitrum" | "optimism"
11
- /** Robinhood Chain (Arbitrum Orbit L2, eip155:4663) ETH-native. */
11
+ /** Robinhood Chain (Arbitrum Orbit L2, eip155:4663) - ETH-native. */
12
12
  | "robinhood"
13
- /** Stable (eip155:988) Tether/Bitfinex payments L1, settles USDT0. */
13
+ /** Stable (eip155:988) - Tether/Bitfinex payments L1, settles USDT0. */
14
14
  | "stable" | (string & {});
15
15
  /**
16
16
  * One payment option attached to a {@link Resource}.
@@ -189,7 +189,7 @@ export interface PlatformFeeResult {
189
189
  txSig?: string;
190
190
  /** Whether the fee was successfully charged. */
191
191
  success: boolean;
192
- /** Error message if the fee charge failed (non-fatal the use result is still returned). */
192
+ /** Error message if the fee charge failed (non-fatal - the use result is still returned). */
193
193
  error?: string;
194
194
  }
195
195
  /** Result returned by {@link XPay.use}. */
@@ -218,7 +218,7 @@ export interface UseResult {
218
218
  }
219
219
  /** Options passed to {@link XPay.discover}. */
220
220
  export interface DiscoverOptions {
221
- /** Free-text query matched against resource URL, metadata, and category. */
221
+ /** Free-text query - matched against resource URL, metadata, and category. */
222
222
  query?: string;
223
223
  /** Restrict to specific networks. Defaults to all configured. */
224
224
  networks?: Network[];
@@ -246,7 +246,7 @@ export interface Signer {
246
246
  address: string;
247
247
  /**
248
248
  * Sign an arbitrary message (used for x402 payment authorization payloads).
249
- * The exact bytes signed depend on the network see implementations.
249
+ * The exact bytes signed depend on the network - see implementations.
250
250
  */
251
251
  signMessage(message: Uint8Array): Promise<Uint8Array>;
252
252
  /**
@@ -280,7 +280,7 @@ export interface Signer {
280
280
  * Optional (EVM signers): sign an EIP-712 typed-data payload and return the
281
281
  * hex signature. When present, `use()` pays eip155 endpoints gaslessly via
282
282
  * a signed EIP-3009 `transferWithAuthorization` (the facilitator broadcasts
283
- * and covers gas no native ETH needed); when absent, it falls back to the
283
+ * and covers gas - no native ETH needed); when absent, it falls back to the
284
284
  * legacy `pay()` (broadcasts an ERC-20 transfer, wallet pays its own gas).
285
285
  */
286
286
  signEvmTypedData?(typedData: {
@@ -295,7 +295,7 @@ export interface Signer {
295
295
  * Optional (EVM signers): return the underlying ethers `Wallet` (connected to
296
296
  * a provider) so higher-level flows like on-chain DEX trades can read chain
297
297
  * state and broadcast arbitrary contract calls (swaps, approvals). Typed
298
- * `unknown` to keep ethers out of the core type surface callers cast it.
298
+ * `unknown` to keep ethers out of the core type surface - callers cast it.
299
299
  * Mirrors {@link Signer.getKitSigner}. Implemented by `rawEvmSigner`.
300
300
  */
301
301
  getEvmWallet?(): unknown;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Use call a paid resource, handling x402 payment end-to-end.
2
+ * Use - call a paid resource, handling x402 payment end-to-end.
3
3
  *
4
4
  * Two modes:
5
5
  * - **Catalog mode** (`resource` has `accepts[]`): we pick a requirement up
@@ -21,13 +21,13 @@ export interface UseArgs {
21
21
  guardrail: Guardrail;
22
22
  body?: unknown;
23
23
  headers?: Record<string, string>;
24
- /** AgenC hire settings (RPC, review window) used only for AgenC resources. */
24
+ /** AgenC hire settings (RPC, review window) - used only for AgenC resources. */
25
25
  agenc?: AgencHireConfig;
26
26
  }
27
27
  export declare function use(args: UseArgs): Promise<UseResult>;
28
28
  /**
29
29
  * Convenience: call any URL with x402 support. Agents can use this when they
30
- * have a URL but no catalog entry e.g. crawled from the web.
30
+ * have a URL but no catalog entry - e.g. crawled from the web.
31
31
  */
32
32
  export interface UseByUrlArgs {
33
33
  url: string;
@@ -40,8 +40,8 @@ export interface UseByUrlArgs {
40
40
  export declare function useByUrl(args: UseByUrlArgs): Promise<UseResult>;
41
41
  /**
42
42
  * Charge the xPay platform fee ($0.01 USDC) via the x402 endpoint.
43
- * Fires after every successful `use` call (including AgenC hires exported
44
- * for the agenc module). Non-fatal a failure is reported in
43
+ * Fires after every successful `use` call (including AgenC hires - exported
44
+ * for the agenc module). Non-fatal - a failure is reported in
45
45
  * `platformFee.error` rather than throwing.
46
46
  */
47
47
  export declare function chargePlatformFee(wallet: Wallet): Promise<PlatformFeeResult>;
package/dist/use/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Use call a paid resource, handling x402 payment end-to-end.
2
+ * Use - call a paid resource, handling x402 payment end-to-end.
3
3
  *
4
4
  * Two modes:
5
5
  * - **Catalog mode** (`resource` has `accepts[]`): we pick a requirement up
@@ -16,21 +16,21 @@ import { buildSvmPaymentHeader, isSvmNetwork } from "../x402/svm-payment.js";
16
16
  import { buildEvmPaymentHeader, hasEvmDomainParams, isEvmNetwork } from "../x402/evm-payment.js";
17
17
  import { isAgencResource } from "../agenc/api.js";
18
18
  export async function use(args) {
19
- // AgenC listings are not HTTP resources payment is an on-chain escrow
19
+ // AgenC listings are not HTTP resources - payment is an on-chain escrow
20
20
  // hire, so branch before any x402 catalog / live-challenge logic.
21
21
  if (isAgencResource(args.resource)) {
22
22
  const { useAgencHire } = await import("../agenc/hire.js");
23
23
  return useAgencHire(args);
24
24
  }
25
25
  // If we have accepts up front, pick the network we can actually pay on
26
- // (balance-aware) and take the fast path unless the chosen option is
26
+ // (balance-aware) and take the fast path - unless the chosen option is
27
27
  // missing fields that only a live 402 challenge carries.
28
28
  if (args.resource.accepts.length > 0) {
29
29
  const req = await args.wallet.pickRequirementByBalance(args.resource.accepts);
30
30
  if (req) {
31
31
  if (!reqNeedsLiveChallenge(args, req))
32
32
  return useWithRequirements(args, req);
33
- // Chosen option needs a live 402 (SVM v2 missing feePayer) fall through.
33
+ // Chosen option needs a live 402 (SVM v2 missing feePayer) - fall through.
34
34
  }
35
35
  else if (args.wallet.pickRequirement(args.resource.accepts)) {
36
36
  // We can sign for an option but no payable network has the funds.
@@ -41,7 +41,7 @@ export async function use(args) {
41
41
  return useWithLiveChallenge(args);
42
42
  }
43
43
  /**
44
- * Catalog entries are snapshots they carry payTo/asset/amount but not the
44
+ * Catalog entries are snapshots - they carry payTo/asset/amount but not the
45
45
  * per-facilitator settlement fields that only a fresh 402 challenge provides.
46
46
  * SVM v2 settlement needs `extra.feePayer` (the facilitator's fee-payer
47
47
  * pubkey); gasless EVM settlement needs the asset's EIP-712 domain params
@@ -75,7 +75,7 @@ export async function useByUrl(args) {
75
75
  });
76
76
  }
77
77
  async function useWithRequirements(args, req) {
78
- // Guardrail runs *before* signing this is the security boundary.
78
+ // Guardrail runs *before* signing - this is the security boundary.
79
79
  await args.guardrail.check({ resource: args.resource, requirement: req });
80
80
  const settled = await settle(args, req, args.resource.x402Version ?? 1);
81
81
  const res = await callResource(args, settled.header);
@@ -87,11 +87,11 @@ async function useWithLiveChallenge(args) {
87
87
  // Step 1: probe without payment.
88
88
  const probe = await callResource(args, undefined);
89
89
  if (probe.res.status !== 402) {
90
- // No payment required return the probe response as-is. (Useful when a
90
+ // No payment required - return the probe response as-is. (Useful when a
91
91
  // resource later becomes free or for sanity checks.)
92
92
  return finalize(probe, "unknown", "0");
93
93
  }
94
- // Step 2: parse the 402 challenge may live in the body OR a response header.
94
+ // Step 2: parse the 402 challenge - may live in the body OR a response header.
95
95
  const { accepts: reqs } = extractRequirements(probe.res.headers, probe.data);
96
96
  if (reqs.length === 0) {
97
97
  throw new Error(`xpay.use: ${args.resource.resource} returned 402 but no parseable accepts[] in body or headers`);
@@ -117,13 +117,13 @@ async function useWithLiveChallenge(args) {
117
117
  * value plus accounting fields. Picks the right encoding by network:
118
118
  *
119
119
  * SVM (solana / solana:*) + signer has getKitSigner →
120
- * canonical x402 v2 sign-but-don't-broadcast, header carries the
120
+ * canonical x402 v2 - sign-but-don't-broadcast, header carries the
121
121
  * signed tx, facilitator settles. Returns header only (no txSig until
122
122
  * the upstream call comes back).
123
123
  *
124
124
  * EVM (eip155:* / base / ethereum / …) + signer has signEvmTypedData +
125
125
  * requirement carries EIP-712 domain params →
126
- * canonical x402 v2 gasless EIP-3009 transferWithAuthorization
126
+ * canonical x402 v2 - gasless EIP-3009 transferWithAuthorization
127
127
  * signature in the header, facilitator broadcasts and pays gas.
128
128
  *
129
129
  * Anything else (legacy v1) →
@@ -142,7 +142,7 @@ async function settle(args, req, x402Version) {
142
142
  });
143
143
  return { header, network };
144
144
  }
145
- // Gasless EVM v2 sign an EIP-3009 transferWithAuthorization, facilitator
145
+ // Gasless EVM v2 - sign an EIP-3009 transferWithAuthorization, facilitator
146
146
  // broadcasts and pays gas. Needs the EIP-712 domain params from the 402
147
147
  // challenge; catalog snapshots without them were already routed through the
148
148
  // live flow by reqNeedsLiveChallenge().
@@ -157,7 +157,7 @@ async function settle(args, req, x402Version) {
157
157
  });
158
158
  return { header, network };
159
159
  }
160
- // Legacy path sign + broadcast on our side, send txSig in the header.
160
+ // Legacy path - sign + broadcast on our side, send txSig in the header.
161
161
  const txSig = await signer.pay(req);
162
162
  return { header: paymentHeader(req, txSig, x402Version), network, txSig };
163
163
  }
@@ -168,7 +168,7 @@ async function callResource(args, paymentHeader) {
168
168
  };
169
169
  if (paymentHeader) {
170
170
  // Most x402 servers read `X-PAYMENT`; some (e.g. Nansen) read
171
- // `Payment-Signature`. The payload is identical, so send both servers
171
+ // `Payment-Signature`. The payload is identical, so send both - servers
172
172
  // ignore the header name they don't recognise.
173
173
  headers["x-payment"] = paymentHeader;
174
174
  headers["payment-signature"] = paymentHeader;
@@ -195,7 +195,7 @@ async function callResource(args, paymentHeader) {
195
195
  }
196
196
  function finalize(raw, network, amountPaid, txSig) {
197
197
  if (!raw.res.ok) {
198
- throw new Error(`xpay.use: ${raw.res.status} ${raw.res.statusText} ${typeof raw.data === "string" ? raw.data : JSON.stringify(raw.data)}`);
198
+ throw new Error(`xpay.use: ${raw.res.status} ${raw.res.statusText} - ${typeof raw.data === "string" ? raw.data : JSON.stringify(raw.data)}`);
199
199
  }
200
200
  // For SVM v2 calls the facilitator broadcasts and echoes settlement details
201
201
  // in the `PAYMENT-RESPONSE` header. If present, prefer its signature over
@@ -233,8 +233,8 @@ const PLATFORM_FEE_URL = "https://api.xona-agent.com/platform-fee";
233
233
  const PLATFORM_FEE_AMOUNT = 0.01;
234
234
  /**
235
235
  * Charge the xPay platform fee ($0.01 USDC) via the x402 endpoint.
236
- * Fires after every successful `use` call (including AgenC hires exported
237
- * for the agenc module). Non-fatal a failure is reported in
236
+ * Fires after every successful `use` call (including AgenC hires - exported
237
+ * for the agenc module). Non-fatal - a failure is reported in
238
238
  * `platformFee.error` rather than throwing.
239
239
  */
240
240
  export async function chargePlatformFee(wallet) {
@@ -262,7 +262,7 @@ export async function chargePlatformFee(wallet) {
262
262
  if (!req) {
263
263
  return { amount: PLATFORM_FEE_AMOUNT, success: false, error: `platform-fee: wallet has no signer for ${reqs.map(r => r.network).join(", ")}` };
264
264
  }
265
- // Pay and retry use a minimal UseArgs stub (no guardrail needed for our own fee).
265
+ // Pay and retry - use a minimal UseArgs stub (no guardrail needed for our own fee).
266
266
  const network = normalizeNetwork(req.network);
267
267
  const signer = wallet.signer(network);
268
268
  let header;
@@ -302,13 +302,13 @@ export async function chargePlatformFee(wallet) {
302
302
  /**
303
303
  * Build a clear "you can't afford this" error listing the USDC balance on each
304
304
  * network the wallet could have paid on. Raised only when every payable option
305
- * is underfunded better than attempting a doomed payment and surfacing a raw
305
+ * is underfunded - better than attempting a doomed payment and surfacing a raw
306
306
  * 402 from the upstream provider.
307
307
  */
308
308
  async function insufficientBalanceError(reqs, wallet) {
309
309
  const nets = [...new Set(reqs.map((r) => normalizeNetwork(r.network)).filter((n) => wallet.has(n)))];
310
310
  const parts = await Promise.all(nets.map(async (n) => `${n} $${(await wallet.balance(n).catch(() => 0)).toFixed(2)}`));
311
- return new Error(`xpay.use: insufficient USDC balance to pay on any funded network ${parts.join(", ")}. ` +
311
+ return new Error(`xpay.use: insufficient USDC balance to pay on any funded network - ${parts.join(", ")}. ` +
312
312
  `Fund one of these and retry.`);
313
313
  }
314
314
  function normalizeNetwork(raw) {
@@ -324,7 +324,7 @@ function normalizeNetwork(raw) {
324
324
  return "robinhood";
325
325
  if (raw === "eip155:988")
326
326
  return "stable";
327
- // Solana CAIP any `solana:<genesis>` form collapses to our "solana" slug.
327
+ // Solana CAIP - any `solana:<genesis>` form collapses to our "solana" slug.
328
328
  if (raw === "solana" || raw.startsWith("solana:") || raw.startsWith("solana-"))
329
329
  return "solana";
330
330
  return raw;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Multi-network wallet. Thin facade over per-network {@link Signer}s.
3
3
  *
4
- * The wallet doesn't hold keys signers do. This module just exposes a
4
+ * The wallet doesn't hold keys - signers do. This module just exposes a
5
5
  * unified view (addresses, balances) and lets callers pick which network to
6
6
  * use for a given payment.
7
7
  */
@@ -28,7 +28,7 @@ export interface Wallet {
28
28
  pickRequirement(reqs: PaymentRequirement[]): PaymentRequirement | undefined;
29
29
  /**
30
30
  * Balance-aware picker. Among requirements we have a signer for, prefer the
31
- * first (in listed order) whose wallet balance covers the cost so a $0
31
+ * first (in listed order) whose wallet balance covers the cost - so a $0
32
32
  * Base wallet falls through to a funded Solana one. When there are multiple
33
33
  * payable networks but none can cover the cost, returns `undefined` so the
34
34
  * caller can raise a clear "insufficient balance" error instead of attempting
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Multi-network wallet. Thin facade over per-network {@link Signer}s.
3
3
  *
4
- * The wallet doesn't hold keys signers do. This module just exposes a
4
+ * The wallet doesn't hold keys - signers do. This module just exposes a
5
5
  * unified view (addresses, balances) and lets callers pick which network to
6
6
  * use for a given payment.
7
7
  */
@@ -18,7 +18,7 @@ export function createWallet(opts) {
18
18
  function matchNetwork(raw) {
19
19
  if (signers[raw])
20
20
  return raw;
21
- // Solana CAIP `solana:<genesis-hash>` (mainnet/devnet/testnet) → "solana".
21
+ // Solana CAIP - `solana:<genesis-hash>` (mainnet/devnet/testnet) → "solana".
22
22
  if ((raw === "solana" || raw.startsWith("solana:") || raw.startsWith("solana-")) && signers["solana"]) {
23
23
  return "solana";
24
24
  }
@@ -71,7 +71,7 @@ export function createWallet(opts) {
71
71
  return candidates[0];
72
72
  // Multiple payable networks: read each balance in parallel and pick the
73
73
  // first (listed order) that covers the cost. Compare assumes USDC
74
- // (6 decimals) the asset for virtually all x402 calls.
74
+ // (6 decimals) - the asset for virtually all x402 calls.
75
75
  const scored = await Promise.all(candidates.map(async (req) => {
76
76
  const net = matchNetwork(req.network);
77
77
  const bal = await balanceOf(net);