openzoo 0.49.14 → 0.49.16

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/lib/config.js CHANGED
@@ -54,27 +54,45 @@ export const LEOS_MINT = FUNDING_ASSETS[2].mint;
54
54
  /**
55
55
  * EVM-side balances `openzoo balance` reports, grouped by rail. `usd` is a
56
56
  * known price (stables); null means "no honest price here" and the CLI prints
57
- * `?` rather than inventing one. The memecoins are Robinhood Chain ERC-20s
58
- * (18 decimals, verified on-chain 2026-08-14); their wrapped x402 twins are
59
- * in-deploy and will appear in the 402 itself when live.
57
+ * `?` rather than inventing one.
58
+ *
59
+ * ONLY LIST WHAT THE 402 ACCEPTS. The Robinhood memecoins (ODDBALLER / IOU /
60
+ * ROBINHOODS) were removed 2026-08-24 along with every wrapped rail: they were
61
+ * only ever payable through X402Wrapper twins the payer had to mint first, and
62
+ * the gateway no longer offers them. Reporting a balance the user cannot spend
63
+ * reads as "you have funds" and then fails at payment.
60
64
  */
61
65
  export const EVM_FUNDING_ASSETS = {
62
66
  base: [
63
67
  { symbol: 'USDC', address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', decimals: 6, usd: 1 },
64
68
  ],
65
69
  robinhood: [
70
+ // Canonical Paxos USDG, pinned by ADDRESS: six impersonators on this chain
71
+ // answer symbol() == "USDG" with 41k-111k holders each.
66
72
  { symbol: 'USDG', address: '0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168', decimals: 6, usd: 1 },
67
- { symbol: 'ODDBALLER', address: '0x923eb7BD5B84a1a114CB57212cE2F2e87AE60E2A', decimals: 18, usd: null },
68
- // note rides into the banner CA block: IOU is accepted by design, but its
69
- // 402 row fails closed whenever DexScreener has no pool to price it from.
70
- { symbol: 'IOU', address: '0xf391999FACbEE613D4024191Dd31060540BF0bEd', decimals: 18, usd: null, note: 'accepted — quoting paused while its price feed is down' },
71
- { symbol: 'ROBINHOODS', address: '0xC42cF61C16aaC797b991cf9C1ac8Ae70bA74A286', decimals: 18, usd: null },
73
+ ],
74
+ arbitrum: [
75
+ { symbol: 'USDC', address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', decimals: 6, usd: 1 },
76
+ ],
77
+ optimism: [
78
+ { symbol: 'USDC', address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', decimals: 6, usd: 1 },
79
+ ],
80
+ world: [
81
+ { symbol: 'USDC', address: '0x79A02482A880bCE3F13e09Da970dC34db4CD24d1', decimals: 6, usd: 1 },
72
82
  ],
73
83
  };
74
84
 
75
85
  /** RPC endpoint for an EVM rail name. */
76
86
  export function evmRpcFor(rail) {
77
- return rail === 'base' ? config.baseRpcUrl : rail === 'robinhood' ? config.rhRpcUrl : null;
87
+ // A rail with no RPC here reports NO balance at all — silently. Every entry
88
+ // in EVM_FUNDING_ASSETS needs a row, or `openzoo balance` just omits the
89
+ // chain and the user concludes they hold nothing there.
90
+ if (rail === 'base') return config.baseRpcUrl;
91
+ if (rail === 'robinhood') return config.rhRpcUrl;
92
+ if (rail === 'arbitrum') return process.env.OPENZOO_ARBITRUM_RPC || 'https://arb1.arbitrum.io/rpc';
93
+ if (rail === 'optimism') return process.env.OPENZOO_OPTIMISM_RPC || 'https://mainnet.optimism.io';
94
+ if (rail === 'world') return process.env.OPENZOO_WORLD_RPC || 'https://worldchain-mainnet.gateway.tenderly.co';
95
+ return null;
78
96
  }
79
97
 
80
98
  /**
@@ -103,11 +121,10 @@ export function fundingLine(address) {
103
121
  export const RAIL_FUNDING = {
104
122
  solana: { label: 'Solana', assets: ['USDC', 'TOKEN', 'LEOS'] },
105
123
  base: { label: 'Base', assets: ['USDC'] },
106
- robinhood: {
107
- label: 'Robinhood Chain',
108
- assets: ['USDG', 'ODDBALLER', 'IOU', 'ROBINHOODS'],
109
- note: 'plus a sliver of RH ETH for the conversion gas',
110
- },
124
+ robinhood: { label: 'Robinhood Chain', assets: ['USDG'] },
125
+ arbitrum: { label: 'Arbitrum', assets: ['USDC'] },
126
+ optimism: { label: 'Optimism', assets: ['USDC'] },
127
+ world: { label: 'World Chain', assets: ['USDC'] },
111
128
  };
112
129
 
113
130
  /**
package/lib/info.js CHANGED
@@ -13,7 +13,15 @@ export function printAddress() {
13
13
  console.log(`evm (Base · Robinhood) : ${privateKeyToAccount(evmPrivateKey).address}`);
14
14
  }
15
15
 
16
- const CHAIN_LABEL = { base: 'Base', robinhood: 'Robinhood Chain' };
16
+ // Every rail in EVM_FUNDING_ASSETS needs an entry or the header prints the raw
17
+ // key ("arbitrum") instead of a name.
18
+ const CHAIN_LABEL = {
19
+ base: 'Base',
20
+ robinhood: 'Robinhood Chain',
21
+ arbitrum: 'Arbitrum',
22
+ optimism: 'Optimism',
23
+ world: 'World Chain',
24
+ };
17
25
 
18
26
  function fmtUi(raw, decimals) {
19
27
  return Number(raw) / 10 ** decimals;
package/lib/openclaw.js CHANGED
@@ -90,6 +90,28 @@ export function mergeOpenClawConfig(existing, { port, entries, defaultId, forceD
90
90
  api: 'openai-completions',
91
91
  models: entries,
92
92
  };
93
+ // REPAIR WIZARD-CREATED ZOO PROVIDERS TOO. OpenClaw's own Custom Provider
94
+ // flow points at the zoo but ignores what /v1/models says: cost is
95
+ // hard-coded $0.00 and contextWindow defaults to 128k — measured
96
+ // 2026-08-24 on a `custom-x402-tokens-fly-dev` provider whose status line
97
+ // read "0/128k" while every zoo model is client-usable to 128M via spill.
98
+ // Any OTHER provider whose baseUrl is a zoo endpoint gets its model rows
99
+ // fixed in place (window always; cost only when the id is in our entries).
100
+ const ZOO_BASE_RE = /localhost:8402|127\.0\.0\.1:8402|x402-tokens\.fly\.dev|api\.openzoo\.fun/i;
101
+ const repaired = [];
102
+ const costById = new Map(entries.map((e) => [e.id, e.cost]));
103
+ for (const [name, prov] of Object.entries(cfg.models.providers)) {
104
+ if (name === PROVIDER_KEY || !prov || typeof prov !== 'object') continue;
105
+ if (!ZOO_BASE_RE.test(String(prov.baseUrl || ''))) continue;
106
+ for (const m of Array.isArray(prov.models) ? prov.models : []) {
107
+ let touched = false;
108
+ if (Number(m.contextWindow) < 128_000_000) { m.contextWindow = 128_000_000; touched = true; }
109
+ const bare = String(m.id || '').replace(/^openzoo[-/]/i, '');
110
+ const cost = costById.get(m.id) || costById.get(bare);
111
+ if (cost && (!m.cost || (!m.cost.input && !m.cost.output))) { m.cost = { ...cost }; touched = true; }
112
+ if (touched) repaired.push(`${name}/${m.id}`);
113
+ }
114
+ }
93
115
  let changedDefault = false;
94
116
  const ref = defaultId ? `${PROVIDER_KEY}/${defaultId}` : null;
95
117
  if (ref) {
@@ -104,7 +126,7 @@ export function mergeOpenClawConfig(existing, { port, entries, defaultId, forceD
104
126
  changedDefault = true;
105
127
  }
106
128
  }
107
- return { cfg, changedDefault };
129
+ return { cfg, changedDefault, repaired };
108
130
  }
109
131
 
110
132
  async function fetchCatalogRows() {
@@ -174,7 +196,7 @@ export async function setupOpenClaw(argv = []) {
174
196
  fs.mkdirSync(path.dirname(file), { recursive: true });
175
197
  }
176
198
 
177
- const { cfg, changedDefault } = mergeOpenClawConfig(existing, {
199
+ const { cfg, changedDefault, repaired } = mergeOpenClawConfig(existing, {
178
200
  port: config.port,
179
201
  entries,
180
202
  defaultId,
@@ -183,6 +205,9 @@ export async function setupOpenClaw(argv = []) {
183
205
  fs.writeFileSync(file, `${JSON.stringify(cfg, null, 2)}\n`);
184
206
 
185
207
  console.log(`wrote ${entries.length} zoo model(s) with real ceiling prices into ${file}`);
208
+ for (const r of repaired || []) {
209
+ console.log(` repaired wizard-created zoo provider entry: ${r} (contextWindow -> 128M, cost when known)`);
210
+ }
186
211
  for (const e of entries) {
187
212
  console.log(` ${PROVIDER_KEY}/${e.id} $${e.cost.input}/Mtok in, $${e.cost.output}/Mtok out`);
188
213
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.49.14",
3
+ "version": "0.49.16",
4
4
  "description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
5
5
  "license": "MIT",
6
6
  "type": "module",