mycomesh-consumer 0.5.1 → 0.6.1

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.
@@ -7,6 +7,21 @@
7
7
  "registry": "0x0ff3210e8e8abf5f5bfa73a39e60db7416b6c8c7",
8
8
  "relay_directory": "0xa0aaad9393f51cb5786c69f152133a174588bdab",
9
9
  "probe_ledger": "0x30055eae6645cce8754f834a17689d20a3795ca3",
10
+ "tiers": {
11
+ "1": {
12
+ "name": "OpenAI frontier",
13
+ "models": [
14
+ "gpt-5.5"
15
+ ]
16
+ },
17
+ "2": {
18
+ "name": "Anthropic Claude",
19
+ "models": [
20
+ "claude-sonnet-4-6",
21
+ "claude-opus-4-8"
22
+ ]
23
+ }
24
+ },
10
25
  "deployment_block": 11809185,
11
26
  "rpc_urls": [
12
27
  "https://ethereum-sepolia-rpc.publicnode.com",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mycomesh-consumer",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "MycoMesh V11 Consumer: a custodied deposit, relay-blind encrypted requests to any Provider, and a local OpenAI-compatible endpoint.",
5
5
  "repository": {
6
6
  "type": "git",
package/src/console.mjs CHANGED
@@ -7,6 +7,7 @@ import { listRequests, loadRequest } from "./disputes.mjs";
7
7
  import { outputText } from "./protocol.mjs";
8
8
  import { createWallet, ownerAddress, unlockWallet, walletAddress } from "./wallet.mjs";
9
9
  import { addTenant, loadTenants, revokeTenant, setBudget, tenantStatus } from "./tenants.mjs";
10
+ import { networkPrices } from "./pricing.mjs";
10
11
 
11
12
  const PAGE = new URL("./web/console.html", import.meta.url);
12
13
 
@@ -52,6 +53,7 @@ export function consoleRoutes({ consumer, dataDir }) {
52
53
  for (const relay of relays) for (const provider of relay.providers) provider.reputation = records[provider.signer] || null;
53
54
  return { relays };
54
55
  },
56
+ "GET /api/pricing": async () => ({ tiers: await networkPrices(network) }),
55
57
  "GET /api/history": async () => {
56
58
  const entries = listRequests(dataDir, outputText, 50);
57
59
  await Promise.all(entries.map(async (entry) => {
@@ -0,0 +1,35 @@
1
+ // Network prices per tier (see ProviderJuryRegistryV11): base price x a multiplier that follows daily utilisation.
2
+ import { encodeCall } from "./eip712.mjs";
3
+ import { rpcCall } from "./chain.mjs";
4
+
5
+ const EPOCH = 86_400;
6
+ const UNIT = 1_000_000n;
7
+
8
+ async function words(network, signature, pairs) {
9
+ const raw = (await rpcCall(network.rpc_urls, "eth_call", [{ to: network.registry, data: encodeCall(signature, pairs) }, "latest"])).slice(2);
10
+ return Array.from({ length: raw.length / 64 }, (_, i) => BigInt(`0x${raw.slice(i * 64, i * 64 + 64)}`));
11
+ }
12
+
13
+ /** Every tier the manifest names, with today's prices and the utilisation that set them. */
14
+ export async function networkPrices(network) {
15
+ const block = await rpcCall(network.rpc_urls, "eth_getBlockByNumber", ["latest", false]);
16
+ const today = BigInt(Math.floor(Number(BigInt(block.timestamp)) / EPOCH));
17
+ const tiers = [];
18
+ for (const [id, meta] of Object.entries(network.tiers || {})) {
19
+ const tier = BigInt(id);
20
+ const [baseIn, baseOut, minFee, , targetBps, active] = await words(network, "tiers(uint32)", [["uint", tier]]);
21
+ if (!active) continue;
22
+ const multiplier = (await words(network, "multiplierFor(uint32,uint64)", [["uint", tier], ["uint", today]]))[0];
23
+ const previous = (await words(network, "multiplierFor(uint32,uint64)", [["uint", tier], ["uint", today - 1n]]))[0];
24
+ const [demand] = await words(network, "demandAt(uint32,uint64)", [["uint", tier], ["uint", today - 1n]]);
25
+ const [supply] = await words(network, "supplyAt(uint32,uint64)", [["uint", tier], ["uint", today - 1n]]);
26
+ const scale = (value) => ((value * multiplier + UNIT - 1n) / UNIT).toString();
27
+ tiers.push({
28
+ tier: Number(tier), name: meta.name, models: meta.models, target_bps: Number(targetBps),
29
+ multiplier: Number(multiplier), multiplier_yesterday: Number(previous),
30
+ prices: { input_per_1k: scale(baseIn), output_per_1k: scale(baseOut), minimum_fee: scale(minFee) },
31
+ yesterday: { demand: demand.toString(), supply: supply.toString(), utilization_bps: supply ? Number((demand * 10_000n) / supply) : 0 },
32
+ });
33
+ }
34
+ return tiers;
35
+ }
@@ -120,6 +120,10 @@
120
120
  <section id="tab-network">
121
121
  <p class="muted">Relay 来自内置清单和链上 Relay 目录,本机逐个核对签名身份;自签证书的 Relay 按链上登记的指纹核验,不依赖证书机构。
122
122
  选择 Provider 时先看链上能证明的:近期是否被确认欺诈、经本机重新判分的探针失败率、累计干净成交,最后才看价格。价格单位:每 1000 个 token 的 tUSDC。</p>
123
+ <h2 style="margin-top:0">网络价格</h2>
124
+ <p class="muted">全网统一价,像比特币难度一样每天自动调整:前一天的利用率(成交 ÷ 在线产能)高于目标就涨,低于就降,单日最多 ±10%。</p>
125
+ <table style="margin-bottom:22px"><thead><tr><th>档位</th><th>模型</th><th>输入 / 1k</th><th>输出 / 1k</th><th>最低</th><th>价格系数</th><th>昨日利用率 / 目标</th></tr></thead>
126
+ <tbody id="pricing"></tbody></table>
123
127
  <div id="network"></div>
124
128
  </section>
125
129
  </main>
@@ -331,7 +335,18 @@ async function refreshHistory() {
331
335
  }
332
336
 
333
337
  // ---------------- network ----------------
338
+ async function refreshPricing() {
339
+ const { tiers } = await api("/api/pricing");
340
+ $("pricing").innerHTML = tiers.map((t) => {
341
+ const change = t.multiplier_yesterday ? (t.multiplier / t.multiplier_yesterday - 1) * 100 : 0;
342
+ const arrow = change > 0.05 ? `<span style="color:var(--warn)">▲ ${change.toFixed(1)}%</span>` : change < -0.05 ? `<span style="color:var(--accent)">▼ ${(-change).toFixed(1)}%</span>` : "持平";
343
+ return `<tr><td>${t.name}</td><td>${t.models.join(", ")}</td><td>${fmt(t.prices.input_per_1k)}</td><td>${fmt(t.prices.output_per_1k)}</td>
344
+ <td>${fmt(t.prices.minimum_fee)}</td><td>${(t.multiplier / 1e6).toFixed(3)}× ${arrow}</td>
345
+ <td>${(t.yesterday.utilization_bps / 100).toFixed(1)}% / ${(t.target_bps / 100).toFixed(0)}%</td></tr>`;
346
+ }).join("") || `<tr><td colspan="7" class="muted">这个网络还没有启用网络定价。</td></tr>`;
347
+ }
334
348
  async function refreshNetwork() {
349
+ refreshPricing().catch(() => {});
335
350
  const { relays } = await api("/api/network");
336
351
  $("relays").textContent = `Relay ${relays.filter((r) => r.healthy).length}/${relays.length}`;
337
352
  $("relays").className = relays.some((r) => r.healthy) ? "badge ok" : "badge";