chain-insights 0.73.2 → 0.73.4

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/cli.cjs CHANGED
@@ -122,7 +122,7 @@ function fail(err) {
122
122
  function registerSubscriptionCommands(program, command) {
123
123
  program.command("subscription").description("Buy and check the Chain Insights subscription, paid in $CIA on Robinhood Chain").addCommand(command("topup").description("Show the wallet address and QR code to fund with $CIA and ETH on Robinhood Chain").option("--no-open", "Print the top-up page URL without opening a browser").option("--json", "Print machine-readable top-up facts").action(async (opts) => {
124
124
  try {
125
- const { runSubscriptionTopup } = await Promise.resolve().then(() => require("./topup--nWtDnWP.cjs"));
125
+ const { runSubscriptionTopup } = await Promise.resolve().then(() => require("./topup-DVTCU2le.cjs"));
126
126
  await runSubscriptionTopup(opts);
127
127
  } catch (err) {
128
128
  fail(err);
@@ -592,7 +592,7 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
592
592
  })).addCommand(createCliCommand("topup").description("Open a local browser page to top up the payment wallet").option("--no-open", "Print the top-up URL without opening a browser").option("--json", "Print machine-readable top-up metadata").action(async (opts) => {
593
593
  try {
594
594
  const { assertWalletKeyNotPublic, buildTopupInfo, getWalletAccount } = await Promise.resolve().then(() => require("./tools-Cmnq7yip.cjs")).then((n) => n.tools_exports);
595
- const { startTopupServer } = await Promise.resolve().then(() => require("./topup-server-BkGM8P99.cjs")).then((n) => n.topup_server_exports);
595
+ const { startTopupServer } = await Promise.resolve().then(() => require("./topup-server-f4Gx0vji.cjs")).then((n) => n.topup_server_exports);
596
596
  const account = await getWalletAccount();
597
597
  assertWalletKeyNotPublic(account);
598
598
  const url = await startTopupServer(account);
package/dist/cli.mjs CHANGED
@@ -120,7 +120,7 @@ function fail(err) {
120
120
  function registerSubscriptionCommands(program, command) {
121
121
  program.command("subscription").description("Buy and check the Chain Insights subscription, paid in $CIA on Robinhood Chain").addCommand(command("topup").description("Show the wallet address and QR code to fund with $CIA and ETH on Robinhood Chain").option("--no-open", "Print the top-up page URL without opening a browser").option("--json", "Print machine-readable top-up facts").action(async (opts) => {
122
122
  try {
123
- const { runSubscriptionTopup } = await import("./topup-CfFe1bGS.mjs");
123
+ const { runSubscriptionTopup } = await import("./topup-B6gZbTmv.mjs");
124
124
  await runSubscriptionTopup(opts);
125
125
  } catch (err) {
126
126
  fail(err);
@@ -590,7 +590,7 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
590
590
  })).addCommand(createCliCommand("topup").description("Open a local browser page to top up the payment wallet").option("--no-open", "Print the top-up URL without opening a browser").option("--json", "Print machine-readable top-up metadata").action(async (opts) => {
591
591
  try {
592
592
  const { assertWalletKeyNotPublic, buildTopupInfo, getWalletAccount } = await import("./tools-D9ep9E7Q.mjs").then((n) => n.p);
593
- const { startTopupServer } = await import("./topup-server-B0VKHslr.mjs").then((n) => n.r);
593
+ const { startTopupServer } = await import("./topup-server-BcT7DIpd.mjs").then((n) => n.r);
594
594
  const account = await getWalletAccount();
595
595
  assertWalletKeyNotPublic(account);
596
596
  const url = await startTopupServer(account);
package/dist/index.cjs CHANGED
@@ -3,8 +3,8 @@ const require_config = require("./config-BxtMoo9c.cjs");
3
3
  const require_wallet = require("./wallet-CgIAfdxL.cjs");
4
4
  const require_create = require("./create-DdggkF04.cjs");
5
5
  const require_tools = require("./tools-Cmnq7yip.cjs");
6
- const require_topup_server = require("./topup-server-C58eWflv.cjs");
7
- const require_topup_server$1 = require("./topup-server-BkGM8P99.cjs");
6
+ const require_topup_server = require("./topup-server-ShuYSyBY.cjs");
7
+ const require_topup_server$1 = require("./topup-server-f4Gx0vji.cjs");
8
8
  const require_client = require("./client-C9uwHnBS.cjs");
9
9
  exports.buildTopupInfo = require_tools.buildTopupInfo;
10
10
  exports.createMcpFetchClient = require_client.createMcpFetchClient;
package/dist/index.d.cts CHANGED
@@ -119,11 +119,22 @@ export declare function getWalletBalanceText(account?: PaymentWalletAccount): Pr
119
119
  export declare function buildTopupInfo(address: string, topupUrl?: string): TopupInfo;
120
120
  //#endregion
121
121
  //#region src/wallet/mcp-proxy/topup-server.d.ts
122
- export declare function generateArtifactHtml(walletAddressInput: string, topupUrl: string): string;
122
+ /**
123
+ * The top-up rails. base-usdc funds pay-per-call queries with USDC on Base;
124
+ * robinhood-cia funds the subscription with $CIA and ETH on Robinhood Chain.
125
+ * One local server per rail.
126
+ */
127
+ type TopupRail = 'base-usdc' | 'robinhood-cia';
128
+ export declare function generateArtifactHtml(walletAddressInput: string, topupUrl: string, rail?: TopupRail): string;
123
129
  //#endregion
124
130
  //#region src/wallet/topup-server.d.ts
125
131
  export declare function getTopupUrl(): string | null;
126
- export declare function startTopupServer(account: PaymentWalletAccount | string): Promise<string>;
132
+ /**
133
+ * The browser top-up page of `cia wallet topup` (rail base-usdc) and of
134
+ * `cia subscription topup` (rail robinhood-cia): one page, only its text
135
+ * differs by rail.
136
+ */
137
+ export declare function startTopupServer(account: PaymentWalletAccount | string, rail?: TopupRail): Promise<string>;
127
138
  //#endregion
128
139
  //#region src/mcp/client.d.ts
129
140
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/config/schema.ts","../src/config/index.ts","../src/wallet/index.ts","../src/wallet/create.ts","../src/wallet/tools.ts","../src/wallet/mcp-proxy/topup-server.ts","../src/wallet/topup-server.ts","../src/mcp/client.ts"],"mappings":";;;cA4Da,cAAY,EAAA;;;;;;;;;;;;;;;;GAcvB,EAAA,KAAA;KAEU,qBAAqB,EAAE,aAAa;;;wBC3B1B,cAAc,QAAQ;wBAMtB,WAAW,SAAS,QAAQ,sBAAsB;wBAsDlD,oBAAoB;;;wBCnF1B,0BAA0B,gBAAgB;wBAO1C,4BAA4B,qBAAqB;;;;;;;;wBAW3C,WAAW,qBAAqB;UAwBrC;;EAEf;;;;;;;;wBAuCoB,oBACpB,oBACA,UAAS,6BACR,QAAQ;;;;;;;wBAkEW,cAAc;;;;;wBAwCd,sBAAsB;;;UCnN3B;EACf;EACA;;wBAGc,4BAA4B;wBAI5B,wBAAwB;wBAQxB,0BACd,oBACA,UAAS;;;cCXE;cACA;UAgDI;EACf,SAAS;EACT,YAAY;;EAEZ;;UAGe;EACf;EACA;EACA,iBAAiB;EACjB;EACA,uBAAuB;EACvB;;UAoDe;EACf,SAAS;EACT;EACA;EACA,iBAAiB;EACjB;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;IACE,QAAQ;;;;;;;;wBASU,oBAAoB,QAAQ;wBAoB5B,eACpB,SAAS,kBACT,8BACC;wBAsBmB,cACpB,SAAS,kBACT,8BACC;wBAuQa,oBACd,iBACA,qBACA;wBAaoB,uBACpB,UAAU,uBACT,QAAQ;wBAyBK,0BAA0B,QAAQ;wBAK5B,qBAAqB,UAAU,uBAAuB;wBAI5D,eAAe,iBAAiB,oBAAoB;;;wBC3UpD,qBAAqB,4BAA4B;;;wBChFjD;wBAcM,iBAAiB,SAAS,gCAAgC;;;;;;;;;;;;;;;wBCkKhE,qBAAqB,2BAA2B,4BAAkB"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/config/schema.ts","../src/config/index.ts","../src/wallet/index.ts","../src/wallet/create.ts","../src/wallet/tools.ts","../src/wallet/mcp-proxy/topup-server.ts","../src/wallet/topup-server.ts","../src/mcp/client.ts"],"mappings":";;;cA4Da,cAAY,EAAA;;;;;;;;;;;;;;;;GAcvB,EAAA,KAAA;KAEU,qBAAqB,EAAE,aAAa;;;wBC3B1B,cAAc,QAAQ;wBAMtB,WAAW,SAAS,QAAQ,sBAAsB;wBAsDlD,oBAAoB;;;wBCnF1B,0BAA0B,gBAAgB;wBAO1C,4BAA4B,qBAAqB;;;;;;;;wBAW3C,WAAW,qBAAqB;UAwBrC;;EAEf;;;;;;;;wBAuCoB,oBACpB,oBACA,UAAS,6BACR,QAAQ;;;;;;;wBAkEW,cAAc;;;;;wBAwCd,sBAAsB;;;UCnN3B;EACf;EACA;;wBAGc,4BAA4B;wBAI5B,wBAAwB;wBAQxB,0BACd,oBACA,UAAS;;;cCXE;cACA;UAgDI;EACf,SAAS;EACT,YAAY;;EAEZ;;UAGe;EACf;EACA;EACA,iBAAiB;EACjB;EACA,uBAAuB;EACvB;;UAoDe;EACf,SAAS;EACT;EACA;EACA,iBAAiB;EACjB;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;IACE,QAAQ;;;;;;;;wBASU,oBAAoB,QAAQ;wBAoB5B,eACpB,SAAS,kBACT,8BACC;wBAsBmB,cACpB,SAAS,kBACT,8BACC;wBAuQa,oBACd,iBACA,qBACA;wBAaoB,uBACpB,UAAU,uBACT,QAAQ;wBAyBK,0BAA0B,QAAQ;wBAK5B,qBAAqB,UAAU,uBAAuB;wBAI5D,eAAe,iBAAiB,oBAAoB;;;;;;;;KC9cxD;wBAgKI,qBACd,4BACA,kBACA,OAAM;;;wBC9GQ;;;;;;wBAmBM,iBACpB,SAAS,+BACT,OAAM,YACL;;;;;;;;;;;;;;;wBCwJa,qBAAqB,2BAA2B,4BAAkB"}
package/dist/index.d.mts CHANGED
@@ -119,11 +119,22 @@ export declare function getWalletBalanceText(account?: PaymentWalletAccount): Pr
119
119
  export declare function buildTopupInfo(address: string, topupUrl?: string): TopupInfo;
120
120
  //#endregion
121
121
  //#region src/wallet/mcp-proxy/topup-server.d.ts
122
- export declare function generateArtifactHtml(walletAddressInput: string, topupUrl: string): string;
122
+ /**
123
+ * The top-up rails. base-usdc funds pay-per-call queries with USDC on Base;
124
+ * robinhood-cia funds the subscription with $CIA and ETH on Robinhood Chain.
125
+ * One local server per rail.
126
+ */
127
+ type TopupRail = 'base-usdc' | 'robinhood-cia';
128
+ export declare function generateArtifactHtml(walletAddressInput: string, topupUrl: string, rail?: TopupRail): string;
123
129
  //#endregion
124
130
  //#region src/wallet/topup-server.d.ts
125
131
  export declare function getTopupUrl(): string | null;
126
- export declare function startTopupServer(account: PaymentWalletAccount | string): Promise<string>;
132
+ /**
133
+ * The browser top-up page of `cia wallet topup` (rail base-usdc) and of
134
+ * `cia subscription topup` (rail robinhood-cia): one page, only its text
135
+ * differs by rail.
136
+ */
137
+ export declare function startTopupServer(account: PaymentWalletAccount | string, rail?: TopupRail): Promise<string>;
127
138
  //#endregion
128
139
  //#region src/mcp/client.d.ts
129
140
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/config/schema.ts","../src/config/index.ts","../src/wallet/index.ts","../src/wallet/create.ts","../src/wallet/tools.ts","../src/wallet/mcp-proxy/topup-server.ts","../src/wallet/topup-server.ts","../src/mcp/client.ts"],"mappings":";;;cA4Da,cAAY,EAAA;;;;;;;;;;;;;;;;GAcvB,EAAA,KAAA;KAEU,qBAAqB,EAAE,aAAa;;;wBC3B1B,cAAc,QAAQ;wBAMtB,WAAW,SAAS,QAAQ,sBAAsB;wBAsDlD,oBAAoB;;;wBCnF1B,0BAA0B,gBAAgB;wBAO1C,4BAA4B,qBAAqB;;;;;;;;wBAW3C,WAAW,qBAAqB;UAwBrC;;EAEf;;;;;;;;wBAuCoB,oBACpB,oBACA,UAAS,6BACR,QAAQ;;;;;;;wBAkEW,cAAc;;;;;wBAwCd,sBAAsB;;;UCnN3B;EACf;EACA;;wBAGc,4BAA4B;wBAI5B,wBAAwB;wBAQxB,0BACd,oBACA,UAAS;;;cCXE;cACA;UAgDI;EACf,SAAS;EACT,YAAY;;EAEZ;;UAGe;EACf;EACA;EACA,iBAAiB;EACjB;EACA,uBAAuB;EACvB;;UAoDe;EACf,SAAS;EACT;EACA;EACA,iBAAiB;EACjB;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;IACE,QAAQ;;;;;;;;wBASU,oBAAoB,QAAQ;wBAoB5B,eACpB,SAAS,kBACT,8BACC;wBAsBmB,cACpB,SAAS,kBACT,8BACC;wBAuQa,oBACd,iBACA,qBACA;wBAaoB,uBACpB,UAAU,uBACT,QAAQ;wBAyBK,0BAA0B,QAAQ;wBAK5B,qBAAqB,UAAU,uBAAuB;wBAI5D,eAAe,iBAAiB,oBAAoB;;;wBC3UpD,qBAAqB,4BAA4B;;;wBChFjD;wBAcM,iBAAiB,SAAS,gCAAgC;;;;;;;;;;;;;;;wBCkKhE,qBAAqB,2BAA2B,4BAAkB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/config/schema.ts","../src/config/index.ts","../src/wallet/index.ts","../src/wallet/create.ts","../src/wallet/tools.ts","../src/wallet/mcp-proxy/topup-server.ts","../src/wallet/topup-server.ts","../src/mcp/client.ts"],"mappings":";;;cA4Da,cAAY,EAAA;;;;;;;;;;;;;;;;GAcvB,EAAA,KAAA;KAEU,qBAAqB,EAAE,aAAa;;;wBC3B1B,cAAc,QAAQ;wBAMtB,WAAW,SAAS,QAAQ,sBAAsB;wBAsDlD,oBAAoB;;;wBCnF1B,0BAA0B,gBAAgB;wBAO1C,4BAA4B,qBAAqB;;;;;;;;wBAW3C,WAAW,qBAAqB;UAwBrC;;EAEf;;;;;;;;wBAuCoB,oBACpB,oBACA,UAAS,6BACR,QAAQ;;;;;;;wBAkEW,cAAc;;;;;wBAwCd,sBAAsB;;;UCnN3B;EACf;EACA;;wBAGc,4BAA4B;wBAI5B,wBAAwB;wBAQxB,0BACd,oBACA,UAAS;;;cCXE;cACA;UAgDI;EACf,SAAS;EACT,YAAY;;EAEZ;;UAGe;EACf;EACA;EACA,iBAAiB;EACjB;EACA,uBAAuB;EACvB;;UAoDe;EACf,SAAS;EACT;EACA;EACA,iBAAiB;EACjB;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;IACE,QAAQ;;;;;;;;wBASU,oBAAoB,QAAQ;wBAoB5B,eACpB,SAAS,kBACT,8BACC;wBAsBmB,cACpB,SAAS,kBACT,8BACC;wBAuQa,oBACd,iBACA,qBACA;wBAaoB,uBACpB,UAAU,uBACT,QAAQ;wBAyBK,0BAA0B,QAAQ;wBAK5B,qBAAqB,UAAU,uBAAuB;wBAI5D,eAAe,iBAAiB,oBAAoB;;;;;;;;KC9cxD;wBAgKI,qBACd,4BACA,kBACA,OAAM;;;wBC9GQ;;;;;;wBAmBM,iBACpB,SAAS,+BACT,OAAM,YACL;;;;;;;;;;;;;;;wBCwJa,qBAAqB,2BAA2B,4BAAkB"}
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { i as saveConfig, n as loadConfig, r as resetConfigCache } from "./confi
2
2
  import { a as setWalletPrivateKey, i as normalizeWalletPrivateKey, n as encryptKey, o as walletAddressFromPrivateKey, r as isWalletConfigured, t as decryptKey } from "./wallet-QTo5YCFR.mjs";
3
3
  import { i as isWalletBackupConfirmed, n as formatWalletBackupWarning, r as generateWalletPrivateKey } from "./create-CpfZq2fx.mjs";
4
4
  import { a as formatWalletBalanceResult, c as getWalletAccount, i as formatWalletBalance, l as getWalletBalanceResult, o as getBalanceEth, r as buildTopupInfo, s as getBalanceUsdc, u as getWalletBalanceText } from "./tools-D9ep9E7Q.mjs";
5
- import { n as generateArtifactHtml } from "./topup-server-RQ6-c92F.mjs";
6
- import { n as startTopupServer, t as getTopupUrl } from "./topup-server-B0VKHslr.mjs";
5
+ import { n as generateArtifactHtml } from "./topup-server-KQDviFXG.mjs";
6
+ import { n as startTopupServer, t as getTopupUrl } from "./topup-server-BcT7DIpd.mjs";
7
7
  import { i as createMcpFetchClient } from "./client-7qOfAdpH.mjs";
8
8
  export { buildTopupInfo, createMcpFetchClient, decryptKey, encryptKey, formatWalletBackupWarning, formatWalletBalance, formatWalletBalanceResult, generateArtifactHtml, generateWalletPrivateKey, getBalanceEth, getBalanceUsdc, getTopupUrl, getWalletAccount, getWalletBalanceResult, getWalletBalanceText, isWalletBackupConfirmed, isWalletConfigured, loadConfig, normalizeWalletPrivateKey, resetConfigCache, saveConfig, setWalletPrivateKey, startTopupServer, walletAddressFromPrivateKey };
@@ -1833,7 +1833,7 @@ async function createProxy() {
1833
1833
  };
1834
1834
  server.registerTool(tool.name, toolConfig, handler);
1835
1835
  }
1836
- const { registerTopupView, TOPUP_VIEW_URI } = await Promise.resolve().then(() => require("./topup-server-C58eWflv.cjs")).then((n) => n.topup_server_exports);
1836
+ const { registerTopupView, TOPUP_VIEW_URI } = await Promise.resolve().then(() => require("./topup-server-ShuYSyBY.cjs")).then((n) => n.topup_server_exports);
1837
1837
  await registerTopupView(server, { walletAddress: localTopupWalletAddress });
1838
1838
  server.registerResource("Chain Insights view", CLAUDE_VIEW_URI, {
1839
1839
  title: "Chain Insights view",
@@ -1829,7 +1829,7 @@ async function createProxy() {
1829
1829
  };
1830
1830
  server.registerTool(tool.name, toolConfig, handler);
1831
1831
  }
1832
- const { registerTopupView, TOPUP_VIEW_URI } = await import("./topup-server-RQ6-c92F.mjs").then((n) => n.a);
1832
+ const { registerTopupView, TOPUP_VIEW_URI } = await import("./topup-server-KQDviFXG.mjs").then((n) => n.a);
1833
1833
  await registerTopupView(server, { walletAddress: localTopupWalletAddress });
1834
1834
  server.registerResource("Chain Insights view", CLAUDE_VIEW_URI, {
1835
1835
  title: "Chain Insights view",
@@ -1,5 +1,6 @@
1
- import { i as startTopupServer, o as qrTerminalText, t as SUBSCRIPTION_TOPUP_TEXT } from "./topup-server-RQ6-c92F.mjs";
1
+ import { o as qrTerminalText, t as SUBSCRIPTION_TOPUP_TEXT } from "./topup-server-KQDviFXG.mjs";
2
2
  import { a as ROBINHOOD_NETWORK_DISPLAY, n as CIA_TOKEN_ADDRESS, r as ROBINHOOD_CHAIN_ID, t as CIA_SYMBOL } from "./robinhood-CCTMagwM.mjs";
3
+ import { n as startTopupServer } from "./topup-server-BcT7DIpd.mjs";
3
4
  //#region src/subscription/topup.ts
4
5
  function subscriptionTopupFacts(walletAddress, topupUrl) {
5
6
  return {
@@ -42,4 +43,4 @@ async function runSubscriptionTopup(opts) {
42
43
  //#endregion
43
44
  export { runSubscriptionTopup };
44
45
 
45
- //# sourceMappingURL=topup-CfFe1bGS.mjs.map
46
+ //# sourceMappingURL=topup-B6gZbTmv.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topup-B6gZbTmv.mjs","names":[],"sources":["../src/subscription/topup.ts"],"sourcesContent":["import { qrTerminalText } from '../wallet/mcp-proxy/qr.js'\nimport { SUBSCRIPTION_TOPUP_TEXT } from '../wallet/mcp-proxy/topup-server.js'\nimport { startTopupServer } from '../wallet/topup-server.js'\nimport {\n CIA_SYMBOL,\n CIA_TOKEN_ADDRESS,\n ROBINHOOD_CHAIN_ID,\n ROBINHOOD_NETWORK_DISPLAY,\n} from '../wallet/robinhood.js'\n\nexport interface SubscriptionTopupFacts {\n wallet_address: string\n network: typeof ROBINHOOD_NETWORK_DISPLAY\n chain_id: typeof ROBINHOOD_CHAIN_ID\n token: typeof CIA_SYMBOL\n token_contract: typeof CIA_TOKEN_ADDRESS\n gas_token: 'ETH'\n topup_url?: string\n}\n\nexport function subscriptionTopupFacts(walletAddress: string, topupUrl?: string): SubscriptionTopupFacts {\n return {\n wallet_address: walletAddress,\n network: ROBINHOOD_NETWORK_DISPLAY,\n chain_id: ROBINHOOD_CHAIN_ID,\n token: CIA_SYMBOL,\n token_contract: CIA_TOKEN_ADDRESS,\n gas_token: 'ETH',\n ...(topupUrl ? { topup_url: topupUrl } : {}),\n }\n}\n\n/** The terminal text of `cia subscription topup`: facts, then the QR code. */\nexport function subscriptionTopupText(facts: SubscriptionTopupFacts): string {\n return [\n ...(facts.topup_url ? [`Top-up page: ${facts.topup_url}`] : []),\n `Wallet: ${facts.wallet_address}`,\n `Network: ${facts.network} (chain ID ${facts.chain_id})`,\n `Token: ${facts.token} ${facts.token_contract}, and a little ETH for gas`,\n '',\n qrTerminalText(facts.wallet_address),\n '',\n SUBSCRIPTION_TOPUP_TEXT,\n ].join('\\n')\n}\n\n/** `cia subscription topup`: the user's own wallet, never the payment address. */\nexport async function runSubscriptionTopup(opts: { open?: boolean; json?: boolean }): Promise<void> {\n const { assertWalletKeyNotPublic, getWalletAccount } = await import('../wallet/tools.js')\n const account = await getWalletAccount()\n assertWalletKeyNotPublic(account)\n const url = await startTopupServer(account.address, 'robinhood-cia')\n const facts = subscriptionTopupFacts(account.address, url)\n console.log(opts.json ? JSON.stringify(facts, null, 2) : subscriptionTopupText(facts))\n if (!opts.json) console.log('Press Ctrl+C to stop the top-up page.')\n if (opts.open !== false) {\n const open = (await import('open')).default\n await open(url)\n }\n}\n"],"mappings":";;;;AAoBA,SAAgB,uBAAuB,eAAuB,UAA2C;CACvG,OAAO;EACL,gBAAgB;EAChB,SAAS;EACT,UAAU;EACV,OAAO;EACP,gBAAgB;EAChB,WAAW;EACX,GAAI,WAAW,EAAE,WAAW,SAAS,IAAI,CAAC;CAC5C;AACF;;AAGA,SAAgB,sBAAsB,OAAuC;CAC3E,OAAO;EACL,GAAI,MAAM,YAAY,CAAC,gBAAgB,MAAM,WAAW,IAAI,CAAC;EAC7D,gBAAgB,MAAM;EACtB,gBAAgB,MAAM,QAAQ,aAAa,MAAM,SAAS;EAC1D,gBAAgB,MAAM,MAAM,GAAG,MAAM,eAAe;EACpD;EACA,eAAe,MAAM,cAAc;EACnC;EACA;CACF,CAAC,CAAC,KAAK,IAAI;AACb;;AAGA,eAAsB,qBAAqB,MAAyD;CAClG,MAAM,EAAE,0BAA0B,qBAAqB,MAAM,OAAO,uBAAqB,CAAA,MAAA,MAAA,EAAA,CAAA;CACzF,MAAM,UAAU,MAAM,iBAAiB;CACvC,yBAAyB,OAAO;CAChC,MAAM,MAAM,MAAM,iBAAiB,QAAQ,SAAS,eAAe;CACnE,MAAM,QAAQ,uBAAuB,QAAQ,SAAS,GAAG;CACzD,QAAQ,IAAI,KAAK,OAAO,KAAK,UAAU,OAAO,MAAM,CAAC,IAAI,sBAAsB,KAAK,CAAC;CACrF,IAAI,CAAC,KAAK,MAAM,QAAQ,IAAI,uCAAuC;CACnE,IAAI,KAAK,SAAS,OAAO;EACvB,MAAM,QAAQ,MAAM,OAAO,QAAA,CAAS;EACpC,MAAM,KAAK,GAAG;CAChB;AACF"}
@@ -1,5 +1,6 @@
1
- const require_topup_server = require("./topup-server-C58eWflv.cjs");
1
+ const require_topup_server = require("./topup-server-ShuYSyBY.cjs");
2
2
  const require_robinhood = require("./robinhood-ChiT69sc.cjs");
3
+ const require_topup_server$1 = require("./topup-server-f4Gx0vji.cjs");
3
4
  //#region src/subscription/topup.ts
4
5
  function subscriptionTopupFacts(walletAddress, topupUrl) {
5
6
  return {
@@ -30,7 +31,7 @@ async function runSubscriptionTopup(opts) {
30
31
  const { assertWalletKeyNotPublic, getWalletAccount } = await Promise.resolve().then(() => require("./tools-Cmnq7yip.cjs")).then((n) => n.tools_exports);
31
32
  const account = await getWalletAccount();
32
33
  assertWalletKeyNotPublic(account);
33
- const url = await require_topup_server.startTopupServer(account.address, "robinhood-cia");
34
+ const url = await require_topup_server$1.startTopupServer(account.address, "robinhood-cia");
34
35
  const facts = subscriptionTopupFacts(account.address, url);
35
36
  console.log(opts.json ? JSON.stringify(facts, null, 2) : subscriptionTopupText(facts));
36
37
  if (!opts.json) console.log("Press Ctrl+C to stop the top-up page.");
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
2
- import { i as startTopupServer$1, n as generateArtifactHtml, r as getTopupUrl$1 } from "./topup-server-RQ6-c92F.mjs";
2
+ import { i as startTopupServer$1, n as generateArtifactHtml, r as getTopupUrl$1 } from "./topup-server-KQDviFXG.mjs";
3
3
  import { isAddress } from "viem";
4
4
  import { createServer } from "node:http";
5
5
  //#region src/wallet/topup-server.ts
@@ -70,10 +70,15 @@ async function stopTopupServer() {
70
70
  artifactServerState = null;
71
71
  await new Promise((resolve) => server.close(() => resolve()));
72
72
  }
73
- async function startTopupServer(account) {
73
+ /**
74
+ * The browser top-up page of `cia wallet topup` (rail base-usdc) and of
75
+ * `cia subscription topup` (rail robinhood-cia): one page, only its text
76
+ * differs by rail.
77
+ */
78
+ async function startTopupServer(account, rail = "base-usdc") {
74
79
  const walletAddress = toWalletAddress(account);
75
- if (artifactServerState && artifactServerState.address.toLowerCase() === walletAddress.toLowerCase()) return artifactServerState.url;
76
- const assetServerUrl = await startTopupServer$1(walletAddress);
80
+ if (artifactServerState && artifactServerState.rail === rail && artifactServerState.address.toLowerCase() === walletAddress.toLowerCase()) return artifactServerState.url;
81
+ const assetServerUrl = await startTopupServer$1(walletAddress, rail);
77
82
  if (artifactServerState) await stopTopupServer();
78
83
  const server = createServer((req, res) => {
79
84
  const reqUrl = req.url ?? "/";
@@ -91,7 +96,7 @@ async function startTopupServer(account) {
91
96
  const { pathname } = proxyTarget;
92
97
  if (pathname === "/" || pathname === "/index.html") {
93
98
  const artifactUrl = artifactServerState?.url ?? assetServerUrl;
94
- send(res, 200, generateArtifactHtml(walletAddress, artifactUrl), "text/html; charset=utf-8");
99
+ send(res, 200, generateArtifactHtml(walletAddress, artifactUrl, rail), "text/html; charset=utf-8");
95
100
  return;
96
101
  }
97
102
  if (pathname.startsWith("/assets/") || pathname.startsWith("/api/")) {
@@ -119,6 +124,7 @@ async function startTopupServer(account) {
119
124
  });
120
125
  artifactServerState = {
121
126
  address: walletAddress,
127
+ rail,
122
128
  assetServerUrl,
123
129
  server,
124
130
  url
@@ -128,4 +134,4 @@ async function startTopupServer(account) {
128
134
  //#endregion
129
135
  export { startTopupServer as n, topup_server_exports as r, getTopupUrl as t };
130
136
 
131
- //# sourceMappingURL=topup-server-B0VKHslr.mjs.map
137
+ //# sourceMappingURL=topup-server-BcT7DIpd.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topup-server-BcT7DIpd.mjs","names":["getCopiedTopupUrl","startCopiedTopupServer"],"sources":["../src/wallet/topup-server.ts"],"sourcesContent":["import {\n generateArtifactHtml,\n getTopupUrl as getCopiedTopupUrl,\n startTopupServer as startCopiedTopupServer,\n type TopupRail,\n} from './mcp-proxy/topup-server.js'\nimport { createServer, type Server, type ServerResponse } from 'node:http'\nimport { isAddress } from 'viem'\nimport type { PaymentWalletAccount } from './tools.js'\n\ninterface ArtifactServerState {\n address: string\n rail: TopupRail\n assetServerUrl: string\n server: Server\n url: string\n}\n\nlet artifactServerState: ArtifactServerState | null = null\nconst REQUEST_TARGET_BASE = 'http://localhost'\n\nclass ProxyRequestError extends Error {\n status: number\n\n constructor(status: number, message: string) {\n super(message)\n this.name = 'ProxyRequestError'\n this.status = status\n }\n}\n\ninterface NormalizedProxyTarget {\n pathAndSearch: string\n pathname: string\n}\n\nfunction toWalletAddress(account: PaymentWalletAccount | string): string {\n const address = typeof account === 'string' ? account : account.address\n if (!isAddress(address)) {\n throw new Error('Wallet address must be a valid 0x-prefixed 20-byte EVM address')\n }\n return address\n}\n\nfunction send(\n res: ServerResponse,\n status: number,\n body: string | Buffer,\n contentType: string\n): void {\n res.writeHead(status, {\n 'content-type': contentType,\n 'cache-control': 'no-store',\n 'access-control-allow-origin': '*',\n })\n res.end(body)\n}\n\nfunction normalizeProxyTarget(reqUrl: string): NormalizedProxyTarget {\n if (!reqUrl.startsWith('/') || reqUrl.startsWith('//')) {\n throw new ProxyRequestError(400, 'Proxy request target must be an origin-form path')\n }\n\n const parsed = new URL(reqUrl, REQUEST_TARGET_BASE)\n if (parsed.origin !== REQUEST_TARGET_BASE) {\n throw new ProxyRequestError(400, 'Absolute and protocol-relative proxy targets are not allowed')\n }\n\n let decodedPathname: string\n try {\n decodedPathname = decodeURIComponent(parsed.pathname)\n } catch {\n throw new ProxyRequestError(400, 'Proxy request target contains invalid encoding')\n }\n\n if (decodedPathname.startsWith('//') || /^\\/[a-z][a-z0-9+.-]*:\\/\\//i.test(decodedPathname)) {\n throw new ProxyRequestError(400, 'Encoded host override targets are not allowed')\n }\n\n return {\n pathAndSearch: `${parsed.pathname}${parsed.search}`,\n pathname: parsed.pathname,\n }\n}\n\nasync function proxyToCopiedServer(\n proxyTarget: NormalizedProxyTarget,\n res: ServerResponse,\n assetServerUrl: string\n): Promise<void> {\n const allowedOrigin = new URL(assetServerUrl).origin\n const upstreamUrl = new URL(proxyTarget.pathAndSearch, assetServerUrl)\n if (upstreamUrl.origin !== allowedOrigin) {\n throw new ProxyRequestError(403, 'Upstream origin is not allowed')\n }\n\n const upstream = await fetch(upstreamUrl)\n const contentType = upstream.headers.get('content-type') ?? 'application/octet-stream'\n const body = Buffer.from(await upstream.arrayBuffer())\n send(res, upstream.status, body, contentType)\n}\n\nexport { generateArtifactHtml }\n\nexport function getTopupArtifactUrl(): string | null {\n return artifactServerState?.url ?? null\n}\n\nexport function getTopupUrl(): string | null {\n return getTopupArtifactUrl() ?? getCopiedTopupUrl()\n}\n\nexport async function stopTopupServer(): Promise<void> {\n if (!artifactServerState) {\n return\n }\n\n const { server } = artifactServerState\n artifactServerState = null\n await new Promise<void>((resolve) => server.close(() => resolve()))\n}\n\n/**\n * The browser top-up page of `cia wallet topup` (rail base-usdc) and of\n * `cia subscription topup` (rail robinhood-cia): one page, only its text\n * differs by rail.\n */\nexport async function startTopupServer(\n account: PaymentWalletAccount | string,\n rail: TopupRail = 'base-usdc'\n): Promise<string> {\n const walletAddress = toWalletAddress(account)\n\n if (\n artifactServerState &&\n artifactServerState.rail === rail &&\n artifactServerState.address.toLowerCase() === walletAddress.toLowerCase()\n ) {\n return artifactServerState.url\n }\n\n const assetServerUrl = await startCopiedTopupServer(walletAddress, rail)\n\n if (artifactServerState) {\n await stopTopupServer()\n }\n\n const server = createServer((req, res) => {\n const reqUrl = req.url ?? '/'\n let proxyTarget: NormalizedProxyTarget\n try {\n proxyTarget = normalizeProxyTarget(reqUrl)\n } catch (err) {\n if (err instanceof ProxyRequestError) {\n send(\n res,\n err.status,\n JSON.stringify({ error: err.message }) + '\\n',\n 'application/json; charset=utf-8'\n )\n return\n }\n send(\n res,\n 400,\n JSON.stringify({ error: 'Invalid request target' }) + '\\n',\n 'application/json; charset=utf-8'\n )\n return\n }\n const { pathname } = proxyTarget\n\n if (pathname === '/' || pathname === '/index.html') {\n const artifactUrl = artifactServerState?.url ?? assetServerUrl\n send(res, 200, generateArtifactHtml(walletAddress, artifactUrl, rail), 'text/html; charset=utf-8')\n return\n }\n\n if (pathname.startsWith('/assets/') || pathname.startsWith('/api/')) {\n void proxyToCopiedServer(proxyTarget, res, assetServerUrl).catch((err) => {\n if (err instanceof ProxyRequestError) {\n send(\n res,\n err.status,\n JSON.stringify({ error: err.message }) + '\\n',\n 'application/json; charset=utf-8'\n )\n return\n }\n send(\n res,\n 502,\n JSON.stringify({ error: (err as Error).message }) + '\\n',\n 'application/json; charset=utf-8'\n )\n })\n return\n }\n\n send(res, 404, JSON.stringify({ error: 'Not found' }) + '\\n', 'application/json; charset=utf-8')\n })\n\n const url = await new Promise<string>((resolve, reject) => {\n server.once('error', reject)\n server.listen(0, '127.0.0.1', () => {\n const addressInfo = server.address()\n if (!addressInfo || typeof addressInfo === 'string') {\n reject(new Error('Failed to start topup artifact server'))\n return\n }\n resolve(`http://localhost:${addressInfo.port}`)\n })\n })\n\n artifactServerState = {\n address: walletAddress,\n rail,\n assetServerUrl,\n server,\n url,\n }\n\n return url\n}\n"],"mappings":"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"}
@@ -301,6 +301,9 @@ var topup_server_exports = /* @__PURE__ */ __exportAll({
301
301
  topupViewHtml: () => topupViewHtml
302
302
  });
303
303
  const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
304
+ const BASE_CHAIN_ID = "0x2105";
305
+ /** Robinhood Chain, chain ID 4663. */
306
+ const ROBINHOOD_CHAIN_ID_HEX = "0x1237";
304
307
  const __dirname = dirname(fileURLToPath(import.meta.url));
305
308
  function loadAsset(name) {
306
309
  const paths = [join(__dirname, "assets", name), join(__dirname, "..", "src", "assets", name)];
@@ -418,11 +421,35 @@ async function startTopupServer(wallet, rail = "base-usdc") {
418
421
  server.on("error", reject);
419
422
  });
420
423
  }
421
- function generateArtifactHtml(walletAddressInput, topupUrl) {
424
+ /**
425
+ * The text of the browser top-up page, per rail. The page is the wallet
426
+ * top-up page of `cia wallet topup` (aphex5, 2026-10-28: copy the wallet
427
+ * top-up page and change only Base Network to Robinhood Chain and $CIA):
428
+ * the logo, the background, the layout and the script never fork by rail.
429
+ */
430
+ const ARTIFACT_PAGE_TEXT = {
431
+ "base-usdc": {
432
+ subtitle: "Fund your wallet with USDC on Base",
433
+ badge: "Base Network &middot; USDC",
434
+ currency: "USDC",
435
+ balanceField: "balance_usdc",
436
+ gasNote: "Base ETH is used for one-time payment setup gas."
437
+ },
438
+ "robinhood-cia": {
439
+ subtitle: "Fund your wallet with $CIA on Robinhood Chain",
440
+ badge: "Robinhood Chain &middot; $CIA",
441
+ currency: "$CIA",
442
+ balanceField: "balance_cia",
443
+ gasNote: "Robinhood Chain ETH is used for the buy transaction gas."
444
+ }
445
+ };
446
+ function generateArtifactHtml(walletAddressInput, topupUrl, rail = "base-usdc") {
447
+ const text = ARTIFACT_PAGE_TEXT[rail];
422
448
  const walletAddress = assertWalletAddress(walletAddressInput);
423
449
  const safeWalletAddress = escapeHtml(walletAddress);
424
450
  const safeTopupUrl = escapeHtml(topupUrl);
425
451
  const topupUrlJson = jsonForScript(topupUrl);
452
+ const qrSvg = generateQrSvg(walletAddress, { cellSize: 8 });
426
453
  return `<!DOCTYPE html>
427
454
  <html lang="en">
428
455
  <head>
@@ -509,14 +536,14 @@ function generateArtifactHtml(walletAddressInput, topupUrl) {
509
536
  <body>
510
537
  <div class="card">
511
538
  <div class="logo"><img src="${safeTopupUrl}/assets/logo.png" alt="Chain Insights"></div>
512
- <p class="subtitle">Fund your wallet with USDC on Base</p>
513
- <div class="qr">${generateQrSvg(walletAddress, { cellSize: 8 })}</div>
539
+ <p class="subtitle">${text.subtitle}</p>
540
+ <div class="qr">${qrSvg}</div>
514
541
  <div class="address-wrap">
515
542
  <div class="address" id="addr" onclick="selectAndCopy()">${safeWalletAddress}</div>
516
543
  <div class="address-hint" id="addrHint">Click to copy address</div>
517
544
  </div>
518
- <div class="badge"><span class="dot"></span>Base Network &middot; USDC</div>
519
- <p class="balance-line" id="balLine">Current balance: <span class="amount" id="bal">--</span> USDC<br>Gas balance: <span class="gas" id="gas">--</span> ETH<br>Base ETH is used for one-time payment setup gas.</p>
545
+ <div class="badge"><span class="dot"></span>${text.badge}</div>
546
+ <p class="balance-line" id="balLine">Current balance: <span class="amount" id="bal">--</span> ${text.currency}<br>Gas balance: <span class="gas" id="gas">--</span> ETH<br>${text.gasNote}</p>
520
547
  </div>
521
548
  <script>
522
549
  // MCP Apps protocol handshake for the wallet top-up page.
@@ -579,9 +606,9 @@ function fetchBal() {
579
606
  var el = document.getElementById('bal');
580
607
  var gas = document.getElementById('gas');
581
608
  var line = document.getElementById('balLine');
582
- var val = parseFloat(d.balance_usdc || '0').toFixed(2);
609
+ var val = parseFloat(d.${text.balanceField} || '0').toFixed(2);
583
610
  var gasVal = d.balance_eth === 'unknown' ? '--' : parseFloat(d.balance_eth || '0').toFixed(6);
584
- if (d.balance_usdc === 'unknown') { el.textContent = '--'; gas.textContent = gasVal; return; }
611
+ if (d.${text.balanceField} === 'unknown') { el.textContent = '--'; gas.textContent = gasVal; return; }
585
612
  el.textContent = val;
586
613
  gas.textContent = gasVal;
587
614
  if (lastBal !== null && val !== lastBal) {
@@ -626,77 +653,49 @@ function selectAndCopy() {
626
653
  </body>
627
654
  </html>`;
628
655
  }
629
- /** The text of the subscription top-up page and of `cia subscription topup`. */
656
+ /** The text of `cia subscription topup` in the terminal. */
630
657
  const SUBSCRIPTION_TOPUP_TEXT = "Send $CIA and a little ETH on Robinhood Chain to your own wallet. Then run `cia subscription buy --days N`.";
631
658
  const TOPUP_PAGE_TEXT = {
632
659
  "base-usdc": {
633
660
  title: "Chain Insights — Fund Wallet",
634
661
  subtitle: "Fund your wallet to use blockchain intelligence tools",
635
662
  badge: "Base Network &middot; USDC",
636
- balances: [{
637
- id: "balance",
638
- label: "Current balance",
639
- currency: "USDC",
640
- field: "balance_usdc",
641
- decimals: 2
642
- }, {
643
- id: "gasBalance",
644
- label: "Gas balance",
645
- currency: "ETH",
646
- field: "balance_eth",
647
- decimals: 6
648
- }],
663
+ currency: "USDC",
664
+ balanceField: "balance_usdc",
649
665
  gasNote: "Base ETH is used for one-time payment setup gas.",
650
- info: "Send Base USDC to the wallet address above."
666
+ info: "Send Base USDC to the wallet address above.",
667
+ tokenAddress: USDC_ADDRESS,
668
+ chainIdHex: BASE_CHAIN_ID
651
669
  },
652
670
  "robinhood-cia": {
653
- title: "Chain Insights — Fund the subscription wallet",
654
- subtitle: "Fund your wallet for the Chain Insights subscription",
671
+ title: "Chain Insights — Fund Subscription Wallet",
672
+ subtitle: "Fund your wallet to buy a Chain Insights subscription",
655
673
  badge: "Robinhood Chain &middot; $CIA",
656
- balances: [{
657
- id: "balance",
658
- label: "Current balance",
659
- currency: "$CIA",
660
- field: "balance_cia",
661
- decimals: 2
662
- }, {
663
- id: "gasBalance",
664
- label: "Gas balance",
665
- currency: "ETH",
666
- field: "balance_eth",
667
- decimals: 6
668
- }],
669
- gasNote: "Robinhood Chain ETH pays the gas of the two buy transactions.",
670
- info: `Send \$CIA and a little ETH on Robinhood Chain to your own wallet. Then run <code>cia subscription buy --days N</code>.<br>Robinhood Chain (chain ID 4663) &middot; $CIA <code>${CIA_TOKEN_ADDRESS}</code><br>This page shows your own address only. It signs nothing and sends nothing.`
674
+ currency: "$CIA",
675
+ balanceField: "balance_cia",
676
+ gasNote: "Robinhood Chain ETH is used for the buy transaction gas.",
677
+ info: "Send $CIA and Robinhood Chain ETH to the wallet address above.",
678
+ tokenAddress: CIA_TOKEN_ADDRESS,
679
+ chainIdHex: ROBINHOOD_CHAIN_ID_HEX
671
680
  }
672
681
  };
673
682
  /**
674
- * The one local top-up page: the wallet address, its QR code (drawn here, no
675
- * script from outside), the network and the balances. It names only the
676
- * user's own wallet, never where a payment goes.
683
+ * The one local top-up page: the wallet address, its QR code, the network
684
+ * and the balances. It names only the user's own wallet, never where a
685
+ * payment goes.
677
686
  */
678
687
  function generateTopupPage(walletAddressInput, rail = "base-usdc") {
688
+ const text = TOPUP_PAGE_TEXT[rail];
679
689
  const walletAddress = assertWalletAddress(walletAddressInput);
680
690
  const safeWalletAddress = escapeHtml(walletAddress);
681
691
  const walletAddressJson = jsonForScript(walletAddress);
682
- const text = TOPUP_PAGE_TEXT[rail];
683
- const qrSvg = generateQrSvg(walletAddress, { cellSize: 5 });
684
- const balanceRows = text.balances.map((row) => ` <div class="balance-row">
685
- <span class="balance-label">${row.label}</span>
686
- <span class="balance-value" id="${row.id}">—<span class="currency">${row.currency}</span></span>
687
- </div>`).join("\n");
688
- const balancesJson = JSON.stringify(text.balances.map(({ id, currency, field, decimals }) => ({
689
- id,
690
- currency,
691
- field,
692
- decimals
693
- })));
694
692
  return `<!DOCTYPE html>
695
693
  <html lang="en">
696
694
  <head>
697
695
  <meta charset="utf-8">
698
696
  <meta name="viewport" content="width=device-width, initial-scale=1">
699
697
  <title>${text.title}</title>
698
+ <script src="https://cdn.jsdelivr.net/npm/qrcode-generator@1.4.4/qrcode.min.js"><\/script>
700
699
  <style>
701
700
  * { margin: 0; padding: 0; box-sizing: border-box; }
702
701
 
@@ -748,7 +747,7 @@ function generateTopupPage(walletAddressInput, rail = "base-usdc") {
748
747
  margin-bottom: 24px;
749
748
  }
750
749
 
751
- .qr-container svg, .qr-container canvas, .qr-container img {
750
+ .qr-container canvas, .qr-container img {
752
751
  border-radius: 12px;
753
752
  background: #fff;
754
753
  padding: 12px;
@@ -903,12 +902,6 @@ function generateTopupPage(walletAddressInput, rail = "base-usdc") {
903
902
  color: rgba(255, 255, 255, 0.3);
904
903
  line-height: 1.6;
905
904
  }
906
-
907
- .info code {
908
- font-family: 'SF Mono', 'Fira Code', monospace;
909
- color: #f2dda6;
910
- word-break: break-all;
911
- }
912
905
  </style>
913
906
  </head>
914
907
  <body>
@@ -919,7 +912,7 @@ function generateTopupPage(walletAddressInput, rail = "base-usdc") {
919
912
  </div>
920
913
 
921
914
  <div class="card">
922
- <div class="qr-container" id="qr">${qrSvg}</div>
915
+ <div class="qr-container" id="qr"></div>
923
916
 
924
917
  <div class="address-box">
925
918
  <code id="address">${safeWalletAddress}</code>
@@ -931,7 +924,14 @@ function generateTopupPage(walletAddressInput, rail = "base-usdc") {
931
924
  ${text.badge}
932
925
  </div>
933
926
 
934
- ${balanceRows}
927
+ <div class="balance-row">
928
+ <span class="balance-label">Current balance</span>
929
+ <span class="balance-value" id="balance">—<span class="currency">${text.currency}</span></span>
930
+ </div>
931
+ <div class="balance-row">
932
+ <span class="balance-label">Gas balance</span>
933
+ <span class="balance-value" id="gasBalance">—<span class="currency">ETH</span></span>
934
+ </div>
935
935
  <p class="gas-note">${text.gasNote}</p>
936
936
 
937
937
  <div class="status" id="status"></div>
@@ -942,14 +942,27 @@ ${balanceRows}
942
942
 
943
943
  <script>
944
944
  const WALLET = ${walletAddressJson};
945
- const BALANCES = ${balancesJson};
945
+ const USDC = '${text.tokenAddress}';
946
+ const CHAIN_ID = '${text.chainIdHex}';
947
+
948
+ // QR code
949
+ (function() {
950
+ var qr = qrcode(0, 'M');
951
+ qr.addData(WALLET);
952
+ qr.make();
953
+ document.getElementById('qr').innerHTML = qr.createSvgTag(5, 0);
954
+ var svg = document.querySelector('#qr svg');
955
+ if (svg) { svg.style.borderRadius = '12px'; svg.style.background = '#fff'; svg.style.padding = '12px'; }
956
+ })();
946
957
 
947
958
  // Copy address — fallback for sandboxed iframes where navigator.clipboard is blocked
948
959
  function copyAddress() {
949
960
  var ok = false;
961
+ // Try modern clipboard API first
950
962
  if (navigator.clipboard && navigator.clipboard.writeText) {
951
963
  navigator.clipboard.writeText(WALLET).then(function() { ok = true; }).catch(function() {});
952
964
  }
965
+ // Fallback: hidden textarea + execCommand
953
966
  if (!ok) {
954
967
  var ta = document.createElement('textarea');
955
968
  ta.value = WALLET;
@@ -966,18 +979,20 @@ function copyAddress() {
966
979
  setTimeout(function() { btn.classList.remove('copied'); btn.innerHTML = '&#x2398;'; }, 2000);
967
980
  }
968
981
 
969
- function showBalance(row, value) {
970
- document.getElementById(row.id).innerHTML = value + '<span class="currency">' + row.currency + '</span>';
971
- }
972
-
973
- // Fetch balances
982
+ // Fetch balance
974
983
  async function fetchBalance() {
975
- var json = {};
976
- try { json = await (await fetch('/api/balance')).json(); } catch(e) {}
977
- BALANCES.forEach(function(row) {
978
- var raw = json[row.field];
979
- showBalance(row, raw === undefined || raw === 'unknown' ? '—' : Number(raw || 0).toFixed(row.decimals));
980
- });
984
+ try {
985
+ var resp = await fetch('/api/balance');
986
+ var json = await resp.json();
987
+ if (json.${text.balanceField} === 'unknown') throw new Error('balance unavailable');
988
+ var balance = Number(json.${text.balanceField} || 0).toFixed(2);
989
+ document.getElementById('balance').innerHTML = balance + '<span class="currency">${text.currency}</span>';
990
+ var gasBalance = json.balance_eth === 'unknown' ? '—' : Number(json.balance_eth || 0).toFixed(6);
991
+ document.getElementById('gasBalance').innerHTML = gasBalance + '<span class="currency">ETH</span>';
992
+ } catch(e) {
993
+ document.getElementById('balance').innerHTML = '—<span class="currency">${text.currency}</span>';
994
+ document.getElementById('gasBalance').innerHTML = '—<span class="currency">ETH</span>';
995
+ }
981
996
  }
982
997
  fetchBalance();
983
998
  setInterval(fetchBalance, 15000);
@@ -1426,4 +1441,4 @@ async function registerTopupView(server, deps) {
1426
1441
  //#endregion
1427
1442
  export { topup_server_exports as a, startTopupServer as i, generateArtifactHtml as n, qrTerminalText as o, getTopupUrl as r, SUBSCRIPTION_TOPUP_TEXT as t };
1428
1443
 
1429
- //# sourceMappingURL=topup-server-RQ6-c92F.mjs.map
1444
+ //# sourceMappingURL=topup-server-KQDviFXG.mjs.map