bulletin-deploy 0.7.8 → 0.7.9-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bug-report.js +4 -4
- package/dist/{chunk-KRL6D3YY.js → chunk-2KBYGMG5.js} +1 -1
- package/dist/{chunk-4HGXZ225.js → chunk-3XEROH7U.js} +479 -33
- package/dist/{chunk-BTAGLNZY.js → chunk-7WTKLCKX.js} +2 -2
- package/dist/{chunk-ZTUUEMII.js → chunk-DHG4F2IN.js} +1 -1
- package/dist/{chunk-R7SSZDXQ.js → chunk-M2ULKTBL.js} +1 -1
- package/dist/{chunk-RUY7MR2M.js → chunk-TGOSZVL5.js} +3 -3
- package/dist/deploy.js +6 -6
- package/dist/dotns.d.ts +38 -0
- package/dist/dotns.js +3 -3
- package/dist/index.js +6 -6
- package/dist/memory-report.js +2 -2
- package/dist/run-state.js +1 -1
- package/dist/telemetry.js +2 -2
- package/dist/version-check.js +3 -3
- package/package.json +1 -1
package/dist/bug-report.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
offerBugReport,
|
|
10
10
|
scrubSecrets,
|
|
11
11
|
setDeployContext
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-7WTKLCKX.js";
|
|
13
|
+
import "./chunk-DHG4F2IN.js";
|
|
14
|
+
import "./chunk-M2ULKTBL.js";
|
|
15
|
+
import "./chunk-2KBYGMG5.js";
|
|
16
16
|
import "./chunk-QGM4M3NI.js";
|
|
17
17
|
export {
|
|
18
18
|
buildCliFlagsSummary,
|
|
@@ -2,13 +2,14 @@ import {
|
|
|
2
2
|
captureWarning,
|
|
3
3
|
setDeployAttribute,
|
|
4
4
|
withSpan
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-M2ULKTBL.js";
|
|
6
6
|
import {
|
|
7
7
|
isTestnetSpecName
|
|
8
8
|
} from "./chunk-RP4YJYNB.js";
|
|
9
9
|
|
|
10
10
|
// src/dotns.ts
|
|
11
11
|
import { spawn } from "child_process";
|
|
12
|
+
import crypto from "crypto";
|
|
12
13
|
import { readFileSync } from "fs";
|
|
13
14
|
import { dirname, join } from "path";
|
|
14
15
|
import { createClient, Enum } from "polkadot-api";
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
decodeFunctionResult,
|
|
23
24
|
keccak256,
|
|
24
25
|
toBytes,
|
|
26
|
+
formatEther,
|
|
25
27
|
isAddress,
|
|
26
28
|
bytesToHex,
|
|
27
29
|
isHex,
|
|
@@ -143,12 +145,36 @@ var ProofOfPersonhoodStatus = {
|
|
|
143
145
|
ProofOfPersonhoodFull: 2,
|
|
144
146
|
Reserved: 3
|
|
145
147
|
};
|
|
148
|
+
var DOTNS_REGISTRAR_CONTROLLER_ABI = [
|
|
149
|
+
{ inputs: [{ name: "registration", type: "tuple", components: [{ name: "label", type: "string" }, { name: "owner", type: "address" }, { name: "secret", type: "bytes32" }, { name: "reserved", type: "bool" }] }], name: "makeCommitment", outputs: [{ name: "", type: "bytes32" }], stateMutability: "view", type: "function" },
|
|
150
|
+
{ inputs: [{ name: "commitment", type: "bytes32" }], name: "commit", outputs: [], stateMutability: "nonpayable", type: "function" },
|
|
151
|
+
{ inputs: [], name: "minCommitmentAge", outputs: [{ name: "", type: "uint256" }], stateMutability: "view", type: "function" },
|
|
152
|
+
{ inputs: [{ name: "commitment", type: "bytes32" }], name: "commitments", outputs: [{ name: "", type: "uint256" }], stateMutability: "view", type: "function" },
|
|
153
|
+
{ inputs: [{ name: "registration", type: "tuple", components: [{ name: "label", type: "string" }, { name: "owner", type: "address" }, { name: "secret", type: "bytes32" }, { name: "reserved", type: "bool" }] }], name: "register", outputs: [], stateMutability: "payable", type: "function" }
|
|
154
|
+
];
|
|
155
|
+
var DOTNS_REGISTRAR_ABI = [
|
|
156
|
+
{ inputs: [{ name: "tokenId", type: "uint256" }], name: "ownerOf", outputs: [{ name: "", type: "address" }], stateMutability: "view", type: "function" }
|
|
157
|
+
];
|
|
146
158
|
var POP_RULES_ABI = [
|
|
159
|
+
{ inputs: [{ name: "name", type: "string" }], name: "classifyName", outputs: [{ name: "requirement", type: "uint8" }, { name: "message", type: "string" }], stateMutability: "pure", type: "function" },
|
|
160
|
+
{ inputs: [{ name: "name", type: "string" }], name: "price", outputs: [{ name: "", type: "uint256" }], stateMutability: "view", type: "function" },
|
|
161
|
+
{ inputs: [{ name: "", type: "address" }], name: "userPopStatus", outputs: [{ name: "", type: "uint8" }], stateMutability: "view", type: "function" },
|
|
162
|
+
{ inputs: [{ name: "status", type: "uint8" }], name: "setUserPopStatus", outputs: [], stateMutability: "nonpayable", type: "function" },
|
|
147
163
|
{ inputs: [{ name: "name", type: "string" }], name: "isBaseNameReserved", outputs: [{ name: "isReserved", type: "bool" }, { name: "reservationOwner", type: "address" }, { name: "expiryTimestamp", type: "uint64" }], stateMutability: "view", type: "function" }
|
|
148
164
|
];
|
|
149
165
|
var DOTNS_REGISTRY_ABI = [
|
|
166
|
+
{ 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" },
|
|
167
|
+
{ inputs: [{ name: "node", type: "bytes32" }, { name: "newResolver", type: "address" }], name: "setResolver", outputs: [], stateMutability: "nonpayable", type: "function" },
|
|
150
168
|
{ inputs: [{ name: "node", type: "bytes32" }], name: "owner", outputs: [{ name: "", type: "address" }], stateMutability: "view", type: "function" }
|
|
151
169
|
];
|
|
170
|
+
var DOTNS_CONTENT_RESOLVER_ABI = [
|
|
171
|
+
{ inputs: [{ name: "node", type: "bytes32" }, { name: "hash", type: "bytes" }], name: "setContenthash", outputs: [], stateMutability: "nonpayable", type: "function" },
|
|
172
|
+
{ inputs: [{ name: "node", type: "bytes32" }], name: "contenthash", outputs: [{ name: "", type: "bytes" }], stateMutability: "view", type: "function" }
|
|
173
|
+
];
|
|
174
|
+
var DOTNS_TEXT_RESOLVER_ABI = [
|
|
175
|
+
{ inputs: [{ name: "node", type: "bytes32" }, { name: "key", type: "string" }, { name: "value", type: "string" }], name: "setText", outputs: [], stateMutability: "nonpayable", type: "function" },
|
|
176
|
+
{ inputs: [{ name: "node", type: "bytes32" }, { name: "key", type: "string" }], name: "text", outputs: [{ name: "", type: "string" }], stateMutability: "view", type: "function" }
|
|
177
|
+
];
|
|
152
178
|
function convertToHexString(value) {
|
|
153
179
|
if (!value) return "0x";
|
|
154
180
|
if (typeof value?.asHex === "function") return value.asHex();
|
|
@@ -359,6 +385,11 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
|
|
|
359
385
|
const isErr = !ok || didRevert || !!err || (typeof successFlag === "boolean" ? !successFlag : false);
|
|
360
386
|
return { gasConsumed, gasRequired, storageDeposit: { value: storageDepositValue }, result: { isOk, isErr, value: { data: ok ? returnData : "0x", flags: ok ? flags : 1n } } };
|
|
361
387
|
}
|
|
388
|
+
async estimateGasForCall(originSubstrateAddress, contractAddress, value, encodedData) {
|
|
389
|
+
const result = await this.performDryRunCall(originSubstrateAddress, contractAddress, value, encodedData);
|
|
390
|
+
if (!result.result.isOk) return { success: false, gasConsumed: result.gasConsumed, storageDeposit: result.storageDeposit.value, gasRequired: result.gasRequired, revertData: result.result.value.data, revertFlags: result.result.value.flags };
|
|
391
|
+
return { success: true, gasConsumed: result.gasConsumed, storageDeposit: result.storageDeposit.value, gasRequired: result.gasRequired };
|
|
392
|
+
}
|
|
362
393
|
async checkIfAccountMapped(substrateAddress) {
|
|
363
394
|
try {
|
|
364
395
|
const evmAddress = await this.getEvmAddress(substrateAddress);
|
|
@@ -369,6 +400,151 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
|
|
|
369
400
|
return false;
|
|
370
401
|
}
|
|
371
402
|
}
|
|
403
|
+
async ensureAccountMapped(substrateAddress, signer) {
|
|
404
|
+
if (isAddress(substrateAddress)) throw new Error("ensureAccountMapped requires SS58 Substrate address, not EVM H160 address");
|
|
405
|
+
if (this.mappedAccounts.has(substrateAddress)) return;
|
|
406
|
+
const isMapped = await this.checkIfAccountMapped(substrateAddress);
|
|
407
|
+
if (isMapped) {
|
|
408
|
+
this.mappedAccounts.add(substrateAddress);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
try {
|
|
412
|
+
await this.signAndSubmitWithRetry(() => this.client.tx.Revive.map_account(), signer, () => {
|
|
413
|
+
}, "Revive.map_account");
|
|
414
|
+
this.mappedAccounts.add(substrateAddress);
|
|
415
|
+
} catch (error) {
|
|
416
|
+
const errorMessage = error?.message || String(error);
|
|
417
|
+
if (errorMessage.includes("AccountAlreadyMapped")) {
|
|
418
|
+
this.mappedAccounts.add(substrateAddress);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
throw error;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
signAndSubmitExtrinsic(extrinsic, signer, statusCallback, opts = {}) {
|
|
425
|
+
return new Promise((resolve, reject) => {
|
|
426
|
+
let settled = false;
|
|
427
|
+
let deadlinePoller = null;
|
|
428
|
+
let sub;
|
|
429
|
+
const finish = (fn) => (...args) => {
|
|
430
|
+
if (!settled) {
|
|
431
|
+
settled = true;
|
|
432
|
+
if (deadlinePoller) clearInterval(deadlinePoller);
|
|
433
|
+
try {
|
|
434
|
+
sub?.unsubscribe();
|
|
435
|
+
} catch {
|
|
436
|
+
}
|
|
437
|
+
fn(...args);
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
const startWallClockMs = Date.now();
|
|
441
|
+
let startChainTimeMs = null;
|
|
442
|
+
deadlinePoller = setInterval(async () => {
|
|
443
|
+
if (settled) return;
|
|
444
|
+
try {
|
|
445
|
+
if (opts.nonceFallback) {
|
|
446
|
+
const nonce = await verifyNonceAdvanced(opts.nonceFallback.rpcs, opts.nonceFallback.senderSS58, opts.nonceFallback.expectedNonce);
|
|
447
|
+
if (nonce.advanced) {
|
|
448
|
+
statusCallback("included");
|
|
449
|
+
finish(resolve)(`nonce-advanced:${nonce.witnessRpc}`);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (Date.now() - startWallClockMs > TX_WALL_CLOCK_CEILING_MS) {
|
|
454
|
+
statusCallback("failed");
|
|
455
|
+
finish(reject)(new Error(`Transaction did not settle within ${TX_WALL_CLOCK_CEILING_MS / 1e3}s wall-clock (chain may be stalled)`));
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
const chainNowMs = Number(await this.client.query.Timestamp.Now.getValue());
|
|
459
|
+
if (startChainTimeMs === null) startChainTimeMs = chainNowMs;
|
|
460
|
+
const chainElapsedMs = chainNowMs - startChainTimeMs;
|
|
461
|
+
if (chainElapsedMs > TX_CHAIN_TIME_BUDGET_MS) {
|
|
462
|
+
statusCallback("failed");
|
|
463
|
+
finish(reject)(new Error(`Transaction not included after ${Math.floor(chainElapsedMs / 1e3)}s of chain progress (budget=${TX_CHAIN_TIME_BUDGET_MS / 1e3}s)`));
|
|
464
|
+
}
|
|
465
|
+
} catch {
|
|
466
|
+
}
|
|
467
|
+
}, 6e3);
|
|
468
|
+
try {
|
|
469
|
+
sub = extrinsic.signSubmitAndWatch(signer, { mortality: { mortal: true, period: 256 } }).subscribe({
|
|
470
|
+
next: (event) => {
|
|
471
|
+
const transactionHash = event.txHash?.toString();
|
|
472
|
+
switch (event.type) {
|
|
473
|
+
case "signed":
|
|
474
|
+
statusCallback("signing");
|
|
475
|
+
break;
|
|
476
|
+
case "broadcasted":
|
|
477
|
+
statusCallback("broadcasting");
|
|
478
|
+
break;
|
|
479
|
+
case "txBestBlocksState":
|
|
480
|
+
if (event.found) statusCallback("included");
|
|
481
|
+
break;
|
|
482
|
+
case "finalized":
|
|
483
|
+
if (event.dispatchError || event.ok === false) {
|
|
484
|
+
statusCallback("failed");
|
|
485
|
+
finish(reject)(new Error(`Transaction failed: ${event.dispatchError?.toString?.() ?? "dispatch error"}`));
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
statusCallback("finalized");
|
|
489
|
+
finish(resolve)(transactionHash);
|
|
490
|
+
return;
|
|
491
|
+
case "invalid":
|
|
492
|
+
case "dropped":
|
|
493
|
+
statusCallback("failed");
|
|
494
|
+
finish(reject)(new Error(`Transaction ${event.type}`));
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
error: (error) => {
|
|
499
|
+
statusCallback("failed");
|
|
500
|
+
finish(reject)(error);
|
|
501
|
+
},
|
|
502
|
+
complete: () => {
|
|
503
|
+
if (settled) return;
|
|
504
|
+
statusCallback("failed");
|
|
505
|
+
finish(reject)(new Error("transaction subscription closed before finalization"));
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
} catch (error) {
|
|
509
|
+
statusCallback("failed");
|
|
510
|
+
finish(reject)(error);
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
async signAndSubmitWithRetry(buildExtrinsic, signer, statusCallback, label, opts = {}) {
|
|
515
|
+
let lastError;
|
|
516
|
+
for (let attempt = 1; attempt <= DOTNS_TX_MAX_ATTEMPTS; attempt++) {
|
|
517
|
+
try {
|
|
518
|
+
return await this.signAndSubmitExtrinsic(buildExtrinsic(), signer, statusCallback, opts);
|
|
519
|
+
} catch (e) {
|
|
520
|
+
lastError = e;
|
|
521
|
+
const decision = classifyTxRetryDecision(e);
|
|
522
|
+
if (decision === "abort" || attempt === DOTNS_TX_MAX_ATTEMPTS) break;
|
|
523
|
+
const short = (e?.message ?? String(e)).slice(0, 80);
|
|
524
|
+
console.log(` ${label}: attempt ${attempt}/${DOTNS_TX_MAX_ATTEMPTS} failed (${short}), retrying...`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
528
|
+
}
|
|
529
|
+
async submitTransaction(contractAddress, value, encodedData, signerSubstrateAddress, signer, statusCallback, { rpcs, useNoncePolling }) {
|
|
530
|
+
await this.ensureAccountMapped(signerSubstrateAddress, signer);
|
|
531
|
+
const gasEstimate = await this.estimateGasForCall(signerSubstrateAddress, contractAddress, value, encodedData);
|
|
532
|
+
if (!gasEstimate.success) throw new Error(`Contract execution would revert: ${gasEstimate.revertData ?? "0x"}`);
|
|
533
|
+
const weightLimit = { proof_size: gasEstimate.gasRequired.proofSize, ref_time: gasEstimate.gasRequired.referenceTime };
|
|
534
|
+
const minimumStorageDeposit = 2000000000000n;
|
|
535
|
+
let storageDepositLimit = gasEstimate.storageDeposit === 0n ? minimumStorageDeposit : gasEstimate.storageDeposit * 120n / 100n;
|
|
536
|
+
if (storageDepositLimit < minimumStorageDeposit) storageDepositLimit = minimumStorageDeposit;
|
|
537
|
+
const buildExtrinsic = () => this.client.tx.Revive.call({ dest: Binary.fromHex(contractAddress), value, weight_limit: weightLimit, storage_deposit_limit: storageDepositLimit, data: Binary.fromHex(encodedData) });
|
|
538
|
+
let nonceFallback;
|
|
539
|
+
if (useNoncePolling) {
|
|
540
|
+
try {
|
|
541
|
+
const nonce = await fetchNonce(rpcs, signerSubstrateAddress);
|
|
542
|
+
nonceFallback = { rpcs, senderSS58: signerSubstrateAddress, expectedNonce: nonce };
|
|
543
|
+
} catch {
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return await this.signAndSubmitWithRetry(buildExtrinsic, signer, statusCallback, "Revive.call", { nonceFallback });
|
|
547
|
+
}
|
|
372
548
|
};
|
|
373
549
|
async function runDotnsCli(argv, env) {
|
|
374
550
|
return new Promise((resolve, reject) => {
|
|
@@ -438,6 +614,7 @@ var DotNS = class {
|
|
|
438
614
|
// Stored credentials for CLI subprocess calls. Never logged or exposed.
|
|
439
615
|
_mnemonic = null;
|
|
440
616
|
_keyUri = null;
|
|
617
|
+
_usesExternalSigner = false;
|
|
441
618
|
constructor() {
|
|
442
619
|
this.client = null;
|
|
443
620
|
this.clientWrapper = null;
|
|
@@ -448,27 +625,33 @@ var DotNS = class {
|
|
|
448
625
|
this.connected = false;
|
|
449
626
|
}
|
|
450
627
|
async connect(options = {}) {
|
|
451
|
-
if (options.signer || options.signerAddress) {
|
|
452
|
-
throw new Error("External signer mode is not supported with dotns-cli subprocess \u2014 tracked as a follow-up (#158 regression notice)");
|
|
453
|
-
}
|
|
454
628
|
const rpc = options.rpc || process.env.DOTNS_RPC || RPC_ENDPOINTS[0];
|
|
455
629
|
this.rpc = rpc;
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
this._keyUri = isKeyUri ? source : null;
|
|
461
|
-
this._mnemonic = isKeyUri ? null : source;
|
|
462
|
-
if (options.derivationPath && !isKeyUri && this._mnemonic) {
|
|
463
|
-
this._keyUri = `${this._mnemonic}${options.derivationPath}`;
|
|
630
|
+
this._usesExternalSigner = Boolean(options.signer && options.signerAddress);
|
|
631
|
+
let authEnv = {};
|
|
632
|
+
if (this._usesExternalSigner) {
|
|
633
|
+
this._keyUri = null;
|
|
464
634
|
this._mnemonic = null;
|
|
635
|
+
this.signer = options.signer;
|
|
636
|
+
this.substrateAddress = options.signerAddress;
|
|
637
|
+
} else {
|
|
638
|
+
const mnemonicArg = options.mnemonic || process.env.DOTNS_MNEMONIC || process.env.MNEMONIC;
|
|
639
|
+
const keyUriArg = options.keyUri || process.env.DOTNS_KEY_URI;
|
|
640
|
+
const source = keyUriArg || mnemonicArg || DEFAULT_MNEMONIC;
|
|
641
|
+
const isKeyUri = Boolean(keyUriArg);
|
|
642
|
+
this._keyUri = isKeyUri ? source : null;
|
|
643
|
+
this._mnemonic = isKeyUri ? null : source;
|
|
644
|
+
if (options.derivationPath && !isKeyUri && this._mnemonic) {
|
|
645
|
+
this._keyUri = `${this._mnemonic}${options.derivationPath}`;
|
|
646
|
+
this._mnemonic = null;
|
|
647
|
+
}
|
|
648
|
+
authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
|
|
649
|
+
await cryptoWaitReady();
|
|
650
|
+
const keyring = new Keyring({ type: "sr25519" });
|
|
651
|
+
const account = this._keyUri ? keyring.addFromUri(this._keyUri) : keyring.addFromMnemonic(source);
|
|
652
|
+
this.signer = getPolkadotSigner(account.publicKey, "Sr25519", async (input) => account.sign(input));
|
|
653
|
+
this.substrateAddress = account.address;
|
|
465
654
|
}
|
|
466
|
-
const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
|
|
467
|
-
await cryptoWaitReady();
|
|
468
|
-
const keyring = new Keyring({ type: "sr25519" });
|
|
469
|
-
const account = this._keyUri ? keyring.addFromUri(this._keyUri) : keyring.addFromMnemonic(source);
|
|
470
|
-
this.signer = getPolkadotSigner(account.publicKey, "Sr25519", async (input) => account.sign(input));
|
|
471
|
-
this.substrateAddress = account.address;
|
|
472
655
|
console.log(` SS58 Address: ${this.substrateAddress}`);
|
|
473
656
|
try {
|
|
474
657
|
this.client = createClient(getWsProvider(rpc, { heartbeatTimeout: WS_HEARTBEAT_TIMEOUT_MS }));
|
|
@@ -485,22 +668,26 @@ var DotNS = class {
|
|
|
485
668
|
}
|
|
486
669
|
if (!await this.clientWrapper.checkIfAccountMapped(this.substrateAddress)) {
|
|
487
670
|
console.log(` Mapping account on Asset Hub Revive...`);
|
|
488
|
-
|
|
489
|
-
await
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
671
|
+
if (this._usesExternalSigner) {
|
|
672
|
+
await this.clientWrapper.ensureAccountMapped(this.substrateAddress, this.signer);
|
|
673
|
+
} else {
|
|
674
|
+
try {
|
|
675
|
+
await runDotnsCli(["account", "map", ...rpcFlag(rpc)], authEnv);
|
|
676
|
+
} catch (e) {
|
|
677
|
+
captureWarning("account map failed during connect (will rely on chain confirmation)", { error: e.message?.slice(0, 200) });
|
|
678
|
+
}
|
|
679
|
+
const mappingDeadline = Date.now() + 15e3;
|
|
680
|
+
let mappingConfirmed = false;
|
|
681
|
+
while (Date.now() < mappingDeadline) {
|
|
682
|
+
if (await this.clientWrapper.checkIfAccountMapped(this.substrateAddress)) {
|
|
683
|
+
mappingConfirmed = true;
|
|
684
|
+
break;
|
|
685
|
+
}
|
|
686
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
687
|
+
}
|
|
688
|
+
if (!mappingConfirmed) {
|
|
689
|
+
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.`);
|
|
499
690
|
}
|
|
500
|
-
await new Promise((r) => setTimeout(r, 1500));
|
|
501
|
-
}
|
|
502
|
-
if (!mappingConfirmed) {
|
|
503
|
-
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.`);
|
|
504
691
|
}
|
|
505
692
|
}
|
|
506
693
|
console.log(` Account: mapped`);
|
|
@@ -673,9 +860,31 @@ var DotNS = class {
|
|
|
673
860
|
}
|
|
674
861
|
return decodeFunctionResult({ abi: contractAbi, functionName, data: callResult.result.value.data });
|
|
675
862
|
}
|
|
863
|
+
async contractTransaction(contractAddress, value, contractAbi, functionName, args = [], statusCallback = () => {
|
|
864
|
+
}, { useNoncePolling } = {}) {
|
|
865
|
+
this.ensureConnected();
|
|
866
|
+
if (!this.clientWrapper) throw new Error("contractTransaction: polkadot-api client not available");
|
|
867
|
+
const encodedCallData = encodeFunctionData({ abi: contractAbi, functionName, args });
|
|
868
|
+
const rpcs = this.rpc ? [this.rpc, ...RPC_ENDPOINTS.filter((ep) => ep !== this.rpc)] : RPC_ENDPOINTS;
|
|
869
|
+
return await withTimeout(
|
|
870
|
+
this.clientWrapper.submitTransaction(contractAddress, value, encodedCallData, this.substrateAddress, this.signer, statusCallback, { rpcs, useNoncePolling }),
|
|
871
|
+
OPERATION_TIMEOUT_MS,
|
|
872
|
+
functionName
|
|
873
|
+
);
|
|
874
|
+
}
|
|
676
875
|
async checkOwnership(label, ownerAddress = null) {
|
|
677
876
|
this.ensureConnected();
|
|
678
877
|
const checkAddress = (ownerAddress || this.evmAddress).toLowerCase();
|
|
878
|
+
if (this._usesExternalSigner) {
|
|
879
|
+
const tokenId = computeDomainTokenId(label);
|
|
880
|
+
try {
|
|
881
|
+
const owner = await withTimeout(this.contractCall(CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 3e4, "ownerOf");
|
|
882
|
+
const owned = owner.toLowerCase() === checkAddress;
|
|
883
|
+
return { owned, owner };
|
|
884
|
+
} catch {
|
|
885
|
+
return { owned: false, owner: null };
|
|
886
|
+
}
|
|
887
|
+
}
|
|
679
888
|
try {
|
|
680
889
|
const result = await runDotnsCli(
|
|
681
890
|
["lookup", "owner-of", label, "--json", ...rpcFlag(this.rpc)]
|
|
@@ -690,6 +899,11 @@ var DotNS = class {
|
|
|
690
899
|
}
|
|
691
900
|
async getUserPopStatus(ownerAddress = null) {
|
|
692
901
|
this.ensureConnected();
|
|
902
|
+
if (this._usesExternalSigner) {
|
|
903
|
+
const checkAddress = ownerAddress || this.evmAddress;
|
|
904
|
+
const result = await withTimeout(this.contractCall(CONTRACTS.POP_RULES, POP_RULES_ABI, "userPopStatus", [checkAddress]), 3e4, "userPopStatus");
|
|
905
|
+
return typeof result === "bigint" ? Number(result) : result;
|
|
906
|
+
}
|
|
693
907
|
if (ownerAddress && ownerAddress.toLowerCase() !== (this.evmAddress ?? "").toLowerCase()) {
|
|
694
908
|
if (!this.clientWrapper) return 0;
|
|
695
909
|
return 0;
|
|
@@ -719,6 +933,11 @@ var DotNS = class {
|
|
|
719
933
|
return;
|
|
720
934
|
}
|
|
721
935
|
console.log(` Setting PoP status to ${desiredStatusName}...`);
|
|
936
|
+
if (this._usesExternalSigner) {
|
|
937
|
+
const txHash = await this.contractTransaction(CONTRACTS.POP_RULES, 0n, POP_RULES_ABI, "setUserPopStatus", [status], (s) => console.log(` ${s}`));
|
|
938
|
+
console.log(` Tx: ${txHash}`);
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
722
941
|
const statusStr = desiredStatusName.replace("ProofOfPersonhood", "").toLowerCase() || "none";
|
|
723
942
|
const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
|
|
724
943
|
const result = await runDotnsCli(
|
|
@@ -745,6 +964,18 @@ var DotNS = class {
|
|
|
745
964
|
this.ensureConnected();
|
|
746
965
|
console.log(`
|
|
747
966
|
Registering subdomain ${sublabel}.${parentLabel}.dot...`);
|
|
967
|
+
if (this._usesExternalSigner) {
|
|
968
|
+
const parentNode = namehash(`${parentLabel}.dot`);
|
|
969
|
+
const subnodeRecord = { parentNode, subLabel: sublabel, parentLabel, owner: this.evmAddress };
|
|
970
|
+
const txHash = await this.contractTransaction(CONTRACTS.DOTNS_REGISTRY, 0n, DOTNS_REGISTRY_ABI, "setSubnodeOwner", [subnodeRecord], (s) => console.log(` ${s}`), { useNoncePolling: true });
|
|
971
|
+
console.log(` Tx: ${txHash}`);
|
|
972
|
+
console.log(` Setting resolver...`);
|
|
973
|
+
const subnodeNode = namehash(`${sublabel}.${parentLabel}.dot`);
|
|
974
|
+
const resolverTxHash = await this.contractTransaction(CONTRACTS.DOTNS_REGISTRY, 0n, DOTNS_REGISTRY_ABI, "setResolver", [subnodeNode, CONTRACTS.DOTNS_CONTENT_RESOLVER], (s) => console.log(` ${s}`), { useNoncePolling: true });
|
|
975
|
+
console.log(` Tx: ${resolverTxHash}`);
|
|
976
|
+
console.log(` Subdomain registered!`);
|
|
977
|
+
return { sublabel, parentLabel, owner: this.evmAddress };
|
|
978
|
+
}
|
|
748
979
|
const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
|
|
749
980
|
const result = await runDotnsCli(
|
|
750
981
|
["register", "subname", "-n", sublabel, "-p", parentLabel, "--json", ...rpcFlag(this.rpc)],
|
|
@@ -768,6 +999,25 @@ var DotNS = class {
|
|
|
768
999
|
}
|
|
769
1000
|
if (!ipfsCid) throw new Error(`setContenthash: cannot decode contenthash ${contenthashHex} to an IPFS CID`);
|
|
770
1001
|
console.log(` Setting contenthash: ${ipfsCid}`);
|
|
1002
|
+
if (this._usesExternalSigner) {
|
|
1003
|
+
const txHash = await this.contractTransaction(CONTRACTS.DOTNS_CONTENT_RESOLVER, 0n, DOTNS_CONTENT_RESOLVER_ABI, "setContenthash", [node, contenthashHex], (s) => console.log(` ${s}`), { useNoncePolling: true });
|
|
1004
|
+
console.log(` Tx: ${txHash}`);
|
|
1005
|
+
const expected = contenthashHex.toLowerCase();
|
|
1006
|
+
let onChain = "0x";
|
|
1007
|
+
for (let attempt = 1; attempt <= 4; attempt++) {
|
|
1008
|
+
onChain = (await this.getContenthash(domainName) || "0x").toLowerCase();
|
|
1009
|
+
if (onChain === expected) break;
|
|
1010
|
+
if (attempt < 4) await new Promise((r) => setTimeout(r, 8e3));
|
|
1011
|
+
}
|
|
1012
|
+
if (onChain !== expected) {
|
|
1013
|
+
throw new Error(
|
|
1014
|
+
`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.`
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
console.log(` Verified on-chain: ${ipfsCid}
|
|
1018
|
+
`);
|
|
1019
|
+
return { node };
|
|
1020
|
+
}
|
|
771
1021
|
const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
|
|
772
1022
|
const setResult = await runDotnsCli(
|
|
773
1023
|
["content", "set", domainName, ipfsCid, "--json", ...rpcFlag(this.rpc)],
|
|
@@ -792,6 +1042,20 @@ var DotNS = class {
|
|
|
792
1042
|
return withSpan("deploy.dotns.set-text", `2c. set-text ${key}`, {}, async () => {
|
|
793
1043
|
this.ensureConnected();
|
|
794
1044
|
console.log(` Setting text[${key}]: ${value}`);
|
|
1045
|
+
if (this._usesExternalSigner) {
|
|
1046
|
+
const node = namehash(`${domainName}.dot`);
|
|
1047
|
+
const txHash = await this.contractTransaction(CONTRACTS.DOTNS_RESOLVER, 0n, DOTNS_TEXT_RESOLVER_ABI, "setText", [node, key, value], (s) => console.log(` ${s}`), { useNoncePolling: true });
|
|
1048
|
+
console.log(` Tx: ${txHash}`);
|
|
1049
|
+
const onChain2 = await withTimeout(this.contractCall(CONTRACTS.DOTNS_RESOLVER, DOTNS_TEXT_RESOLVER_ABI, "text", [node, key]), 3e4, "text");
|
|
1050
|
+
if ((onChain2 ?? "") !== value) {
|
|
1051
|
+
throw new Error(
|
|
1052
|
+
`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.`
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1055
|
+
console.log(` Verified text[${key}]: ${onChain2}
|
|
1056
|
+
`);
|
|
1057
|
+
return { value, txHash };
|
|
1058
|
+
}
|
|
795
1059
|
const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
|
|
796
1060
|
const setResult = await _cli(
|
|
797
1061
|
["text", "set", domainName, key, value, "--json", ...rpcFlag(this.rpc)],
|
|
@@ -814,11 +1078,155 @@ var DotNS = class {
|
|
|
814
1078
|
}
|
|
815
1079
|
async getContenthash(domainName) {
|
|
816
1080
|
this.ensureConnected();
|
|
1081
|
+
if (this._usesExternalSigner) {
|
|
1082
|
+
const node = namehash(`${domainName}.dot`);
|
|
1083
|
+
const result2 = await withTimeout(
|
|
1084
|
+
this.contractCall(CONTRACTS.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [node]),
|
|
1085
|
+
3e4,
|
|
1086
|
+
"contenthash"
|
|
1087
|
+
);
|
|
1088
|
+
return typeof result2 === "string" ? result2 : result2?.toString?.() ?? String(result2);
|
|
1089
|
+
}
|
|
817
1090
|
const result = await runDotnsCli(
|
|
818
1091
|
["content", "view", domainName, "--json", ...rpcFlag(this.rpc)]
|
|
819
1092
|
);
|
|
820
1093
|
return result.contenthash ?? "0x";
|
|
821
1094
|
}
|
|
1095
|
+
async classifyName(label) {
|
|
1096
|
+
this.ensureConnected();
|
|
1097
|
+
if (!this._usesExternalSigner) {
|
|
1098
|
+
const classification = classifyDotnsLabel(label);
|
|
1099
|
+
return { requiredStatus: classification.status, message: classification.message };
|
|
1100
|
+
}
|
|
1101
|
+
console.log(`
|
|
1102
|
+
Classifying name via PopOracle...`);
|
|
1103
|
+
const result = await withTimeout(this.contractCall(CONTRACTS.POP_RULES, POP_RULES_ABI, "classifyName", [label]), 3e4, "classifyName");
|
|
1104
|
+
const requiredStatus = typeof result[0] === "bigint" ? Number(result[0]) : result[0];
|
|
1105
|
+
const message = result[1];
|
|
1106
|
+
console.log(` Required status: ${popStatusName(requiredStatus)}`);
|
|
1107
|
+
console.log(` Message: ${message}`);
|
|
1108
|
+
return { requiredStatus, message };
|
|
1109
|
+
}
|
|
1110
|
+
async ensureNotRegistered(label) {
|
|
1111
|
+
this.ensureConnected();
|
|
1112
|
+
console.log(`
|
|
1113
|
+
Checking availability of ${label}.dot...`);
|
|
1114
|
+
const tokenId = computeDomainTokenId(label);
|
|
1115
|
+
try {
|
|
1116
|
+
const owner = await withTimeout(this.contractCall(CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 3e4, "Availability check");
|
|
1117
|
+
if (owner !== zeroAddress) throw new Error(`Domain ${label}.dot already owned by ${owner}`);
|
|
1118
|
+
} catch (error) {
|
|
1119
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1120
|
+
if (errorMessage.includes("already owned")) throw error;
|
|
1121
|
+
}
|
|
1122
|
+
console.log(` ${label}.dot is available`);
|
|
1123
|
+
}
|
|
1124
|
+
async generateCommitment(label, includeReverse = false) {
|
|
1125
|
+
this.ensureConnected();
|
|
1126
|
+
console.log(`
|
|
1127
|
+
Generating commitment hash...`);
|
|
1128
|
+
label = validateDomainLabel(label);
|
|
1129
|
+
const secret = `0x${crypto.randomBytes(32).toString("hex")}`;
|
|
1130
|
+
const registration = { label, owner: this.evmAddress, secret, reserved: includeReverse };
|
|
1131
|
+
const commitment = await withTimeout(this.contractCall(CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, DOTNS_REGISTRAR_CONTROLLER_ABI, "makeCommitment", [registration]), 3e4, "Commitment generation");
|
|
1132
|
+
console.log(` Commitment: ${commitment}`);
|
|
1133
|
+
return { commitment, registration };
|
|
1134
|
+
}
|
|
1135
|
+
async submitCommitment(commitment) {
|
|
1136
|
+
this.ensureConnected();
|
|
1137
|
+
console.log(`
|
|
1138
|
+
Submitting commitment...`);
|
|
1139
|
+
const txHash = await this.contractTransaction(CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, 0n, DOTNS_REGISTRAR_CONTROLLER_ABI, "commit", [commitment], (s) => console.log(` ${s}`));
|
|
1140
|
+
console.log(` Tx: ${txHash}`);
|
|
1141
|
+
console.log(` Committed at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
1142
|
+
}
|
|
1143
|
+
async waitForCommitmentAge(commitment) {
|
|
1144
|
+
this.ensureConnected();
|
|
1145
|
+
const POLL_TIMEOUT_MS = 9e4;
|
|
1146
|
+
const POLL_INTERVAL_MS = 3e3;
|
|
1147
|
+
console.log(`
|
|
1148
|
+
Reading minimum commitment age...`);
|
|
1149
|
+
const [minimumAge, initialCommitTimestamp] = await Promise.all([
|
|
1150
|
+
withTimeout(this.contractCall(CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, DOTNS_REGISTRAR_CONTROLLER_ABI, "minCommitmentAge", []), 3e4, "minCommitmentAge"),
|
|
1151
|
+
withTimeout(this.contractCall(CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, DOTNS_REGISTRAR_CONTROLLER_ABI, "commitments", [commitment]), 3e4, "commitments")
|
|
1152
|
+
]);
|
|
1153
|
+
const minimumAgeSeconds = typeof minimumAge === "bigint" ? Number(minimumAge) : minimumAge;
|
|
1154
|
+
const commitTimestamp = typeof initialCommitTimestamp === "bigint" ? Number(initialCommitTimestamp) : initialCommitTimestamp;
|
|
1155
|
+
if (commitTimestamp === 0) {
|
|
1156
|
+
throw new Error("Commitment not found on-chain. It may not have been included in a block yet.");
|
|
1157
|
+
}
|
|
1158
|
+
console.log(` Minimum commitment age: ${minimumAgeSeconds}s`);
|
|
1159
|
+
console.log(` Commitment stored on-chain (timestamp: ${commitTimestamp})`);
|
|
1160
|
+
console.log(` Waiting for on-chain block.timestamp > ${commitTimestamp + minimumAgeSeconds}...`);
|
|
1161
|
+
const pollDeadline = Date.now() + POLL_TIMEOUT_MS;
|
|
1162
|
+
while (Date.now() < pollDeadline) {
|
|
1163
|
+
const nowMs = await this.clientWrapper.client.query.Timestamp.Now.getValue();
|
|
1164
|
+
const chainNowSeconds = Math.floor(Number(nowMs) / 1e3);
|
|
1165
|
+
if (isCommitmentMature(chainNowSeconds, commitTimestamp, minimumAgeSeconds)) {
|
|
1166
|
+
console.log(` Commitment age requirement met (chain.now=${chainNowSeconds}, target>${commitTimestamp + minimumAgeSeconds})`);
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const remaining = Math.ceil((pollDeadline - Date.now()) / 1e3);
|
|
1170
|
+
console.log(` Chain time ${chainNowSeconds}, waiting for > ${commitTimestamp + minimumAgeSeconds} (${remaining}s left)...`);
|
|
1171
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
1172
|
+
}
|
|
1173
|
+
throw new Error(`Commitment still too new after ${POLL_TIMEOUT_MS / 1e3}s of polling chain time. The chain may be stalled.`);
|
|
1174
|
+
}
|
|
1175
|
+
async getPriceAndValidate(label) {
|
|
1176
|
+
this.ensureConnected();
|
|
1177
|
+
console.log(`
|
|
1178
|
+
Checking price and eligibility...`);
|
|
1179
|
+
label = validateDomainLabel(label);
|
|
1180
|
+
const baseName = stripTrailingDigits(label);
|
|
1181
|
+
const reservationInfo = await withTimeout(this.contractCall(CONTRACTS.POP_RULES, POP_RULES_ABI, "isBaseNameReserved", [baseName]), 3e4, "isBaseNameReserved");
|
|
1182
|
+
const [isReserved, reservationOwner] = reservationInfo;
|
|
1183
|
+
if (isReserved && reservationOwner.toLowerCase() !== this.evmAddress.toLowerCase()) throw new Error("Base name reserved for original Lite registrant");
|
|
1184
|
+
const classificationResult = await withTimeout(this.contractCall(CONTRACTS.POP_RULES, POP_RULES_ABI, "classifyName", [label]), 3e4, "classifyName");
|
|
1185
|
+
const requiredStatus = typeof classificationResult[0] === "bigint" ? Number(classificationResult[0]) : classificationResult[0];
|
|
1186
|
+
const message = classificationResult[1];
|
|
1187
|
+
const userStatus = await this.getUserPopStatus();
|
|
1188
|
+
if (requiredStatus === ProofOfPersonhoodStatus.Reserved) throw new Error(message);
|
|
1189
|
+
if (requiredStatus === ProofOfPersonhoodStatus.ProofOfPersonhoodFull) {
|
|
1190
|
+
if (userStatus !== ProofOfPersonhoodStatus.ProofOfPersonhoodFull) throw new Error("Requires Full Personhood verification");
|
|
1191
|
+
} else if (requiredStatus === ProofOfPersonhoodStatus.ProofOfPersonhoodLite) {
|
|
1192
|
+
if (userStatus !== ProofOfPersonhoodStatus.ProofOfPersonhoodLite && userStatus !== ProofOfPersonhoodStatus.ProofOfPersonhoodFull) throw new Error("Requires Personhood Lite verification");
|
|
1193
|
+
} else {
|
|
1194
|
+
const trailingDigitCount = countTrailingDigits(label);
|
|
1195
|
+
if (trailingDigitCount === 0 || userStatus === ProofOfPersonhoodStatus.ProofOfPersonhoodLite) {
|
|
1196
|
+
throw new Error("Personhood Lite cannot register base names \u2014 this name class requires a Full or NoStatus signer");
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
const priceRaw = await withTimeout(this.contractCall(CONTRACTS.POP_RULES, POP_RULES_ABI, "price", [label]), 3e4, "price");
|
|
1200
|
+
const priceWei = typeof priceRaw === "bigint" ? priceRaw : BigInt(priceRaw);
|
|
1201
|
+
console.log(` Required status: ${popStatusName(requiredStatus)}`);
|
|
1202
|
+
console.log(` User status: ${popStatusName(userStatus)}`);
|
|
1203
|
+
console.log(` Price: ${formatEther(priceWei)} PAS`);
|
|
1204
|
+
return { priceWei, requiredStatus, userStatus, message };
|
|
1205
|
+
}
|
|
1206
|
+
async finalizeRegistration(registration, priceWei) {
|
|
1207
|
+
this.ensureConnected();
|
|
1208
|
+
console.log(`
|
|
1209
|
+
Finalizing registration for ${registration.label}.dot...`);
|
|
1210
|
+
const bufferedPaymentWei = priceWei * 110n / 100n;
|
|
1211
|
+
const bufferedPaymentNative = convertWeiToNative(bufferedPaymentWei);
|
|
1212
|
+
console.log(` Oracle price: ${formatEther(priceWei)} PAS`);
|
|
1213
|
+
console.log(` Paying: ${formatEther(bufferedPaymentWei)} PAS`);
|
|
1214
|
+
const txHash = await this.contractTransaction(CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, bufferedPaymentNative, DOTNS_REGISTRAR_CONTROLLER_ABI, "register", [registration], (s) => console.log(` ${s}`));
|
|
1215
|
+
console.log(` Tx: ${txHash}`);
|
|
1216
|
+
}
|
|
1217
|
+
async verifyOwnership(label) {
|
|
1218
|
+
this.ensureConnected();
|
|
1219
|
+
console.log(`
|
|
1220
|
+
Verifying ownership...`);
|
|
1221
|
+
const tokenId = computeDomainTokenId(label);
|
|
1222
|
+
const actualOwner = await withTimeout(this.contractCall(CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 3e4, "ownerOf");
|
|
1223
|
+
if (actualOwner.toLowerCase() !== this.evmAddress.toLowerCase()) {
|
|
1224
|
+
console.log(` Expected: ${this.evmAddress}`);
|
|
1225
|
+
console.log(` Actual: ${actualOwner}`);
|
|
1226
|
+
throw new Error(`Owner mismatch for ${label}.dot`);
|
|
1227
|
+
}
|
|
1228
|
+
console.log(` Owner: ${actualOwner}`);
|
|
1229
|
+
}
|
|
822
1230
|
// View-only readiness check. Runs every chain read needed to predict whether
|
|
823
1231
|
// `register(label)` will succeed, so the caller can fail-fast BEFORE the
|
|
824
1232
|
// Bulletin chunk upload. Never writes to chain. See issue #100.
|
|
@@ -1018,6 +1426,43 @@ var DotNS = class {
|
|
|
1018
1426
|
}
|
|
1019
1427
|
const explicitStatus = options.status || process.env.DOTNS_STATUS;
|
|
1020
1428
|
const reverse = options.reverse ?? (process.env.DOTNS_REVERSE ?? "false").toLowerCase() === "true";
|
|
1429
|
+
if (this._usesExternalSigner) {
|
|
1430
|
+
const [classification] = await Promise.all([
|
|
1431
|
+
this.classifyName(label),
|
|
1432
|
+
this.ensureNotRegistered(label)
|
|
1433
|
+
]);
|
|
1434
|
+
const requiredStatus = classification.requiredStatus;
|
|
1435
|
+
if (requiredStatus === ProofOfPersonhoodStatus.Reserved) {
|
|
1436
|
+
throw new Error(classification.message);
|
|
1437
|
+
}
|
|
1438
|
+
const initialUserStatus = await this.getUserPopStatus();
|
|
1439
|
+
const isTestnet = await this.isTestnet();
|
|
1440
|
+
const explicitStatusNum = explicitStatus ? parseProofOfPersonhoodStatus(explicitStatus) : void 0;
|
|
1441
|
+
const targetUserStatus = simulateUserStatus(initialUserStatus, requiredStatus, { explicitStatus: explicitStatusNum, isTestnet });
|
|
1442
|
+
if (!canRegister(requiredStatus, targetUserStatus, countTrailingDigits(label))) {
|
|
1443
|
+
throw new Error(
|
|
1444
|
+
`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.`
|
|
1445
|
+
);
|
|
1446
|
+
}
|
|
1447
|
+
if (targetUserStatus !== initialUserStatus && targetUserStatus !== ProofOfPersonhoodStatus.NoStatus) {
|
|
1448
|
+
await this.setUserPopStatus(targetUserStatus);
|
|
1449
|
+
const userStatus = await this.getUserPopStatus();
|
|
1450
|
+
if (userStatus !== targetUserStatus) {
|
|
1451
|
+
throw new Error(
|
|
1452
|
+
"setUserPopStatus did not land as expected (wanted " + targetUserStatus + ", got " + userStatus + "). Check RPC connectivity and POP_RULES contract."
|
|
1453
|
+
);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
const { commitment, registration } = await this.generateCommitment(label, reverse);
|
|
1457
|
+
await withSpan("deploy.dotns.submit-commitment", "2a-i. submit-commitment", {}, () => this.submitCommitment(commitment));
|
|
1458
|
+
await withSpan("deploy.dotns.wait-commitment-age", "2a-ii. wait-commitment-age", {}, () => this.waitForCommitmentAge(commitment));
|
|
1459
|
+
const pricing = await withSpan("deploy.dotns.price-validation", "2a-iii. price-validation", {}, () => this.getPriceAndValidate(label));
|
|
1460
|
+
await withSpan("deploy.dotns.finalize-registration", "2a-iv. finalize-registration", {}, () => this.finalizeRegistration(registration, pricing.priceWei));
|
|
1461
|
+
await this.verifyOwnership(label);
|
|
1462
|
+
console.log(`
|
|
1463
|
+
Registration complete!`);
|
|
1464
|
+
return { label, owner: this.evmAddress };
|
|
1465
|
+
}
|
|
1021
1466
|
const statusArgs = explicitStatus ? ["-s", explicitStatus] : [];
|
|
1022
1467
|
const reverseArgs = reverse ? ["-r"] : [];
|
|
1023
1468
|
console.log(`
|
|
@@ -1066,6 +1511,7 @@ var DotNS = class {
|
|
|
1066
1511
|
}
|
|
1067
1512
|
this._mnemonic = null;
|
|
1068
1513
|
this._keyUri = null;
|
|
1514
|
+
this._usesExternalSigner = false;
|
|
1069
1515
|
}
|
|
1070
1516
|
};
|
|
1071
1517
|
var dotns = new DotNS();
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
classifyErrorArea,
|
|
3
3
|
isInteractive,
|
|
4
4
|
promptYesNo
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DHG4F2IN.js";
|
|
6
6
|
import {
|
|
7
7
|
VERSION,
|
|
8
8
|
getCurrentSentryTraceId
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-M2ULKTBL.js";
|
|
10
10
|
|
|
11
11
|
// src/bug-report.ts
|
|
12
12
|
import { execSync, execFileSync } from "child_process";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
setDeployContext
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7WTKLCKX.js";
|
|
4
4
|
import {
|
|
5
5
|
DotNS,
|
|
6
6
|
TX_TIMEOUT_MS,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
parseDomainName,
|
|
9
9
|
popStatusName,
|
|
10
10
|
verifyNonceAdvanced
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-3XEROH7U.js";
|
|
12
12
|
import {
|
|
13
13
|
MirrorSkipped,
|
|
14
14
|
mirrorToGitHubPages,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
truncateAddress,
|
|
28
28
|
withDeploySpan,
|
|
29
29
|
withSpan
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-M2ULKTBL.js";
|
|
31
31
|
import {
|
|
32
32
|
merkleizeJS
|
|
33
33
|
} from "./chunk-B7GUYYAN.js";
|
package/dist/deploy.js
CHANGED
|
@@ -26,13 +26,13 @@ import {
|
|
|
26
26
|
storeChunkedContent,
|
|
27
27
|
storeDirectory,
|
|
28
28
|
storeFile
|
|
29
|
-
} from "./chunk-
|
|
30
|
-
import "./chunk-
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-
|
|
29
|
+
} from "./chunk-TGOSZVL5.js";
|
|
30
|
+
import "./chunk-7WTKLCKX.js";
|
|
31
|
+
import "./chunk-DHG4F2IN.js";
|
|
32
|
+
import "./chunk-3XEROH7U.js";
|
|
33
33
|
import "./chunk-HOTQDYHD.js";
|
|
34
|
-
import "./chunk-
|
|
35
|
-
import "./chunk-
|
|
34
|
+
import "./chunk-M2ULKTBL.js";
|
|
35
|
+
import "./chunk-2KBYGMG5.js";
|
|
36
36
|
import "./chunk-B7GUYYAN.js";
|
|
37
37
|
import "./chunk-RP4YJYNB.js";
|
|
38
38
|
import "./chunk-QGM4M3NI.js";
|
package/dist/dotns.d.ts
CHANGED
|
@@ -124,7 +124,27 @@ declare class ReviveClientWrapper {
|
|
|
124
124
|
constructor(client: any);
|
|
125
125
|
getEvmAddress(substrateAddress: string): Promise<string>;
|
|
126
126
|
performDryRunCall(originSubstrateAddress: string, contractAddress: string, value: bigint, encodedData: string): Promise<any>;
|
|
127
|
+
estimateGasForCall(originSubstrateAddress: string, contractAddress: string, value: bigint, encodedData: string): Promise<any>;
|
|
127
128
|
checkIfAccountMapped(substrateAddress: string): Promise<boolean>;
|
|
129
|
+
ensureAccountMapped(substrateAddress: string, signer: PolkadotSigner): Promise<void>;
|
|
130
|
+
signAndSubmitExtrinsic(extrinsic: any, signer: PolkadotSigner, statusCallback: (status: string) => void, opts?: {
|
|
131
|
+
nonceFallback?: {
|
|
132
|
+
rpcs: string[];
|
|
133
|
+
senderSS58: string;
|
|
134
|
+
expectedNonce: number;
|
|
135
|
+
};
|
|
136
|
+
}): Promise<string>;
|
|
137
|
+
signAndSubmitWithRetry(buildExtrinsic: () => any, signer: PolkadotSigner, statusCallback: (status: string) => void, label: string, opts?: {
|
|
138
|
+
nonceFallback?: {
|
|
139
|
+
rpcs: string[];
|
|
140
|
+
senderSS58: string;
|
|
141
|
+
expectedNonce: number;
|
|
142
|
+
};
|
|
143
|
+
}): Promise<string>;
|
|
144
|
+
submitTransaction(contractAddress: string, value: bigint, encodedData: string, signerSubstrateAddress: string, signer: PolkadotSigner, statusCallback: (status: string) => void, { rpcs, useNoncePolling }: {
|
|
145
|
+
rpcs: string[];
|
|
146
|
+
useNoncePolling?: boolean;
|
|
147
|
+
}): Promise<string>;
|
|
128
148
|
}
|
|
129
149
|
declare function runDotnsCli(argv: string[], env?: Record<string, string>): Promise<unknown>;
|
|
130
150
|
declare class DotNS {
|
|
@@ -137,6 +157,7 @@ declare class DotNS {
|
|
|
137
157
|
connected: boolean;
|
|
138
158
|
private _mnemonic;
|
|
139
159
|
private _keyUri;
|
|
160
|
+
private _usesExternalSigner;
|
|
140
161
|
constructor();
|
|
141
162
|
connect(options?: DotNSConnectOptions): Promise<this>;
|
|
142
163
|
ensureConnected(): void;
|
|
@@ -149,6 +170,9 @@ declare class DotNS {
|
|
|
149
170
|
} | null>;
|
|
150
171
|
private submitTransfer;
|
|
151
172
|
contractCall(contractAddress: string, contractAbi: readonly any[], functionName: string, args?: any[]): Promise<any>;
|
|
173
|
+
contractTransaction(contractAddress: string, value: bigint, contractAbi: readonly any[], functionName: string, args?: any[], statusCallback?: (status: string) => void, { useNoncePolling }?: {
|
|
174
|
+
useNoncePolling?: boolean;
|
|
175
|
+
}): Promise<string>;
|
|
152
176
|
checkOwnership(label: string, ownerAddress?: string | null): Promise<OwnershipResult>;
|
|
153
177
|
getUserPopStatus(ownerAddress?: string | null): Promise<number>;
|
|
154
178
|
setUserPopStatus(status: number): Promise<void>;
|
|
@@ -166,6 +190,20 @@ declare class DotNS {
|
|
|
166
190
|
txHash: string;
|
|
167
191
|
}>;
|
|
168
192
|
getContenthash(domainName: string): Promise<string>;
|
|
193
|
+
classifyName(label: string): Promise<{
|
|
194
|
+
requiredStatus: number;
|
|
195
|
+
message: string;
|
|
196
|
+
}>;
|
|
197
|
+
ensureNotRegistered(label: string): Promise<void>;
|
|
198
|
+
generateCommitment(label: string, includeReverse?: boolean): Promise<{
|
|
199
|
+
commitment: any;
|
|
200
|
+
registration: any;
|
|
201
|
+
}>;
|
|
202
|
+
submitCommitment(commitment: any): Promise<void>;
|
|
203
|
+
waitForCommitmentAge(commitment: any): Promise<void>;
|
|
204
|
+
getPriceAndValidate(label: string): Promise<PriceValidationResult>;
|
|
205
|
+
finalizeRegistration(registration: any, priceWei: bigint): Promise<void>;
|
|
206
|
+
verifyOwnership(label: string): Promise<void>;
|
|
169
207
|
preflight(label: string, explicitStatusOverride?: string): Promise<DotnsPreflightResult>;
|
|
170
208
|
private gateOnFeeBalance;
|
|
171
209
|
register(label: string, options?: DotNSConnectOptions & {
|
package/dist/dotns.js
CHANGED
|
@@ -35,9 +35,9 @@ import {
|
|
|
35
35
|
stripTrailingDigits,
|
|
36
36
|
validateDomainLabel,
|
|
37
37
|
verifyNonceAdvanced
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import "./chunk-
|
|
40
|
-
import "./chunk-
|
|
38
|
+
} from "./chunk-3XEROH7U.js";
|
|
39
|
+
import "./chunk-M2ULKTBL.js";
|
|
40
|
+
import "./chunk-2KBYGMG5.js";
|
|
41
41
|
import "./chunk-RP4YJYNB.js";
|
|
42
42
|
import "./chunk-QGM4M3NI.js";
|
|
43
43
|
export {
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deploy
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-TGOSZVL5.js";
|
|
4
|
+
import "./chunk-7WTKLCKX.js";
|
|
5
|
+
import "./chunk-DHG4F2IN.js";
|
|
6
6
|
import {
|
|
7
7
|
DotNS,
|
|
8
8
|
parseDomainName
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-3XEROH7U.js";
|
|
10
10
|
import "./chunk-HOTQDYHD.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-M2ULKTBL.js";
|
|
12
12
|
import {
|
|
13
13
|
VERSION,
|
|
14
14
|
loadRunState,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
shouldSkipStaleWarning,
|
|
19
19
|
stateFilePath,
|
|
20
20
|
writeRunState
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-2KBYGMG5.js";
|
|
22
22
|
import {
|
|
23
23
|
merkleizeJS
|
|
24
24
|
} from "./chunk-B7GUYYAN.js";
|
package/dist/memory-report.js
CHANGED
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
maybeWriteMemoryReport,
|
|
6
6
|
safeHeap,
|
|
7
7
|
sampleFromBytes
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-M2ULKTBL.js";
|
|
9
|
+
import "./chunk-2KBYGMG5.js";
|
|
10
10
|
import "./chunk-QGM4M3NI.js";
|
|
11
11
|
export {
|
|
12
12
|
DEFAULT_THRESHOLD_MB,
|
package/dist/run-state.js
CHANGED
package/dist/telemetry.js
CHANGED
package/dist/version-check.js
CHANGED
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
isPreReleaseVersion,
|
|
9
9
|
preReleaseWarning,
|
|
10
10
|
promptYesNo
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-DHG4F2IN.js";
|
|
12
|
+
import "./chunk-M2ULKTBL.js";
|
|
13
|
+
import "./chunk-2KBYGMG5.js";
|
|
14
14
|
import "./chunk-QGM4M3NI.js";
|
|
15
15
|
export {
|
|
16
16
|
assessVersion,
|