bulletin-deploy 0.7.20 → 0.7.21

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 (39) hide show
  1. package/README.md +0 -2
  2. package/assets/environments.json +2 -7
  3. package/bin/bulletin-deploy +0 -6
  4. package/dist/bug-report.js +4 -5
  5. package/dist/{chunk-GGHSZZZ3.js → chunk-2VNGK2MU.js} +13 -19
  6. package/dist/{chunk-UVIG5UAV.js → chunk-BFXHVC23.js} +72 -38
  7. package/dist/{chunk-HUT7ZGRQ.js → chunk-F36C363Y.js} +3 -11
  8. package/dist/{chunk-CD27FW4F.js → chunk-G2P5UIPX.js} +3 -3
  9. package/dist/{chunk-6LODTEG3.js → chunk-RJAFD4LO.js} +1 -1
  10. package/dist/{chunk-EZUICRCA.js → chunk-SA37SLYF.js} +2 -2
  11. package/dist/{chunk-BR2EQ2X3.js → chunk-VTTN4BX7.js} +209 -483
  12. package/dist/{chunk-GNVDLLZI.js → chunk-ZY6QLNKQ.js} +1 -1
  13. package/dist/chunk-probe.js +3 -4
  14. package/dist/chunker.js +0 -1
  15. package/dist/deploy.d.ts +1 -9
  16. package/dist/deploy.js +8 -9
  17. package/dist/dotns.d.ts +9 -33
  18. package/dist/dotns.js +3 -12
  19. package/dist/environments.d.ts +0 -4
  20. package/dist/environments.js +1 -2
  21. package/dist/errors.js +0 -1
  22. package/dist/gh-pages-mirror.js +0 -1
  23. package/dist/incremental-stats.js +0 -1
  24. package/dist/index.js +8 -9
  25. package/dist/manifest-embed.js +0 -1
  26. package/dist/manifest-fetch.js +0 -1
  27. package/dist/manifest-roundtrip.js +0 -1
  28. package/dist/manifest.js +0 -1
  29. package/dist/memory-report.js +2 -3
  30. package/dist/merkle.js +8 -9
  31. package/dist/mirror.js +0 -1
  32. package/dist/pool.js +0 -1
  33. package/dist/run-state.js +1 -2
  34. package/dist/telemetry.js +2 -3
  35. package/dist/version-check.js +3 -4
  36. package/docs/e2e-bootstrap.md +9 -15
  37. package/package.json +3 -3
  38. package/dist/chunk-QGM4M3NI.js +0 -37
  39. package/dist/wrapper-IFSKR7DG.js +0 -3651
@@ -5,13 +5,10 @@ import {
5
5
  captureWarning,
6
6
  setDeployAttribute,
7
7
  withSpan
8
- } from "./chunk-GGHSZZZ3.js";
8
+ } from "./chunk-2VNGK2MU.js";
9
9
 
10
10
  // src/dotns.ts
11
- import { spawn } from "child_process";
12
11
  import crypto from "crypto";
13
- import { readFileSync } from "fs";
14
- import { dirname, join } from "path";
15
12
  import { createClient, Enum } from "polkadot-api";
16
13
  import { getPolkadotSigner } from "polkadot-api/signer";
17
14
  import { getWsProvider } from "polkadot-api/ws";
@@ -33,59 +30,6 @@ import {
33
30
  concatHex
34
31
  } from "viem";
35
32
  import { CID } from "multiformats/cid";
36
- import { createRequire } from "module";
37
- var _require = createRequire(import.meta.url);
38
- var DOTNS_CLI_ENV = "BULLETIN_DEPLOY_DOTNS_CLI";
39
- var DOTNS_CLI_HOST_VALUES = /* @__PURE__ */ new Set(["host", "host-dispatch"]);
40
- function resolveDotnsCliPackage() {
41
- const cliPath = _require.resolve("@parity/dotns-cli");
42
- const pkgDir = dirname(dirname(cliPath));
43
- const pkg = JSON.parse(readFileSync(join(pkgDir, "package.json"), "utf-8"));
44
- return { path: cliPath, version: pkg.version };
45
- }
46
- function resolveDotnsCliInvocation(env = process.env, packageResolver = resolveDotnsCliPackage) {
47
- const override = env[DOTNS_CLI_ENV]?.trim();
48
- if (override) {
49
- if (DOTNS_CLI_HOST_VALUES.has(override)) {
50
- return { command: process.execPath, argsPrefix: ["dotns"], version: "host-dispatch", source: "host-dispatch" };
51
- }
52
- return { command: override, argsPrefix: [], version: "override", source: "command-override" };
53
- }
54
- try {
55
- const pkg = packageResolver();
56
- return { command: process.execPath, argsPrefix: [pkg.path], version: pkg.version, source: "package" };
57
- } catch (err) {
58
- return {
59
- command: process.execPath,
60
- argsPrefix: ["dotns"],
61
- version: "unknown",
62
- source: "host-dispatch-fallback",
63
- resolutionError: err instanceof Error ? err.message : String(err)
64
- };
65
- }
66
- }
67
- function describeDotnsCliInvocation(cli) {
68
- if (cli.source === "package") return `${cli.command} ${cli.argsPrefix[0]}`;
69
- if (cli.source === "command-override") return `${cli.command} (from ${DOTNS_CLI_ENV})`;
70
- return `${cli.command} dotns`;
71
- }
72
- function dotnsCliFailureHint(cli) {
73
- if (cli.source === "host-dispatch-fallback") {
74
- return `@parity/dotns-cli was not resolvable from node_modules, so bulletin-deploy tried host binary dispatch (${process.execPath} dotns ...). Set ${DOTNS_CLI_ENV}=host to opt into that path explicitly, set ${DOTNS_CLI_ENV} to a dotns command/path, or install @parity/dotns-cli. Underlying resolution error: ${cli.resolutionError ?? "unknown"}`;
75
- }
76
- if (cli.source === "host-dispatch") {
77
- return `${DOTNS_CLI_ENV}=host uses host binary dispatch (${process.execPath} dotns ...).`;
78
- }
79
- if (cli.source === "command-override") {
80
- return `${DOTNS_CLI_ENV} uses a direct command/path (${cli.command}).`;
81
- }
82
- return null;
83
- }
84
- function withDotnsCliFailureHint(message, cli) {
85
- const hint = dotnsCliFailureHint(cli);
86
- return hint ? `${message}
87
- ${hint}` : message;
88
- }
89
33
  var ONE_PAS = 10000000000n;
90
34
  var FEE_FLOOR_OWNED = ONE_PAS / 100n;
91
35
  var FEE_FLOOR_REGISTER = ONE_PAS / 10n;
@@ -114,6 +58,8 @@ var CONTRACTS = {
114
58
  STORE_FACTORY: "0x030296782F4d3046B080BcB017f01837561D9702",
115
59
  POP_RULES: "0x4e8920B1E69d0cEA9b23CBFC87A17Ee6fE02d2d3"
116
60
  };
61
+ var PERSONHOOD_PRECOMPILE_ADDRESS = "0x000000000000000000000000000000000a010000";
62
+ var PERSONHOOD_CONTEXT = "0x646f746e73000000000000000000000000000000000000000000000000000000";
117
63
  var DECIMALS = 12n;
118
64
  var NATIVE_TO_ETH_RATIO = 1000000n;
119
65
  var CONNECTION_TIMEOUT_MS = 3e4;
@@ -135,7 +81,7 @@ function classifyTxRetryDecision(err) {
135
81
  var DEFAULT_MNEMONIC = "bottom drive obey lake curtain smoke basket hold race lonely fit walk";
136
82
  var _rpcIdCounter = 0;
137
83
  async function fetchNonceFromEndpoint(rpc, ss58Address) {
138
- const WS = globalThis.WebSocket ?? (await import("./wrapper-IFSKR7DG.js")).default;
84
+ if (!globalThis.WebSocket) throw new Error("WebSocket support is required to fetch nonce");
139
85
  return new Promise((resolve, reject) => {
140
86
  let done = false;
141
87
  const settle = (fn, ...args) => {
@@ -149,7 +95,7 @@ async function fetchNonceFromEndpoint(rpc, ss58Address) {
149
95
  fn(...args);
150
96
  };
151
97
  const timer = setTimeout(() => settle(reject, new Error(`fetchNonce timed out after 8s for ${rpc}`)), 8e3);
152
- const ws = new WS(rpc);
98
+ const ws = new WebSocket(rpc);
153
99
  const id = ++_rpcIdCounter;
154
100
  ws.onopen = () => ws.send(JSON.stringify({ jsonrpc: "2.0", id, method: "system_accountNextIndex", params: [ss58Address] }));
155
101
  ws.onmessage = (e) => {
@@ -199,10 +145,30 @@ var POP_RULES_ABI = [
199
145
  { inputs: [{ name: "name", type: "string" }], name: "price", outputs: [{ name: "", type: "uint256" }], stateMutability: "view", type: "function" },
200
146
  { inputs: [{ name: "name", type: "string" }, { name: "userAddress", type: "address" }], name: "priceWithCheck", outputs: [{ name: "metadata", type: "tuple", components: [{ name: "price", type: "uint256" }, { name: "status", type: "uint8" }, { name: "userStatus", type: "uint8" }, { name: "message", type: "string" }] }], stateMutability: "view", type: "function" },
201
147
  { inputs: [{ name: "name", type: "string" }, { name: "userAddress", type: "address" }], name: "priceWithoutCheck", outputs: [{ name: "metadata", type: "tuple", components: [{ name: "price", type: "uint256" }, { name: "status", type: "uint8" }, { name: "userStatus", type: "uint8" }, { name: "message", type: "string" }] }], stateMutability: "view", type: "function" },
202
- { inputs: [{ name: "", type: "address" }], name: "userPopStatus", outputs: [{ name: "", type: "uint8" }], stateMutability: "view", type: "function" },
203
148
  { inputs: [{ name: "status", type: "uint8" }], name: "setUserPopStatus", outputs: [], stateMutability: "nonpayable", type: "function" },
204
149
  { inputs: [{ name: "name", type: "string" }], name: "isBaseNameReserved", outputs: [{ name: "isReserved", type: "bool" }, { name: "reservationOwner", type: "address" }, { name: "expiryTimestamp", type: "uint64" }], stateMutability: "view", type: "function" }
205
150
  ];
151
+ var PERSONHOOD_ABI = [
152
+ {
153
+ type: "function",
154
+ name: "personhoodStatus",
155
+ inputs: [
156
+ { name: "account", type: "address" },
157
+ { name: "context", type: "bytes32" }
158
+ ],
159
+ outputs: [
160
+ {
161
+ name: "info",
162
+ type: "tuple",
163
+ components: [
164
+ { name: "status", type: "uint8" },
165
+ { name: "contextAlias", type: "bytes32" }
166
+ ]
167
+ }
168
+ ],
169
+ stateMutability: "view"
170
+ }
171
+ ];
206
172
  var DOTNS_REGISTRY_ABI = [
207
173
  { inputs: [{ name: "record", type: "tuple", components: [{ name: "parentNode", type: "bytes32" }, { name: "subLabel", type: "string" }, { name: "parentLabel", type: "string" }, { name: "owner", type: "address" }] }], name: "setSubnodeOwner", outputs: [{ name: "subnode", type: "bytes32" }], stateMutability: "nonpayable", type: "function" },
208
174
  { inputs: [{ name: "node", type: "bytes32" }, { name: "newResolver", type: "address" }], name: "setResolver", outputs: [], stateMutability: "nonpayable", type: "function" },
@@ -253,9 +219,9 @@ function extractStorageDepositCharge(rawStorageDeposit) {
253
219
  if (rawStorageDeposit.value != null) return convertToBigInt(rawStorageDeposit.value, 0n);
254
220
  return 0n;
255
221
  }
256
- function dotnsContractName(address) {
222
+ function dotnsContractName(address, contracts = CONTRACTS) {
257
223
  const normalized = address.toLowerCase();
258
- for (const [name, contractAddress] of Object.entries(CONTRACTS)) {
224
+ for (const [name, contractAddress] of Object.entries({ ...CONTRACTS, ...contracts })) {
259
225
  if (contractAddress.toLowerCase() === normalized) return name;
260
226
  }
261
227
  return "unknown";
@@ -266,17 +232,13 @@ function stringifyDebugValue(value) {
266
232
  function dotnsTxDebugEnabled() {
267
233
  return process.env.BULLETIN_DEPLOY_DOTNS_DEBUG === "1" || process.env.DOTNS_DEBUG === "1";
268
234
  }
269
- function isContractRevertLike(error) {
270
- const message = error instanceof Error ? error.message : String(error);
271
- return /\brevert(?:ed|ing)?\b/i.test(message);
272
- }
273
235
  function formatWeight(weight) {
274
236
  if (!weight) return "unknown";
275
237
  return `ref_time=${weight.referenceTime.toString()} proof_size=${weight.proofSize.toString()}`;
276
238
  }
277
239
  function formatContractDryRunFailure(gasEstimate, context) {
278
240
  const functionName = context.functionName ?? "unknown";
279
- const contractName = dotnsContractName(context.contractAddress);
241
+ const contractName = dotnsContractName(context.contractAddress, context.contracts);
280
242
  const lines = [
281
243
  `Contract execution would revert during ${functionName} on ${contractName}`,
282
244
  ` contract: ${context.contractAddress}`,
@@ -359,14 +321,6 @@ function validateDomainLabel(label) {
359
321
  function isCommitmentMature(chainNowSeconds, commitTimestampSeconds, minimumAgeSeconds) {
360
322
  return chainNowSeconds > commitTimestampSeconds + minimumAgeSeconds;
361
323
  }
362
- function isExplicitCommitmentBuffer(envValue) {
363
- if (envValue === void 0 || envValue === "") return false;
364
- const parsed = Number(envValue);
365
- return Number.isFinite(parsed) && parsed > 0;
366
- }
367
- function isLikelyCommitmentRace(msg) {
368
- return /CommitmentTooNew/i.test(msg) || /Revive\.ContractReverted/i.test(msg);
369
- }
370
324
  function classifyDotnsLabel(label) {
371
325
  const totalLength = label.length;
372
326
  const trailingDigits = countTrailingDigits(label);
@@ -400,6 +354,10 @@ function canRegister(requiredStatus, userStatus, trailingDigits) {
400
354
  }
401
355
  return trailingDigits !== 0 && userStatus !== ProofOfPersonhoodStatus.ProofOfPersonhoodLite;
402
356
  }
357
+ function exampleNoStatusLabel(label) {
358
+ const base = stripTrailingDigits(validateDomainLabel(label)).replace(/[^a-z0-9-]/g, "x");
359
+ return `${base.padEnd(9, "x").slice(0, 9)}00.dot`;
360
+ }
403
361
  function simulateUserStatus(currentStatus, requiredStatus, options) {
404
362
  const canSelfAttest = options.canSelfAttest ?? true;
405
363
  const max = (a, b) => a > b ? a : b;
@@ -440,6 +398,16 @@ function parseProofOfPersonhoodStatus(status) {
440
398
  function popStatusName(status) {
441
399
  return Object.keys(ProofOfPersonhoodStatus).find((k) => ProofOfPersonhoodStatus[k] === status) ?? String(status);
442
400
  }
401
+ function normalizeProofOfPersonhoodStatus(status) {
402
+ if (typeof status === "number") return status;
403
+ if (typeof status === "bigint") return Number(status);
404
+ if (typeof status === "string") return Number(status);
405
+ throw new Error(`Unexpected ProofOfPersonhoodStatus type: ${typeof status}`);
406
+ }
407
+ function parsePersonhoodStatusResult(result) {
408
+ const status = Array.isArray(result) ? result[0]?.status ?? result[0] : result?.status;
409
+ return normalizeProofOfPersonhoodStatus(status);
410
+ }
443
411
  var ReviveClientWrapper = class _ReviveClientWrapper {
444
412
  static DRY_RUN_STORAGE_LIMIT = 18446744073709551615n;
445
413
  static DRY_RUN_WEIGHT_LIMIT = { ref_time: 18446744073709551615n, proof_size: 18446744073709551615n };
@@ -608,7 +576,7 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
608
576
  }
609
577
  throw lastError instanceof Error ? lastError : new Error(String(lastError));
610
578
  }
611
- async submitTransaction(contractAddress, value, encodedData, signerSubstrateAddress, signer, statusCallback, { rpcs, useNoncePolling, functionName, args }) {
579
+ async submitTransaction(contractAddress, value, encodedData, signerSubstrateAddress, signer, statusCallback, { rpcs, useNoncePolling, functionName, args, contracts }) {
612
580
  await this.ensureAccountMapped(signerSubstrateAddress, signer);
613
581
  const signerEvmAddress = await this.getEvmAddress(signerSubstrateAddress);
614
582
  const gasEstimate = await this.estimateGasForCall(signerSubstrateAddress, contractAddress, value, encodedData);
@@ -620,7 +588,8 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
620
588
  signerEvmAddress,
621
589
  value,
622
590
  encodedData,
623
- args
591
+ args,
592
+ contracts
624
593
  }));
625
594
  }
626
595
  const weightLimit = { proof_size: gasEstimate.gasRequired.proofSize, ref_time: gasEstimate.gasRequired.referenceTime };
@@ -639,69 +608,6 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
639
608
  return await this.signAndSubmitWithRetry(buildExtrinsic, signer, statusCallback, "Revive.call", { nonceFallback });
640
609
  }
641
610
  };
642
- async function runDotnsCli(argv, env) {
643
- return new Promise((resolve, reject) => {
644
- const cli = resolveDotnsCliInvocation();
645
- try {
646
- setDeployAttribute("deploy.dotns_cli.version", cli.version);
647
- setDeployAttribute("deploy.dotns_cli.source", cli.source);
648
- } catch {
649
- }
650
- const proc = spawn(cli.command, [...cli.argsPrefix, ...argv], {
651
- stdio: ["ignore", "pipe", "pipe"],
652
- env: { ...process.env, ...env }
653
- });
654
- let stdout = "";
655
- let stderr = "";
656
- proc.stdout.on("data", (chunk) => {
657
- stdout += chunk.toString();
658
- });
659
- proc.stderr.on("data", (chunk) => {
660
- stderr += chunk.toString();
661
- });
662
- proc.on("close", (code) => {
663
- const out = stdout.trim();
664
- const err = stderr.trim();
665
- if (code === 0) {
666
- if (!out) {
667
- resolve({});
668
- return;
669
- }
670
- try {
671
- resolve(JSON.parse(out));
672
- } catch {
673
- resolve({ raw: out });
674
- }
675
- return;
676
- }
677
- let errorMsg = `dotns ${argv[0] ?? ""} failed (exit ${code})`;
678
- if (err) {
679
- try {
680
- const parsed = JSON.parse(err);
681
- if (parsed?.error) errorMsg = parsed.error;
682
- } catch {
683
- errorMsg = err.slice(0, 500) || errorMsg;
684
- }
685
- } else if (out) {
686
- errorMsg = out.slice(0, 500);
687
- }
688
- reject(new Error(withDotnsCliFailureHint(errorMsg, cli)));
689
- });
690
- proc.on("error", (err) => reject(new Error(withDotnsCliFailureHint(`Failed to spawn DotNS CLI via ${describeDotnsCliInvocation(cli)}: ${err.message}`, cli))));
691
- });
692
- }
693
- function buildAuthEnv(opts) {
694
- const env = {};
695
- if (opts.keyUri) {
696
- env.DOTNS_KEY_URI = opts.keyUri;
697
- } else if (opts.mnemonic) {
698
- env.DOTNS_MNEMONIC = opts.mnemonic;
699
- }
700
- return env;
701
- }
702
- function rpcFlag(rpc) {
703
- return rpc ? ["--rpc", rpc] : [];
704
- }
705
611
  var DotNS = class {
706
612
  client;
707
613
  clientWrapper;
@@ -714,21 +620,9 @@ var DotNS = class {
714
620
  // bulletin-deploy resolves the asset-hub list via environments.json; falls
715
621
  // back to the legacy paseo-only RPC_ENDPOINTS for direct library callers.
716
622
  assetHubEndpoints;
717
- // Stored credentials for CLI subprocess calls. Never logged or exposed.
718
- _mnemonic = null;
719
- _keyUri = null;
720
623
  _usesExternalSigner = false;
721
- _skipDotnsCli = false;
722
624
  _contracts = CONTRACTS;
723
625
  _nativeToEthRatio = NATIVE_TO_ETH_RATIO;
724
- _dotnsSelfAttest = true;
725
- // True when we must use direct contract calls instead of dotns-cli.
726
- // Either an external signer was provided, or --skip-dotns-cli was set
727
- // (needed for environments with custom contract addresses that dotns-cli
728
- // does not support).
729
- get _useContractPath() {
730
- return this._usesExternalSigner || this._skipDotnsCli;
731
- }
732
626
  constructor() {
733
627
  this.client = null;
734
628
  this.clientWrapper = null;
@@ -749,29 +643,20 @@ var DotNS = class {
749
643
  const rpc = options.rpc || process.env.DOTNS_RPC || this.assetHubEndpoints[0];
750
644
  this.rpc = rpc;
751
645
  this._usesExternalSigner = Boolean(options.signer && options.signerAddress);
752
- this._skipDotnsCli = options.skipDotnsCli ?? false;
753
- this._dotnsSelfAttest = options.dotnsSelfAttest ?? true;
754
- let authEnv = {};
755
646
  if (this._usesExternalSigner) {
756
- this._keyUri = null;
757
- this._mnemonic = null;
758
647
  this.signer = options.signer;
759
648
  this.substrateAddress = options.signerAddress;
760
649
  } else {
761
650
  const mnemonicArg = options.mnemonic || process.env.DOTNS_MNEMONIC || process.env.MNEMONIC;
762
651
  const keyUriArg = options.keyUri || process.env.DOTNS_KEY_URI;
763
- const source = keyUriArg || mnemonicArg || DEFAULT_MNEMONIC;
652
+ let source = keyUriArg || mnemonicArg || DEFAULT_MNEMONIC;
764
653
  const isKeyUri = Boolean(keyUriArg);
765
- this._keyUri = isKeyUri ? source : null;
766
- this._mnemonic = isKeyUri ? null : source;
767
- if (options.derivationPath && !isKeyUri && this._mnemonic) {
768
- this._keyUri = `${this._mnemonic}${options.derivationPath}`;
769
- this._mnemonic = null;
654
+ if (options.derivationPath && !isKeyUri && source) {
655
+ source = `${source}${options.derivationPath}`;
770
656
  }
771
- authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
772
657
  await cryptoWaitReady();
773
658
  const keyring = new Keyring({ type: "sr25519" });
774
- const account = this._keyUri ? keyring.addFromUri(this._keyUri) : keyring.addFromMnemonic(source);
659
+ const account = isKeyUri || options.derivationPath ? keyring.addFromUri(source) : keyring.addFromMnemonic(source);
775
660
  this.signer = getPolkadotSigner(account.publicKey, "Sr25519", async (input) => account.sign(input));
776
661
  this.substrateAddress = account.address;
777
662
  }
@@ -792,48 +677,50 @@ var DotNS = class {
792
677
  this.connected = true;
793
678
  if (options.nativeToEthRatio) this._nativeToEthRatio = options.nativeToEthRatio;
794
679
  try {
795
- if (options.autoAccountMapping) {
796
- await this.ensureAutoMappedAccountReady();
797
- } else {
798
- if (!await this.clientWrapper.checkIfAccountMapped(this.substrateAddress)) {
799
- console.log(` Mapping account on Asset Hub Revive...`);
800
- if (this._usesExternalSigner) {
801
- await this.clientWrapper.ensureAccountMapped(this.substrateAddress, this.signer);
802
- } else {
803
- try {
804
- await runDotnsCli(["account", "map", ...rpcFlag(rpc)], authEnv);
805
- } catch (e) {
806
- captureWarning("account map failed during connect (will rely on chain confirmation)", { error: e.message?.slice(0, 200) });
807
- }
808
- const mappingDeadline = Date.now() + 15e3;
809
- let mappingConfirmed = false;
810
- while (Date.now() < mappingDeadline) {
811
- if (await this.clientWrapper.checkIfAccountMapped(this.substrateAddress)) {
812
- mappingConfirmed = true;
813
- break;
814
- }
815
- await new Promise((r) => setTimeout(r, 1500));
816
- }
817
- if (!mappingConfirmed) {
818
- throw new Error(`Account mapping did not take effect on-chain for ${this.substrateAddress}. The map_account tx may have been dropped or hit a dispatch error \u2014 check the signer's balance for existential deposit + fees.`);
819
- }
820
- }
821
- }
822
- console.log(` Account: mapped`);
823
- }
680
+ await this.ensureMappedAccountReady(options.autoAccountMapping ?? false);
824
681
  } catch (e) {
825
682
  this.connected = false;
826
683
  throw e;
827
684
  }
828
685
  return this;
829
686
  }
687
+ async ensureMappedAccountReady(autoAccountMapping = false) {
688
+ this.ensureConnected();
689
+ if (!this.clientWrapper || !this.substrateAddress || !this.signer) {
690
+ throw new Error("Account mapping unavailable before DotNS signer is initialized");
691
+ }
692
+ if (autoAccountMapping) {
693
+ await this.ensureAutoMappedAccountReady();
694
+ return;
695
+ }
696
+ if (await this.clientWrapper.checkIfAccountMapped(this.substrateAddress)) {
697
+ console.log(` Account: mapped`);
698
+ return;
699
+ }
700
+ console.log(` Mapping account on Asset Hub Revive...`);
701
+ try {
702
+ await this.clientWrapper.ensureAccountMapped(this.substrateAddress, this.signer);
703
+ } catch (e) {
704
+ if (await this.clientWrapper.checkIfAccountMapped(this.substrateAddress)) {
705
+ console.log(` Account: mapped`);
706
+ return;
707
+ }
708
+ captureWarning("explicit account mapping failed; falling back to Revive auto-map trigger", {
709
+ signer: this.substrateAddress,
710
+ error: e?.message?.slice?.(0, 200) ?? String(e).slice(0, 200)
711
+ });
712
+ await this.ensureAutoMappedAccountReady();
713
+ return;
714
+ }
715
+ console.log(` Account: mapped`);
716
+ }
830
717
  async ensureAutoMappedAccountReady() {
831
718
  this.ensureConnected();
832
719
  if (!this.clientWrapper || !this.substrateAddress || !this.signer) {
833
720
  throw new Error("Account auto-mapping unavailable before DotNS signer is initialized");
834
721
  }
835
722
  if (await this.clientWrapper.checkIfAccountMapped(this.substrateAddress)) {
836
- console.log(` Account: auto-mapped`);
723
+ console.log(` Account: auto-mapped (Revive.OriginalAccount confirmed)`);
837
724
  return;
838
725
  }
839
726
  if (await this.isTestnet()) {
@@ -875,7 +762,7 @@ var DotNS = class {
875
762
  if (!await this.clientWrapper.checkIfAccountMapped(this.substrateAddress)) {
876
763
  throw new Error(`Account auto-mapping did not take effect on-chain for ${this.substrateAddress}. The signer needs enough testnet PAS to submit the Revive auto-map trigger before DotNS preflight can run. Top up at ${PASEO_FAUCET_URL} or fund Alice/Bob so auto-top-up can help.`);
877
764
  }
878
- console.log(` Account: auto-mapped`);
765
+ console.log(` Account: auto-mapped (Revive.OriginalAccount confirmed)`);
879
766
  }
880
767
  ensureConnected() {
881
768
  if (!this.connected) throw new Error("Not connected. Call connect() first.");
@@ -1044,7 +931,8 @@ var DotNS = class {
1044
931
  signerEvmAddress: this.evmAddress ?? void 0,
1045
932
  value: 0n,
1046
933
  encodedData: encodedCallData,
1047
- args
934
+ args,
935
+ contracts: this._contracts
1048
936
  }));
1049
937
  }
1050
938
  return decodeFunctionResult({ abi: contractAbi, functionName, data: callResult.result.value.data });
@@ -1056,7 +944,7 @@ var DotNS = class {
1056
944
  const encodedCallData = encodeFunctionData({ abi: contractAbi, functionName, args });
1057
945
  const rpcs = this.rpc ? [this.rpc, ...this.assetHubEndpoints.filter((ep) => ep !== this.rpc)] : this.assetHubEndpoints;
1058
946
  return await withTimeout(
1059
- this.clientWrapper.submitTransaction(contractAddress, value, encodedCallData, this.substrateAddress, this.signer, statusCallback, { rpcs, useNoncePolling, functionName, args }),
947
+ this.clientWrapper.submitTransaction(contractAddress, value, encodedCallData, this.substrateAddress, this.signer, statusCallback, { rpcs, useNoncePolling, functionName, args, contracts: this._contracts }),
1060
948
  OPERATION_TIMEOUT_MS,
1061
949
  functionName
1062
950
  );
@@ -1064,22 +952,9 @@ var DotNS = class {
1064
952
  async checkOwnership(label, ownerAddress = null) {
1065
953
  this.ensureConnected();
1066
954
  const checkAddress = (ownerAddress || this.evmAddress).toLowerCase();
1067
- if (this._useContractPath) {
1068
- const tokenId = computeDomainTokenId(label);
1069
- try {
1070
- const owner = await withTimeout(this.contractCall(this._contracts.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 3e4, "ownerOf");
1071
- const owned = owner.toLowerCase() === checkAddress;
1072
- return { owned, owner };
1073
- } catch {
1074
- return { owned: false, owner: null };
1075
- }
1076
- }
955
+ const tokenId = computeDomainTokenId(label);
1077
956
  try {
1078
- const result = await runDotnsCli(
1079
- ["lookup", "owner-of", label, "--json", ...rpcFlag(this.rpc)]
1080
- );
1081
- if (!result.registered) return { owned: false, owner: null };
1082
- const owner = result.ownerEvm;
957
+ const owner = await withTimeout(this.contractCall(this._contracts.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 3e4, "ownerOf");
1083
958
  const owned = owner.toLowerCase() === checkAddress;
1084
959
  return { owned, owner };
1085
960
  } catch {
@@ -1089,56 +964,21 @@ var DotNS = class {
1089
964
  async getUserPopStatus(ownerAddress = null) {
1090
965
  this.ensureConnected();
1091
966
  const checkAddress = ownerAddress || this.evmAddress;
1092
- if (this._usesExternalSigner || this._contracts.POP_RULES !== CONTRACTS.POP_RULES) {
1093
- try {
1094
- const result = await withTimeout(this.contractCall(this._contracts.POP_RULES, POP_RULES_ABI, "userPopStatus", [checkAddress]), 3e4, "userPopStatus");
1095
- return typeof result === "bigint" ? Number(result) : result;
1096
- } catch (e) {
1097
- if (isContractRevertLike(e)) return 0;
1098
- throw e;
1099
- }
1100
- }
1101
- if (ownerAddress && ownerAddress.toLowerCase() !== (this.evmAddress ?? "").toLowerCase()) {
1102
- if (!this.clientWrapper) return 0;
1103
- return 0;
967
+ try {
968
+ const result = await withTimeout(
969
+ this.contractCall(PERSONHOOD_PRECOMPILE_ADDRESS, PERSONHOOD_ABI, "personhoodStatus", [checkAddress, PERSONHOOD_CONTEXT]),
970
+ 3e4,
971
+ "personhoodStatus"
972
+ );
973
+ return parsePersonhoodStatusResult(result);
974
+ } catch (e) {
975
+ throw new Error(
976
+ `Could not read DotNS Personhood status for ${checkAddress} from the Personhood precompile. Check the Asset Hub RPC/environment and contact the DotNS team if the signer should be whitelisted. Underlying: ${e?.message ?? String(e)}`
977
+ );
1104
978
  }
1105
- const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
1106
- const info = await runDotnsCli(
1107
- ["pop", "info", "--json", ...rpcFlag(this.rpc)],
1108
- authEnv
1109
- );
1110
- return info.statusCode ?? 0;
1111
979
  }
1112
- async setUserPopStatus(status) {
1113
- this.ensureConnected();
1114
- console.log(`
1115
- Checking current PoP status...`);
1116
- const currentStatus = await this.getUserPopStatus();
1117
- const currentStatusName = popStatusName(currentStatus);
1118
- const desiredStatusName = popStatusName(status);
1119
- console.log(` Current: ${currentStatusName}`);
1120
- console.log(` Desired: ${desiredStatusName}`);
1121
- if (currentStatus === status) {
1122
- console.log(` Status already set, skipping update`);
1123
- return;
1124
- }
1125
- if (currentStatus > status) {
1126
- console.log(` Current status already satisfies desired, skipping downgrade`);
1127
- return;
1128
- }
1129
- console.log(` Setting PoP status to ${desiredStatusName}...`);
1130
- if (this._useContractPath) {
1131
- const txHash = await this.contractTransaction(this._contracts.POP_RULES, 0n, POP_RULES_ABI, "setUserPopStatus", [status], (s) => console.log(` ${s}`));
1132
- console.log(` Tx: ${txHash}`);
1133
- return;
1134
- }
1135
- const statusStr = desiredStatusName.replace("ProofOfPersonhood", "").toLowerCase() || "none";
1136
- const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
1137
- const result = await runDotnsCli(
1138
- ["pop", "set", statusStr, "--json", ...rpcFlag(this.rpc)],
1139
- authEnv
1140
- );
1141
- console.log(` PoP status set: ${result.statusCode}`);
980
+ async setUserPopStatus(_status) {
981
+ throw new Error("DotNS self-attestation is no longer available. Personhood status is read from the Personhood precompile; contact the DotNS team for whitelisting / status changes.");
1142
982
  }
1143
983
  async checkSubdomainOwnership(sublabel, parentLabel) {
1144
984
  this.ensureConnected();
@@ -1158,25 +998,16 @@ var DotNS = class {
1158
998
  this.ensureConnected();
1159
999
  console.log(`
1160
1000
  Registering subdomain ${sublabel}.${parentLabel}.dot...`);
1161
- if (this._useContractPath) {
1162
- const parentNode = namehash(`${parentLabel}.dot`);
1163
- const subnodeRecord = { parentNode, subLabel: sublabel, parentLabel, owner: this.evmAddress };
1164
- const txHash = await this.contractTransaction(this._contracts.DOTNS_REGISTRY, 0n, DOTNS_REGISTRY_ABI, "setSubnodeOwner", [subnodeRecord], (s) => console.log(` ${s}`), { useNoncePolling: true });
1165
- console.log(` Tx: ${txHash}`);
1166
- console.log(` Setting resolver...`);
1167
- const subnodeNode = namehash(`${sublabel}.${parentLabel}.dot`);
1168
- const resolverTxHash = await this.contractTransaction(this._contracts.DOTNS_REGISTRY, 0n, DOTNS_REGISTRY_ABI, "setResolver", [subnodeNode, this._contracts.DOTNS_CONTENT_RESOLVER], (s) => console.log(` ${s}`), { useNoncePolling: true });
1169
- console.log(` Tx: ${resolverTxHash}`);
1170
- console.log(` Subdomain registered!`);
1171
- return { sublabel, parentLabel, owner: this.evmAddress };
1172
- }
1173
- const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
1174
- const result = await runDotnsCli(
1175
- ["register", "subname", "-n", sublabel, "-p", parentLabel, "--json", ...rpcFlag(this.rpc)],
1176
- authEnv
1177
- );
1178
- console.log(` Subdomain registered: ${result.domain}`);
1179
- return { sublabel, parentLabel, owner: result.owner ?? this.evmAddress };
1001
+ const parentNode = namehash(`${parentLabel}.dot`);
1002
+ const subnodeRecord = { parentNode, subLabel: sublabel, parentLabel, owner: this.evmAddress };
1003
+ const txHash = await this.contractTransaction(this._contracts.DOTNS_REGISTRY, 0n, DOTNS_REGISTRY_ABI, "setSubnodeOwner", [subnodeRecord], (s) => console.log(` ${s}`), { useNoncePolling: true });
1004
+ console.log(` Tx: ${txHash}`);
1005
+ console.log(` Setting resolver...`);
1006
+ const subnodeNode = namehash(`${sublabel}.${parentLabel}.dot`);
1007
+ const resolverTxHash = await this.contractTransaction(this._contracts.DOTNS_REGISTRY, 0n, DOTNS_REGISTRY_ABI, "setResolver", [subnodeNode, this._contracts.DOTNS_CONTENT_RESOLVER], (s) => console.log(` ${s}`), { useNoncePolling: true });
1008
+ console.log(` Tx: ${resolverTxHash}`);
1009
+ console.log(` Subdomain registered!`);
1010
+ return { sublabel, parentLabel, owner: this.evmAddress };
1180
1011
  });
1181
1012
  }
1182
1013
  async setContenthash(domainName, contenthashHex) {
@@ -1193,45 +1024,25 @@ var DotNS = class {
1193
1024
  }
1194
1025
  if (!ipfsCid) throw new Error(`setContenthash: cannot decode contenthash ${contenthashHex} to an IPFS CID`);
1195
1026
  console.log(` Setting contenthash: ${ipfsCid}`);
1196
- if (this._useContractPath) {
1197
- const txHash = await this.contractTransaction(this._contracts.DOTNS_CONTENT_RESOLVER, 0n, DOTNS_CONTENT_RESOLVER_ABI, "setContenthash", [node, contenthashHex], (s) => console.log(` ${s}`), { useNoncePolling: true });
1198
- console.log(` Tx: ${txHash}`);
1199
- const expected = contenthashHex.toLowerCase();
1200
- const MAX_CHAIN_WAIT_SECONDS = 90;
1201
- const POLL_INTERVAL_MS = 2e3;
1202
- const startChainMs = Number(await this.clientWrapper.client.query.Timestamp.Now.getValue());
1203
- let onChain = "0x";
1204
- while (true) {
1205
- onChain = (await this.getContenthash(domainName) || "0x").toLowerCase();
1206
- if (onChain === expected) break;
1207
- const nowChainMs = Number(await this.clientWrapper.client.query.Timestamp.Now.getValue());
1208
- const chainElapsed = (nowChainMs - startChainMs) / 1e3;
1209
- if (chainElapsed >= MAX_CHAIN_WAIT_SECONDS) break;
1210
- console.log(` Awaiting finalization (chain time +${Math.floor(chainElapsed)}s / ${MAX_CHAIN_WAIT_SECONDS}s)...`);
1211
- await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
1212
- }
1213
- if (onChain !== expected) {
1214
- throw new Error(
1215
- `Post-deploy verification failed for ${domainName}.dot: on-chain contenthash is ${onChain}, not the ${expected} we just wrote. The setContenthash tx may have silently failed, or another party overwrote the domain. Re-run the deploy to retry.`
1216
- );
1217
- }
1218
- console.log(` Verified on-chain: ${ipfsCid}
1219
- `);
1220
- return { node };
1027
+ const txHash = await this.contractTransaction(this._contracts.DOTNS_CONTENT_RESOLVER, 0n, DOTNS_CONTENT_RESOLVER_ABI, "setContenthash", [node, contenthashHex], (s) => console.log(` ${s}`), { useNoncePolling: true });
1028
+ console.log(` Tx: ${txHash}`);
1029
+ const expected = contenthashHex.toLowerCase();
1030
+ const MAX_CHAIN_WAIT_SECONDS = 90;
1031
+ const POLL_INTERVAL_MS = 2e3;
1032
+ const startChainMs = Number(await this.clientWrapper.client.query.Timestamp.Now.getValue());
1033
+ let onChain = "0x";
1034
+ while (true) {
1035
+ onChain = (await this.getContenthash(domainName) || "0x").toLowerCase();
1036
+ if (onChain === expected) break;
1037
+ const nowChainMs = Number(await this.clientWrapper.client.query.Timestamp.Now.getValue());
1038
+ const chainElapsed = (nowChainMs - startChainMs) / 1e3;
1039
+ if (chainElapsed >= MAX_CHAIN_WAIT_SECONDS) break;
1040
+ console.log(` Awaiting finalization (chain time +${Math.floor(chainElapsed)}s / ${MAX_CHAIN_WAIT_SECONDS}s)...`);
1041
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
1221
1042
  }
1222
- const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
1223
- const setResult = await runDotnsCli(
1224
- ["content", "set", domainName, ipfsCid, "--json", ...rpcFlag(this.rpc)],
1225
- authEnv
1226
- );
1227
- console.log(` Tx: ${setResult.txHash}`);
1228
- const viewResult = await runDotnsCli(
1229
- ["content", "view", domainName, "--json", ...rpcFlag(this.rpc)]
1230
- );
1231
- const onChainCid = viewResult.cid;
1232
- if (!onChainCid || onChainCid !== ipfsCid) {
1043
+ if (onChain !== expected) {
1233
1044
  throw new Error(
1234
- `Post-deploy verification failed for ${domainName}.dot: on-chain CID is ${onChainCid ?? "null"}, not the ${ipfsCid} we just wrote. The setContenthash tx may have silently failed, or another party overwrote the domain. Re-run the deploy to retry.`
1045
+ `Post-deploy verification failed for ${domainName}.dot: on-chain contenthash is ${onChain}, not the ${expected} we just wrote. The setContenthash tx may have silently failed, or another party overwrote the domain. Re-run the deploy to retry.`
1235
1046
  );
1236
1047
  }
1237
1048
  console.log(` Verified on-chain: ${ipfsCid}
@@ -1239,66 +1050,49 @@ var DotNS = class {
1239
1050
  return { node };
1240
1051
  });
1241
1052
  }
1242
- async setTextRecord(domainName, key, value, _cli = runDotnsCli) {
1053
+ async setTextRecord(domainName, key, value) {
1243
1054
  return withSpan("deploy.dotns.set-text", `2c. set-text ${key}`, {}, async () => {
1244
1055
  this.ensureConnected();
1245
1056
  console.log(` Setting text[${key}]: ${value}`);
1246
- if (this._useContractPath) {
1247
- const node = namehash(`${domainName}.dot`);
1248
- const txHash = await this.contractTransaction(this._contracts.DOTNS_RESOLVER, 0n, DOTNS_TEXT_RESOLVER_ABI, "setText", [node, key, value], (s) => console.log(` ${s}`), { useNoncePolling: true });
1249
- console.log(` Tx: ${txHash}`);
1250
- const onChain2 = await withTimeout(this.contractCall(this._contracts.DOTNS_RESOLVER, DOTNS_TEXT_RESOLVER_ABI, "text", [node, key]), 3e4, "text");
1251
- if ((onChain2 ?? "") !== value) {
1252
- throw new Error(
1253
- `Post-set verification failed for text[${key}] on ${domainName}.dot: on-chain value is ${JSON.stringify(onChain2 ?? "")}, not ${JSON.stringify(value)} we just wrote. The setText tx may have silently failed, or another writer overwrote the record.`
1254
- );
1255
- }
1256
- console.log(` Verified text[${key}]: ${onChain2}
1257
- `);
1258
- return { value, txHash };
1057
+ const node = namehash(`${domainName}.dot`);
1058
+ const txHash = await this.contractTransaction(this._contracts.DOTNS_RESOLVER, 0n, DOTNS_TEXT_RESOLVER_ABI, "setText", [node, key, value], (s) => console.log(` ${s}`), { useNoncePolling: true });
1059
+ console.log(` Tx: ${txHash}`);
1060
+ const MAX_CHAIN_WAIT_SECONDS = 90;
1061
+ const POLL_INTERVAL_MS = 2e3;
1062
+ const startChainMs = Number(await this.clientWrapper.client.query.Timestamp.Now.getValue());
1063
+ let onChainValue = "";
1064
+ while (true) {
1065
+ const onChain = await withTimeout(this.contractCall(this._contracts.DOTNS_RESOLVER, DOTNS_TEXT_RESOLVER_ABI, "text", [node, key]), 3e4, "text");
1066
+ onChainValue = onChain ?? "";
1067
+ if (onChainValue === value) break;
1068
+ const nowChainMs = Number(await this.clientWrapper.client.query.Timestamp.Now.getValue());
1069
+ const chainElapsed = (nowChainMs - startChainMs) / 1e3;
1070
+ if (chainElapsed >= MAX_CHAIN_WAIT_SECONDS) break;
1071
+ console.log(` Awaiting text finalization (chain time +${Math.floor(chainElapsed)}s / ${MAX_CHAIN_WAIT_SECONDS}s)...`);
1072
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
1259
1073
  }
1260
- const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
1261
- const setResult = await _cli(
1262
- ["text", "set", domainName, key, value, "--json", ...rpcFlag(this.rpc)],
1263
- authEnv
1264
- );
1265
- console.log(` Tx: ${setResult.txHash}`);
1266
- const viewResult = await _cli(
1267
- ["text", "view", domainName, key, "--json", ...rpcFlag(this.rpc)]
1268
- );
1269
- const onChain = viewResult.value ?? "";
1270
- if (onChain !== value) {
1074
+ if (onChainValue !== value) {
1271
1075
  throw new Error(
1272
- `Post-set verification failed for text[${key}] on ${domainName}.dot: on-chain value is ${JSON.stringify(onChain)}, not ${JSON.stringify(value)} we just wrote. The setText tx may have silently failed, or another writer overwrote the record.`
1076
+ `Post-set verification failed for text[${key}] on ${domainName}.dot: on-chain value is ${JSON.stringify(onChainValue)}, not ${JSON.stringify(value)} we just wrote. The setText tx may have silently failed, or another writer overwrote the record.`
1273
1077
  );
1274
1078
  }
1275
- console.log(` Verified text[${key}]: ${onChain}
1079
+ console.log(` Verified text[${key}]: ${onChainValue}
1276
1080
  `);
1277
- return { value, txHash: setResult.txHash };
1081
+ return { value, txHash };
1278
1082
  });
1279
1083
  }
1280
1084
  async getContenthash(domainName) {
1281
1085
  this.ensureConnected();
1282
- if (this._useContractPath) {
1283
- const node = namehash(`${domainName}.dot`);
1284
- const result2 = await withTimeout(
1285
- this.contractCall(this._contracts.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [node]),
1286
- 3e4,
1287
- "contenthash"
1288
- );
1289
- return typeof result2 === "string" ? result2 : result2?.toString?.() ?? String(result2);
1290
- }
1291
- const result = await runDotnsCli(
1292
- ["content", "view", domainName, "--json", ...rpcFlag(this.rpc)]
1086
+ const node = namehash(`${domainName}.dot`);
1087
+ const result = await withTimeout(
1088
+ this.contractCall(this._contracts.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [node]),
1089
+ 3e4,
1090
+ "contenthash"
1293
1091
  );
1294
- return result.contenthash ?? "0x";
1092
+ return typeof result === "string" ? result : result?.toString?.() ?? String(result);
1295
1093
  }
1296
1094
  async classifyName(label) {
1297
1095
  this.ensureConnected();
1298
- if (!this._useContractPath) {
1299
- const classification = classifyDotnsLabel(label);
1300
- return { requiredStatus: classification.status, message: classification.message };
1301
- }
1302
1096
  console.log(`
1303
1097
  Classifying name via PopOracle...`);
1304
1098
  const result = await withTimeout(this.contractCall(this._contracts.POP_RULES, POP_RULES_ABI, "classifyName", [label]), 3e4, "classifyName");
@@ -1432,7 +1226,7 @@ var DotNS = class {
1432
1226
  // View-only readiness check. Runs every chain read needed to predict whether
1433
1227
  // `register(label)` will succeed, so the caller can fail-fast BEFORE the
1434
1228
  // Bulletin chunk upload. Never writes to chain. See issue #100.
1435
- async preflight(label, explicitStatusOverride, dotnsSelfAttest = this._dotnsSelfAttest) {
1229
+ async preflight(label) {
1436
1230
  return withSpan("deploy.dotns.preflight", `preflight ${label}.dot`, {}, async () => {
1437
1231
  this.ensureConnected();
1438
1232
  const validated = validateDomainLabel(label);
@@ -1526,20 +1320,28 @@ var DotNS = class {
1526
1320
  signerFreeBalance
1527
1321
  };
1528
1322
  }
1529
- const explicitStatus = explicitStatusOverride ?? process.env.DOTNS_STATUS;
1530
- const explicitStatusNum = explicitStatus ? parseProofOfPersonhoodStatus(explicitStatus) : void 0;
1531
- const targetPopStatus = simulateUserStatus(userStatus, classification.status, {
1532
- explicitStatus: explicitStatusNum,
1533
- isTestnet,
1534
- canSelfAttest: dotnsSelfAttest
1535
- });
1536
- const selfAttestedTargetPopStatus = simulateUserStatus(userStatus, classification.status, {
1537
- explicitStatus: explicitStatusNum,
1538
- isTestnet,
1539
- canSelfAttest: true
1540
- });
1541
- const wouldNeedSelfAttest = selfAttestedTargetPopStatus !== userStatus && selfAttestedTargetPopStatus !== ProofOfPersonhoodStatus.NoStatus && canRegister(classification.status, selfAttestedTargetPopStatus, trailingDigits);
1542
- if (!dotnsSelfAttest && isTestnet && wouldNeedSelfAttest) {
1323
+ const targetPopStatus = userStatus;
1324
+ if (!canRegister(classification.status, userStatus, trailingDigits)) {
1325
+ if (classification.status === ProofOfPersonhoodStatus.NoStatus && userStatus === ProofOfPersonhoodStatus.ProofOfPersonhoodLite) {
1326
+ return {
1327
+ label: validated,
1328
+ classification,
1329
+ userStatus,
1330
+ trailingDigits,
1331
+ baselength,
1332
+ isAvailable: true,
1333
+ existingOwner: null,
1334
+ isBaseNameReserved: isReserved,
1335
+ reservationOwner,
1336
+ isTestnet,
1337
+ canProceed: false,
1338
+ reason: `${validated}.dot: this name class is NoStatus-compatible, but Personhood Lite signers cannot register NoStatus-class labels. Self-attestation is no longer available. Use a NoStatus or Full signer, or contact the DotNS team for whitelisting / Personhood status help.`,
1339
+ plannedAction: "abort",
1340
+ needsPopUpgrade: false,
1341
+ targetPopStatus,
1342
+ signerFreeBalance
1343
+ };
1344
+ }
1543
1345
  const currentName = popStatusName(userStatus);
1544
1346
  const requiredName = popStatusName(classification.status);
1545
1347
  return {
@@ -1554,28 +1356,7 @@ var DotNS = class {
1554
1356
  reservationOwner,
1555
1357
  isTestnet,
1556
1358
  canProceed: false,
1557
- reason: `This environment does not allow DotNS self-attestation (Preview/Paseo Next v2 POP_RULES owner-gated setUserPopStatus). ${validated}.dot requires ${requiredName}, but this signer is ${currentName}. Use a NoStatus-compatible label (base length >= 9 with exactly two trailing digits, e.g. e2epoolns01.dot) or ask the environment operator to grant the signer the required PoP status.`,
1558
- plannedAction: "abort",
1559
- needsPopUpgrade: false,
1560
- targetPopStatus,
1561
- signerFreeBalance
1562
- };
1563
- }
1564
- if (!canRegister(classification.status, targetPopStatus, trailingDigits)) {
1565
- const className = popStatusName(classification.status);
1566
- return {
1567
- label: validated,
1568
- classification,
1569
- userStatus,
1570
- trailingDigits,
1571
- baselength,
1572
- isAvailable: true,
1573
- existingOwner: null,
1574
- isBaseNameReserved: isReserved,
1575
- reservationOwner,
1576
- isTestnet,
1577
- canProceed: false,
1578
- reason: `${validated}.dot classifies as ${className}; this signer cannot register it (PopRules.priceWithCheck gate). Remediations: use a signer with Full PoP, or pick a base name of 6-8 chars + trailing 00 (which classifies as PopLite).`,
1359
+ reason: `${validated}.dot requires ${requiredName}, but this signer is ${currentName}. Self-attestation is no longer available. Choose a NoStatus-compatible name (base length >= 9 with exactly two trailing digits, for example ${exampleNoStatusLabel(validated)}) or contact the DotNS team for whitelisting / Personhood status.`,
1579
1360
  plannedAction: "abort",
1580
1361
  needsPopUpgrade: false,
1581
1362
  targetPopStatus,
@@ -1595,7 +1376,7 @@ var DotNS = class {
1595
1376
  isTestnet,
1596
1377
  canProceed: true,
1597
1378
  plannedAction: "register",
1598
- needsPopUpgrade: targetPopStatus !== userStatus,
1379
+ needsPopUpgrade: false,
1599
1380
  targetPopStatus
1600
1381
  }, signerFreeBalance, isTestnet);
1601
1382
  });
@@ -1646,97 +1427,48 @@ var DotNS = class {
1646
1427
  }
1647
1428
  return { ...candidate, signerFreeBalance: effectiveBalance, feeFloor, toppedUp };
1648
1429
  }
1649
- async register(label, options = {}, _cli = runDotnsCli) {
1430
+ async register(label, options = {}) {
1650
1431
  return withSpan("deploy.dotns.register", `2a. register ${label}.dot`, {}, async () => {
1651
1432
  if (!this.connected) await this.connect(options);
1652
1433
  label = validateDomainLabel(label);
1653
1434
  const trailingDigitCount = countTrailingDigits(label);
1654
1435
  const preClassification = classifyDotnsLabel(label);
1655
- if (preClassification.status === ProofOfPersonhoodStatus.NoStatus) {
1656
- const userStatus = await this.getUserPopStatus();
1657
- if (trailingDigitCount === 0 || userStatus === ProofOfPersonhoodStatus.ProofOfPersonhoodLite) {
1658
- throw new Error("Personhood Lite cannot register base names \u2014 this name class requires a Full or NoStatus signer");
1659
- }
1436
+ const preRequiredStatus = preClassification.status;
1437
+ if (preRequiredStatus === ProofOfPersonhoodStatus.Reserved) {
1438
+ throw new Error(preClassification.message);
1660
1439
  }
1661
- const explicitStatus = options.status || process.env.DOTNS_STATUS;
1662
- const reverse = options.reverse ?? (process.env.DOTNS_REVERSE ?? "false").toLowerCase() === "true";
1663
- if (this._useContractPath) {
1664
- const [classification] = await Promise.all([
1665
- this.classifyName(label),
1666
- this.ensureNotRegistered(label)
1667
- ]);
1668
- const requiredStatus = classification.requiredStatus;
1669
- if (requiredStatus === ProofOfPersonhoodStatus.Reserved) {
1670
- throw new Error(classification.message);
1671
- }
1672
- const initialUserStatus = await this.getUserPopStatus();
1673
- const isTestnet = await this.isTestnet();
1674
- const explicitStatusNum = explicitStatus ? parseProofOfPersonhoodStatus(explicitStatus) : void 0;
1675
- const targetUserStatus = simulateUserStatus(initialUserStatus, requiredStatus, {
1676
- explicitStatus: explicitStatusNum,
1677
- isTestnet,
1678
- canSelfAttest: this._dotnsSelfAttest
1679
- });
1680
- if (!canRegister(requiredStatus, targetUserStatus, countTrailingDigits(label))) {
1440
+ const rejectIneligible = (statusRequired, userStatus2) => {
1441
+ if (statusRequired === ProofOfPersonhoodStatus.NoStatus && userStatus2 === ProofOfPersonhoodStatus.ProofOfPersonhoodLite) {
1681
1442
  throw new Error(
1682
- `This label classifies as ${popStatusName(requiredStatus)}; the registrar will reject this signer (PopRules.priceWithCheck). Remediations: use a signer with Full PoP, or pick a shorter base name (6-8 chars + trailing 00) that classifies as PopLite.`
1443
+ `${label}.dot: this name class is NoStatus-compatible, but Personhood Lite signers cannot register NoStatus-class labels. Self-attestation is no longer available. Use a NoStatus or Full signer, or contact the DotNS team for whitelisting / Personhood status help.`
1683
1444
  );
1684
1445
  }
1685
- if (targetUserStatus !== initialUserStatus && targetUserStatus !== ProofOfPersonhoodStatus.NoStatus) {
1686
- await this.setUserPopStatus(targetUserStatus);
1687
- const userStatus = await this.getUserPopStatus();
1688
- if (userStatus !== targetUserStatus) {
1689
- throw new Error(
1690
- "setUserPopStatus did not land as expected (wanted " + targetUserStatus + ", got " + userStatus + "). Check RPC connectivity and POP_RULES contract."
1691
- );
1692
- }
1693
- }
1694
- const { commitment, registration } = await this.generateCommitment(label, reverse);
1695
- await withSpan("deploy.dotns.submit-commitment", "2a-i. submit-commitment", {}, () => this.submitCommitment(commitment));
1696
- await withSpan("deploy.dotns.wait-commitment-age", "2a-ii. wait-commitment-age", {}, () => this.waitForCommitmentAge(commitment));
1697
- const pricing = await withSpan("deploy.dotns.price-validation", "2a-iii. price-validation", {}, () => this.getPriceAndValidate(label));
1698
- await withSpan("deploy.dotns.finalize-registration", "2a-iv. finalize-registration", {}, () => this.finalizeRegistration(registration, pricing.priceWei));
1699
- await this.verifyOwnership(label);
1700
- console.log(`
1701
- Registration complete!`);
1702
- return { label, owner: this.evmAddress };
1703
- }
1704
- const statusArgs = explicitStatus ? ["-s", explicitStatus] : [];
1705
- const reverseArgs = reverse ? ["-r"] : [];
1706
- console.log(`
1707
- Registering ${label}.dot via dotns CLI...`);
1708
- const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
1709
- const userSetBuffer = isExplicitCommitmentBuffer(process.env.DOTNS_COMMITMENT_BUFFER);
1710
- if (!userSetBuffer) {
1711
- authEnv.DOTNS_COMMITMENT_BUFFER = "30";
1712
- }
1713
- const runRegister = async (bufferSeconds) => {
1714
- const env = bufferSeconds ? { ...authEnv, DOTNS_COMMITMENT_BUFFER: bufferSeconds } : authEnv;
1715
- return await _cli(
1716
- ["register", "domain", "-n", label, "--json", ...statusArgs, ...reverseArgs, ...rpcFlag(this.rpc)],
1717
- env
1446
+ throw new Error(
1447
+ `${label}.dot requires ${popStatusName(statusRequired)}, but this signer is ${popStatusName(userStatus2)}. Self-attestation is no longer available. Choose a NoStatus-compatible name (base length >= 9 with exactly two trailing digits, for example ${exampleNoStatusLabel(label)}) or contact the DotNS team for whitelisting / Personhood status.`
1718
1448
  );
1719
1449
  };
1720
- let result;
1721
- try {
1722
- result = await runRegister();
1723
- } catch (err) {
1724
- const msg = err.message;
1725
- if (!isLikelyCommitmentRace(msg)) throw err;
1726
- const retryBuffer = userSetBuffer ? void 0 : "60";
1727
- console.log(` register reverted on first attempt \u2014 retrying once${retryBuffer ? ` with DOTNS_COMMITMENT_BUFFER=${retryBuffer}s` : ""} (commit-reveal race; block-time lag typically resolves within a block or two).`);
1728
- try {
1729
- result = await runRegister(retryBuffer);
1730
- } catch (retryErr) {
1731
- const retryMsg = retryErr.message;
1732
- if (!isLikelyCommitmentRace(retryMsg)) throw retryErr;
1733
- const likelyCause = /CommitmentTooNew/i.test(retryMsg) ? `the chain's block timestamps are lagging wall-clock by more than 30s across two register attempts. This is usually a transient block-production slowdown. Retry in a minute, or set DOTNS_COMMITMENT_BUFFER=60 (or higher) to absorb longer drift. Upstream fix tracked at paritytech/dotns-sdk#105.` : `the register tx reverted twice in a row. This is typically a commit-reveal timing race (block-production slowdown), but could also be a contract rejection (label already taken, PoP status mismatch). Try again in a minute; if it persists, verify the label is available. Upstream: paritytech/dotns-sdk#105.`;
1734
- throw new Error(`DotNS register failed after retry: ${likelyCause} Underlying: ${retryMsg}`);
1735
- }
1450
+ const reverse = options.reverse ?? (process.env.DOTNS_REVERSE ?? "false").toLowerCase() === "true";
1451
+ const [classification] = await Promise.all([
1452
+ this.classifyName(label),
1453
+ this.ensureNotRegistered(label)
1454
+ ]);
1455
+ const requiredStatus = classification.requiredStatus;
1456
+ if (requiredStatus === ProofOfPersonhoodStatus.Reserved) {
1457
+ throw new Error(classification.message);
1736
1458
  }
1459
+ const userStatus = await this.getUserPopStatus();
1460
+ if (!canRegister(requiredStatus, userStatus, trailingDigitCount)) {
1461
+ rejectIneligible(requiredStatus, userStatus);
1462
+ }
1463
+ const { commitment, registration } = await this.generateCommitment(label, reverse);
1464
+ await withSpan("deploy.dotns.submit-commitment", "2a-i. submit-commitment", {}, () => this.submitCommitment(commitment));
1465
+ await withSpan("deploy.dotns.wait-commitment-age", "2a-ii. wait-commitment-age", {}, () => this.waitForCommitmentAge(commitment));
1466
+ const pricing = await withSpan("deploy.dotns.price-validation", "2a-iii. price-validation", {}, () => this.getPriceAndValidate(label));
1467
+ await withSpan("deploy.dotns.finalize-registration", "2a-iv. finalize-registration", {}, () => this.finalizeRegistration(registration, pricing.priceWei));
1468
+ await this.verifyOwnership(label);
1737
1469
  console.log(`
1738
- Registration complete! Owner: ${result.owner}`);
1739
- return { label, owner: result.owner };
1470
+ Registration complete!`);
1471
+ return { label, owner: this.evmAddress };
1740
1472
  });
1741
1473
  }
1742
1474
  disconnect() {
@@ -1746,15 +1478,12 @@ var DotNS = class {
1746
1478
  this.clientWrapper = null;
1747
1479
  this.connected = false;
1748
1480
  }
1749
- this._mnemonic = null;
1750
- this._keyUri = null;
1751
1481
  this._usesExternalSigner = false;
1752
1482
  }
1753
1483
  };
1754
1484
  var dotns = new DotNS();
1755
1485
 
1756
1486
  export {
1757
- resolveDotnsCliInvocation,
1758
1487
  fmtPas,
1759
1488
  feeFloorFor,
1760
1489
  RPC_ENDPOINTS,
@@ -1782,15 +1511,12 @@ export {
1782
1511
  sanitizeDomainLabel,
1783
1512
  validateDomainLabel,
1784
1513
  isCommitmentMature,
1785
- isExplicitCommitmentBuffer,
1786
- isLikelyCommitmentRace,
1787
1514
  classifyDotnsLabel,
1788
1515
  canRegister,
1789
1516
  simulateUserStatus,
1790
1517
  parseDomainName,
1791
1518
  parseProofOfPersonhoodStatus,
1792
1519
  popStatusName,
1793
- runDotnsCli,
1794
1520
  DotNS,
1795
1521
  dotns
1796
1522
  };