@candledottv/cli 0.13.2 → 0.13.3

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 (3) hide show
  1. package/README.md +2 -0
  2. package/dist/index.js +1071 -186
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -524,7 +524,7 @@ var init_terminal_theme = __esm(() => {
524
524
  });
525
525
 
526
526
  // src/version.ts
527
- var CLI_VERSION = "0.13.2";
527
+ var CLI_VERSION = "0.13.3";
528
528
 
529
529
  // src/presentation.ts
530
530
  function terminalStyle(deps, stream, machine = false) {
@@ -56836,17 +56836,17 @@ var require_stream = __commonJS((exports) => {
56836
56836
  this.view[this.start] = char;
56837
56837
  this.start += 1;
56838
56838
  }
56839
- appendUint16(num) {
56839
+ appendUint16(num2) {
56840
56840
  this.ensureCapacity(2);
56841
- const value = new Uint16Array([num]);
56841
+ const value = new Uint16Array([num2]);
56842
56842
  const view = new Uint8Array(value.buffer);
56843
56843
  this.view[this.start] = view[1];
56844
56844
  this.view[this.start + 1] = view[0];
56845
56845
  this.start += 2;
56846
56846
  }
56847
- appendUint24(num) {
56847
+ appendUint24(num2) {
56848
56848
  this.ensureCapacity(3);
56849
- const value = new Uint32Array([num]);
56849
+ const value = new Uint32Array([num2]);
56850
56850
  const view = new Uint8Array(value.buffer);
56851
56851
  this.view[this.start] = view[2];
56852
56852
  this.view[this.start + 1] = view[1];
@@ -57091,9 +57091,9 @@ var require_tag = __commonJS((exports) => {
57091
57091
  isUniversal() {
57092
57092
  return this.class === TAG_CLASS.UNIVERSAL;
57093
57093
  }
57094
- isContextSpecific(num) {
57094
+ isContextSpecific(num2) {
57095
57095
  const res = this.class === TAG_CLASS.CONTEXT_SPECIFIC;
57096
- return num !== undefined ? res && this.number === num : res;
57096
+ return num2 !== undefined ? res && this.number === num2 : res;
57097
57097
  }
57098
57098
  isBoolean() {
57099
57099
  return this.isUniversal() && this.number === UNIVERSAL_TAG.BOOLEAN;
@@ -58780,14 +58780,14 @@ var require_key = __commonJS((exports) => {
58780
58780
  value: ext.subs[ext.subs.length - 1].value
58781
58781
  };
58782
58782
  });
58783
- const identity3 = {
58783
+ const identity4 = {
58784
58784
  extensions: { issuer },
58785
58785
  subjectAlternativeName: cert.subjectAltName,
58786
58786
  oids
58787
58787
  };
58788
58788
  return {
58789
58789
  key: core_1.crypto.createPublicKey(cert.publicKey),
58790
- identity: identity3
58790
+ identity: identity4
58791
58791
  };
58792
58792
  }
58793
58793
  });
@@ -59555,8 +59555,8 @@ var require_merkle = __commonJS((exports) => {
59555
59555
  function innerProofSize(index, size) {
59556
59556
  return bitLength(index ^ size - BigInt(1));
59557
59557
  }
59558
- function onesCount(num) {
59559
- return num.toString(2).split("1").length - 1;
59558
+ function onesCount(num2) {
59559
+ return num2.toString(2).split("1").length - 1;
59560
59560
  }
59561
59561
  function bitLength(n) {
59562
59562
  if (n === 0n) {
@@ -59803,15 +59803,15 @@ var require_verifier2 = __commonJS((exports) => {
59803
59803
  });
59804
59804
  }
59805
59805
  }
59806
- verifyPolicy(policy, identity3) {
59806
+ verifyPolicy(policy, identity4) {
59807
59807
  if (policy.subjectAlternativeName) {
59808
- (0, policy_1.verifySubjectAlternativeName)(policy.subjectAlternativeName, identity3.subjectAlternativeName);
59808
+ (0, policy_1.verifySubjectAlternativeName)(policy.subjectAlternativeName, identity4.subjectAlternativeName);
59809
59809
  }
59810
59810
  if (policy.extensions) {
59811
- (0, policy_1.verifyExtensions)(policy.extensions, identity3.extensions);
59811
+ (0, policy_1.verifyExtensions)(policy.extensions, identity4.extensions);
59812
59812
  }
59813
59813
  if (policy.oids) {
59814
- (0, policy_1.verifyOIDs)(policy.oids, identity3.oids);
59814
+ (0, policy_1.verifyOIDs)(policy.oids, identity4.oids);
59815
59815
  }
59816
59816
  }
59817
59817
  }
@@ -60261,9 +60261,9 @@ class ParseStatus2 {
60261
60261
  }
60262
60262
  static async mergeObjectAsync(status, pairs) {
60263
60263
  const syncPairs = [];
60264
- for (const pair of pairs) {
60265
- const key = await pair.key;
60266
- const value = await pair.value;
60264
+ for (const pair2 of pairs) {
60265
+ const key = await pair2.key;
60266
+ const value = await pair2.value;
60267
60267
  syncPairs.push({
60268
60268
  key,
60269
60269
  value
@@ -60273,8 +60273,8 @@ class ParseStatus2 {
60273
60273
  }
60274
60274
  static mergeObjectSync(status, pairs) {
60275
60275
  const finalObject = {};
60276
- for (const pair of pairs) {
60277
- const { key, value } = pair;
60276
+ for (const pair2 of pairs) {
60277
+ const { key, value } = pair2;
60278
60278
  if (key.status === "aborted")
60279
60279
  return INVALID2;
60280
60280
  if (value.status === "aborted")
@@ -60283,7 +60283,7 @@ class ParseStatus2 {
60283
60283
  status.dirty();
60284
60284
  if (value.status === "dirty")
60285
60285
  status.dirty();
60286
- if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
60286
+ if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair2.alwaysSet)) {
60287
60287
  finalObject[key.value] = value.value;
60288
60288
  }
60289
60289
  }
@@ -62266,13 +62266,13 @@ var init_types3 = __esm(() => {
62266
62266
  if (ctx.common.async) {
62267
62267
  return Promise.resolve().then(async () => {
62268
62268
  const syncPairs = [];
62269
- for (const pair of pairs) {
62270
- const key = await pair.key;
62271
- const value = await pair.value;
62269
+ for (const pair2 of pairs) {
62270
+ const key = await pair2.key;
62271
+ const value = await pair2.value;
62272
62272
  syncPairs.push({
62273
62273
  key,
62274
62274
  value,
62275
- alwaysSet: pair.alwaysSet
62275
+ alwaysSet: pair2.alwaysSet
62276
62276
  });
62277
62277
  }
62278
62278
  return syncPairs;
@@ -62799,9 +62799,9 @@ var init_types3 = __esm(() => {
62799
62799
  if (ctx.common.async) {
62800
62800
  const finalMap = new Map;
62801
62801
  return Promise.resolve().then(async () => {
62802
- for (const pair of pairs) {
62803
- const key = await pair.key;
62804
- const value = await pair.value;
62802
+ for (const pair2 of pairs) {
62803
+ const key = await pair2.key;
62804
+ const value = await pair2.value;
62805
62805
  if (key.status === "aborted" || value.status === "aborted") {
62806
62806
  return INVALID2;
62807
62807
  }
@@ -62814,9 +62814,9 @@ var init_types3 = __esm(() => {
62814
62814
  });
62815
62815
  } else {
62816
62816
  const finalMap = new Map;
62817
- for (const pair of pairs) {
62818
- const key = pair.key;
62819
- const value = pair.value;
62817
+ for (const pair2 of pairs) {
62818
+ const key = pair2.key;
62819
+ const value = pair2.value;
62820
62820
  if (key.status === "aborted" || value.status === "aborted") {
62821
62821
  return INVALID2;
62822
62822
  }
@@ -63771,7 +63771,7 @@ __export(exports_util, {
63771
63771
  joinValues: () => joinValues,
63772
63772
  issue: () => issue,
63773
63773
  isPlainObject: () => isPlainObject2,
63774
- isObject: () => isObject4,
63774
+ isObject: () => isObject5,
63775
63775
  hexToUint8Array: () => hexToUint8Array,
63776
63776
  getSizableOrigin: () => getSizableOrigin,
63777
63777
  getParsedType: () => getParsedType3,
@@ -63938,11 +63938,11 @@ function esc(str) {
63938
63938
  function slugify(input) {
63939
63939
  return input.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
63940
63940
  }
63941
- function isObject4(data) {
63941
+ function isObject5(data) {
63942
63942
  return typeof data === "object" && data !== null && !Array.isArray(data);
63943
63943
  }
63944
63944
  function isPlainObject2(o) {
63945
- if (isObject4(o) === false)
63945
+ if (isObject5(o) === false)
63946
63946
  return false;
63947
63947
  const ctor = o.constructor;
63948
63948
  if (ctor === undefined)
@@ -63950,7 +63950,7 @@ function isPlainObject2(o) {
63950
63950
  if (typeof ctor !== "function")
63951
63951
  return true;
63952
63952
  const prot = ctor.prototype;
63953
- if (isObject4(prot) === false)
63953
+ if (isObject5(prot) === false)
63954
63954
  return false;
63955
63955
  if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) {
63956
63956
  return false;
@@ -65831,13 +65831,13 @@ var init_schemas = __esm(() => {
65831
65831
  }
65832
65832
  return propValues;
65833
65833
  });
65834
- const isObject5 = isObject4;
65834
+ const isObject6 = isObject5;
65835
65835
  const catchall = def.catchall;
65836
65836
  let value;
65837
65837
  inst._zod.parse = (payload, ctx) => {
65838
65838
  value ?? (value = _normalized.value);
65839
65839
  const input = payload.value;
65840
- if (!isObject5(input)) {
65840
+ if (!isObject6(input)) {
65841
65841
  payload.issues.push({
65842
65842
  expected: "object",
65843
65843
  code: "invalid_type",
@@ -65935,7 +65935,7 @@ var init_schemas = __esm(() => {
65935
65935
  return (payload, ctx) => fn(shape, payload, ctx);
65936
65936
  };
65937
65937
  let fastpass;
65938
- const isObject5 = isObject4;
65938
+ const isObject6 = isObject5;
65939
65939
  const jit = !globalConfig.jitless;
65940
65940
  const allowsEval2 = allowsEval;
65941
65941
  const fastEnabled = jit && allowsEval2.value;
@@ -65944,7 +65944,7 @@ var init_schemas = __esm(() => {
65944
65944
  inst._zod.parse = (payload, ctx) => {
65945
65945
  value ?? (value = _normalized.value);
65946
65946
  const input = payload.value;
65947
- if (!isObject5(input)) {
65947
+ if (!isObject6(input)) {
65948
65948
  payload.issues.push({
65949
65949
  expected: "object",
65950
65950
  code: "invalid_type",
@@ -66048,7 +66048,7 @@ var init_schemas = __esm(() => {
66048
66048
  });
66049
66049
  inst._zod.parse = (payload, ctx) => {
66050
66050
  const input = payload.value;
66051
- if (!isObject4(input)) {
66051
+ if (!isObject5(input)) {
66052
66052
  payload.issues.push({
66053
66053
  code: "invalid_type",
66054
66054
  expected: "object",
@@ -71662,10 +71662,10 @@ class McpServer2 {
71662
71662
  return registeredResourceTemplate;
71663
71663
  }
71664
71664
  }
71665
- _createRegisteredResource(name2, title, uri, metadata, readCallback) {
71665
+ _createRegisteredResource(name2, title2, uri, metadata, readCallback) {
71666
71666
  const registeredResource = {
71667
71667
  name: name2,
71668
- title,
71668
+ title: title2,
71669
71669
  metadata,
71670
71670
  readCallback,
71671
71671
  enabled: true,
@@ -71694,10 +71694,10 @@ class McpServer2 {
71694
71694
  this._registeredResources[uri] = registeredResource;
71695
71695
  return registeredResource;
71696
71696
  }
71697
- _createRegisteredResourceTemplate(name2, title, template, metadata, readCallback) {
71697
+ _createRegisteredResourceTemplate(name2, title2, template, metadata, readCallback) {
71698
71698
  const registeredResourceTemplate = {
71699
71699
  resourceTemplate: template,
71700
- title,
71700
+ title: title2,
71701
71701
  metadata,
71702
71702
  readCallback,
71703
71703
  enabled: true,
@@ -71731,9 +71731,9 @@ class McpServer2 {
71731
71731
  }
71732
71732
  return registeredResourceTemplate;
71733
71733
  }
71734
- _createRegisteredPrompt(name2, title, description, argsSchema, callback) {
71734
+ _createRegisteredPrompt(name2, title2, description, argsSchema, callback) {
71735
71735
  const registeredPrompt = {
71736
- title,
71736
+ title: title2,
71737
71737
  description,
71738
71738
  argsSchema: argsSchema === undefined ? undefined : objectFromShape(argsSchema),
71739
71739
  callback,
@@ -71772,10 +71772,10 @@ class McpServer2 {
71772
71772
  }
71773
71773
  return registeredPrompt;
71774
71774
  }
71775
- _createRegisteredTool(name2, title, description, inputSchema, outputSchema, annotations, execution, _meta, handler) {
71775
+ _createRegisteredTool(name2, title2, description, inputSchema, outputSchema, annotations, execution, _meta, handler) {
71776
71776
  validateAndWarnToolName2(name2);
71777
71777
  const registeredTool = {
71778
- title,
71778
+ title: title2,
71779
71779
  description,
71780
71780
  inputSchema: getZodSchemaObject2(inputSchema),
71781
71781
  outputSchema: getZodSchemaObject2(outputSchema),
@@ -71849,8 +71849,8 @@ class McpServer2 {
71849
71849
  if (this._registeredTools[name2]) {
71850
71850
  throw new Error(`Tool ${name2} is already registered`);
71851
71851
  }
71852
- const { title, description, inputSchema, outputSchema, annotations, _meta } = config2;
71853
- return this._createRegisteredTool(name2, title, description, inputSchema, outputSchema, annotations, { taskSupport: "forbidden" }, _meta, cb);
71852
+ const { title: title2, description, inputSchema, outputSchema, annotations, _meta } = config2;
71853
+ return this._createRegisteredTool(name2, title2, description, inputSchema, outputSchema, annotations, { taskSupport: "forbidden" }, _meta, cb);
71854
71854
  }
71855
71855
  prompt(name2, ...rest) {
71856
71856
  if (this._registeredPrompts[name2]) {
@@ -71874,8 +71874,8 @@ class McpServer2 {
71874
71874
  if (this._registeredPrompts[name2]) {
71875
71875
  throw new Error(`Prompt ${name2} is already registered`);
71876
71876
  }
71877
- const { title, description, argsSchema } = config2;
71878
- const registeredPrompt = this._createRegisteredPrompt(name2, title, description, argsSchema, cb);
71877
+ const { title: title2, description, argsSchema } = config2;
71878
+ const registeredPrompt = this._createRegisteredPrompt(name2, title2, description, argsSchema, cb);
71879
71879
  this.setPromptRequestHandlers();
71880
71880
  this.sendPromptListChanged();
71881
71881
  return registeredPrompt;
@@ -74269,6 +74269,17 @@ var HELP = {
74269
74269
  ],
74270
74270
  env: ENV_API
74271
74271
  },
74272
+ scan: {
74273
+ group: "Trade",
74274
+ summary: "The token card for one contract: market, all-time high, safety facts, tracked wallets",
74275
+ intro: "The token card for one pasted contract",
74276
+ description: "Prints the token card a Quant group gets when a contract is pasted, from the public card route (GET /api/v1/tokens/:chain/:mint/card): ticker, name, chain and launchpad, then price, market cap, the all-time high since launch, 5 minute change, liquidity, volume and buys and sells, the bundles, snipers, insiders, fresh-wallet and wallet-age facts, tracked wallets and signals in the last hour, the same-name token that leads, whether Candle's forensics covers it, and the Candle page. Facts only: there is no score and no verdict. A field with no source prints a dash, never a guess, and a Sources block names where each figure came from. The chain is read from the address (0x is Hood, base58 is Solana); --chain overrides it, and any other address is refused before a request. Free for every plan: needs no key and sends none. Off on a deployment until TOKEN_CARD_ENABLED is on; until then the command answers TOKEN_CARD_DISABLED.",
74277
+ usage: ["candle scan <contract address> [--chain solana|hood] [--json]"],
74278
+ rows: [],
74279
+ flags: [{ invocation: "--chain <chain>", description: "solana or hood; read from the address when omitted" }],
74280
+ examples: ["candle scan <mint>", "candle scan 0x<token> --json"],
74281
+ env: ["CANDLE_API_URL"]
74282
+ },
74272
74283
  portfolio: {
74273
74284
  group: "Account",
74274
74285
  intro: "Holdings, prices and value of every wallet",
@@ -74377,13 +74388,19 @@ var HELP = {
74377
74388
  },
74378
74389
  token: {
74379
74390
  group: "Account",
74380
- summary: "Token events, cluster analysis, forensics and the vamp finder",
74381
- description: "events lists one token's signals, callouts and tracked-wallet trades, one event per line: time, kind, name or short address, action, size. Needs no key; a configured key is sent so wallet group names follow its tier. Off on a deployment until TOKEN_EVENTS_ENABLED is on; until then the command answers TOKEN_EVENTS_DISABLED. clusters reads third-party estimates of linked Solana wallets. Exchange, pool and service wallets may be grouped together; the figures do not establish common ownership or wrongdoing. Unavailable analysis is a normal result and exits 0. Needs no key and sends none. forensics and vamp-candidates send the profile's API key when it has one. Where the API offers x402 per-use payments, forensics past the free rate and the vamp finder without a key (or past a Free account's daily allowance) answer with a price: the CLI pays it in USDC from a Solana vault key, at a terminal, after a typed confirm (or --yes), within the limits candle spend sets, or prints the price and pays nothing. A paid call that Candle then fails to serve is credited, never refunded.",
74391
+ summary: "Token About pages, events, cluster analysis, forensics and the vamp finder",
74392
+ intro: "Token About pages, events, clusters, forensics, vamp finder",
74393
+ description: "about, claim, section, history and flag are the token's About page: three shared sections (thesis, tokenomics, lore) any eligible holder may edit, with full history. about and history are public and send no key. about --capabilities reads this account's own eligibility (token-pages:read). claim, section set, section restore and flag act as the key's account and need token-pages:write; neither scope is in any preset, so grant them with keys create --scopes token-pages:read,token-pages:write. Candle checks on every write that the account's Candle-known wallets hold at least 0.5% of the token's current supply (any positive balance to flag); the scope is never a holding. A creator proof is a message, never a transaction: claim --creator --challenge prints the exact bytes to sign (and --message-out writes them to a file), you sign them on your own machine, for example with candle sign message, and claim --creator --challenge-id <id> --signature <sig> sends the signature; a creator wallet already among the account's known wallets needs no signature. Section text comes from --file and is checked here first (valid UTF-8, at most 32 KiB, no control characters but newline and tab, thesis 280 characters, tokenomics and lore 5,000); the file is only read. Every write sends an Idempotency-Key and retries once on no answer with the same key. Exit codes: 0 done, 1 refused (the code is in --json), 2 usage or local input refused (nothing sent), 3 no answer so the outcome is unknown (rerun with the printed --idempotency-key), 4 revision conflict (your file is untouched; read history, merge, rerun with the latest --base-revision). Token page switches ship off; a switched-off server answers feature_off or not_found. events lists one token's signals, callouts and tracked-wallet trades, one event per line: time, kind, name or short address, action, size. Needs no key; a configured key is sent so wallet group names follow its tier. Off on a deployment until TOKEN_EVENTS_ENABLED is on; until then the command answers TOKEN_EVENTS_DISABLED. clusters reads third-party estimates of linked Solana wallets. Exchange, pool and service wallets may be grouped together; the figures do not establish common ownership or wrongdoing. Unavailable analysis is a normal result and exits 0. Needs no key and sends none. forensics and vamp-candidates send the profile's API key when it has one. Where the API offers x402 per-use payments, forensics past the free rate and the vamp finder without a key (or past a Free account's daily allowance) answer with a price: the CLI pays it in USDC from a Solana vault key, at a terminal, after a typed confirm (or --yes), within the limits candle spend sets, or prints the price and pays nothing. A paid call that Candle then fails to serve is credited, never refunded.",
74382
74394
  usage: [
74383
74395
  "candle token clusters <mint> [--chain solana|hood] [--json]",
74384
74396
  "candle token events <mint> [--chain solana|hood] [--kind trade|signal|callout] [--since <iso-8601>] [--limit <n>] [--before <cursor>] [--json]",
74385
74397
  "candle token forensics <mint> [--chain solana|hood] [--wallet <vault key>] [--yes] [--json]",
74386
- "candle token vamp-candidates [--limit <n>] [--min-copies <n>] [--stage final_stretch|graduated|all] [--wallet <vault key>] [--yes] [--json]"
74398
+ "candle token vamp-candidates [--limit <n>] [--min-copies <n>] [--stage final_stretch|graduated|all] [--wallet <vault key>] [--yes] [--json]",
74399
+ "candle token about <address> [--chain solana|hood] [--capabilities] [--json]",
74400
+ "candle token claim <address> [--creator [--challenge [--message-out <path>] | --challenge-id <id> --signature <sig>]] [--json]",
74401
+ "candle token section set|restore <address> <thesis|tokenomics|lore> --file <path>|--version-id <id> --base-revision <n> [--json]",
74402
+ "candle token history <address> <thesis|tokenomics|lore> [--limit <n>] [--cursor <c>] [--json]",
74403
+ "candle token flag <address> --content <id> --reason <reason> [--detail <text>] [--json]"
74387
74404
  ],
74388
74405
  rows: [
74389
74406
  { invocation: "clusters <mint>", description: "Read cluster analysis, or its unavailable reason" },
@@ -74395,7 +74412,21 @@ var HELP = {
74395
74412
  {
74396
74413
  invocation: "vamp-candidates",
74397
74414
  description: "Tokens near graduation whose ticker others copy; may cost a per-use payment"
74398
- }
74415
+ },
74416
+ {
74417
+ invocation: "about <address>",
74418
+ description: "The token's About page: claim, sections and measured supply; --capabilities adds your eligibility"
74419
+ },
74420
+ {
74421
+ invocation: "claim <address>",
74422
+ description: "Join the page's editors as a holder, or as its creator with --creator (a signed message)"
74423
+ },
74424
+ {
74425
+ invocation: "section set|restore <address> <section>",
74426
+ description: "Write a section from --file, or restore an earlier --version-id, at --base-revision"
74427
+ },
74428
+ { invocation: "history <address> <section>", description: "A section's versions, newest first" },
74429
+ { invocation: "flag <address>", description: "Report one exact version to Candle's review queue" }
74399
74430
  ],
74400
74431
  flags: [
74401
74432
  { invocation: "--chain <chain>", description: "solana (default) or hood; Hood cluster analysis is unavailable" },
@@ -74403,7 +74434,10 @@ var HELP = {
74403
74434
  invocation: "--kind <kind>",
74404
74435
  description: "events: trade, signal or callout; filters the page locally (the route has no kind filter)"
74405
74436
  },
74406
- { invocation: "--limit <n>", description: "events or vamp-candidates: how many to read (events: 1 to 1000)" },
74437
+ {
74438
+ invocation: "--limit <n>",
74439
+ description: "events, history or vamp-candidates: how many to read (events 1 to 1000, history 1 to 50)"
74440
+ },
74407
74441
  { invocation: "--min-copies <n>", description: "vamp-candidates: copies in the last 24h, at least" },
74408
74442
  { invocation: "--since <iso-8601>", description: "events: list only events at or after this time" },
74409
74443
  { invocation: "--before <cursor>", description: "events: continue the page a previous answer's cursor names" },
@@ -74412,9 +74446,24 @@ var HELP = {
74412
74446
  invocation: "--wallet <vault key>",
74413
74447
  description: "The Solana vault key that pays, by label or address (needed when the vault has several)"
74414
74448
  },
74415
- { invocation: "--yes", description: "Pay without the typed confirm (the vault unlock still prompts)" }
74449
+ { invocation: "--yes", description: "Pay without the typed confirm (the vault unlock still prompts)" },
74450
+ { invocation: "--file <path>", description: "section set: the section text, UTF-8; an empty file needs --clear" },
74451
+ {
74452
+ invocation: "--base-revision <n>",
74453
+ description: "section set|restore: the revision you started from (0 first)"
74454
+ },
74455
+ { invocation: "--version-id <id>", description: "section restore: the earlier version to copy into a new one" },
74456
+ { invocation: "--content <id>", description: "flag: the exact version id being reported" },
74457
+ {
74458
+ invocation: "--reason <reason>",
74459
+ description: "flag: spam, scam, abuse, misleading, unsafe_link or other; --detail adds up to 500 characters"
74460
+ },
74461
+ { invocation: "--idempotency-key <key>", description: "Writes: reuse a key to retry without writing twice" }
74416
74462
  ],
74417
74463
  examples: [
74464
+ "candle token about <mint> --capabilities",
74465
+ "candle token section set <mint> thesis --file ./thesis.txt --base-revision 3",
74466
+ "candle token claim <mint> --creator --challenge --message-out ./proof.txt",
74418
74467
  "candle token clusters <mint>",
74419
74468
  "candle token clusters <mint> --json",
74420
74469
  "candle token events <mint> --kind signal --limit 50",
@@ -97343,6 +97392,190 @@ async function quantTerms(args, ctx) {
97343
97392
  return 1;
97344
97393
  }
97345
97394
 
97395
+ // src/commands/scan.ts
97396
+ init_args();
97397
+ init_client();
97398
+ init_human_output();
97399
+ init_presentation();
97400
+ init_render();
97401
+ var USAGE10 = "Usage: candle scan <contract address> [--chain solana|hood] [--json]";
97402
+ var OTHER_CHAIN = "Candle trades Solana and Hood today; that is not a Solana or Hood contract address.";
97403
+ var HOOD_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
97404
+ var SOLANA_ADDRESS = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
97405
+ function chainOfAddress(address) {
97406
+ if (HOOD_ADDRESS.test(address))
97407
+ return "hood";
97408
+ if (SOLANA_ADDRESS.test(address))
97409
+ return "solana";
97410
+ return null;
97411
+ }
97412
+ var isObject2 = (value) => value !== null && typeof value === "object";
97413
+ function readCard(body) {
97414
+ if (!isObject2(body) || body.success !== true || !isObject2(body.card))
97415
+ return null;
97416
+ const card2 = body.card;
97417
+ const blocks = ["identity", "market", "forensics", "events", "hacc", "sameName", "sources", "links"];
97418
+ if (typeof card2.mint !== "string" || card2.chain !== "solana" && card2.chain !== "hood")
97419
+ return null;
97420
+ if (!blocks.every((block2) => isObject2(card2[block2])))
97421
+ return null;
97422
+ return card2;
97423
+ }
97424
+ var num = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
97425
+ function usd(value) {
97426
+ const n = num(value);
97427
+ return n === null ? null : formatUsd(n, { compact: true });
97428
+ }
97429
+ function percentChange(value) {
97430
+ const n = num(value);
97431
+ if (n === null)
97432
+ return null;
97433
+ const rounded = Number(n.toFixed(1));
97434
+ return `${rounded > 0 ? "+" : ""}${rounded}%`;
97435
+ }
97436
+ function title(card2) {
97437
+ const { symbol, name: name2, launchpad, isCandle } = card2.identity;
97438
+ const parts = [
97439
+ symbol || shortAddress2(card2.mint),
97440
+ name2 && name2 !== symbol ? name2 : null,
97441
+ card2.chain === "hood" ? "Hood" : "Solana",
97442
+ launchpad,
97443
+ isCandle === true ? "launched on Candle" : null
97444
+ ];
97445
+ return parts.filter((part) => typeof part === "string" && part.length > 0).join(" · ");
97446
+ }
97447
+ function fact(card2, key) {
97448
+ if (card2.hacc.state !== "ok")
97449
+ return null;
97450
+ const field = card2.hacc.facts.fields?.[key];
97451
+ return field?.state === "ok" && field.display ? field.display : null;
97452
+ }
97453
+ function pair(a, b, missing) {
97454
+ return a === null && b === null ? null : `${a ?? missing} / ${b ?? missing}`;
97455
+ }
97456
+ function eventsLine(card2, missing) {
97457
+ const events = card2.events;
97458
+ if (events.state !== "ok")
97459
+ return `${missing} (${events.state})`;
97460
+ const parts = [
97461
+ `${events.trackedBuys} bought, ${events.trackedSells} sold`,
97462
+ `${events.signals} signal${events.signals === 1 ? "" : "s"}`,
97463
+ `${events.callouts} callout${events.callouts === 1 ? "" : "s"}`
97464
+ ];
97465
+ const names = Array.isArray(events.names) && events.names.length > 0 ? ` (${events.names.join(", ")})` : "";
97466
+ return `${parts.join(" · ")}${names}`;
97467
+ }
97468
+ function sameNameLine(card2, missing) {
97469
+ const same = card2.sameName;
97470
+ if (same.state === "off" || same.state === "unavailable")
97471
+ return `${missing} (${same.state})`;
97472
+ if (same.state === "none")
97473
+ return "none found";
97474
+ const display = same.display && same.display !== "–" ? same.display : missing;
97475
+ return same.trailing === true ? `${display} (this token trails)` : display;
97476
+ }
97477
+ function forensicsLine(card2, missing) {
97478
+ switch (card2.forensics.state) {
97479
+ case "ok":
97480
+ return `read; the full report is candle token forensics ${card2.mint}${card2.chain === "hood" ? " --chain hood" : ""}`;
97481
+ case "not_covered":
97482
+ return "not covered for this token (bundles, snipers and insiders are unknown, not clean)";
97483
+ default:
97484
+ return `${missing} (unavailable)`;
97485
+ }
97486
+ }
97487
+ function athLine(card2) {
97488
+ const ath = card2.ath;
97489
+ if (!ath || num(ath.marketCapUsd) === null)
97490
+ return null;
97491
+ return `${formatUsd(ath.marketCapUsd, { compact: true })} on ${formatTime(ath.at, { date: true, now: card2.generatedAt })} (daily high, FDV)`;
97492
+ }
97493
+ async function scan(args, ctx) {
97494
+ const parsed = parseArgs(args, { valueFlags: ["--chain"] });
97495
+ if ("error" in parsed) {
97496
+ writeUsageFailure(ctx.deps, parsed.error, ctx.json);
97497
+ return 2;
97498
+ }
97499
+ const named = parsed.values["--chain"];
97500
+ if (parsed.positionals.length !== 1 || named !== undefined && named !== "solana" && named !== "hood") {
97501
+ writeUsageFailure(ctx.deps, USAGE10, ctx.json);
97502
+ return 2;
97503
+ }
97504
+ const address = parsed.positionals[0].trim();
97505
+ const found = chainOfAddress(address);
97506
+ if (found === null) {
97507
+ writeUsageFailure(ctx.deps, `${OTHER_CHAIN}
97508
+ ${USAGE10}`, ctx.json);
97509
+ return 2;
97510
+ }
97511
+ if (named !== undefined && named !== found) {
97512
+ const label = (c) => c === "hood" ? "Hood" : "Solana";
97513
+ writeUsageFailure(ctx.deps, `That address is a ${label(found)} contract, not a ${label(named)} one. Candle trades Solana and Hood today.
97514
+ ${USAGE10}`, ctx.json);
97515
+ return 2;
97516
+ }
97517
+ const chain2 = found;
97518
+ const result = await apiRequest(`/api/v1/tokens/${chain2}/${encodeURIComponent(address)}/card`, {
97519
+ apiUrl: ctx.apiUrl,
97520
+ auth: "none",
97521
+ credentials: {},
97522
+ env: ctx.deps.env,
97523
+ fetch: ctx.deps.fetch
97524
+ });
97525
+ if (!result.ok) {
97526
+ writeFailure(ctx.deps, result, { apiUrl: ctx.apiUrl, authType: "none" }, ctx.json);
97527
+ return 1;
97528
+ }
97529
+ const card2 = readCard(result.body);
97530
+ if (!card2) {
97531
+ writeFailure(ctx.deps, {
97532
+ ok: false,
97533
+ status: result.status,
97534
+ code: "BAD_RESPONSE",
97535
+ message: "The card answer was not readable.",
97536
+ raw: result.body
97537
+ }, { apiUrl: ctx.apiUrl, authType: "none" }, ctx.json);
97538
+ return 1;
97539
+ }
97540
+ if (ctx.json) {
97541
+ ctx.deps.stdout.write(`${JSON.stringify({ ok: true, data: { card: card2 } })}
97542
+ `);
97543
+ return 0;
97544
+ }
97545
+ const missing = symbols(terminalStyle(ctx.deps, "stdout")).missing;
97546
+ const m = card2.market;
97547
+ const buys = num(m.buys5m);
97548
+ const sells = num(m.sells5m);
97549
+ const rows = [
97550
+ ["Contract", card2.mint],
97551
+ ["Price", num(m.priceUsd) === null ? null : formatPrice(m.priceUsd)],
97552
+ ["Market cap", usd(m.marketCapUsd)],
97553
+ ["All-time high", athLine(card2)],
97554
+ ["5m change", percentChange(m.change5mPct)],
97555
+ ["Liquidity", usd(m.liquidityUsd)],
97556
+ ["Volume 5m", usd(m.volume5mUsd)],
97557
+ ["Buys / sells 5m", pair(buys === null ? null : String(buys), sells === null ? null : String(sells), missing)],
97558
+ ["Bundles", fact(card2, "bundles")],
97559
+ ["Snipers", fact(card2, "snipers")],
97560
+ ["Insiders", fact(card2, "insiders")],
97561
+ ["Fresh 1d / 7d", pair(fact(card2, "fresh_1d"), fact(card2, "fresh_7d"), missing)],
97562
+ ["Mean wallet age", fact(card2, "avg_wallet_age")],
97563
+ ["Tracked, 1h", eventsLine(card2, missing)],
97564
+ ["Same name", sameNameLine(card2, missing)],
97565
+ ["Forensics", forensicsLine(card2, missing)],
97566
+ ["Market as of", num(m.updatedAt) === null ? null : formatTime(m.updatedAt, { now: card2.generatedAt })],
97567
+ ["Candle page", card2.links.token]
97568
+ ];
97569
+ writeFields(ctx.deps, "stdout", rows, title(card2));
97570
+ const sources2 = Object.entries(card2.sources).filter(([, text3]) => typeof text3 === "string");
97571
+ if (sources2.length > 0) {
97572
+ ctx.deps.stdout.write(`
97573
+ `);
97574
+ writeFields(ctx.deps, "stdout", sources2, "Sources");
97575
+ }
97576
+ return 0;
97577
+ }
97578
+
97346
97579
  // src/commands/setup.ts
97347
97580
  init_human_output();
97348
97581
  init_presentation();
@@ -97354,8 +97587,8 @@ init_profiles();
97354
97587
  init_render();
97355
97588
  var SKILLS_CLAUDE_COMMAND = "/plugin marketplace add candledottv/agentic";
97356
97589
  var CODING_AGENTS_DOCS = "https://docs.candle.tv/developers/coding-agents";
97357
- function section(deps, title) {
97358
- writeHeading(deps, "stdout", title);
97590
+ function section(deps, title2) {
97591
+ writeHeading(deps, "stdout", title2);
97359
97592
  }
97360
97593
  async function setup(args, ctx) {
97361
97594
  const { deps, apiUrl, json } = ctx;
@@ -99097,7 +99330,7 @@ async function teeRename(args, ctx) {
99097
99330
  });
99098
99331
  const preview = await call2({
99099
99332
  dryRun: true,
99100
- renames: pairs.map((pair) => ({ wallet: pair.from, label: pair.to }))
99333
+ renames: pairs.map((pair2) => ({ wallet: pair2.from, label: pair2.to }))
99101
99334
  });
99102
99335
  if (!preview.ok)
99103
99336
  return serverFailure(ctx, preview, pairs, batch);
@@ -99388,7 +99621,7 @@ init_deps();
99388
99621
  init_human_output();
99389
99622
  init_render();
99390
99623
  var KINDS = ["trade", "signal", "callout"];
99391
- var USAGE10 = "Usage: candle token events <mint> [--chain solana|hood] [--kind trade|signal|callout] [--since <iso-8601>] [--limit <n>] [--before <cursor>] [--json]";
99624
+ var USAGE11 = "Usage: candle token events <mint> [--chain solana|hood] [--kind trade|signal|callout] [--since <iso-8601>] [--limit <n>] [--before <cursor>] [--json]";
99392
99625
  function readEventsBody(body) {
99393
99626
  if (body === null || typeof body !== "object" || !Array.isArray(body.events))
99394
99627
  return null;
@@ -99446,11 +99679,11 @@ async function tokenEvents(args, ctx) {
99446
99679
  const since = parsed.values["--since"];
99447
99680
  const before = parsed.values["--before"];
99448
99681
  if (parsed.positionals.length !== 1 || chain2 !== "solana" && chain2 !== "hood") {
99449
- writeUsageFailure(ctx.deps, USAGE10, ctx.json);
99682
+ writeUsageFailure(ctx.deps, USAGE11, ctx.json);
99450
99683
  return 2;
99451
99684
  }
99452
99685
  if (kind !== undefined && !KINDS.includes(kind)) {
99453
- writeUsageFailure(ctx.deps, USAGE10, ctx.json);
99686
+ writeUsageFailure(ctx.deps, USAGE11, ctx.json);
99454
99687
  return 2;
99455
99688
  }
99456
99689
  if (limit !== undefined && !/^[1-9][0-9]{0,3}$/.test(limit) || Number(limit) > 1000) {
@@ -99523,13 +99756,657 @@ async function tokenEvents(args, ctx) {
99523
99756
  return 0;
99524
99757
  }
99525
99758
 
99759
+ // src/commands/token-pages.ts
99760
+ init_esm();
99761
+ init_args();
99762
+ init_client();
99763
+ init_deps();
99764
+ init_human_output();
99765
+ init_presentation();
99766
+ init_render();
99767
+ import { createHash as createHash5, randomUUID as randomUUID10 } from "node:crypto";
99768
+ var EXIT_OUTCOME_UNKNOWN = 3;
99769
+ var EXIT_REVISION_CONFLICT = 4;
99770
+ var TOKEN_PAGE_LIMITS = { thesis: 280, tokenomics: 5000, lore: 5000, update: 1000, comment: 500 };
99771
+ var TOKEN_PAGE_BODY_CAP_BYTES = 32 * 1024;
99772
+ var TOKEN_PAGE_SECTIONS = ["thesis", "tokenomics", "lore"];
99773
+ var FLAG_REASONS = ["spam", "scam", "abuse", "misleading", "unsafe_link", "other"];
99774
+ var FLAG_DETAIL_LIMIT = 500;
99775
+ var USAGE12 = {
99776
+ about: "Usage: candle token about <address> [--chain solana|hood] [--capabilities]",
99777
+ claim: "Usage: candle token claim <address> [--chain solana|hood] [--creator [--challenge [--message-out <path>] | --challenge-id <id> --signature <sig>]] [--idempotency-key <key>]",
99778
+ section: `Usage: candle token section set <address> <thesis|tokenomics|lore> --file <path> --base-revision <n> [--clear] [--chain solana|hood] [--idempotency-key <key>]
99779
+ candle token section restore <address> <thesis|tokenomics|lore> --version-id <id> --base-revision <n> [--chain solana|hood] [--idempotency-key <key>]`,
99780
+ history: "Usage: candle token history <address> <thesis|tokenomics|lore> [--chain solana|hood] [--limit <n>] [--cursor <c>]",
99781
+ flag: "Usage: candle token flag <address> --content <id> --reason <spam|scam|abuse|misleading|unsafe_link|other> [--detail <text>] [--chain solana|hood] [--idempotency-key <key>]"
99782
+ };
99783
+ var REFUSALS = {
99784
+ feature_off: "This token page action is switched off on this Candle server. Nothing was written.",
99785
+ not_found: "No such token page, item or version here, or token pages are switched off on this Candle server.",
99786
+ insufficient_holding: "This account's Candle-known wallets hold less than 0.5% of the token's current supply (any positive balance is enough to flag). Nothing was written.",
99787
+ eligibility_unavailable: "Candle could not read complete, fresh wallet and supply evidence for this account just now. Nothing was written; try again shortly.",
99788
+ restricted: "This account is restricted from writing on this token page.",
99789
+ revision_conflict: "The section changed since the base revision you gave.",
99790
+ idempotency_conflict: "This idempotency key was already used for a different request. Nothing was written.",
99791
+ idempotency_key_required: "The request carried no usable Idempotency-Key.",
99792
+ challenge_used: "That creator challenge was already used, or the creator evidence changed. Request a new one.",
99793
+ invalid_signature: "The signature does not verify for that challenge, or the challenge expired (5 minutes). Request a new one.",
99794
+ creator_unknown: "Candle has no verified creator for this token, so there is nothing to prove.",
99795
+ creator_proof_unsupported: "The verified creator cannot sign a message (a contract or multisig), so creator proof is not available.",
99796
+ invalid_text: "Candle refused the text: too long, empty, or holding invalid Unicode or control characters.",
99797
+ invalid_body: "Candle refused the request body.",
99798
+ invalid_token: "That is not a valid address on that chain.",
99799
+ invalid_section: "Sections are thesis, tokenomics and lore.",
99800
+ invalid_query: "Candle refused the query (limit is 1-50; the cursor must come from this list).",
99801
+ no_identity_wallet: "This key's account has no wallet Candle can use as its identity.",
99802
+ rate_limited: "Too many token page requests; wait a minute and try again.",
99803
+ unavailable: "Token pages are unavailable on this Candle server just now.",
99804
+ measurements_unavailable: "Measurements are unavailable just now; try again shortly."
99805
+ };
99806
+ var SECTION_SUGGESTION = "Your file was not changed. Read the newer text with candle token history, merge, then rerun with --base-revision set to the latest revision.";
99807
+ function usageFor(ctx, line) {
99808
+ return (message) => {
99809
+ writeUsageFailure(ctx.deps, message ? `${message}
99810
+ ${line}` : line, ctx.json);
99811
+ return 2;
99812
+ };
99813
+ }
99814
+ function chainOf(values) {
99815
+ const chain2 = values["--chain"] ?? "solana";
99816
+ return chain2 === "solana" || chain2 === "hood" ? chain2 : undefined;
99817
+ }
99818
+ function pagePath(chain2, address, rest = "") {
99819
+ return `/api/v1/token-pages/${chain2}/${encodeURIComponent(address)}${rest}`;
99820
+ }
99821
+ function refusalOf2(result) {
99822
+ if (result.ok)
99823
+ return null;
99824
+ const raw = result.raw;
99825
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
99826
+ return null;
99827
+ const { success: success2, error, ...extra } = raw;
99828
+ if (success2 !== false || typeof error !== "string")
99829
+ return null;
99830
+ return { status: result.status, code: error, extra };
99831
+ }
99832
+ function writeRefusal(ctx, refusal3, suggestion) {
99833
+ const message = REFUSALS[refusal3.code] ?? `Candle refused the request (${refusal3.code}).`;
99834
+ if (ctx.json) {
99835
+ ctx.deps.stdout.write(`${JSON.stringify({ ok: false, code: refusal3.code, status: refusal3.status, message, ...refusal3.extra, ...suggestion ? { suggestion } : {} })}
99836
+ `);
99837
+ return;
99838
+ }
99839
+ ctx.deps.stderr.write(`${suggestion ? `${message} ${suggestion}` : message}
99840
+ `);
99841
+ }
99842
+ function writeApiFailure(ctx, result, authType) {
99843
+ const refusal3 = refusalOf2(result);
99844
+ if (refusal3) {
99845
+ writeRefusal(ctx, refusal3);
99846
+ return 1;
99847
+ }
99848
+ writeFailure(ctx.deps, result, { apiUrl: ctx.apiUrl, authType }, ctx.json);
99849
+ return 1;
99850
+ }
99851
+ function dataOf(result) {
99852
+ const body = result.ok ? result.body : null;
99853
+ return body && typeof body === "object" && "data" in body ? body.data : body;
99854
+ }
99855
+ async function read2(ctx, path, apiKey) {
99856
+ return apiRequest(path, {
99857
+ apiUrl: ctx.apiUrl,
99858
+ ...apiKey ? { auth: "key", credentials: { apiKey } } : { auth: "none", credentials: {} },
99859
+ fetch: ctx.deps.fetch,
99860
+ env: ctx.deps.env
99861
+ });
99862
+ }
99863
+ async function requireKey(ctx) {
99864
+ const key = await resolveApiKey(ctx.deps, ctx.profile);
99865
+ if (key)
99866
+ return key;
99867
+ writeLocalFailure(ctx.deps, {
99868
+ code: "API_KEY_REQUIRED",
99869
+ message: "This needs an API key with the token-pages scopes.",
99870
+ suggestion: "Create one with: candle keys create --scopes token-pages:read,token-pages:write"
99871
+ }, ctx.json);
99872
+ return;
99873
+ }
99874
+ async function write(ctx, input) {
99875
+ const send = async () => {
99876
+ try {
99877
+ return await apiRequest(input.path, {
99878
+ apiUrl: ctx.apiUrl,
99879
+ method: input.method,
99880
+ body: input.body,
99881
+ auth: "key",
99882
+ credentials: { apiKey: input.apiKey },
99883
+ headers: { "Idempotency-Key": input.idempotencyKey },
99884
+ fetch: ctx.deps.fetch,
99885
+ env: ctx.deps.env
99886
+ });
99887
+ } catch {
99888
+ return { ok: false, status: 0, message: "The response was cut off before it finished.", raw: undefined };
99889
+ }
99890
+ };
99891
+ const first = await send();
99892
+ if (first.ok || first.status !== 0 || first.code)
99893
+ return first;
99894
+ const second = await send();
99895
+ if (second.ok || second.status !== 0 || second.code)
99896
+ return second;
99897
+ return "unknown";
99898
+ }
99899
+ function writeUnknown(ctx, idempotencyKey) {
99900
+ writeLocalFailure(ctx.deps, {
99901
+ code: "OUTCOME_UNKNOWN",
99902
+ message: "Candle did not answer, twice, so whether this write landed is not known.",
99903
+ suggestion: `Rerun the same command with --idempotency-key ${idempotencyKey}: Candle returns the first result instead of writing twice.`,
99904
+ details: { idempotencyKey }
99905
+ }, ctx.json);
99906
+ return EXIT_OUTCOME_UNKNOWN;
99907
+ }
99908
+ function idempotencyKeyOf(values, usage11) {
99909
+ const given = values["--idempotency-key"];
99910
+ if (given === undefined)
99911
+ return randomUUID10();
99912
+ if (given.length < 1 || given.length > 128)
99913
+ return usage11("--idempotency-key must be 1 to 128 characters.");
99914
+ return given;
99915
+ }
99916
+ function sectionOf(value) {
99917
+ return TOKEN_PAGE_SECTIONS.includes(value ?? "") ? value : undefined;
99918
+ }
99919
+ var REVISION = /^(0|[1-9][0-9]{0,18})$/;
99920
+ var UUID2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
99921
+ function bpsPercent(bps2) {
99922
+ if (bps2 === null || bps2 === undefined || !/^\d+$/.test(bps2))
99923
+ return;
99924
+ const n = BigInt(bps2);
99925
+ return `${n / 100n}.${(n % 100n).toString().padStart(2, "0")}%`;
99926
+ }
99927
+ function identity3(who2) {
99928
+ if (!who2)
99929
+ return;
99930
+ if (who2.kind === "candle")
99931
+ return "Candle";
99932
+ if (who2.kind === "agent")
99933
+ return terminalText(who2.name ?? "Agent");
99934
+ return terminalText(who2.name ?? who2.account);
99935
+ }
99936
+ function sectionText(bytes, section2) {
99937
+ if (bytes.length > TOKEN_PAGE_BODY_CAP_BYTES)
99938
+ return { error: `The file is over ${TOKEN_PAGE_BODY_CAP_BYTES} bytes.` };
99939
+ let decoded;
99940
+ try {
99941
+ decoded = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
99942
+ } catch {
99943
+ return { error: "The file is not valid UTF-8." };
99944
+ }
99945
+ const text3 = decoded.replace(/\r\n?/g, `
99946
+ `);
99947
+ for (const char of text3) {
99948
+ const c = char.codePointAt(0) ?? 0;
99949
+ if (c < 32 && c !== 10 && c !== 9 || c === 127 || c >= 128 && c < 160 || c >= 55296 && c <= 57343)
99950
+ return { error: `The file holds a control character (U+${c.toString(16).toUpperCase().padStart(4, "0")}).` };
99951
+ }
99952
+ const length = [...text3].length;
99953
+ const limit = TOKEN_PAGE_LIMITS[section2];
99954
+ if (length > limit)
99955
+ return { error: `${section2} is at most ${limit} characters; the file has ${length}.` };
99956
+ return { text: text3 };
99957
+ }
99958
+ function signatureFor(chain2, given) {
99959
+ const value = given.trim();
99960
+ if (chain2 === "hood")
99961
+ return /^0x[0-9a-fA-F]{130}$/.test(value) ? value : undefined;
99962
+ try {
99963
+ const bytes = value.endsWith("=") || /[+/]/.test(value) ? base64.decode(value) : base58.decode(value);
99964
+ return bytes.length === 64 ? base64.encode(bytes) : undefined;
99965
+ } catch {
99966
+ return;
99967
+ }
99968
+ }
99969
+ function factValue(fact2) {
99970
+ if (fact2.raw === undefined)
99971
+ return fact2.status;
99972
+ const value = fact2.decimals ? rawUnits2(fact2.raw, fact2.decimals) : fact2.raw;
99973
+ return `${value}${fact2.unit === "token" ? "" : ` ${fact2.unit}`} (${fact2.status}, ${fact2.coverage}, ${terminalText(fact2.source)}${fact2.measuredAt ? `, ${fact2.measuredAt}` : ""})`;
99974
+ }
99975
+ function rawUnits2(raw, decimals) {
99976
+ if (!/^\d+$/.test(raw))
99977
+ return raw;
99978
+ const padded = raw.padStart(decimals + 1, "0");
99979
+ const whole = padded.slice(0, padded.length - decimals);
99980
+ const fraction = padded.slice(padded.length - decimals).replace(/0+$/, "");
99981
+ return fraction ? `${whole}.${fraction}` : whole;
99982
+ }
99983
+ function writeAbout(ctx, about) {
99984
+ const claim = about.claim;
99985
+ writeFields(ctx.deps, "stdout", [
99986
+ ["Token", `${about.token.chain} ${about.token.address}`],
99987
+ ["Revision", about.revision],
99988
+ [
99989
+ "Claim",
99990
+ claim.state === "unclaimed" ? "unclaimed" : `claimed by ${claim.state === "dev" ? "dev" : "community"}`
99991
+ ],
99992
+ ["Lead", identity3(claim.lead) ?? "no current eligible lead"],
99993
+ ["Eligible", claim.eligibleAccounts === null ? "refreshing" : String(claim.eligibleAccounts)],
99994
+ [
99995
+ "Switches",
99996
+ Object.entries(about.features).map(([name2, on]) => `${name2} ${on ? "on" : "off"}`).join(", ")
99997
+ ]
99998
+ ], "About");
99999
+ for (const section2 of TOKEN_PAGE_SECTIONS) {
100000
+ const v = about.sections[section2];
100001
+ if (!v)
100002
+ continue;
100003
+ writeHeading(ctx.deps, "stdout", `${section2} (revision ${v.revision})`);
100004
+ writeFields(ctx.deps, "stdout", [
100005
+ ["Written by", `${identity3(v.author)}${v.dev ? " (dev)" : ""}`],
100006
+ ["Share then", bpsPercent(v.shareBps)],
100007
+ ["At", v.createdAt],
100008
+ ["Version", v.id]
100009
+ ]);
100010
+ if (v.newerAwaitingReview)
100011
+ notice(ctx.deps, "stdout", "note", "A newer version is hidden pending review.");
100012
+ if (v.linksWithheld)
100013
+ notice(ctx.deps, "stdout", "note", "Links are withheld pending review.");
100014
+ ctx.deps.stdout.write(`
100015
+ ${terminalTextKeepingLines(v.text)}
100016
+ `);
100017
+ }
100018
+ writeHeading(ctx.deps, "stdout", "Supply, measured by Candle");
100019
+ const facts = about.facts.filter((f) => f.status === "known" || f.status === "stale");
100020
+ if (!facts.length)
100021
+ ctx.deps.stdout.write(` Measurements unavailable
100022
+ `);
100023
+ else
100024
+ writeFields(ctx.deps, "stdout", facts.map((f) => [terminalText(f.metric), factValue(f)]));
100025
+ }
100026
+ function terminalTextKeepingLines(text3) {
100027
+ return text3.split(`
100028
+ `).map((line) => terminalText(line.replace(/\t/g, " "))).join(`
100029
+ `);
100030
+ }
100031
+ async function tokenAbout(args, ctx) {
100032
+ const usage11 = usageFor(ctx, USAGE12.about);
100033
+ const parsed = parseArgs(args, { valueFlags: ["--chain"], booleanFlags: ["--capabilities"] });
100034
+ if ("error" in parsed)
100035
+ return usage11(parsed.error);
100036
+ const chain2 = chainOf(parsed.values);
100037
+ const address = parsed.positionals[0];
100038
+ if (parsed.positionals.length !== 1 || !address)
100039
+ return usage11();
100040
+ if (!chain2)
100041
+ return usage11("--chain must be solana or hood.");
100042
+ const withCapabilities = parsed.booleans.has("--capabilities");
100043
+ const apiKey = withCapabilities ? await requireKey(ctx) : undefined;
100044
+ if (withCapabilities && !apiKey)
100045
+ return 1;
100046
+ const summary = await read2(ctx, pagePath(chain2, address));
100047
+ if (!summary.ok)
100048
+ return writeApiFailure(ctx, summary, "none");
100049
+ let capabilities;
100050
+ if (apiKey) {
100051
+ const own = await read2(ctx, pagePath(chain2, address, "/capabilities"), apiKey);
100052
+ if (!own.ok)
100053
+ return writeApiFailure(ctx, own, "key");
100054
+ capabilities = dataOf(own);
100055
+ }
100056
+ const about = dataOf(summary);
100057
+ if (ctx.json) {
100058
+ ctx.deps.stdout.write(`${JSON.stringify({ ok: true, data: about, ...apiKey ? { capabilities } : {} })}
100059
+ `);
100060
+ return 0;
100061
+ }
100062
+ writeAbout(ctx, about);
100063
+ if (apiKey) {
100064
+ const c = capabilities;
100065
+ writeFields(ctx.deps, "stdout", [
100066
+ ["Can claim", c.canClaim ? "yes" : "no"],
100067
+ ["Can edit", c.canEdit ? "yes" : "no"],
100068
+ ["Can flag", c.canFlag ? "yes" : "no"],
100069
+ ["Creator", c.creatorProven ? "proven" : "not proven"],
100070
+ ["Share now", bpsPercent(c.shareBps)],
100071
+ ["Observed", c.observedAt],
100072
+ ["Why not", c.refusal ? REFUSALS[c.refusal] ?? c.refusal : undefined]
100073
+ ], "This account");
100074
+ }
100075
+ return 0;
100076
+ }
100077
+ async function tokenClaim(args, ctx) {
100078
+ const usage11 = usageFor(ctx, USAGE12.claim);
100079
+ const parsed = parseArgs(args, {
100080
+ valueFlags: ["--chain", "--challenge-id", "--signature", "--message-out", "--idempotency-key"],
100081
+ booleanFlags: ["--creator", "--challenge"],
100082
+ pathFlags: ["--message-out"]
100083
+ });
100084
+ if ("error" in parsed)
100085
+ return usage11(parsed.error);
100086
+ const { values, booleans } = parsed;
100087
+ const chain2 = chainOf(values);
100088
+ const address = parsed.positionals[0];
100089
+ if (parsed.positionals.length !== 1 || !address)
100090
+ return usage11();
100091
+ if (!chain2)
100092
+ return usage11("--chain must be solana or hood.");
100093
+ const creator = booleans.has("--creator");
100094
+ const challenge = booleans.has("--challenge");
100095
+ const challengeId = values["--challenge-id"];
100096
+ const given = values["--signature"];
100097
+ if ((challenge || challengeId !== undefined || given !== undefined) && !creator)
100098
+ return usage11("--challenge, --challenge-id and --signature are for --creator.");
100099
+ if (challenge && (challengeId !== undefined || given !== undefined))
100100
+ return usage11("--challenge asks for a new challenge; send the signature in a second run.");
100101
+ if (challengeId === undefined !== (given === undefined))
100102
+ return usage11("--challenge-id and --signature go together.");
100103
+ if (values["--message-out"] !== undefined && !challenge)
100104
+ return usage11("--message-out goes with --challenge.");
100105
+ if (challengeId !== undefined && !UUID2.test(challengeId))
100106
+ return usage11("--challenge-id is the id the challenge printed.");
100107
+ let signature;
100108
+ if (given !== undefined) {
100109
+ signature = signatureFor(chain2, given);
100110
+ if (!signature)
100111
+ return usage11(chain2 === "hood" ? "--signature must be the 0x-hex message signature (65 bytes)." : "--signature must be the 64-byte Ed25519 signature, base58 or base64.");
100112
+ }
100113
+ const idempotencyKey = idempotencyKeyOf(values, usage11);
100114
+ if (typeof idempotencyKey === "number")
100115
+ return idempotencyKey;
100116
+ const apiKey = await requireKey(ctx);
100117
+ if (!apiKey)
100118
+ return 1;
100119
+ if (challenge)
100120
+ return creatorChallenge(ctx, chain2, address, apiKey, values["--message-out"]);
100121
+ const body = { kind: creator ? "creator" : "holder", ...challengeId ? { challengeId, signature } : {} };
100122
+ const result = await write(ctx, {
100123
+ method: "POST",
100124
+ path: pagePath(chain2, address, "/claims"),
100125
+ body,
100126
+ apiKey,
100127
+ idempotencyKey
100128
+ });
100129
+ if (result === "unknown")
100130
+ return writeUnknown(ctx, idempotencyKey);
100131
+ if (!result.ok) {
100132
+ const refusal3 = refusalOf2(result);
100133
+ if (refusal3?.code === "invalid_signature" && creator && !challengeId) {
100134
+ writeRefusal(ctx, refusal3, `This account's known wallets do not include the verified creator, so the claim needs a signed challenge: candle token claim ${address} --chain ${chain2} --creator --challenge`);
100135
+ return 1;
100136
+ }
100137
+ return writeApiFailure(ctx, result, "key");
100138
+ }
100139
+ const data = dataOf(result);
100140
+ if (ctx.json)
100141
+ ctx.deps.stdout.write(`${JSON.stringify({ ok: true, data, idempotencyKey })}
100142
+ `);
100143
+ else
100144
+ writeFields(ctx.deps, "stdout", [
100145
+ ["Kind", data.kind],
100146
+ ["Creator", data.creatorProven ? "proven" : "not proven"],
100147
+ ["Revision", data.revision]
100148
+ ], "Claimed");
100149
+ return 0;
100150
+ }
100151
+ async function creatorChallenge(ctx, chain2, address, apiKey, messageOut) {
100152
+ const result = await apiRequest(pagePath(chain2, address, "/creator-challenges"), {
100153
+ apiUrl: ctx.apiUrl,
100154
+ method: "POST",
100155
+ body: {},
100156
+ auth: "key",
100157
+ credentials: { apiKey },
100158
+ fetch: ctx.deps.fetch,
100159
+ env: ctx.deps.env
100160
+ });
100161
+ if (!result.ok)
100162
+ return writeApiFailure(ctx, result, "key");
100163
+ const data = dataOf(result);
100164
+ const bytes = new TextEncoder().encode(data.message);
100165
+ const sha2564 = createHash5("sha256").update(bytes).digest("hex");
100166
+ if (messageOut !== undefined) {
100167
+ try {
100168
+ await ctx.deps.writeFile(messageOut, data.message);
100169
+ } catch (error) {
100170
+ writeLocalFailure(ctx.deps, {
100171
+ code: "MESSAGE_OUT_FAILED",
100172
+ message: `The challenge could not be written to ${messageOut}: ${error instanceof Error ? error.message : error}.`,
100173
+ details: { challengeId: data.challengeId }
100174
+ }, ctx.json);
100175
+ return 1;
100176
+ }
100177
+ }
100178
+ const next = `candle token claim ${address} --chain ${chain2} --creator --challenge-id ${data.challengeId} --signature <signature>`;
100179
+ if (ctx.json) {
100180
+ ctx.deps.stdout.write(`${JSON.stringify({ ok: true, data, byteLength: bytes.length, sha256: sha2564, ...messageOut ? { messageOut } : {}, next })}
100181
+ `);
100182
+ return 0;
100183
+ }
100184
+ writeFields(ctx.deps, "stdout", [
100185
+ ["Challenge", data.challengeId],
100186
+ ["Expires", data.expiresAt],
100187
+ ["Bytes", String(bytes.length)],
100188
+ ["sha256", sha2564],
100189
+ ["Written to", messageOut]
100190
+ ], "Creator challenge (a message, not a transaction)");
100191
+ ctx.deps.stdout.write(`
100192
+ Sign exactly these UTF-8 bytes (between the lines, no trailing newline) with the creator wallet:
100193
+ -----
100194
+ ${data.message}
100195
+ -----
100196
+ `);
100197
+ notice(ctx.deps, "stdout", "note", `Sign it on your own machine, for example candle sign message --wallet <external> --file ${messageOut ?? "<file holding exactly these bytes>"}, then run: ${next}`);
100198
+ return 0;
100199
+ }
100200
+ var SECTION_FLAGS = {
100201
+ set: { valueFlags: ["--chain", "--file", "--base-revision", "--idempotency-key"], booleanFlags: ["--clear"] },
100202
+ restore: { valueFlags: ["--chain", "--version-id", "--base-revision", "--idempotency-key"], booleanFlags: [] }
100203
+ };
100204
+ async function tokenSection(args, ctx) {
100205
+ const usage11 = usageFor(ctx, USAGE12.section);
100206
+ const action2 = args[0];
100207
+ if (action2 !== "set" && action2 !== "restore")
100208
+ return usage11();
100209
+ const spec = SECTION_FLAGS[action2];
100210
+ const parsed = parseArgs(args.slice(1), {
100211
+ valueFlags: [...spec.valueFlags],
100212
+ booleanFlags: [...spec.booleanFlags],
100213
+ ...action2 === "set" ? { pathFlags: ["--file"] } : {}
100214
+ });
100215
+ if ("error" in parsed)
100216
+ return usage11(parsed.error);
100217
+ const { values } = parsed;
100218
+ const chain2 = chainOf(values);
100219
+ const [address, sectionName] = parsed.positionals;
100220
+ if (parsed.positionals.length !== 2 || !address)
100221
+ return usage11();
100222
+ if (!chain2)
100223
+ return usage11("--chain must be solana or hood.");
100224
+ const section2 = sectionOf(sectionName);
100225
+ if (!section2)
100226
+ return usage11("The section is thesis, tokenomics or lore.");
100227
+ const base2 = values["--base-revision"];
100228
+ if (base2 === undefined || !REVISION.test(base2))
100229
+ return usage11("--base-revision is the section's current revision (0 for a first write), from candle token about.");
100230
+ const idempotencyKey = idempotencyKeyOf(values, usage11);
100231
+ if (typeof idempotencyKey === "number")
100232
+ return idempotencyKey;
100233
+ let body;
100234
+ let path;
100235
+ let method;
100236
+ if (action2 === "set") {
100237
+ const file = values["--file"];
100238
+ if (file === undefined)
100239
+ return usage11("--file is required: the section text comes from a file.");
100240
+ let bytes;
100241
+ try {
100242
+ bytes = await ctx.deps.readBytes(file);
100243
+ } catch (error) {
100244
+ writeLocalFailure(ctx.deps, {
100245
+ code: "FILE_UNREADABLE",
100246
+ message: `${file} could not be read: ${error instanceof Error ? error.message : error}.`
100247
+ }, ctx.json);
100248
+ return 2;
100249
+ }
100250
+ const checked = sectionText(bytes, section2);
100251
+ if ("error" in checked) {
100252
+ writeLocalFailure(ctx.deps, { code: "TEXT_REFUSED", message: `${checked.error} Nothing was sent.` }, ctx.json);
100253
+ return 2;
100254
+ }
100255
+ const empty = checked.text.trim().length === 0;
100256
+ if (empty && !parsed.booleans.has("--clear"))
100257
+ return usage11("The file is empty. An empty write clears the section; pass --clear to mean that.");
100258
+ if (!empty && parsed.booleans.has("--clear"))
100259
+ return usage11("--clear is for an empty file.");
100260
+ body = { text: checked.text, baseRevision: base2 };
100261
+ path = pagePath(chain2, address, `/sections/${section2}`);
100262
+ method = "PUT";
100263
+ } else {
100264
+ const versionId = values["--version-id"];
100265
+ if (versionId === undefined || !UUID2.test(versionId))
100266
+ return usage11("--version-id is a version id from candle token history.");
100267
+ body = { versionId, baseRevision: base2 };
100268
+ path = pagePath(chain2, address, `/sections/${section2}/restore`);
100269
+ method = "POST";
100270
+ }
100271
+ const apiKey = await requireKey(ctx);
100272
+ if (!apiKey)
100273
+ return 1;
100274
+ const result = await write(ctx, { method, path, body, apiKey, idempotencyKey });
100275
+ if (result === "unknown")
100276
+ return writeUnknown(ctx, idempotencyKey);
100277
+ if (!result.ok) {
100278
+ const refusal3 = refusalOf2(result);
100279
+ if (refusal3?.code === "revision_conflict") {
100280
+ const latest = refusal3.extra.latest;
100281
+ writeRefusal(ctx, refusal3, `${latest?.revision !== undefined ? `The latest is revision ${latest.revision}. ` : ""}${action2 === "set" ? SECTION_SUGGESTION : "Rerun with --base-revision set to the latest revision."}`);
100282
+ return EXIT_REVISION_CONFLICT;
100283
+ }
100284
+ return writeApiFailure(ctx, result, "key");
100285
+ }
100286
+ const data = dataOf(result);
100287
+ if (ctx.json)
100288
+ ctx.deps.stdout.write(`${JSON.stringify({ ok: true, data, idempotencyKey })}
100289
+ `);
100290
+ else
100291
+ writeFields(ctx.deps, "stdout", [
100292
+ ["Revision", data.revision],
100293
+ ["Version", data.id]
100294
+ ], action2 === "set" ? `${section2} saved` : `${section2} restored as a new version`);
100295
+ return 0;
100296
+ }
100297
+ async function tokenHistory(args, ctx) {
100298
+ const usage11 = usageFor(ctx, USAGE12.history);
100299
+ const parsed = parseArgs(args, { valueFlags: ["--chain", "--limit", "--cursor"] });
100300
+ if ("error" in parsed)
100301
+ return usage11(parsed.error);
100302
+ const { values } = parsed;
100303
+ const chain2 = chainOf(values);
100304
+ const [address, sectionName] = parsed.positionals;
100305
+ if (parsed.positionals.length !== 2 || !address)
100306
+ return usage11();
100307
+ if (!chain2)
100308
+ return usage11("--chain must be solana or hood.");
100309
+ const section2 = sectionOf(sectionName);
100310
+ if (!section2)
100311
+ return usage11("The section is thesis, tokenomics or lore.");
100312
+ const limit = values["--limit"];
100313
+ if (limit !== undefined && (!/^[1-9]\d?$/.test(limit) || Number(limit) > 50))
100314
+ return usage11("--limit is a whole number from 1 to 50.");
100315
+ const query = new URLSearchParams({
100316
+ ...limit !== undefined ? { limit } : {},
100317
+ ...values["--cursor"] !== undefined ? { cursor: values["--cursor"] } : {}
100318
+ });
100319
+ const result = await read2(ctx, pagePath(chain2, address, `/sections/${section2}/history${query.size ? `?${query}` : ""}`));
100320
+ if (!result.ok)
100321
+ return writeApiFailure(ctx, result, "none");
100322
+ const data = dataOf(result);
100323
+ if (ctx.json) {
100324
+ ctx.deps.stdout.write(`${JSON.stringify({ ok: true, data })}
100325
+ `);
100326
+ return 0;
100327
+ }
100328
+ if (!data.items.length)
100329
+ ctx.deps.stdout.write(`No ${section2} versions.
100330
+ `);
100331
+ for (const item of data.items) {
100332
+ writeHeading(ctx.deps, "stdout", `revision ${item.revision}`);
100333
+ writeFields(ctx.deps, "stdout", [
100334
+ ["Version", item.id],
100335
+ ["Written by", `${identity3(item.author)}${item.dev ? " (dev)" : ""}`],
100336
+ ["Share then", bpsPercent(item.shareBps)],
100337
+ ["At", item.createdAt],
100338
+ ["Restored from", item.restoredFrom ?? undefined],
100339
+ ["State", item.tombstone ?? "visible"]
100340
+ ]);
100341
+ if (item.text !== null)
100342
+ ctx.deps.stdout.write(`
100343
+ ${terminalTextKeepingLines(item.text)}
100344
+ `);
100345
+ }
100346
+ if (data.nextCursor)
100347
+ ctx.deps.stdout.write(`
100348
+ More: --cursor ${data.nextCursor}
100349
+ `);
100350
+ return 0;
100351
+ }
100352
+ async function tokenFlag(args, ctx) {
100353
+ const usage11 = usageFor(ctx, USAGE12.flag);
100354
+ const parsed = parseArgs(args, { valueFlags: ["--chain", "--content", "--reason", "--detail", "--idempotency-key"] });
100355
+ if ("error" in parsed)
100356
+ return usage11(parsed.error);
100357
+ const { values } = parsed;
100358
+ const chain2 = chainOf(values);
100359
+ const address = parsed.positionals[0];
100360
+ if (parsed.positionals.length !== 1 || !address)
100361
+ return usage11();
100362
+ if (!chain2)
100363
+ return usage11("--chain must be solana or hood.");
100364
+ const contentId = values["--content"];
100365
+ if (contentId === undefined || !UUID2.test(contentId))
100366
+ return usage11("--content is the exact version id being reported (candle token about or history).");
100367
+ const reason = values["--reason"];
100368
+ if (!reason || !FLAG_REASONS.includes(reason))
100369
+ return usage11(`--reason is one of ${FLAG_REASONS.join(", ")}.`);
100370
+ const detail = values["--detail"];
100371
+ if (detail !== undefined && [...detail].length > FLAG_DETAIL_LIMIT)
100372
+ return usage11(`--detail is at most ${FLAG_DETAIL_LIMIT} characters.`);
100373
+ const idempotencyKey = idempotencyKeyOf(values, usage11);
100374
+ if (typeof idempotencyKey === "number")
100375
+ return idempotencyKey;
100376
+ const apiKey = await requireKey(ctx);
100377
+ if (!apiKey)
100378
+ return 1;
100379
+ const body = { contentId, reason, ...detail !== undefined ? { detail } : {} };
100380
+ const result = await write(ctx, {
100381
+ method: "POST",
100382
+ path: pagePath(chain2, address, "/flags"),
100383
+ body,
100384
+ apiKey,
100385
+ idempotencyKey
100386
+ });
100387
+ if (result === "unknown")
100388
+ return writeUnknown(ctx, idempotencyKey);
100389
+ if (!result.ok)
100390
+ return writeApiFailure(ctx, result, "key");
100391
+ const data = dataOf(result);
100392
+ if (ctx.json)
100393
+ ctx.deps.stdout.write(`${JSON.stringify({ ok: true, data, idempotencyKey })}
100394
+ `);
100395
+ else
100396
+ writeFields(ctx.deps, "stdout", [
100397
+ ["Content", data.contentId],
100398
+ ["Hidden", data.hidden ? "yes, pending Candle review" : "no"]
100399
+ ], "Reported");
100400
+ return 0;
100401
+ }
100402
+
99526
100403
  // src/commands/token-paid.ts
99527
100404
  init_args();
99528
100405
  init_deps();
99529
100406
  init_render();
99530
100407
  init_solana_endpoint();
99531
100408
  init_solana_lite();
99532
- import { randomUUID as randomUUID10 } from "node:crypto";
100409
+ import { randomUUID as randomUUID11 } from "node:crypto";
99533
100410
 
99534
100411
  // src/x402/pay.ts
99535
100412
  init_client();
@@ -99548,7 +100425,7 @@ class X402DecodeError extends Error {
99548
100425
  }
99549
100426
  }
99550
100427
  var BASE64 = /^[A-Za-z0-9+/]*={0,2}$/;
99551
- var isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
100428
+ var isObject3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
99552
100429
  var isString = (value) => typeof value === "string";
99553
100430
  function encodeHeader(value) {
99554
100431
  return Buffer.from(JSON.stringify(value), "utf8").toString("base64");
@@ -99563,12 +100440,12 @@ function decodeHeader(value) {
99563
100440
  } catch {
99564
100441
  throw new X402DecodeError("not JSON");
99565
100442
  }
99566
- if (!isObject2(parsed))
100443
+ if (!isObject3(parsed))
99567
100444
  throw new X402DecodeError("not a JSON object");
99568
100445
  return parsed;
99569
100446
  }
99570
100447
  function parseRequirements(value) {
99571
- if (!isObject2(value))
100448
+ if (!isObject3(value))
99572
100449
  throw new X402DecodeError("requirements are not an object");
99573
100450
  const { scheme, network: network2, amount, asset, payTo, maxTimeoutSeconds, extra } = value;
99574
100451
  if (!isString(scheme) || !isString(network2) || !isString(amount) || !isString(asset) || !isString(payTo)) {
@@ -99577,7 +100454,7 @@ function parseRequirements(value) {
99577
100454
  if (typeof maxTimeoutSeconds !== "number" || !Number.isInteger(maxTimeoutSeconds)) {
99578
100455
  throw new X402DecodeError("maxTimeoutSeconds is not an integer");
99579
100456
  }
99580
- if (extra !== undefined && !isObject2(extra))
100457
+ if (extra !== undefined && !isObject3(extra))
99581
100458
  throw new X402DecodeError("extra is not an object");
99582
100459
  return { scheme, network: network2, amount, asset, payTo, maxTimeoutSeconds, ...extra ? { extra } : {} };
99583
100460
  }
@@ -99586,7 +100463,7 @@ function decodePaymentRequired(header) {
99586
100463
  if (object4.x402Version !== X402_VERSION)
99587
100464
  throw new X402DecodeError("x402Version is not 2");
99588
100465
  const resource = object4.resource;
99589
- if (!isObject2(resource) || !isString(resource.url))
100466
+ if (!isObject3(resource) || !isString(resource.url))
99590
100467
  throw new X402DecodeError("resource is missing");
99591
100468
  if (!Array.isArray(object4.accepts))
99592
100469
  throw new X402DecodeError("accepts is not an array");
@@ -99601,7 +100478,7 @@ function decodePaymentRequired(header) {
99601
100478
  ...isString(resource.mimeType) ? { mimeType: resource.mimeType } : {}
99602
100479
  },
99603
100480
  accepts: object4.accepts.map(parseRequirements),
99604
- ...isObject2(object4.extensions) ? { extensions: object4.extensions } : {}
100481
+ ...isObject3(object4.extensions) ? { extensions: object4.extensions } : {}
99605
100482
  };
99606
100483
  }
99607
100484
  function paymentRequiredOf(headers2) {
@@ -99647,14 +100524,14 @@ function encodePaymentPayload(args) {
99647
100524
  // src/x402/siwx.ts
99648
100525
  init_esm();
99649
100526
  var SIWX_EXTENSION = "sign-in-with-x";
99650
- var isObject3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
100527
+ var isObject4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
99651
100528
  function spendChallengeOf(extensions, apiHost, network2) {
99652
100529
  const extension = extensions?.[SIWX_EXTENSION];
99653
- if (!isObject3(extension) || !isObject3(extension.info))
100530
+ if (!isObject4(extension) || !isObject4(extension.info))
99654
100531
  return null;
99655
100532
  const info3 = extension.info;
99656
100533
  const chains = Array.isArray(extension.supportedChains) ? extension.supportedChains : [];
99657
- const chain2 = chains.find((c) => isObject3(c) && c.chainId === network2 && c.type === "ed25519");
100534
+ const chain2 = chains.find((c) => isObject4(c) && c.chainId === network2 && c.type === "ed25519");
99658
100535
  if (!chain2)
99659
100536
  return null;
99660
100537
  const { domain, uri, version, nonce, issuedAt, expirationTime } = info3;
@@ -100121,7 +100998,7 @@ async function runPaidRead(ctx, input) {
100121
100998
  blockhash: blockhashFor(ctx),
100122
100999
  env: ctx.deps.env,
100123
101000
  now: ctx.deps.now,
100124
- newId: randomUUID10
101001
+ newId: randomUUID11
100125
101002
  });
100126
101003
  const line = paymentLine(paid);
100127
101004
  if (line && !ctx.json)
@@ -100216,7 +101093,7 @@ init_render();
100216
101093
  init_solana_verify();
100217
101094
  init_trading();
100218
101095
  init_swap();
100219
- var USAGE11 = "Usage: candle transfer --to <address|wallet name|vault> --asset <SOL|USDC|CNDL|ETH|USDG>|--mint <mint>|--token <0x...> --amount <decimal|max> [--wallet <name>] [--rpc-url <url>] [--yes] [--json]";
101096
+ var USAGE13 = "Usage: candle transfer --to <address|wallet name|vault> --asset <SOL|USDC|CNDL|ETH|USDG>|--mint <mint>|--token <0x...> --amount <decimal|max> [--wallet <name>] [--rpc-url <url>] [--yes] [--json]";
100220
101097
  var TRANSFER_ASSETS = [...Object.keys(BASES), ...Object.keys(HOOD_BASES)];
100221
101098
  var BASE58_ADDRESS = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
100222
101099
  async function readLinkedWallets(ctx, key) {
@@ -100279,9 +101156,9 @@ function describeDestination(destination) {
100279
101156
  return `address ${destination.address} (not one of this account's linked wallets; Candle decides whether it is allowed)`;
100280
101157
  }
100281
101158
  }
100282
- function writePreview(ctx, title, rows, note) {
101159
+ function writePreview(ctx, title2, rows, note) {
100283
101160
  const style = terminalStyle(ctx.deps, "stderr");
100284
- ctx.deps.stderr.write(`${heading(title, style)}
101161
+ ctx.deps.stderr.write(`${heading(title2, style)}
100285
101162
 
100286
101163
  ${fields(rows, style).join(`
100287
101164
  `)}
@@ -100312,7 +101189,7 @@ async function transfer(args, ctx) {
100312
101189
  const flags2 = parsed.values;
100313
101190
  const asset = flags2["--asset"]?.toUpperCase();
100314
101191
  if (parsed.positionals.length !== 0 || !flags2["--to"] || !flags2["--amount"] || [flags2["--asset"], flags2["--mint"], flags2["--token"]].filter(Boolean).length !== 1 || asset !== undefined && !TRANSFER_ASSETS.includes(asset) || flags2["--mint"] !== undefined && !BASE58_ADDRESS.test(flags2["--mint"]) || flags2["--token"] !== undefined && !checkEvmAddress(flags2["--token"]).ok) {
100315
- writeUsageFailure(ctx.deps, USAGE11, ctx.json);
101192
+ writeUsageFailure(ctx.deps, USAGE13, ctx.json);
100316
101193
  return 2;
100317
101194
  }
100318
101195
  const to = flags2["--to"];
@@ -100569,7 +101446,7 @@ import { randomBytes as randomBytes11 } from "node:crypto";
100569
101446
  init_presentation();
100570
101447
  var FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
100571
101448
  var INTERVAL_MS3 = 80;
100572
- function stepReporter(write, tty, ascii = false) {
101449
+ function stepReporter(write2, tty, ascii = false) {
100573
101450
  let detach = () => {};
100574
101451
  let timer = null;
100575
101452
  let frame = 0;
@@ -100580,7 +101457,7 @@ function stepReporter(write, tty, ascii = false) {
100580
101457
  clearInterval(timer);
100581
101458
  timer = null;
100582
101459
  if (tty && current !== null)
100583
- write("\r\x1B[2K");
101460
+ write2("\r\x1B[2K");
100584
101461
  current = null;
100585
101462
  };
100586
101463
  return {
@@ -100588,7 +101465,7 @@ function stepReporter(write, tty, ascii = false) {
100588
101465
  clearSpinner();
100589
101466
  current = label;
100590
101467
  if (!tty) {
100591
- write(`${label}...
101468
+ write2(`${label}...
100592
101469
  `);
100593
101470
  return;
100594
101471
  }
@@ -100607,21 +101484,21 @@ function stepReporter(write, tty, ascii = false) {
100607
101484
  process.off("SIGTERM", sigterm);
100608
101485
  };
100609
101486
  timer = setInterval(() => {
100610
- write(`\r\x1B[2K${FRAMES[frame % FRAMES.length]} ${current}`);
101487
+ write2(`\r\x1B[2K${FRAMES[frame % FRAMES.length]} ${current}`);
100611
101488
  frame++;
100612
101489
  }, INTERVAL_MS3);
100613
101490
  if (typeof timer === "object" && "unref" in timer)
100614
101491
  timer.unref();
100615
- write(`${FRAMES[0]} ${label}`);
101492
+ write2(`${FRAMES[0]} ${label}`);
100616
101493
  },
100617
101494
  done(label) {
100618
101495
  clearSpinner();
100619
- write(`${ascii ? "OK" : "✓"} ${label}
101496
+ write2(`${ascii ? "OK" : "✓"} ${label}
100620
101497
  `);
100621
101498
  },
100622
101499
  fail(label) {
100623
101500
  clearSpinner();
100624
- write(`${ascii ? "FAIL" : "✗"} ${label}
101501
+ write2(`${ascii ? "FAIL" : "✗"} ${label}
100625
101502
  `);
100626
101503
  },
100627
101504
  stop: clearSpinner
@@ -100643,7 +101520,7 @@ init_release();
100643
101520
 
100644
101521
  // src/release-assets.ts
100645
101522
  init_release();
100646
- import { createHash as createHash6 } from "node:crypto";
101523
+ import { createHash as createHash7 } from "node:crypto";
100647
101524
 
100648
101525
  // src/bun-crypto-shim.ts
100649
101526
  import crypto3, { KeyObject } from "node:crypto";
@@ -100683,7 +101560,7 @@ installBunCryptoShim();
100683
101560
  var import_bundle = __toESM(require_dist3(), 1);
100684
101561
  var import_protobuf_specs = __toESM(require_dist2(), 1);
100685
101562
  var import_verify = __toESM(require_dist5(), 1);
100686
- import { createHash as createHash5 } from "node:crypto";
101563
+ import { createHash as createHash6 } from "node:crypto";
100687
101564
  // src/sigstore-trusted-root.json
100688
101565
  var sigstore_trusted_root_default = {
100689
101566
  mediaType: "application/vnd.dev.sigstore.trustedroot+json;version=0.1",
@@ -100843,7 +101720,7 @@ function verifyReleaseAsset(bytes, bundleJson, identityUri, issuer) {
100843
101720
  return { ok: false, reason: LEGACY_BUNDLE_REASON };
100844
101721
  try {
100845
101722
  const bundle = import_bundle.bundleFromJSON(bundleJson);
100846
- const digest = createHash5("sha256").update(bytes).digest();
101723
+ const digest = createHash6("sha256").update(bytes).digest();
100847
101724
  const content = bundle.content;
100848
101725
  if (content.$case === "messageSignature") {
100849
101726
  const claimed = content.messageSignature.messageDigest?.digest;
@@ -100906,7 +101783,7 @@ async function downloadSums(deps, base2, tag) {
100906
101783
  }
100907
101784
  }
100908
101785
  function checkReleaseAsset(deps, opts) {
100909
- const actual = createHash6("sha256").update(opts.bytes).digest("hex");
101786
+ const actual = createHash7("sha256").update(opts.bytes).digest("hex");
100910
101787
  const fromSums = opts.sums.split(`
100911
101788
  `).map((line) => line.trim().split(/\s+/)).find((parts) => parts[1] === opts.name)?.[0];
100912
101789
  if (actual !== opts.expectedSha256 || actual !== fromSums) {
@@ -104290,7 +105167,7 @@ async function readLamports(addresses, solana, ctx) {
104290
105167
  }
104291
105168
  async function readEvmBalances(addresses, rpcUrl, fetchFn) {
104292
105169
  const rpc = createEvmRpc(rpcUrl, fetchFn);
104293
- const read2 = {
105170
+ const read3 = {
104294
105171
  host: rpcHostOf2(rpcUrl),
104295
105172
  chainId: undefined,
104296
105173
  requests: 0,
@@ -104299,30 +105176,30 @@ async function readEvmBalances(addresses, rpcUrl, fetchFn) {
104299
105176
  unavailable: []
104300
105177
  };
104301
105178
  try {
104302
- read2.requests += 1;
104303
- read2.chainId = await rpc.chainId();
105179
+ read3.requests += 1;
105180
+ read3.chainId = await rpc.chainId();
104304
105181
  } catch (error) {
104305
- read2.unavailable.push(...addresses);
104306
- read2.failure = error instanceof Error ? error.message : String(error);
104307
- return read2;
105182
+ read3.unavailable.push(...addresses);
105183
+ read3.failure = error instanceof Error ? error.message : String(error);
105184
+ return read3;
104308
105185
  }
104309
- const hood = read2.chainId === BigInt(HOOD_CHAIN_ID);
105186
+ const hood = read3.chainId === BigInt(HOOD_CHAIN_ID);
104310
105187
  for (const address of addresses) {
104311
105188
  try {
104312
- read2.requests += 1;
104313
- read2.wei.set(address, await rpc.getBalance(address));
105189
+ read3.requests += 1;
105190
+ read3.wei.set(address, await rpc.getBalance(address));
104314
105191
  if (hood) {
104315
- read2.requests += 1;
104316
- read2.usdg.set(address, await rpc.erc20BalanceOf(HOOD_USDG_ADDRESS, address));
105192
+ read3.requests += 1;
105193
+ read3.usdg.set(address, await rpc.erc20BalanceOf(HOOD_USDG_ADDRESS, address));
104317
105194
  }
104318
105195
  } catch (error) {
104319
- read2.wei.delete(address);
104320
- read2.usdg.delete(address);
104321
- read2.unavailable.push(address);
104322
- read2.failure ??= error instanceof Error ? error.message : String(error);
105196
+ read3.wei.delete(address);
105197
+ read3.usdg.delete(address);
105198
+ read3.unavailable.push(address);
105199
+ read3.failure ??= error instanceof Error ? error.message : String(error);
104323
105200
  }
104324
105201
  }
104325
- return read2;
105202
+ return read3;
104326
105203
  }
104327
105204
  function evmRequestsPlanned(count3) {
104328
105205
  return `${1 + count3} to ${1 + 2 * count3}`;
@@ -105195,12 +106072,12 @@ async function promoteFresh(ctx, parsed, fromLabel, toKey) {
105195
106072
  });
105196
106073
  }
105197
106074
  async function refuseWithoutRoom(ctx) {
105198
- const read2 = await readAccountRoom(ctx);
105199
- if (!read2.ok) {
105200
- notice(ctx.deps, "stderr", "note", unreadableRoomLine(read2.reason).trim());
106075
+ const read3 = await readAccountRoom(ctx);
106076
+ if (!read3.ok) {
106077
+ notice(ctx.deps, "stderr", "note", unreadableRoomLine(read3.reason).trim());
105201
106078
  return;
105202
106079
  }
105203
- const refusal3 = singleRoomRefusal(read2.room);
106080
+ const refusal3 = singleRoomRefusal(read3.room);
105204
106081
  if (refusal3 !== null)
105205
106082
  throw refusal3;
105206
106083
  }
@@ -107023,15 +107900,15 @@ function parseCounts(count3, teeCount, externalCount, rpcUrl, evmCount, evmTeeCo
107023
107900
  if (typeof evmTeeParsed === "object" && evmTeeParsed !== null)
107024
107901
  return evmTeeParsed;
107025
107902
  const allOmitted = vaultCount === undefined && teeParsed === undefined && externalParsed === undefined;
107026
- const scan = rpcUrl !== undefined;
107903
+ const scan2 = rpcUrl !== undefined;
107027
107904
  const resolve6 = (value) => {
107028
107905
  if (value !== undefined)
107029
107906
  return value;
107030
- return scan ? undefined : 1;
107907
+ return scan2 ? undefined : 1;
107031
107908
  };
107032
- const solanaVault = allOmitted && !scan ? 1 : resolve6(vaultCount);
107033
- const solanaTee = allOmitted && !scan ? 1 : resolve6(teeParsed);
107034
- const solanaExternal = allOmitted && !scan ? 1 : resolve6(externalParsed);
107909
+ const solanaVault = allOmitted && !scan2 ? 1 : resolve6(vaultCount);
107910
+ const solanaTee = allOmitted && !scan2 ? 1 : resolve6(teeParsed);
107911
+ const solanaExternal = allOmitted && !scan2 ? 1 : resolve6(externalParsed);
107035
107912
  return {
107036
107913
  solanaVault,
107037
107914
  solanaTee,
@@ -107133,20 +108010,20 @@ async function addressLooksUsed(rpc, address) {
107133
108010
  return rpc.hasSignatureHistory(address);
107134
108011
  }
107135
108012
  async function matchAgainstAccount(ctx, apiKey, derived) {
107136
- const read2 = await completeLinkedWalletRead(ctx, apiKey);
107137
- if (!read2.complete) {
108013
+ const read3 = await completeLinkedWalletRead(ctx, apiKey);
108014
+ if (!read3.complete) {
107138
108015
  return {
107139
108016
  matched: [],
107140
108017
  unmatched: [],
107141
- account: read2.account || undefined,
108018
+ account: read3.account || undefined,
107142
108019
  complete: false,
107143
- reason: read2.incompleteReason
108020
+ reason: read3.incompleteReason
107144
108021
  };
107145
108022
  }
107146
108023
  ctx.deps.stdout.write(`
107147
- This profile acts as account ${read2.account}.
108024
+ This profile acts as account ${read3.account}.
107148
108025
  `);
107149
- const confirmed = await typedConfirm(ctx, "account", read2.account, `record exposure against account ${read2.account}`);
108026
+ const confirmed = await typedConfirm(ctx, "account", read3.account, `record exposure against account ${read3.account}`);
107150
108027
  if (!confirmed) {
107151
108028
  return {
107152
108029
  matched: [],
@@ -107160,7 +108037,7 @@ This profile acts as account ${read2.account}.
107160
108037
  const matched = [];
107161
108038
  const unmatched = [];
107162
108039
  const externalListed = [];
107163
- for (const row of read2.rows) {
108040
+ for (const row of read3.rows) {
107164
108041
  if (typeof row.address !== "string")
107165
108042
  continue;
107166
108043
  const entry = derived.byAddress.get(lookupKey(row.address));
@@ -107171,7 +108048,7 @@ This profile acts as account ${read2.account}.
107171
108048
  else
107172
108049
  unmatched.push(row.address);
107173
108050
  }
107174
- return { matched, unmatched, externalListed, account: read2.account, complete: true };
108051
+ return { matched, unmatched, externalListed, account: read3.account, complete: true };
107175
108052
  }
107176
108053
  async function writeRestoredIndex(ctx, vault, derived, matches3, counts) {
107177
108054
  const now = new Date(ctx.deps.now()).toISOString();
@@ -107414,17 +108291,17 @@ async function vaultReconcileExposure(args, ctx) {
107414
108291
  suggestion: "Run: candle auth login"
107415
108292
  });
107416
108293
  }
107417
- const read2 = await completeLinkedWalletRead(ctx, apiKey);
107418
- if (!read2.complete) {
107419
- throw new VaultError("VAULT_UNREADABLE", `The linked-wallet read did not complete: ${read2.incompleteReason}. Nothing was flagged.`, {
108294
+ const read3 = await completeLinkedWalletRead(ctx, apiKey);
108295
+ if (!read3.complete) {
108296
+ throw new VaultError("VAULT_UNREADABLE", `The linked-wallet read did not complete: ${read3.incompleteReason}. Nothing was flagged.`, {
107420
108297
  suggestion: "A partial list that happened to list nothing would read as good news, so no exposure is recorded from an incomplete read."
107421
108298
  });
107422
108299
  }
107423
108300
  const recorded = vault.index.hd.discovery?.account;
107424
- if (recorded !== undefined && recorded !== "" && recorded !== read2.account) {
107425
- throw new VaultError("EXPOSURE_ACCOUNT_MISMATCH", `This vault recorded its discovery against account ${recorded}, and this profile acts as ${read2.account}.`, { suggestion: "Switch profile and run it again. Nothing was flagged." });
108301
+ if (recorded !== undefined && recorded !== "" && recorded !== read3.account) {
108302
+ throw new VaultError("EXPOSURE_ACCOUNT_MISMATCH", `This vault recorded its discovery against account ${recorded}, and this profile acts as ${read3.account}.`, { suggestion: "Switch profile and run it again. Nothing was flagged." });
107426
108303
  }
107427
- const listed = new Set(read2.rows.map((row) => lookupKey(row.address)));
108304
+ const listed = new Set(read3.rows.map((row) => lookupKey(row.address)));
107428
108305
  const entries = vault.index.entries.map((entry) => entry.role !== "external" && listed.has(lookupKey(entry.address)) && !entry.exposure.everRemoteExposed ? { ...entry, exposure: { ...entry.exposure, everRemoteExposed: true } } : entry);
107429
108306
  const added = entries.filter((entry, i) => entry !== vault.index.entries[i]);
107430
108307
  const exposedIndexes = { ...vault.index.hd.exposedIndexes };
@@ -107464,8 +108341,8 @@ async function vaultReconcileExposure(args, ctx) {
107464
108341
  if (ctx.json) {
107465
108342
  writeJson(deps, {
107466
108343
  ok: true,
107467
- account: read2.account,
107468
- listed: read2.rows.length,
108344
+ account: read3.account,
108345
+ listed: read3.rows.length,
107469
108346
  newlyFlagged: added.length,
107470
108347
  cleared: 0,
107471
108348
  exposureReconciledAt: now
@@ -107473,8 +108350,8 @@ async function vaultReconcileExposure(args, ctx) {
107473
108350
  return 0;
107474
108351
  }
107475
108352
  writeFields(deps, "stdout", [
107476
- ["Account", read2.account],
107477
- ["Linked wallets read", read2.rows.length],
108353
+ ["Account", read3.account],
108354
+ ["Linked wallets read", read3.rows.length],
107478
108355
  ["Newly flagged remotely exposed", added.length]
107479
108356
  ], "Exposure reconciled");
107480
108357
  notice(deps, "stdout", "note", `Nothing was cleared. This command only ever adds exposure: no read can establish that an address is cold.
@@ -107725,25 +108602,25 @@ async function vaultStatus(args, ctx) {
107725
108602
  }
107726
108603
  const style = terminalStyle(deps, "stdout");
107727
108604
  const miss = symbols(style).missing;
107728
- const write = (line = "") => deps.stdout.write(`${line}
108605
+ const write2 = (line = "") => deps.stdout.write(`${line}
107729
108606
  `);
107730
- write(path);
107731
- write("");
107732
- write(heading("Vault", style));
107733
- write("");
108607
+ write2(path);
108608
+ write2("");
108609
+ write2(heading("Vault", style));
108610
+ write2("");
107734
108611
  for (const line of fields([
107735
108612
  ["Version", String(file.version)],
107736
108613
  ["Generation", String(file.generation)],
107737
108614
  ["Updated", formatTime(file.updatedAt)]
107738
108615
  ], style))
107739
- write(line);
107740
- write("");
107741
- write(heading("Factors", style));
107742
- write("");
107743
- write(`${" ".repeat(2)}${envelopes.length} factors, ${recoverable} recoverable (domains counted once)`);
108616
+ write2(line);
108617
+ write2("");
108618
+ write2(heading("Factors", style));
108619
+ write2("");
108620
+ write2(`${" ".repeat(2)}${envelopes.length} factors, ${recoverable} recoverable (domains counted once)`);
107744
108621
  for (const envelope of envelopes) {
107745
- write("");
107746
- write(`${" ".repeat(2)}${envelope.id}`);
108622
+ write2("");
108623
+ write2(`${" ".repeat(2)}${envelope.id}`);
107747
108624
  const rows = [
107748
108625
  ["Factor", envelope.factor],
107749
108626
  ["Domain", envelope.domain],
@@ -107757,30 +108634,30 @@ async function vaultStatus(args, ctx) {
107757
108634
  if (envelope.sharedDomainNote)
107758
108635
  rows.push(["Note", envelope.sharedDomainNote]);
107759
108636
  for (const line of fields(rows, style, 4))
107760
- write(line);
108637
+ write2(line);
107761
108638
  }
107762
108639
  if (recoverable === 1) {
107763
108640
  notice(deps, "stdout", "warning", "This vault has exactly one recoverable factor. Lose it and no copy of this file can be opened; the recovery phrase is then the only route, and it restores derived keys only.");
107764
108641
  }
107765
- write("");
107766
- write(heading("This machine", style));
108642
+ write2("");
108643
+ write2(heading("This machine", style));
107767
108644
  if (sidecar) {
107768
- write("");
108645
+ write2("");
107769
108646
  for (const line of fields([
107770
108647
  ["Record", "vault.state.json, cleartext, best effort"],
107771
108648
  ["Last generation seen", String(sidecar.lastGeneration)]
107772
108649
  ], style))
107773
- write(line);
108650
+ write2(line);
107774
108651
  if (sidecar.lastVerifiedBackupAt && backup) {
107775
108652
  for (const line of lastBackupLines(sidecar, backup))
107776
- write(line);
108653
+ write2(line);
107777
108654
  }
107778
108655
  if (sidecar.lastBackupSharedDomainAccepted) {
107779
- write(" shared domain accepted for the last backup destination (an unsealed copy, every envelope included)");
108656
+ write2(" shared domain accepted for the last backup destination (an unsealed copy, every envelope included)");
107780
108657
  }
107781
108658
  if (sidecar.removedEnvelopeIds.length > 0) {
107782
- write(` removed envelopes ${sidecar.removedEnvelopeIds.join(", ")}`);
107783
- write(" any copy of this file made while one existed still opens with that factor.");
108659
+ write2(` removed envelopes ${sidecar.removedEnvelopeIds.join(", ")}`);
108660
+ write2(" any copy of this file made while one existed still opens with that factor.");
107784
108661
  }
107785
108662
  } else {
107786
108663
  notice(deps, "stdout", "note", "No vault.state.json beside this vault, so an older copy of it cannot be recognized on this machine.");
@@ -107796,11 +108673,11 @@ A key it holds that was never imported opens with an earlier release's \`wallets
107796
108673
  notice(deps, "stdout", "note", "Run with --unlock to list the keys, the derivation counters and the exposure flags, which are inside the encrypted index.");
107797
108674
  return 0;
107798
108675
  }
107799
- write("");
107800
- write(heading(`Keys (${unlocked.entries.length})`, style));
108676
+ write2("");
108677
+ write2(heading(`Keys (${unlocked.entries.length})`, style));
107801
108678
  for (const entry of unlocked.entries) {
107802
- write("");
107803
- write(`${" ".repeat(2)}${entry.address}`);
108679
+ write2("");
108680
+ write2(`${" ".repeat(2)}${entry.address}`);
107804
108681
  const rows = [
107805
108682
  ["Label", entry.label || miss],
107806
108683
  ["Role", `${entry.role} (${entry.origin})`],
@@ -107814,24 +108691,24 @@ A key it holds that was never imported opens with an earlier release's \`wallets
107814
108691
  rows.push(["Accepted", "an operator asserted this pinned destination's history despite exposureUnknown"]);
107815
108692
  }
107816
108693
  for (const line of fields(rows, style, 4))
107817
- write(line);
108694
+ write2(line);
107818
108695
  }
107819
- write("");
107820
- write(LIST_POINTER);
108696
+ write2("");
108697
+ write2(LIST_POINTER);
107821
108698
  if (unlocked.duplicateLabels.length > 0) {
107822
- write("");
107823
- write(heading(`Duplicate labels (${unlocked.duplicateLabels.length})`, style));
108699
+ write2("");
108700
+ write2(heading(`Duplicate labels (${unlocked.duplicateLabels.length})`, style));
107824
108701
  for (const line of duplicateLabelLines(unlocked.duplicateLabels))
107825
- write(line);
108702
+ write2(line);
107826
108703
  }
107827
- write("");
107828
- write(heading("Derivation counters (next index per branch)", style));
107829
- write("");
108704
+ write2("");
108705
+ write2(heading("Derivation counters (next index per branch)", style));
108706
+ write2("");
107830
108707
  for (const [branch, value] of Object.entries(unlocked.nextIndex)) {
107831
108708
  const exposed = unlocked.exposedIndexes[branch] ?? [];
107832
- write(` ${branch.padEnd(12)} ${value}${exposed.length > 0 ? ` known exposed: ${exposed.join(", ")}` : ""}`);
108709
+ write2(` ${branch.padEnd(12)} ${value}${exposed.length > 0 ? ` known exposed: ${exposed.join(", ")}` : ""}`);
107833
108710
  }
107834
- write(` recovery phrase exported: ${unlocked.rootExported ? "yes" : "no"}`);
108711
+ write2(` recovery phrase exported: ${unlocked.rootExported ? "yes" : "no"}`);
107835
108712
  if (unlocked.restored) {
107836
108713
  notice(deps, "stdout", "note", "This vault was built by `vault restore --phrase`.\nIts keys are recovery artifacts, not fresh cold keys, and it does not allocate new addresses; `vault new-key` and `vault promote --from` refuse here.");
107837
108714
  }
@@ -108074,7 +108951,7 @@ init_human_output();
108074
108951
  init_release();
108075
108952
  import { dirname as dirname11, join as join15 } from "node:path";
108076
108953
  init_key_output();
108077
- var USAGE12 = "Usage: candle verify <file> --bundle <path> [--identity <uri>] [--issuer <url>]";
108954
+ var USAGE14 = "Usage: candle verify <file> --bundle <path> [--identity <uri>] [--issuer <url>]";
108078
108955
  async function resolveIdentity(deps, bundlePath, flag) {
108079
108956
  if (flag)
108080
108957
  return { kind: "ok", uri: flag, provenance: "identity from --identity" };
@@ -108106,19 +108983,19 @@ async function verify(args, ctx) {
108106
108983
  });
108107
108984
  if ("error" in parsed) {
108108
108985
  writeScreenUsageFailure(deps, `${parsed.error}
108109
- ${USAGE12}`, json);
108986
+ ${USAGE14}`, json);
108110
108987
  return 2;
108111
108988
  }
108112
108989
  const file = parsed.positionals[0];
108113
108990
  if (parsed.positionals.length !== 1 || file === undefined) {
108114
108991
  writeScreenUsageFailure(deps, `verify takes exactly one file.
108115
- ${USAGE12}`, json);
108992
+ ${USAGE14}`, json);
108116
108993
  return 2;
108117
108994
  }
108118
108995
  const bundlePath = parsed.values["--bundle"];
108119
108996
  if (!bundlePath) {
108120
108997
  writeScreenUsageFailure(deps, `--bundle is required.
108121
- ${USAGE12}`, json);
108998
+ ${USAGE14}`, json);
108122
108999
  return 2;
108123
109000
  }
108124
109001
  const resolved = await resolveIdentity(deps, bundlePath, parsed.values["--identity"]);
@@ -108132,10 +109009,10 @@ ${USAGE12}`, json);
108132
109009
  }
108133
109010
  if (resolved.kind === "absent") {
108134
109011
  writeScreenUsageFailure(deps, `--identity is required: there is no latest.json beside ${bundlePath} to take the release version from.
108135
- ${USAGE12}`, json);
109012
+ ${USAGE14}`, json);
108136
109013
  return 2;
108137
109014
  }
108138
- const identity3 = resolved.uri;
109015
+ const identity4 = resolved.uri;
108139
109016
  const issuer = parsed.values["--issuer"] ?? RELEASE_ISSUER;
108140
109017
  let bytes;
108141
109018
  let bundleJson;
@@ -108151,23 +109028,23 @@ ${USAGE12}`, json);
108151
109028
  writeScreenLocalFailure(deps, { code: "BUNDLE_UNREADABLE", message: `Could not read the bundle ${bundlePath}: ${messageOf3(error)}` }, json);
108152
109029
  return 1;
108153
109030
  }
108154
- const result = verifyReleaseAsset(bytes, bundleJson, identity3, issuer);
109031
+ const result = verifyReleaseAsset(bytes, bundleJson, identity4, issuer);
108155
109032
  if (!result.ok) {
108156
109033
  writeScreenLocalFailure(deps, {
108157
109034
  code: "SIGNATURE_INVALID",
108158
109035
  message: `Refusing ${file}: ${result.reason}.`,
108159
- suggestion: `Checked against ${identity3} (${resolved.provenance}).`
109036
+ suggestion: `Checked against ${identity4} (${resolved.provenance}).`
108160
109037
  }, json);
108161
109038
  return 1;
108162
109039
  }
108163
109040
  if (json) {
108164
- deps.stdout.write(`${JSON.stringify({ ok: true, file, identity: identity3, issuer, identitySource: resolved.provenance })}
109041
+ deps.stdout.write(`${JSON.stringify({ ok: true, file, identity: identity4, issuer, identitySource: resolved.provenance })}
108165
109042
  `);
108166
109043
  } else {
108167
109044
  writeSuccess(deps, "stdout", "Release signature verified");
108168
109045
  writeFields(deps, "stdout", [
108169
109046
  ["File", file],
108170
- ["Identity", identity3],
109047
+ ["Identity", identity4],
108171
109048
  ["Source", resolved.provenance],
108172
109049
  ["Issuer", issuer]
108173
109050
  ]);
@@ -108380,8 +109257,8 @@ init_solana_alt();
108380
109257
  init_solana_lite();
108381
109258
  init_trading();
108382
109259
  init_swap();
108383
- import { randomUUID as randomUUID11 } from "node:crypto";
108384
- var USAGE13 = "Usage: candle wallet close-empty [--wallet embedded|<tee address|label>] [--keep <mint>]... [--client-trade-id <id>] [--yes] [--json]";
109260
+ import { randomUUID as randomUUID12 } from "node:crypto";
109261
+ var USAGE15 = "Usage: candle wallet close-empty [--wallet embedded|<tee address|label>] [--keep <mint>]... [--client-trade-id <id>] [--yes] [--json]";
108385
109262
  var BASE58_ADDRESS2 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
108386
109263
  var LISTED_ROWS = 50;
108387
109264
  var TOKEN_IX_CLOSE_ACCOUNT3 = 9;
@@ -108644,7 +109521,7 @@ async function closeTee(ctx, key, wallet3, name2, run2) {
108644
109521
  async function walletsCloseEmpty(args, ctx) {
108645
109522
  const lifted = splitKeep(args);
108646
109523
  if ("error" in lifted) {
108647
- writeUsageFailure(ctx.deps, `${lifted.error}. ${USAGE13}`, ctx.json);
109524
+ writeUsageFailure(ctx.deps, `${lifted.error}. ${USAGE15}`, ctx.json);
108648
109525
  return 2;
108649
109526
  }
108650
109527
  const parsed = parseArgs(lifted.rest, { valueFlags: ["--wallet", "--client-trade-id"], booleanFlags: ["--yes"] });
@@ -108653,9 +109530,9 @@ async function walletsCloseEmpty(args, ctx) {
108653
109530
  return 2;
108654
109531
  }
108655
109532
  const named = parsed.values["--client-trade-id"];
108656
- const id = named ?? `close-${randomUUID11()}`;
109533
+ const id = named ?? `close-${randomUUID12()}`;
108657
109534
  if (parsed.positionals.length !== 0 || !validClientId(id) || !lifted.keep.every((m) => BASE58_ADDRESS2.test(m))) {
108658
- writeUsageFailure(ctx.deps, USAGE13, ctx.json);
109535
+ writeUsageFailure(ctx.deps, USAGE15, ctx.json);
108659
109536
  return 2;
108660
109537
  }
108661
109538
  const run2 = { id, named: named !== undefined, keep: lifted.keep, yes: parsed.booleans.has("--yes") };
@@ -109063,9 +109940,15 @@ var COMMANDS = {
109063
109940
  clusters: tokenClusters,
109064
109941
  events: tokenEvents,
109065
109942
  forensics: tokenForensics,
109066
- "vamp-candidates": tokenVampCandidates
109943
+ "vamp-candidates": tokenVampCandidates,
109944
+ about: tokenAbout,
109945
+ claim: tokenClaim,
109946
+ section: tokenSection,
109947
+ history: tokenHistory,
109948
+ flag: tokenFlag
109067
109949
  }
109068
109950
  },
109951
+ scan: { bare: scan },
109069
109952
  spend: {
109070
109953
  bare: spendShow,
109071
109954
  subcommands: {
@@ -109227,6 +110110,7 @@ var NEVER_GUARDED = new Set([
109227
110110
  "verify",
109228
110111
  "plans",
109229
110112
  "token",
110113
+ "scan",
109230
110114
  "spend",
109231
110115
  "update",
109232
110116
  "help",
@@ -109384,7 +110268,8 @@ async function runCommand(argv, deps) {
109384
110268
  const publicPerpsRead = word3 === "perps" && ["markets", "market", "book", "candles"].includes(sub ?? "");
109385
110269
  const coreFace = word3 === "core" && sub === "mcp";
109386
110270
  const actsAsIdentity = !publicPerpsRead && !coreFace && (word3 !== "mcp" || mcpActsAsIdentity(tokens.slice(1)));
109387
- if (ROUTED_COMMANDS.has(word3) && !NEVER_GUARDED.has(word3) && routesToCommand(cmd, sub) && actsAsIdentity) {
110271
+ const tokenPageActs = word3 === "token" && (["claim", "section", "flag"].includes(sub ?? "") || sub === "about" && tokens.includes("--capabilities"));
110272
+ if (ROUTED_COMMANDS.has(word3) && (!NEVER_GUARDED.has(word3) || tokenPageActs) && routesToCommand(cmd, sub) && actsAsIdentity) {
109388
110273
  const verdict = await verifyProfileAccount(ctx, config2);
109389
110274
  if (!verdict.ok) {
109390
110275
  writeLocalFailure(deps, { code: "ACCOUNT_MISMATCH", message: verdict.message, suggestion: verdict.suggestion }, flags2.json);