@parity/dotns-cli 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2005 -2040
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -247567,7 +247567,7 @@ __export(exports_storeManagement, {
|
|
|
247567
247567
|
listStoreCids: () => listStoreCids,
|
|
247568
247568
|
getStoreValue: () => getStoreValue,
|
|
247569
247569
|
getStoreInfo: () => getStoreInfo,
|
|
247570
|
-
ensureStoreAuthorizations: () =>
|
|
247570
|
+
ensureStoreAuthorizations: () => ensureStoreAuthorizations,
|
|
247571
247571
|
deleteStoreValue: () => deleteStoreValue,
|
|
247572
247572
|
checkStoreAuth: () => checkStoreAuth,
|
|
247573
247573
|
cacheCidToStore: () => cacheCidToStore,
|
|
@@ -247784,7 +247784,7 @@ async function unauthorizeDotnsController(clientWrapper, substrateAddress, signe
|
|
|
247784
247784
|
console.log(source_default.gray(" tx: ") + source_default.blue(tx));
|
|
247785
247785
|
console.log(source_default.gray(" target: ") + source_default.white(targetAddress));
|
|
247786
247786
|
}
|
|
247787
|
-
async function
|
|
247787
|
+
async function ensureStoreAuthorizations(clientWrapper, substrateAddress, signer, evmAddress) {
|
|
247788
247788
|
const storeAddress = await resolveStoreAddress(clientWrapper, substrateAddress, evmAddress);
|
|
247789
247789
|
const spinner = ora("Checking Store authorizations").start();
|
|
247790
247790
|
const [controllerAuthorized, registryAuthorized] = await Promise.all([
|
|
@@ -248059,12 +248059,9 @@ function decryptKeystorePayload(ks, password) {
|
|
|
248059
248059
|
}
|
|
248060
248060
|
}
|
|
248061
248061
|
|
|
248062
|
-
// src/cli/commands/
|
|
248063
|
-
|
|
248064
|
-
|
|
248065
|
-
var MNEMONIC_PROMPT = "mnemonic";
|
|
248066
|
-
var KEY_URI_PROMPT = "key-uri";
|
|
248067
|
-
var AUTH_TYPE_UNKNOWN = "unknown";
|
|
248062
|
+
// src/cli/commands/jsonHelpers.ts
|
|
248063
|
+
init_source();
|
|
248064
|
+
init_formatting();
|
|
248068
248065
|
function getMergedOptions(command, fallback) {
|
|
248069
248066
|
const mergedOptions = { ...fallback ?? {} };
|
|
248070
248067
|
let currentCommand = command?.parent;
|
|
@@ -248072,9 +248069,8 @@ function getMergedOptions(command, fallback) {
|
|
|
248072
248069
|
if (typeof currentCommand.opts === "function") {
|
|
248073
248070
|
const parentOptions = currentCommand.opts();
|
|
248074
248071
|
for (const key in parentOptions) {
|
|
248075
|
-
|
|
248076
|
-
|
|
248077
|
-
mergedOptions[optionKey] = parentOptions[optionKey];
|
|
248072
|
+
if (!(key in mergedOptions) && parentOptions[key] !== undefined) {
|
|
248073
|
+
mergedOptions[key] = parentOptions[key];
|
|
248078
248074
|
}
|
|
248079
248075
|
}
|
|
248080
248076
|
}
|
|
@@ -248082,6 +248078,91 @@ function getMergedOptions(command, fallback) {
|
|
|
248082
248078
|
}
|
|
248083
248079
|
return mergedOptions;
|
|
248084
248080
|
}
|
|
248081
|
+
function getJsonFlag(command) {
|
|
248082
|
+
if (command && typeof command.optsWithGlobals === "function") {
|
|
248083
|
+
const options = command.optsWithGlobals();
|
|
248084
|
+
if (typeof options?.json === "boolean")
|
|
248085
|
+
return options.json;
|
|
248086
|
+
}
|
|
248087
|
+
const localOptions = command && typeof command.opts === "function" ? command.opts() : undefined;
|
|
248088
|
+
if (typeof localOptions?.json === "boolean")
|
|
248089
|
+
return localOptions.json;
|
|
248090
|
+
return false;
|
|
248091
|
+
}
|
|
248092
|
+
function emitJsonResult(jsonOutput, result) {
|
|
248093
|
+
if (jsonOutput) {
|
|
248094
|
+
console.log(JSON.stringify(result));
|
|
248095
|
+
return true;
|
|
248096
|
+
}
|
|
248097
|
+
return false;
|
|
248098
|
+
}
|
|
248099
|
+
function handleCommandError(jsonOutput, error2) {
|
|
248100
|
+
const message = formatErrorMessage(error2);
|
|
248101
|
+
if (jsonOutput) {
|
|
248102
|
+
console.error(JSON.stringify({ error: message }));
|
|
248103
|
+
} else {
|
|
248104
|
+
console.error(source_default.red(`
|
|
248105
|
+
✗ Error: ${message}
|
|
248106
|
+
`));
|
|
248107
|
+
}
|
|
248108
|
+
process.exit(1);
|
|
248109
|
+
}
|
|
248110
|
+
async function withCapturedConsole(callback) {
|
|
248111
|
+
const MAX_CAPTURED_ENTRIES = 400;
|
|
248112
|
+
const captured = [];
|
|
248113
|
+
const pushCaptured = (value) => {
|
|
248114
|
+
captured.push(value);
|
|
248115
|
+
if (captured.length > MAX_CAPTURED_ENTRIES) {
|
|
248116
|
+
captured.splice(0, captured.length - MAX_CAPTURED_ENTRIES);
|
|
248117
|
+
}
|
|
248118
|
+
};
|
|
248119
|
+
const capture = (...args) => {
|
|
248120
|
+
pushCaptured(args.map(String).join(" "));
|
|
248121
|
+
};
|
|
248122
|
+
const captureWrite = (chunk) => {
|
|
248123
|
+
pushCaptured(String(chunk));
|
|
248124
|
+
return true;
|
|
248125
|
+
};
|
|
248126
|
+
const saved = {
|
|
248127
|
+
log: console.log,
|
|
248128
|
+
error: console.error,
|
|
248129
|
+
warn: console.warn,
|
|
248130
|
+
info: console.info,
|
|
248131
|
+
stdoutWrite: process.stdout.write.bind(process.stdout),
|
|
248132
|
+
stderrWrite: process.stderr.write.bind(process.stderr)
|
|
248133
|
+
};
|
|
248134
|
+
console.log = capture;
|
|
248135
|
+
console.error = capture;
|
|
248136
|
+
console.warn = capture;
|
|
248137
|
+
console.info = capture;
|
|
248138
|
+
process.stdout.write = captureWrite;
|
|
248139
|
+
process.stderr.write = captureWrite;
|
|
248140
|
+
try {
|
|
248141
|
+
return await callback();
|
|
248142
|
+
} catch (error2) {
|
|
248143
|
+
saved.error(`[captured output before failure]
|
|
248144
|
+
` + captured.join(`
|
|
248145
|
+
`));
|
|
248146
|
+
throw error2;
|
|
248147
|
+
} finally {
|
|
248148
|
+
console.log = saved.log;
|
|
248149
|
+
console.error = saved.error;
|
|
248150
|
+
console.warn = saved.warn;
|
|
248151
|
+
console.info = saved.info;
|
|
248152
|
+
process.stdout.write = saved.stdoutWrite;
|
|
248153
|
+
process.stderr.write = saved.stderrWrite;
|
|
248154
|
+
}
|
|
248155
|
+
}
|
|
248156
|
+
function maybeQuiet(jsonOutput, callback) {
|
|
248157
|
+
return jsonOutput ? withCapturedConsole(callback) : callback();
|
|
248158
|
+
}
|
|
248159
|
+
|
|
248160
|
+
// src/cli/commands/auth.ts
|
|
248161
|
+
var DEFAULT_ACCOUNT_POINTER_FILE = ".default";
|
|
248162
|
+
var KEYSTORE_FILE_EXTENSION = ".json";
|
|
248163
|
+
var MNEMONIC_PROMPT = "mnemonic";
|
|
248164
|
+
var KEY_URI_PROMPT = "key-uri";
|
|
248165
|
+
var AUTH_TYPE_UNKNOWN = "unknown";
|
|
248085
248166
|
function resolvePasswordForCreate(options) {
|
|
248086
248167
|
const fromCli = String(options.password ?? "").trim();
|
|
248087
248168
|
if (fromCli)
|
|
@@ -265069,1712 +265150,1860 @@ async function prepareContext(options2) {
|
|
|
265069
265150
|
|
|
265070
265151
|
// src/cli/commands/bulletin.ts
|
|
265071
265152
|
init_constants();
|
|
265072
|
-
|
|
265073
|
-
|
|
265074
|
-
|
|
265075
|
-
|
|
265076
|
-
|
|
265077
|
-
init_dist();
|
|
265078
|
-
init_polkadotClient();
|
|
265079
|
-
|
|
265080
|
-
// src/commands/lookup.ts
|
|
265081
|
-
init_source();
|
|
265082
|
-
init_ora();
|
|
265083
|
-
init__esm();
|
|
265084
|
-
init_constants();
|
|
265085
|
-
|
|
265086
|
-
// src/utils/validation.ts
|
|
265087
|
-
init__esm();
|
|
265088
|
-
function countTrailingDigits(label) {
|
|
265089
|
-
let count2 = 0;
|
|
265090
|
-
for (let characterIndex = label.length - 1;characterIndex >= 0; characterIndex--) {
|
|
265091
|
-
const asciiCode = label.charCodeAt(characterIndex);
|
|
265092
|
-
if (asciiCode >= 48 && asciiCode <= 57) {
|
|
265093
|
-
count2++;
|
|
265094
|
-
} else {
|
|
265095
|
-
break;
|
|
265096
|
-
}
|
|
265097
|
-
}
|
|
265098
|
-
return count2;
|
|
265153
|
+
init_reporter();
|
|
265154
|
+
function cleanupHeliaAndExit(code8) {
|
|
265155
|
+
Promise.resolve().then(() => (init_heliaClient(), exports_heliaClient)).then(({ destroySharedHeliaClient: destroySharedHeliaClient2 }) => destroySharedHeliaClient2()).catch(() => {}).finally(() => process.exit(code8));
|
|
265156
|
+
setTimeout(() => process.exit(code8), 500);
|
|
265157
|
+
return;
|
|
265099
265158
|
}
|
|
265100
|
-
|
|
265101
|
-
|
|
265159
|
+
var PROFILE_SAMPLE_INTERVAL_MS = 2000;
|
|
265160
|
+
function addReporterOption(command) {
|
|
265161
|
+
return command.option("--reporter <mode>", "Progress reporter: auto, interactive, stream, or quiet", "auto");
|
|
265102
265162
|
}
|
|
265103
|
-
function
|
|
265104
|
-
|
|
265105
|
-
throw new Error("Invalid domain label: must contain only lowercase letters, digits, and hyphens, with minimum length of 3 characters");
|
|
265106
|
-
}
|
|
265107
|
-
if (label.startsWith("-") || label.endsWith("-")) {
|
|
265108
|
-
throw new Error("Invalid domain label: cannot start or end with hyphen");
|
|
265109
|
-
}
|
|
265110
|
-
const trailingDigitCount = countTrailingDigits(label);
|
|
265111
|
-
if (trailingDigitCount > 2) {
|
|
265112
|
-
throw new Error(`Invalid domain label: maximum 2 trailing digits allowed, found ${trailingDigitCount}`);
|
|
265113
|
-
}
|
|
265163
|
+
function createProfileFingerprint(input) {
|
|
265164
|
+
return createHash2("sha256").update(input).digest("hex").slice(0, 16);
|
|
265114
265165
|
}
|
|
265115
|
-
function
|
|
265116
|
-
|
|
265117
|
-
const
|
|
265118
|
-
|
|
265119
|
-
throw new Error(`Invalid governance label: base name must be 5 characters or fewer (got ${baseName.length})`);
|
|
265120
|
-
}
|
|
265166
|
+
function buildDefaultProfileOutputPath(sourcePath, fingerprint) {
|
|
265167
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
265168
|
+
const basename = path9.basename(sourcePath).replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
265169
|
+
return path9.join(os11.homedir(), ".dotns", "upload-profiles", `${timestamp}-${basename}-${fingerprint}.json`);
|
|
265121
265170
|
}
|
|
265122
|
-
|
|
265123
|
-
|
|
265124
|
-
|
|
265125
|
-
|
|
265126
|
-
|
|
265127
|
-
|
|
265128
|
-
|
|
265129
|
-
|
|
265130
|
-
|
|
265131
|
-
|
|
265132
|
-
};
|
|
265133
|
-
|
|
265134
|
-
// src/commands/lookup.ts
|
|
265135
|
-
init_contractInteractions();
|
|
265136
|
-
init_formatting();
|
|
265137
|
-
async function performDomainLookup(label, originSubstrateAddress, clientWrapper) {
|
|
265138
|
-
const fullyQualifiedDomainName = `${label}.dot`;
|
|
265139
|
-
const namehashNode = namehash(fullyQualifiedDomainName);
|
|
265140
|
-
const result = {
|
|
265141
|
-
domain: fullyQualifiedDomainName,
|
|
265142
|
-
node: namehashNode,
|
|
265143
|
-
exists: false,
|
|
265144
|
-
owner: zeroAddress,
|
|
265145
|
-
resolver: zeroAddress,
|
|
265146
|
-
store: null,
|
|
265147
|
-
resolvedAddress: null,
|
|
265148
|
-
ownerBalance: null,
|
|
265149
|
-
baseNameReservation: null
|
|
265171
|
+
function createUploadProfiler(options2) {
|
|
265172
|
+
const startedAtMs = Date.now();
|
|
265173
|
+
const startedAtIso = new Date(startedAtMs).toISOString();
|
|
265174
|
+
let latestSchedulerState = {
|
|
265175
|
+
timestampMs: startedAtMs,
|
|
265176
|
+
window: Math.max(1, options2.initialConcurrency),
|
|
265177
|
+
inFlightBytes: 0,
|
|
265178
|
+
inFlightChunks: 0,
|
|
265179
|
+
completedChunks: 0,
|
|
265180
|
+
retries: 0
|
|
265150
265181
|
};
|
|
265151
|
-
const
|
|
265152
|
-
|
|
265153
|
-
|
|
265154
|
-
|
|
265155
|
-
|
|
265156
|
-
|
|
265157
|
-
|
|
265158
|
-
|
|
265159
|
-
|
|
265160
|
-
|
|
265161
|
-
|
|
265162
|
-
|
|
265163
|
-
|
|
265164
|
-
|
|
265165
|
-
|
|
265166
|
-
|
|
265167
|
-
|
|
265168
|
-
|
|
265169
|
-
|
|
265170
|
-
|
|
265171
|
-
|
|
265172
|
-
|
|
265173
|
-
|
|
265174
|
-
|
|
265175
|
-
|
|
265176
|
-
|
|
265177
|
-
|
|
265178
|
-
|
|
265179
|
-
|
|
265180
|
-
|
|
265181
|
-
|
|
265182
|
-
|
|
265183
|
-
|
|
265184
|
-
|
|
265185
|
-
|
|
265186
|
-
|
|
265187
|
-
|
|
265188
|
-
|
|
265189
|
-
|
|
265190
|
-
|
|
265191
|
-
|
|
265192
|
-
|
|
265193
|
-
|
|
265194
|
-
|
|
265195
|
-
|
|
265196
|
-
|
|
265197
|
-
|
|
265198
|
-
|
|
265199
|
-
|
|
265200
|
-
|
|
265201
|
-
|
|
265202
|
-
|
|
265203
|
-
|
|
265204
|
-
|
|
265205
|
-
|
|
265206
|
-
|
|
265207
|
-
|
|
265208
|
-
|
|
265209
|
-
|
|
265210
|
-
} catch {
|
|
265211
|
-
console.log(source_default.gray(" balance: ") + source_default.yellow("unavailable"));
|
|
265212
|
-
}
|
|
265213
|
-
console.log();
|
|
265214
|
-
const baseName = stripTrailingDigits(label);
|
|
265215
|
-
if (baseName !== label) {
|
|
265216
|
-
result.baseNameReservation = await lookupBaseNameReservation(clientWrapper, originSubstrateAddress, baseName);
|
|
265217
|
-
displayBaseNameReservation(result.baseNameReservation);
|
|
265218
|
-
}
|
|
265219
|
-
console.log("▶ Lookup completed");
|
|
265220
|
-
return result;
|
|
265221
|
-
}
|
|
265222
|
-
async function lookupBaseNameReservation(clientWrapper, originSubstrateAddress, baseName) {
|
|
265223
|
-
try {
|
|
265224
|
-
const reservationInfo = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "isBaseNameReserved", [baseName]);
|
|
265225
|
-
const [isReserved, reservationOwner, expirationTimestamp] = reservationInfo;
|
|
265226
|
-
return {
|
|
265227
|
-
baseName,
|
|
265228
|
-
isReserved,
|
|
265229
|
-
reservedBy: getAddress(reservationOwner),
|
|
265230
|
-
expires: expirationTimestamp > 0n ? new Date(Number(expirationTimestamp) * 1000).toISOString() : null
|
|
265231
|
-
};
|
|
265232
|
-
} catch {
|
|
265233
|
-
return {
|
|
265234
|
-
expires: null,
|
|
265235
|
-
baseName,
|
|
265236
|
-
isReserved: false,
|
|
265237
|
-
reservedBy: zeroAddress
|
|
265182
|
+
const samples = [];
|
|
265183
|
+
const waves = [];
|
|
265184
|
+
const captureSample = () => {
|
|
265185
|
+
const usage = process.memoryUsage();
|
|
265186
|
+
samples.push({
|
|
265187
|
+
timestampMs: Date.now(),
|
|
265188
|
+
heapUsed: usage.heapUsed,
|
|
265189
|
+
rss: usage.rss,
|
|
265190
|
+
arrayBuffers: usage.arrayBuffers,
|
|
265191
|
+
external: usage.external,
|
|
265192
|
+
inFlightBytes: latestSchedulerState.inFlightBytes,
|
|
265193
|
+
inFlightChunks: latestSchedulerState.inFlightChunks,
|
|
265194
|
+
window: latestSchedulerState.window,
|
|
265195
|
+
completed: latestSchedulerState.completedChunks,
|
|
265196
|
+
retries: latestSchedulerState.retries
|
|
265197
|
+
});
|
|
265198
|
+
};
|
|
265199
|
+
captureSample();
|
|
265200
|
+
const timer4 = setInterval(captureSample, PROFILE_SAMPLE_INTERVAL_MS);
|
|
265201
|
+
timer4.unref?.();
|
|
265202
|
+
const summarizeAndWrite = async (finalCid, overrideOutputPath) => {
|
|
265203
|
+
clearInterval(timer4);
|
|
265204
|
+
captureSample();
|
|
265205
|
+
const finishedAtMs = Date.now();
|
|
265206
|
+
const finishedAtIso = new Date(finishedAtMs).toISOString();
|
|
265207
|
+
const totalUploadTimeMs = Math.max(1, finishedAtMs - startedAtMs);
|
|
265208
|
+
const throughputBytesPerSecond = options2.sourceSizeBytes / totalUploadTimeMs * 1000;
|
|
265209
|
+
const peakHeapUsed = Math.max(...samples.map((sample) => sample.heapUsed));
|
|
265210
|
+
const peakRss = Math.max(...samples.map((sample) => sample.rss));
|
|
265211
|
+
const peakArrayBuffers = Math.max(...samples.map((sample) => sample.arrayBuffers));
|
|
265212
|
+
const peakExternal = Math.max(...samples.map((sample) => sample.external));
|
|
265213
|
+
const maxWindowReached = Math.max(...samples.map((sample) => sample.window));
|
|
265214
|
+
const report = {
|
|
265215
|
+
meta: {
|
|
265216
|
+
sourcePath: options2.sourcePath,
|
|
265217
|
+
sourceSizeBytes: options2.sourceSizeBytes,
|
|
265218
|
+
chunkSizeBytes: options2.chunkSizeBytes,
|
|
265219
|
+
rpc: options2.rpc,
|
|
265220
|
+
startedAtIso,
|
|
265221
|
+
finishedAtIso,
|
|
265222
|
+
heapLimitBytes: v8.getHeapStatistics().heap_size_limit,
|
|
265223
|
+
initialConcurrency: options2.initialConcurrency,
|
|
265224
|
+
maxConcurrency: options2.maxConcurrency
|
|
265225
|
+
},
|
|
265226
|
+
samples,
|
|
265227
|
+
waves,
|
|
265228
|
+
summary: {
|
|
265229
|
+
totalUploadTimeMs,
|
|
265230
|
+
totalUploadTimeSeconds: totalUploadTimeMs / 1000,
|
|
265231
|
+
elapsedMs: totalUploadTimeMs,
|
|
265232
|
+
throughputBytesPerSecond,
|
|
265233
|
+
peakHeapUsed,
|
|
265234
|
+
peakRss,
|
|
265235
|
+
peakArrayBuffers,
|
|
265236
|
+
peakExternal,
|
|
265237
|
+
retryCount: latestSchedulerState.retries,
|
|
265238
|
+
maxWindowReached,
|
|
265239
|
+
finalCid
|
|
265240
|
+
}
|
|
265238
265241
|
};
|
|
265239
|
-
|
|
265240
|
-
|
|
265241
|
-
|
|
265242
|
-
|
|
265243
|
-
|
|
265244
|
-
|
|
265245
|
-
console.log(source_default.gray(" isReserved: ") + source_default.white(String(reservation.isReserved)));
|
|
265246
|
-
console.log(source_default.gray(" owner: ") + source_default.white(reservation.reservedBy));
|
|
265247
|
-
if (reservation.expires) {
|
|
265248
|
-
console.log(source_default.gray(" expires: ") + source_default.white(reservation.expires));
|
|
265249
|
-
}
|
|
265250
|
-
console.log();
|
|
265251
|
-
}
|
|
265252
|
-
async function performOwnerOfLookup(name10, substrateAddress, clientWrapper) {
|
|
265253
|
-
if (!name10 || name10.trim().length === 0) {
|
|
265254
|
-
throw new Error("--owner-of requires a <label>");
|
|
265255
|
-
}
|
|
265256
|
-
const label = name10.trim();
|
|
265257
|
-
console.log(source_default.bold(`
|
|
265258
|
-
\uD83D\uDD0E Ownership lookup
|
|
265259
|
-
`));
|
|
265260
|
-
console.log(source_default.gray(" Label: ") + source_default.cyan(label));
|
|
265261
|
-
console.log(source_default.gray(" Domain: ") + source_default.cyan(label + ".dot"));
|
|
265262
|
-
const tokenId = computeDomainTokenId(label);
|
|
265263
|
-
let actualOwner;
|
|
265264
|
-
let isRegistered;
|
|
265265
|
-
try {
|
|
265266
|
-
actualOwner = await withTimeout(performContractCall(clientWrapper, substrateAddress, CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 30000, "ownerOf");
|
|
265267
|
-
isRegistered = actualOwner !== zeroAddress;
|
|
265268
|
-
} catch (error2) {
|
|
265269
|
-
const errorMessage = formatErrorMessage(error2);
|
|
265270
|
-
if (errorMessage.includes("Contract reverted") || errorMessage.includes("does not exist")) {
|
|
265271
|
-
actualOwner = zeroAddress;
|
|
265272
|
-
isRegistered = false;
|
|
265273
|
-
} else {
|
|
265274
|
-
throw error2;
|
|
265275
|
-
}
|
|
265276
|
-
}
|
|
265277
|
-
const ownerSubstrateAddress = isRegistered ? await clientWrapper.getSubstrateAddress(actualOwner) : "(none)";
|
|
265278
|
-
console.log(source_default.gray(`
|
|
265279
|
-
Registered: `) + source_default.white(String(isRegistered)));
|
|
265280
|
-
console.log(source_default.gray(" Owner (EVM): ") + source_default.white(isRegistered ? actualOwner : "(none)"));
|
|
265281
|
-
console.log(source_default.gray(" Owner (Substrate): ") + source_default.white(ownerSubstrateAddress));
|
|
265242
|
+
const outputPath = overrideOutputPath ?? options2.outputPath ?? buildDefaultProfileOutputPath(options2.sourcePath, createProfileFingerprint(`${options2.sourcePath}:${options2.sourceSizeBytes}:${options2.chunkSizeBytes}:${startedAtIso}`));
|
|
265243
|
+
const resolvedOutputPath = path9.resolve(outputPath);
|
|
265244
|
+
await filesystem2.mkdir(path9.dirname(resolvedOutputPath), { recursive: true });
|
|
265245
|
+
await filesystem2.writeFile(resolvedOutputPath, JSON.stringify(report, null, 2), "utf8");
|
|
265246
|
+
return { report, outputPath: resolvedOutputPath };
|
|
265247
|
+
};
|
|
265282
265248
|
return {
|
|
265283
|
-
|
|
265284
|
-
|
|
265285
|
-
|
|
265286
|
-
|
|
265287
|
-
|
|
265249
|
+
onSchedulerState: (state3) => {
|
|
265250
|
+
latestSchedulerState = state3;
|
|
265251
|
+
captureSample();
|
|
265252
|
+
},
|
|
265253
|
+
onWave: (wave) => {
|
|
265254
|
+
waves.push(wave);
|
|
265255
|
+
captureSample();
|
|
265256
|
+
},
|
|
265257
|
+
finalize: summarizeAndWrite
|
|
265288
265258
|
};
|
|
265289
265259
|
}
|
|
265290
|
-
|
|
265291
|
-
|
|
265292
|
-
|
|
265293
|
-
init_ora();
|
|
265294
|
-
init__esm();
|
|
265295
|
-
init_formatting();
|
|
265296
|
-
import crypto16 from "crypto";
|
|
265297
|
-
|
|
265298
|
-
// src/types/types.ts
|
|
265299
|
-
var ProofOfPersonhoodStatus;
|
|
265300
|
-
((ProofOfPersonhoodStatus2) => {
|
|
265301
|
-
ProofOfPersonhoodStatus2[ProofOfPersonhoodStatus2["NoStatus"] = 0] = "NoStatus";
|
|
265302
|
-
ProofOfPersonhoodStatus2[ProofOfPersonhoodStatus2["ProofOfPersonhoodLite"] = 1] = "ProofOfPersonhoodLite";
|
|
265303
|
-
ProofOfPersonhoodStatus2[ProofOfPersonhoodStatus2["ProofOfPersonhoodFull"] = 2] = "ProofOfPersonhoodFull";
|
|
265304
|
-
ProofOfPersonhoodStatus2[ProofOfPersonhoodStatus2["Reserved"] = 3] = "Reserved";
|
|
265305
|
-
})(ProofOfPersonhoodStatus ||= {});
|
|
265306
|
-
|
|
265307
|
-
// src/commands/register.ts
|
|
265308
|
-
init_constants();
|
|
265309
|
-
init_contractInteractions();
|
|
265310
|
-
init_formatting();
|
|
265311
|
-
function redactSecret(secret) {
|
|
265312
|
-
if (secret.length <= 10)
|
|
265313
|
-
return "0x" + "*".repeat(secret.length - 2);
|
|
265314
|
-
const prefix = secret.slice(0, 6);
|
|
265315
|
-
const suffix = secret.slice(-4);
|
|
265316
|
-
const redacted = "*".repeat(secret.length - 10);
|
|
265317
|
-
return `${prefix}${redacted}${suffix}`;
|
|
265318
|
-
}
|
|
265319
|
-
function convertToProofOfPersonhoodStatus(value3) {
|
|
265320
|
-
if (typeof value3 === "number")
|
|
265321
|
-
return value3;
|
|
265322
|
-
if (typeof value3 === "bigint")
|
|
265323
|
-
return Number(value3);
|
|
265324
|
-
throw new Error(`Unexpected ProofOfPersonhoodStatus type: ${typeof value3}`);
|
|
265325
|
-
}
|
|
265326
|
-
async function classifyDomainName(clientWrapper, originSubstrateAddress, label) {
|
|
265327
|
-
const spinner = ora("Classifying name via PopRules").start();
|
|
265328
|
-
try {
|
|
265329
|
-
const classificationResult = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "classifyName", [label]), 30000, "classifyName");
|
|
265330
|
-
const requiredStatus = convertToProofOfPersonhoodStatus(classificationResult[0]);
|
|
265331
|
-
const message2 = classificationResult[1];
|
|
265332
|
-
spinner.succeed("Name classification");
|
|
265333
|
-
console.log(source_default.gray(" required: ") + source_default.white(ProofOfPersonhoodStatus[requiredStatus]));
|
|
265334
|
-
console.log(source_default.gray(" message: ") + source_default.white(message2));
|
|
265335
|
-
return { requiredStatus, message: message2 };
|
|
265336
|
-
} catch (error2) {
|
|
265337
|
-
spinner.fail("Name classification failed");
|
|
265338
|
-
throw error2;
|
|
265260
|
+
async function withBulletinHumanOutput(reporterMode, callback) {
|
|
265261
|
+
if (reporterMode === "quiet") {
|
|
265262
|
+
return withCapturedConsole(callback);
|
|
265339
265263
|
}
|
|
265264
|
+
return withConsoleToStderr(callback);
|
|
265340
265265
|
}
|
|
265341
|
-
async function
|
|
265342
|
-
|
|
265343
|
-
|
|
265344
|
-
|
|
265345
|
-
|
|
265346
|
-
if (owner !== zeroAddress) {
|
|
265347
|
-
spinner.fail(`Name ${source_default.cyan(label + ".dot")} already owned by ${source_default.yellow(owner)}`);
|
|
265348
|
-
throw new Error(`Domain already owned by ${owner}`);
|
|
265349
|
-
}
|
|
265350
|
-
} catch (error2) {
|
|
265351
|
-
const errorMessage = formatErrorMessage(error2);
|
|
265352
|
-
if (errorMessage.includes("already owned"))
|
|
265353
|
-
throw error2;
|
|
265354
|
-
}
|
|
265355
|
-
spinner.succeed(`Name ${source_default.cyan(label + ".dot")} is available`);
|
|
265266
|
+
async function resolveTargetAddress(positionalAddress, mergedOptions, reporterMode) {
|
|
265267
|
+
if (positionalAddress)
|
|
265268
|
+
return positionalAddress;
|
|
265269
|
+
const context = await withBulletinHumanOutput(reporterMode, () => prepareContext({ ...mergedOptions, useBulletin: true }));
|
|
265270
|
+
return context.substrateAddress;
|
|
265356
265271
|
}
|
|
265357
|
-
|
|
265358
|
-
|
|
265359
|
-
|
|
265360
|
-
validateDomainLabel(label);
|
|
265361
|
-
const secret = `0x${crypto16.randomBytes(32).toString("hex")}`;
|
|
265362
|
-
const registration = {
|
|
265363
|
-
label,
|
|
265364
|
-
owner: ownerAddress,
|
|
265365
|
-
secret,
|
|
265366
|
-
reserved: includeReverse
|
|
265367
|
-
};
|
|
265368
|
-
const commitment = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, DOTNS_REGISTRAR_CONTROLLER_ABI, "makeCommitment", [registration]), 30000, "Commitment generation");
|
|
265369
|
-
spinner.succeed("Commitment hash generated");
|
|
265370
|
-
console.log(source_default.gray(" commitment: ") + source_default.blue(commitment));
|
|
265371
|
-
console.log(source_default.gray(" hash: ") + source_default.dim("label + owner + secret + reserved"));
|
|
265372
|
-
console.log(source_default.gray(" secret: ") + source_default.yellow(redactSecret(secret)));
|
|
265373
|
-
console.log(source_default.gray(" reserved: ") + (includeReverse ? source_default.green("true") : source_default.white("false")));
|
|
265374
|
-
return { commitment, registration };
|
|
265375
|
-
} catch (error2) {
|
|
265376
|
-
spinner.fail("Failed to create commitment");
|
|
265377
|
-
throw error2;
|
|
265378
|
-
}
|
|
265272
|
+
function writeBulletinJson(payload) {
|
|
265273
|
+
process.stdout.write(`${JSON.stringify(payload)}
|
|
265274
|
+
`);
|
|
265379
265275
|
}
|
|
265380
|
-
|
|
265381
|
-
|
|
265382
|
-
|
|
265383
|
-
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
265384
|
-
console.log(source_default.gray(" committed: ") + source_default.white(new Date().toISOString()));
|
|
265276
|
+
function writeBulletinJsonError(error2) {
|
|
265277
|
+
writeBulletinJson({ error: formatErrorMessage(error2) });
|
|
265278
|
+
process.exit(1);
|
|
265385
265279
|
}
|
|
265386
|
-
|
|
265387
|
-
const
|
|
265388
|
-
|
|
265389
|
-
|
|
265390
|
-
|
|
265391
|
-
|
|
265392
|
-
|
|
265393
|
-
|
|
265394
|
-
const initialCommitTime = typeof initialCommitTimestamp === "bigint" ? Number(initialCommitTimestamp) : initialCommitTimestamp;
|
|
265395
|
-
if (initialCommitTime === 0) {
|
|
265396
|
-
checkSpinner.fail("Commitment not found on-chain");
|
|
265397
|
-
throw new Error("Commitment not found on-chain. It may not have been included in a block yet.");
|
|
265398
|
-
}
|
|
265399
|
-
const waitSeconds = minimumAgeSeconds + buffer2;
|
|
265400
|
-
checkSpinner.succeed(`Minimum commitment age: ${source_default.yellow(waitSeconds.toString() + "s")}`);
|
|
265401
|
-
const waitSpinner = ora(`Waiting for commitment age (${waitSeconds}s)`).start();
|
|
265402
|
-
let elapsedSeconds = 0;
|
|
265403
|
-
const intervalId = setInterval(() => {
|
|
265404
|
-
elapsedSeconds++;
|
|
265405
|
-
const remainingSeconds = waitSeconds - elapsedSeconds;
|
|
265406
|
-
waitSpinner.text = `Waiting for commitment age (${source_default.yellow(remainingSeconds + "s")} remaining)`;
|
|
265407
|
-
}, 1000);
|
|
265408
|
-
await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1000));
|
|
265409
|
-
clearInterval(intervalId);
|
|
265410
|
-
waitSpinner.text = "Verifying commitment age on-chain";
|
|
265411
|
-
const pollDeadline = Date.now() + COMMITMENT_POLL_TIMEOUT_MS;
|
|
265412
|
-
while (Date.now() < pollDeadline) {
|
|
265413
|
-
const polledTimestamp = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, DOTNS_REGISTRAR_CONTROLLER_ABI, "commitments", [commitment]);
|
|
265414
|
-
const polledCommitTime = typeof polledTimestamp === "bigint" ? Number(polledTimestamp) : polledTimestamp;
|
|
265415
|
-
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
265416
|
-
if (polledCommitTime > 0 && nowSeconds - polledCommitTime >= minimumAgeSeconds) {
|
|
265417
|
-
waitSpinner.succeed("Commitment age requirement met (verified on-chain)");
|
|
265280
|
+
function createPhaseHandler(reporter) {
|
|
265281
|
+
const tasks = new Map;
|
|
265282
|
+
return (event) => {
|
|
265283
|
+
const key = event.phase;
|
|
265284
|
+
const activeTask = tasks.get(key);
|
|
265285
|
+
if (event.state === "start") {
|
|
265286
|
+
activeTask?.stop();
|
|
265287
|
+
tasks.set(key, reporter.task(event.message));
|
|
265418
265288
|
return;
|
|
265419
265289
|
}
|
|
265420
|
-
|
|
265421
|
-
|
|
265422
|
-
|
|
265423
|
-
|
|
265424
|
-
|
|
265425
|
-
}
|
|
265426
|
-
async function getUserProofOfPersonhoodStatus(clientWrapper, originSubstrateAddress, ownerAddress) {
|
|
265427
|
-
const userStatusRaw = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "userPopStatus", [ownerAddress]), 30000, "userPopStatus");
|
|
265428
|
-
return convertToProofOfPersonhoodStatus(userStatusRaw);
|
|
265429
|
-
}
|
|
265430
|
-
async function getPriceAndValidateEligibility(clientWrapper, originSubstrateAddress, label, ownerAddress) {
|
|
265431
|
-
const spinner = ora("Pricing via PopRules.price").start();
|
|
265432
|
-
try {
|
|
265433
|
-
validateDomainLabel(label);
|
|
265434
|
-
const baseName = stripTrailingDigits(label);
|
|
265435
|
-
const reservationInfo = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "isBaseNameReserved", [baseName]), 30000, "isBaseNameReserved");
|
|
265436
|
-
const [isReserved, reservationOwner] = reservationInfo;
|
|
265437
|
-
if (isReserved && checksumAddress(reservationOwner) !== checksumAddress(ownerAddress)) {
|
|
265438
|
-
spinner.fail("Eligibility failed");
|
|
265439
|
-
throw new Error("Base name reserved for original Lite registrant");
|
|
265440
|
-
}
|
|
265441
|
-
const classificationResult = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "priceWithoutCheck", [label, ownerAddress]), 30000, "priceWithoutCheck");
|
|
265442
|
-
const requiredStatus = convertToProofOfPersonhoodStatus(classificationResult.status);
|
|
265443
|
-
const message2 = classificationResult.message;
|
|
265444
|
-
const userStatus = await getUserProofOfPersonhoodStatus(clientWrapper, originSubstrateAddress, ownerAddress);
|
|
265445
|
-
if (requiredStatus === 3 /* Reserved */) {
|
|
265446
|
-
spinner.fail("Eligibility failed");
|
|
265447
|
-
throw new Error(message2);
|
|
265448
|
-
}
|
|
265449
|
-
if (requiredStatus === 2 /* ProofOfPersonhoodFull */) {
|
|
265450
|
-
if (userStatus !== 2 /* ProofOfPersonhoodFull */) {
|
|
265451
|
-
spinner.fail("Eligibility failed");
|
|
265452
|
-
throw new Error("Requires Full Personhood verification");
|
|
265290
|
+
if (event.state === "update") {
|
|
265291
|
+
if (activeTask) {
|
|
265292
|
+
activeTask.update(event.message);
|
|
265293
|
+
} else {
|
|
265294
|
+
tasks.set(key, reporter.task(event.message));
|
|
265453
265295
|
}
|
|
265454
|
-
|
|
265455
|
-
|
|
265456
|
-
|
|
265457
|
-
|
|
265296
|
+
return;
|
|
265297
|
+
}
|
|
265298
|
+
if (event.state === "success") {
|
|
265299
|
+
if (activeTask) {
|
|
265300
|
+
activeTask.succeed(event.message);
|
|
265301
|
+
tasks.delete(key);
|
|
265302
|
+
} else {
|
|
265303
|
+
reporter.success(event.message);
|
|
265458
265304
|
}
|
|
265459
|
-
|
|
265460
|
-
|
|
265461
|
-
|
|
265462
|
-
|
|
265463
|
-
|
|
265464
|
-
|
|
265305
|
+
return;
|
|
265306
|
+
}
|
|
265307
|
+
if (event.state === "warning") {
|
|
265308
|
+
if (activeTask) {
|
|
265309
|
+
activeTask.warn(event.message);
|
|
265310
|
+
tasks.delete(key);
|
|
265311
|
+
} else {
|
|
265312
|
+
reporter.warn(event.message);
|
|
265465
265313
|
}
|
|
265314
|
+
return;
|
|
265466
265315
|
}
|
|
265467
|
-
|
|
265468
|
-
|
|
265469
|
-
|
|
265470
|
-
|
|
265471
|
-
console.log(source_default.gray(" price: ") + source_default.green(`${classificationResult.priceWei > 0n ? formatWeiAsEther(classificationResult.priceWei) : 0n} PAS`));
|
|
265472
|
-
return {
|
|
265473
|
-
priceWei: classificationResult.price ?? classificationResult.priceWei,
|
|
265474
|
-
requiredStatus,
|
|
265475
|
-
userStatus,
|
|
265476
|
-
message: message2,
|
|
265477
|
-
status: requiredStatus,
|
|
265478
|
-
price: classificationResult.price ?? classificationResult.priceWei
|
|
265479
|
-
};
|
|
265480
|
-
} catch (error2) {
|
|
265481
|
-
if (!spinner.isSpinning)
|
|
265482
|
-
throw error2;
|
|
265483
|
-
spinner.fail("Pricing failed");
|
|
265484
|
-
throw error2;
|
|
265485
|
-
}
|
|
265486
|
-
}
|
|
265487
|
-
async function finalizeRegularRegistration(clientWrapper, substrateAddress, signer, registration, priceWei) {
|
|
265488
|
-
const spinner = ora(`Registering ${source_default.cyan(registration.label + ".dot")}`).start();
|
|
265489
|
-
try {
|
|
265490
|
-
const bufferedPaymentWei = priceWei * 110n / 100n;
|
|
265491
|
-
const bufferedPaymentNative = convertWeiToNative(bufferedPaymentWei);
|
|
265492
|
-
console.log(source_default.gray(" oracle: ") + source_default.green(formatWeiAsEther(priceWei) + " PAS"));
|
|
265493
|
-
console.log(source_default.gray(" paying: ") + source_default.green(formatWeiAsEther(bufferedPaymentWei) + " PAS"));
|
|
265494
|
-
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, bufferedPaymentNative, DOTNS_REGISTRAR_CONTROLLER_ABI, "register", [registration], substrateAddress, signer, spinner, "Registration");
|
|
265495
|
-
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
265496
|
-
console.log(source_default.gray(" paid: ") + source_default.green(formatWeiAsEther(bufferedPaymentWei) + " PAS"));
|
|
265497
|
-
} catch (error2) {
|
|
265498
|
-
spinner.fail("Registration failed");
|
|
265499
|
-
throw error2;
|
|
265500
|
-
}
|
|
265501
|
-
}
|
|
265502
|
-
async function finalizeGovernanceRegistration(clientWrapper, substrateAddress, signer, registration) {
|
|
265503
|
-
const spinner = ora(`Registering governance name ${source_default.cyan(registration.label + ".dot")}`).start();
|
|
265504
|
-
try {
|
|
265505
|
-
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, 0n, DOTNS_REGISTRAR_CONTROLLER_ABI, "registerReserved", [registration], substrateAddress, signer, spinner, "Governance Registration");
|
|
265506
|
-
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
265507
|
-
} catch (error2) {
|
|
265508
|
-
spinner.fail("Governance registration failed");
|
|
265509
|
-
throw error2;
|
|
265510
|
-
}
|
|
265511
|
-
}
|
|
265512
|
-
async function registerSubnode(clientWrapper, substrateAddress, signer, sublabel, parentLabel, ownerAddress) {
|
|
265513
|
-
const fullName = `${sublabel}.${parentLabel}.dot`;
|
|
265514
|
-
const spinner = ora(`Registering subname ${source_default.cyan(fullName)}`).start();
|
|
265515
|
-
try {
|
|
265516
|
-
const parentNode = namehash(`${parentLabel}.dot`);
|
|
265517
|
-
const subnodeRecord = {
|
|
265518
|
-
parentNode,
|
|
265519
|
-
subLabel: sublabel,
|
|
265520
|
-
parentLabel,
|
|
265521
|
-
owner: ownerAddress
|
|
265522
|
-
};
|
|
265523
|
-
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRY, 0n, DOTNS_REGISTRY_ABI, "setSubnodeOwner", [subnodeRecord], substrateAddress, signer, spinner, "Subname registration");
|
|
265524
|
-
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
265525
|
-
return transactionHash;
|
|
265526
|
-
} catch (error2) {
|
|
265527
|
-
spinner.fail("Subname registration failed");
|
|
265528
|
-
throw error2;
|
|
265529
|
-
}
|
|
265530
|
-
}
|
|
265531
|
-
async function verifyDomainOwnership(clientWrapper, originSubstrateAddress, label, expectedOwner) {
|
|
265532
|
-
const spinner = ora("Verifying minted ownership").start();
|
|
265533
|
-
try {
|
|
265534
|
-
const tokenId = computeDomainTokenId(label);
|
|
265535
|
-
const actualOwner = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 30000, "ownerOf");
|
|
265536
|
-
if (checksumAddress(actualOwner) !== checksumAddress(expectedOwner)) {
|
|
265537
|
-
spinner.fail("Ownership verification failed");
|
|
265538
|
-
console.log(source_default.gray(" expected: ") + source_default.white(expectedOwner));
|
|
265539
|
-
console.log(source_default.gray(" actual: ") + source_default.white(actualOwner));
|
|
265540
|
-
throw new Error(`Owner mismatch for ${label}.dot`);
|
|
265316
|
+
if (activeTask) {
|
|
265317
|
+
activeTask.fail(event.message);
|
|
265318
|
+
tasks.delete(key);
|
|
265319
|
+
return;
|
|
265541
265320
|
}
|
|
265542
|
-
|
|
265543
|
-
|
|
265544
|
-
return actualOwner;
|
|
265545
|
-
} catch (error2) {
|
|
265546
|
-
spinner.fail("Ownership verification failed");
|
|
265547
|
-
throw error2;
|
|
265548
|
-
}
|
|
265549
|
-
}
|
|
265550
|
-
async function displayDeployedStore(clientWrapper, originSubstrateAddress, ownerAddress) {
|
|
265551
|
-
const spinner = ora("Reading deployed Store address").start();
|
|
265552
|
-
try {
|
|
265553
|
-
const storeAddress = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.STORE_FACTORY, STORE_FACTORY_ABI, "getDeployedStore", [ownerAddress]), 30000, "getDeployedStore");
|
|
265554
|
-
spinner.succeed("Store");
|
|
265555
|
-
console.log(source_default.gray(" store: ") + (storeAddress === zeroAddress ? source_default.yellow("not deployed") : source_default.cyan(storeAddress)));
|
|
265556
|
-
} catch (error2) {
|
|
265557
|
-
spinner.fail("Failed to read Store address");
|
|
265558
|
-
throw error2;
|
|
265559
|
-
}
|
|
265321
|
+
reporter.fail(event.message);
|
|
265322
|
+
};
|
|
265560
265323
|
}
|
|
265561
|
-
|
|
265562
|
-
|
|
265563
|
-
|
|
265564
|
-
|
|
265565
|
-
|
|
265566
|
-
const [controllerAuthorized, registryAuthorized] = await Promise.all([
|
|
265567
|
-
Boolean(await performContractCall(clientWrapper, substrateAddress, storeAddress, STORE_ABI, "isAuthorized", [CONTRACTS.DOTNS_REGISTRAR_CONTROLLER])),
|
|
265568
|
-
Boolean(await performContractCall(clientWrapper, substrateAddress, storeAddress, STORE_ABI, "isAuthorized", [CONTRACTS.DOTNS_REGISTRY]))
|
|
265569
|
-
]);
|
|
265570
|
-
if (controllerAuthorized && registryAuthorized) {
|
|
265571
|
-
spinner.succeed("Store authorizations verified");
|
|
265572
|
-
console.log(source_default.gray(" controller: ") + source_default.white(CONTRACTS.DOTNS_REGISTRAR_CONTROLLER));
|
|
265573
|
-
console.log(source_default.gray(" registry: ") + source_default.white(CONTRACTS.DOTNS_REGISTRY));
|
|
265574
|
-
return;
|
|
265575
|
-
}
|
|
265576
|
-
spinner.warn("Store authorizations need update");
|
|
265577
|
-
if (!controllerAuthorized) {
|
|
265578
|
-
const controllerSpinner = ora("Authorizing registrar controller as Store writer").start();
|
|
265579
|
-
const tx = await submitContractTransaction(clientWrapper, storeAddress, 0n, STORE_ABI, "authorizeStore", [CONTRACTS.DOTNS_REGISTRAR_CONTROLLER], substrateAddress, signer, controllerSpinner, "Authorize controller");
|
|
265580
|
-
console.log(source_default.gray(" tx: ") + source_default.blue(tx));
|
|
265581
|
-
console.log(source_default.gray(" controller: ") + source_default.white(CONTRACTS.DOTNS_REGISTRAR_CONTROLLER));
|
|
265582
|
-
}
|
|
265583
|
-
if (!registryAuthorized) {
|
|
265584
|
-
const registrySpinner = ora("Authorizing registry as Store writer").start();
|
|
265585
|
-
const tx = await submitContractTransaction(clientWrapper, storeAddress, 0n, STORE_ABI, "authorizeStore", [CONTRACTS.DOTNS_REGISTRY], substrateAddress, signer, registrySpinner, "Authorize registry");
|
|
265586
|
-
console.log(source_default.gray(" tx: ") + source_default.blue(tx));
|
|
265587
|
-
console.log(source_default.gray(" registry: ") + source_default.white(CONTRACTS.DOTNS_REGISTRY));
|
|
265588
|
-
}
|
|
265324
|
+
function createRetryHandler(reporter) {
|
|
265325
|
+
return ({ label, retry, totalAttempts, delayMs, errorMessage }) => {
|
|
265326
|
+
reporter.warn(`${label} attempt ${retry + 1}/${totalAttempts} failed: ${errorMessage}`);
|
|
265327
|
+
reporter.detail(`retrying in ${(delayMs / 1000).toFixed(delayMs >= 1000 ? 1 : 0)}s`);
|
|
265328
|
+
};
|
|
265589
265329
|
}
|
|
265590
|
-
|
|
265591
|
-
const
|
|
265592
|
-
|
|
265593
|
-
|
|
265594
|
-
|
|
265595
|
-
|
|
265596
|
-
|
|
265597
|
-
|
|
265598
|
-
|
|
265599
|
-
|
|
265330
|
+
function createChunkedUploadMonitor(reporter, phaseHandler, fileSize, chunkSizeBytes, totalChunks) {
|
|
265331
|
+
const heartbeatIntervalMs = 15000;
|
|
265332
|
+
let latestState = null;
|
|
265333
|
+
let heartbeatTimer;
|
|
265334
|
+
const startedAtMs = Date.now();
|
|
265335
|
+
const stopHeartbeat = () => {
|
|
265336
|
+
if (heartbeatTimer) {
|
|
265337
|
+
clearInterval(heartbeatTimer);
|
|
265338
|
+
heartbeatTimer = undefined;
|
|
265339
|
+
}
|
|
265340
|
+
};
|
|
265341
|
+
const emitHeartbeat = () => {
|
|
265342
|
+
if (!latestState || latestState.inFlightChunks === 0) {
|
|
265343
|
+
stopHeartbeat();
|
|
265600
265344
|
return;
|
|
265601
265345
|
}
|
|
265602
|
-
|
|
265603
|
-
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_RULES, 0n, POP_RULES_ABI, "setUserPopStatus", [status], substrateAddress, signer, updateSpinner, "PoP status update");
|
|
265604
|
-
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
265605
|
-
} catch (error2) {
|
|
265606
|
-
if (checkSpinner.isSpinning)
|
|
265607
|
-
checkSpinner.fail("Failed to check PoP status");
|
|
265608
|
-
throw error2;
|
|
265609
|
-
}
|
|
265610
|
-
}
|
|
265611
|
-
|
|
265612
|
-
// src/cli/commands/lookup.ts
|
|
265613
|
-
init_env();
|
|
265614
|
-
init_formatting();
|
|
265615
|
-
|
|
265616
|
-
// src/cli/transfer.ts
|
|
265617
|
-
init_source();
|
|
265618
|
-
init_ora();
|
|
265619
|
-
init__esm();
|
|
265620
|
-
init_constants();
|
|
265621
|
-
init_formatting();
|
|
265622
|
-
init_contractInteractions();
|
|
265623
|
-
function toChecksummed(a2) {
|
|
265624
|
-
return checksumAddress(a2);
|
|
265625
|
-
}
|
|
265626
|
-
function isLabelLike(input) {
|
|
265627
|
-
return /^[a-z0-9-]{3,}$/.test(input);
|
|
265628
|
-
}
|
|
265629
|
-
function asDotLabel(input) {
|
|
265630
|
-
const raw = input.trim().toLowerCase();
|
|
265631
|
-
if (raw.endsWith(".dot"))
|
|
265632
|
-
return raw.slice(0, -4);
|
|
265633
|
-
return raw;
|
|
265634
|
-
}
|
|
265635
|
-
async function ownerOfLabel(clientWrapper, originSubstrateAddress, label) {
|
|
265636
|
-
const tokenId = computeDomainTokenId(label);
|
|
265637
|
-
return await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]);
|
|
265638
|
-
}
|
|
265639
|
-
async function resolveTransferRecipient(clientWrapper, originSubstrateAddress, recipientIdentifier) {
|
|
265640
|
-
const input = recipientIdentifier.trim();
|
|
265641
|
-
if (isAddress(input))
|
|
265642
|
-
return toChecksummed(input);
|
|
265643
|
-
const label = asDotLabel(input);
|
|
265644
|
-
if (isLabelLike(label)) {
|
|
265645
|
-
const spinner2 = ora(`Resolving ${source_default.cyan(label + ".dot")} to owner address`).start();
|
|
265646
|
-
const ownerAddress = await ownerOfLabel(clientWrapper, originSubstrateAddress, label);
|
|
265647
|
-
if (ownerAddress === zeroAddress) {
|
|
265648
|
-
spinner2.fail(`No owner found for ${source_default.cyan(label + ".dot")} (unregistered)`);
|
|
265649
|
-
throw new Error(`Domain ${label}.dot has no owner`);
|
|
265650
|
-
}
|
|
265651
|
-
spinner2.succeed(`${source_default.cyan(label + ".dot")} → ${source_default.white(toChecksummed(ownerAddress))}`);
|
|
265652
|
-
return toChecksummed(ownerAddress);
|
|
265653
|
-
}
|
|
265654
|
-
const spinner = ora(`Resolving recipient address`).start();
|
|
265655
|
-
const evmAddress = await clientWrapper.getEvmAddress(input);
|
|
265656
|
-
spinner.succeed(`${source_default.white(input)} → ${source_default.white(toChecksummed(evmAddress))}`);
|
|
265657
|
-
return toChecksummed(evmAddress);
|
|
265658
|
-
}
|
|
265659
|
-
async function transferDomain(clientWrapper, originSubstrateAddress, signer, fromAddress, toAddress, label) {
|
|
265660
|
-
const spinner = ora().start();
|
|
265661
|
-
const normLabel = asDotLabel(label);
|
|
265662
|
-
spinner.text = `Validating ${source_default.cyan(normLabel + ".dot")}`;
|
|
265663
|
-
validateDomainLabel(normLabel);
|
|
265664
|
-
spinner.succeed(`Valid: ${source_default.cyan(normLabel + ".dot")}`);
|
|
265665
|
-
spinner.start(`Checking owner of ${source_default.cyan(normLabel + ".dot")}`);
|
|
265666
|
-
const tokenId = computeDomainTokenId(normLabel);
|
|
265667
|
-
const currentOwner = await ownerOfLabel(clientWrapper, originSubstrateAddress, normLabel);
|
|
265668
|
-
const currentOwnerC = toChecksummed(currentOwner);
|
|
265669
|
-
spinner.succeed(`Owner: ${source_default.cyan(normLabel + ".dot")} → ${source_default.white(currentOwnerC)}`);
|
|
265670
|
-
const fromC = toChecksummed(fromAddress);
|
|
265671
|
-
const toC = toChecksummed(toAddress);
|
|
265672
|
-
if (currentOwner === zeroAddress) {
|
|
265673
|
-
spinner.fail(`${source_default.cyan(normLabel + ".dot")} is not registered`);
|
|
265674
|
-
throw new Error(`Cannot transfer: ${normLabel}.dot is not registered`);
|
|
265675
|
-
}
|
|
265676
|
-
if (currentOwnerC !== fromC) {
|
|
265677
|
-
spinner.fail(`Not authorized to transfer ${source_default.cyan(normLabel + ".dot")}`);
|
|
265678
|
-
console.log(source_default.gray(" expected owner: ") + source_default.white(fromC));
|
|
265679
|
-
console.log(source_default.gray(" on-chain owner: ") + source_default.white(currentOwnerC));
|
|
265680
|
-
throw new Error(`Cannot transfer: ${normLabel}.dot owned by ${currentOwnerC}`);
|
|
265681
|
-
}
|
|
265682
|
-
try {
|
|
265683
|
-
const syncSpinner = ora(`Syncing label ${source_default.cyan(normLabel)} with registrar`).start();
|
|
265684
|
-
await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRAR, 0n, DOTNS_REGISTRAR_ABI, "syncLabel", [tokenId, normLabel], originSubstrateAddress, signer, syncSpinner, "Label sync");
|
|
265685
|
-
syncSpinner.succeed("Label synced");
|
|
265686
|
-
} catch (error2) {
|
|
265687
|
-
const errorMessage = formatErrorMessage(error2);
|
|
265688
|
-
if (!errorMessage.includes("LabelAlreadySet")) {
|
|
265689
|
-
console.log(source_default.yellow(" Label sync skipped: " + errorMessage.split(`
|
|
265690
|
-
`)[0]));
|
|
265691
|
-
}
|
|
265692
|
-
}
|
|
265693
|
-
spinner.start(`Submitting transfer ${source_default.cyan(normLabel + ".dot")} → ${source_default.green(toC)}`);
|
|
265694
|
-
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRAR, 0n, DOTNS_REGISTRAR_ABI, "transferFrom", [fromC, toC, tokenId], originSubstrateAddress, signer, spinner, "Transfer");
|
|
265695
|
-
spinner.succeed(`Transfer finalized`);
|
|
265696
|
-
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
265697
|
-
console.log(source_default.gray(" from: ") + source_default.yellow(fromC));
|
|
265698
|
-
console.log(source_default.gray(" to: ") + source_default.green(toC));
|
|
265699
|
-
console.log(source_default.gray(" name: ") + source_default.cyan(normLabel + ".dot"));
|
|
265700
|
-
}
|
|
265701
|
-
|
|
265702
|
-
// src/cli/commands/register.ts
|
|
265703
|
-
init_source();
|
|
265704
|
-
init__esm();
|
|
265705
|
-
|
|
265706
|
-
// src/cli/labels.ts
|
|
265707
|
-
function generateRandomLabel(status) {
|
|
265708
|
-
const alphabet4 = "abcdefghijklmnopqrstuvwxyz";
|
|
265709
|
-
const alphanumeric = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
265710
|
-
const randomInteger = (maxExclusive) => Math.floor(Math.random() * maxExclusive);
|
|
265711
|
-
const randomCharacters = (characterSet, count2) => {
|
|
265712
|
-
let result = "";
|
|
265713
|
-
for (let i2 = 0;i2 < count2; i2++)
|
|
265714
|
-
result += characterSet[randomInteger(characterSet.length)];
|
|
265715
|
-
return result;
|
|
265346
|
+
reporter.detail(`heartbeat | ${latestState.completedChunks}/${totalChunks} chunks | window=${latestState.window} | in-flight=${latestState.inFlightChunks} | bytes=${formatBytes(latestState.inFlightBytes)} | retries=${latestState.retries} | elapsed=${formatDuration((Date.now() - startedAtMs) / 1000)}`);
|
|
265716
265347
|
};
|
|
265717
|
-
|
|
265718
|
-
|
|
265719
|
-
|
|
265720
|
-
|
|
265721
|
-
|
|
265722
|
-
|
|
265723
|
-
|
|
265348
|
+
return {
|
|
265349
|
+
onSchedulerState(state3) {
|
|
265350
|
+
latestState = state3;
|
|
265351
|
+
if (reporter.mode !== "stream") {
|
|
265352
|
+
return;
|
|
265353
|
+
}
|
|
265354
|
+
if (state3.inFlightChunks > 0 && !heartbeatTimer) {
|
|
265355
|
+
heartbeatTimer = setInterval(emitHeartbeat, heartbeatIntervalMs);
|
|
265356
|
+
heartbeatTimer.unref?.();
|
|
265357
|
+
} else if (state3.inFlightChunks === 0) {
|
|
265358
|
+
stopHeartbeat();
|
|
265359
|
+
}
|
|
265360
|
+
},
|
|
265361
|
+
onWave(wave) {
|
|
265362
|
+
const completedChunks = latestState?.completedChunks ?? 0;
|
|
265363
|
+
const bytesUploaded = Math.min(fileSize, completedChunks * chunkSizeBytes);
|
|
265364
|
+
const throughputBytesPerSecond = wave.durationMs > 0 ? wave.succeeded * chunkSizeBytes * 1000 / wave.durationMs : 0;
|
|
265365
|
+
const message2 = `wave #${wave.wave} complete | ${completedChunks}/${totalChunks} chunks | ${formatBytes(bytesUploaded)}/${formatBytes(fileSize)} | ${(wave.durationMs / 1000).toFixed(1)}s | window=${wave.window} | retries=${wave.retries} | ${formatBytes(throughputBytesPerSecond)}/s`;
|
|
265366
|
+
if (reporter.mode === "interactive") {
|
|
265367
|
+
phaseHandler({ phase: "upload", state: "update", message: message2 });
|
|
265368
|
+
} else {
|
|
265369
|
+
reporter.line(message2);
|
|
265370
|
+
}
|
|
265371
|
+
},
|
|
265372
|
+
stop() {
|
|
265373
|
+
stopHeartbeat();
|
|
265374
|
+
}
|
|
265724
265375
|
};
|
|
265725
|
-
if (status === 1 /* ProofOfPersonhoodLite */) {
|
|
265726
|
-
const baseLength = 6 + randomInteger(3);
|
|
265727
|
-
return baseEndingWithLetter(baseLength) + twoDigits();
|
|
265728
|
-
}
|
|
265729
|
-
if (status === 0 /* NoStatus */) {
|
|
265730
|
-
const baseLength = 9 + randomInteger(6);
|
|
265731
|
-
return baseEndingWithLetter(baseLength) + twoDigits();
|
|
265732
|
-
}
|
|
265733
|
-
if (status === 2 /* ProofOfPersonhoodFull */) {
|
|
265734
|
-
const baseLength = randomInteger(2) === 0 ? 6 + randomInteger(3) : 9 + randomInteger(6);
|
|
265735
|
-
return baseEndingWithLetter(baseLength);
|
|
265736
|
-
}
|
|
265737
|
-
throw new Error("Cannot auto-generate Reserved names");
|
|
265738
|
-
}
|
|
265739
|
-
function parseProofOfPersonhoodStatus(statusString) {
|
|
265740
|
-
const normalized = statusString.toLowerCase();
|
|
265741
|
-
if (normalized === "none" || normalized === "nostatus")
|
|
265742
|
-
return 0 /* NoStatus */;
|
|
265743
|
-
if (normalized === "lite" || normalized === "poplite")
|
|
265744
|
-
return 1 /* ProofOfPersonhoodLite */;
|
|
265745
|
-
if (normalized === "full" || normalized === "popfull")
|
|
265746
|
-
return 2 /* ProofOfPersonhoodFull */;
|
|
265747
|
-
throw new Error("Invalid status: use none, lite, or full");
|
|
265748
|
-
}
|
|
265749
|
-
|
|
265750
|
-
// src/cli/commands/register.ts
|
|
265751
|
-
function resolveTransferDestination(options2) {
|
|
265752
|
-
const legacy = options2.transferTo;
|
|
265753
|
-
const modern = options2.to;
|
|
265754
|
-
const destination = legacy ?? modern;
|
|
265755
|
-
if (options2.transfer === true && !destination) {
|
|
265756
|
-
throw new Error("Missing transfer destination: use --to <evm|ss58|label>");
|
|
265757
|
-
}
|
|
265758
|
-
if (options2.transfer === false && legacy) {
|
|
265759
|
-
return legacy;
|
|
265760
|
-
}
|
|
265761
|
-
return destination;
|
|
265762
|
-
}
|
|
265763
|
-
function classifyTransferDestination(destination) {
|
|
265764
|
-
if (isAddress(destination))
|
|
265765
|
-
return "evm";
|
|
265766
|
-
if (isValidSubstrateAddress(destination))
|
|
265767
|
-
return "substrate";
|
|
265768
|
-
return "label";
|
|
265769
|
-
}
|
|
265770
|
-
function isValidTransferDestination(destination) {
|
|
265771
|
-
const kind = classifyTransferDestination(destination);
|
|
265772
|
-
if (kind === "evm" || kind === "substrate")
|
|
265773
|
-
return true;
|
|
265774
|
-
const domainLabelPattern = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
265775
|
-
return domainLabelPattern.test(destination) && destination.length >= 3 && destination.length <= 63;
|
|
265776
|
-
}
|
|
265777
|
-
async function executeRegistration(options2 = {}) {
|
|
265778
|
-
if (options2.mnemonic && options2.keyUri) {
|
|
265779
|
-
throw new Error("Cannot specify both --mnemonic and --key-uri");
|
|
265780
|
-
}
|
|
265781
|
-
if (options2.parent) {
|
|
265782
|
-
return executeSubnameRegistration(options2);
|
|
265783
|
-
}
|
|
265784
|
-
const transferDestination = resolveTransferDestination(options2);
|
|
265785
|
-
if (transferDestination && !isValidTransferDestination(transferDestination)) {
|
|
265786
|
-
throw new Error("Invalid transfer destination: must be valid EVM address, Substrate address, or domain label");
|
|
265787
|
-
}
|
|
265788
|
-
const context = await prepareAssetHubContext(options2);
|
|
265789
|
-
const { clientWrapper, substrateAddress, signer, evmAddress } = context;
|
|
265790
|
-
const statusWasProvided = options2.__statusProvided === true;
|
|
265791
|
-
const popStatusConfig = statusWasProvided ? { mode: "set", status: parseProofOfPersonhoodStatus(options2.status ?? "none") } : { mode: "unchanged" };
|
|
265792
|
-
const label = options2.name ?? generateRandomLabel(popStatusConfig.mode === "set" ? popStatusConfig.status : 0 /* NoStatus */);
|
|
265793
|
-
console.log(source_default.gray(" Mode: ") + source_default.yellow(options2.governance ? "Governance registration" : "Regular registration"));
|
|
265794
|
-
console.log(source_default.gray(" Label: ") + source_default.cyan(label));
|
|
265795
|
-
console.log(source_default.gray(" Domain: ") + source_default.cyan(label + ".dot"));
|
|
265796
|
-
console.log(source_default.gray(" Transfer: ") + (transferDestination ? source_default.green("post-mint") : source_default.gray("none")));
|
|
265797
|
-
await step("Ensuring account mapped", async () => clientWrapper.ensureAccountMapped(substrateAddress, signer));
|
|
265798
|
-
if (options2.governance) {
|
|
265799
|
-
await executeGovernanceRegistration(clientWrapper, substrateAddress, signer, evmAddress, label, transferDestination, options2.commitmentBuffer);
|
|
265800
|
-
} else {
|
|
265801
|
-
await executeRegularRegistration(clientWrapper, substrateAddress, signer, evmAddress, label, popStatusConfig, options2.reverse ?? false, transferDestination, options2.commitmentBuffer);
|
|
265802
|
-
}
|
|
265803
|
-
console.log(`
|
|
265804
|
-
${source_default.bold.green("═══════════════════════════════════════")}`);
|
|
265805
|
-
console.log(`${source_default.bold.green(" ✓ Operation Complete ")}`);
|
|
265806
|
-
console.log(`${source_default.bold.green("═══════════════════════════════════════")}
|
|
265807
|
-
`);
|
|
265808
|
-
console.log(source_default.gray(" Domain: ") + source_default.cyan(label + ".dot"));
|
|
265809
265376
|
}
|
|
265810
|
-
|
|
265811
|
-
|
|
265812
|
-
|
|
265813
|
-
|
|
265814
|
-
|
|
265815
|
-
throw new Error("Missing parent: use --parent <parentlabel>");
|
|
265816
|
-
}
|
|
265817
|
-
const context = await prepareAssetHubContext(options2);
|
|
265818
|
-
const { clientWrapper, substrateAddress, signer, evmAddress } = context;
|
|
265819
|
-
const sublabel = options2.name;
|
|
265820
|
-
const parentLabel = options2.parent;
|
|
265821
|
-
const ownerAddress = options2.owner ?? evmAddress;
|
|
265822
|
-
const fullName = `${sublabel}.${parentLabel}.dot`;
|
|
265823
|
-
console.log(source_default.bold(`
|
|
265824
|
-
▶ Subname Registration
|
|
265825
|
-
`));
|
|
265826
|
-
console.log(source_default.gray(" Subname: ") + source_default.cyan(fullName));
|
|
265827
|
-
console.log(source_default.gray(" Parent: ") + source_default.white(`${parentLabel}.dot`));
|
|
265828
|
-
console.log(source_default.gray(" Owner: ") + source_default.white(ownerAddress));
|
|
265829
|
-
await step("Ensuring account mapped", async () => clientWrapper.ensureAccountMapped(substrateAddress, signer));
|
|
265830
|
-
await registerSubnode(clientWrapper, substrateAddress, signer, sublabel, parentLabel, ownerAddress);
|
|
265831
|
-
console.log(`
|
|
265832
|
-
${source_default.bold.green("═══════════════════════════════════════")}`);
|
|
265833
|
-
console.log(`${source_default.bold.green(" ✓ Subname Registered ")}`);
|
|
265834
|
-
console.log(`${source_default.bold.green("═══════════════════════════════════════")}
|
|
265835
|
-
`);
|
|
265836
|
-
console.log(source_default.gray(" Domain: ") + source_default.cyan(fullName));
|
|
265837
|
-
}
|
|
265838
|
-
async function executeGovernanceRegistration(clientWrapper, substrateAddress, signer, evmAddress, label, transferDestination, commitmentBuffer) {
|
|
265839
|
-
console.log(source_default.bold(`
|
|
265840
|
-
\uD83C\uDFDB Governance registration (commit-reveal)
|
|
265841
|
-
`));
|
|
265842
|
-
validateGovernanceLabel(label);
|
|
265843
|
-
const classification = await step("Classifying name", async () => classifyDomainName(clientWrapper, substrateAddress, label));
|
|
265844
|
-
if (classification.requiredStatus !== 3 /* Reserved */) {
|
|
265845
|
-
throw new Error(`Governance name must classify as Reserved; got ${ProofOfPersonhoodStatus[classification.requiredStatus]}`);
|
|
265846
|
-
}
|
|
265847
|
-
await step("Checking availability", async () => ensureDomainNotRegistered(clientWrapper, substrateAddress, label));
|
|
265848
|
-
const { commitment, registration } = await step("Generating commitment", async () => generateCommitment(clientWrapper, substrateAddress, label, evmAddress, true));
|
|
265849
|
-
await step("Submitting commitment", async () => submitCommitment(clientWrapper, substrateAddress, signer, commitment));
|
|
265850
|
-
await step("Waiting commitment age", async () => waitForMinimumCommitmentAge(clientWrapper, substrateAddress, commitment, commitmentBuffer));
|
|
265851
|
-
await step("Finalizing registration", async () => finalizeGovernanceRegistration(clientWrapper, substrateAddress, signer, registration));
|
|
265852
|
-
await step("Verifying ownership", async () => verifyDomainOwnership(clientWrapper, substrateAddress, label, evmAddress));
|
|
265853
|
-
await step("Displaying store", async () => displayDeployedStore(clientWrapper, substrateAddress, evmAddress));
|
|
265854
|
-
await step("Ensuring store authorizations", async () => ensureStoreAuthorizations(clientWrapper, substrateAddress, signer, evmAddress));
|
|
265855
|
-
if (transferDestination) {
|
|
265856
|
-
const recipient = await step("Resolving recipient", async () => resolveTransferRecipient(clientWrapper, substrateAddress, transferDestination));
|
|
265857
|
-
await step("Transferring domain", async () => transferDomain(clientWrapper, substrateAddress, signer, evmAddress, recipient, label));
|
|
265858
|
-
await step("Verifying ownership", async () => verifyDomainOwnership(clientWrapper, substrateAddress, label, recipient));
|
|
265859
|
-
}
|
|
265860
|
-
}
|
|
265861
|
-
async function executeRegularRegistration(clientWrapper, substrateAddress, signer, evmAddress, label, popStatusConfig, enableReverseRecord, transferDestination, commitmentBuffer) {
|
|
265862
|
-
console.log(source_default.bold(`
|
|
265863
|
-
\uD83E\uDDFE Regular registration (commit-reveal)
|
|
265864
|
-
`));
|
|
265865
|
-
validateDomainLabel(label);
|
|
265866
|
-
const classification = await step("Classifying name", async () => classifyDomainName(clientWrapper, substrateAddress, label));
|
|
265867
|
-
if (popStatusConfig.mode === "set") {
|
|
265868
|
-
await step("Setting PoP status", async () => setUserProofOfPersonhoodStatus(clientWrapper, substrateAddress, signer, evmAddress, label, popStatusConfig.status));
|
|
265869
|
-
}
|
|
265870
|
-
await step("Checking availability", async () => ensureDomainNotRegistered(clientWrapper, substrateAddress, label));
|
|
265871
|
-
const { commitment, registration } = await step("Generating commitment", async () => generateCommitment(clientWrapper, substrateAddress, label, evmAddress, enableReverseRecord));
|
|
265872
|
-
await step("Submitting commitment", async () => submitCommitment(clientWrapper, substrateAddress, signer, commitment));
|
|
265873
|
-
await step("Waiting commitment age", async () => waitForMinimumCommitmentAge(clientWrapper, substrateAddress, commitment, commitmentBuffer));
|
|
265874
|
-
const pricing = await step("Pricing and eligibility", async () => getPriceAndValidateEligibility(clientWrapper, substrateAddress, label, evmAddress));
|
|
265875
|
-
await step("Finalizing registration", async () => finalizeRegularRegistration(clientWrapper, substrateAddress, signer, registration, pricing.priceWei));
|
|
265876
|
-
await step("Verifying ownership", async () => verifyDomainOwnership(clientWrapper, substrateAddress, label, evmAddress));
|
|
265877
|
-
await step("Displaying store", async () => displayDeployedStore(clientWrapper, substrateAddress, evmAddress));
|
|
265878
|
-
await step("Ensuring store authorizations", async () => ensureStoreAuthorizations(clientWrapper, substrateAddress, signer, evmAddress));
|
|
265879
|
-
if (transferDestination) {
|
|
265880
|
-
const recipient = await step("Resolving recipient", async () => resolveTransferRecipient(clientWrapper, substrateAddress, transferDestination));
|
|
265881
|
-
await step("Transferring domain", async () => transferDomain(clientWrapper, substrateAddress, signer, evmAddress, recipient, label));
|
|
265882
|
-
await step("Verifying ownership", async () => verifyDomainOwnership(clientWrapper, substrateAddress, label, recipient));
|
|
265883
|
-
}
|
|
265884
|
-
}
|
|
265885
|
-
|
|
265886
|
-
// src/cli/commands/lookup.ts
|
|
265887
|
-
function createClientWrapper(rpc) {
|
|
265888
|
-
const client = createClient3(getWsProvider(rpc)).getTypedApi(paseo_default);
|
|
265889
|
-
return new ReviveClientWrapper(client);
|
|
265890
|
-
}
|
|
265891
|
-
function getJsonFlag(command) {
|
|
265892
|
-
if (command && typeof command.optsWithGlobals === "function") {
|
|
265893
|
-
const options2 = command.optsWithGlobals();
|
|
265894
|
-
if (typeof options2?.json === "boolean")
|
|
265895
|
-
return options2.json;
|
|
265896
|
-
}
|
|
265897
|
-
const localOptions = command && typeof command.opts === "function" ? command.opts() : undefined;
|
|
265898
|
-
if (typeof localOptions?.json === "boolean")
|
|
265899
|
-
return localOptions.json;
|
|
265900
|
-
return process.argv.includes("--json");
|
|
265901
|
-
}
|
|
265902
|
-
function hasAnyAuthHint(opts) {
|
|
265903
|
-
return opts.mnemonic != null && String(opts.mnemonic).length > 0 || opts.keyUri != null && String(opts.keyUri).length > 0 || opts.keystorePath != null && String(opts.keystorePath).length > 0 || opts.account != null && String(opts.account).length > 0 || opts.password != null && String(opts.password).length > 0;
|
|
265904
|
-
}
|
|
265905
|
-
function withReadOnlyPasswordFallback(opts) {
|
|
265906
|
-
const passwordEnv = process.env.DOTNS_KEYSTORE_PASSWORD;
|
|
265907
|
-
if ((opts.password == null || String(opts.password).length === 0) && passwordEnv && passwordEnv.length > 0) {
|
|
265908
|
-
return { ...opts, password: passwordEnv };
|
|
265909
|
-
}
|
|
265910
|
-
return opts;
|
|
265911
|
-
}
|
|
265912
|
-
async function prepareReadOnlyContext(options2) {
|
|
265913
|
-
const rpc = resolveRpc(options2.rpc);
|
|
265914
|
-
const clientWrapper = await step(`Connecting RPC ${rpc}`, async () => createClientWrapper(rpc));
|
|
265915
|
-
const auth = await step("Resolving read-only account", async () => {
|
|
265916
|
-
if (hasAnyAuthHint(options2)) {
|
|
265917
|
-
const merged = withReadOnlyPasswordFallback(options2);
|
|
265918
|
-
const resolved2 = await resolveAuthSource(merged);
|
|
265919
|
-
return {
|
|
265920
|
-
source: resolved2.source,
|
|
265921
|
-
isKeyUri: resolved2.isKeyUri,
|
|
265922
|
-
resolvedFrom: resolved2.resolvedFrom,
|
|
265923
|
-
account: resolved2.account
|
|
265924
|
-
};
|
|
265925
|
-
}
|
|
265926
|
-
const resolved = await resolveAuthSourceReadOnly();
|
|
265927
|
-
return {
|
|
265928
|
-
source: resolved.source,
|
|
265929
|
-
isKeyUri: resolved.isKeyUri,
|
|
265930
|
-
resolvedFrom: resolved.resolvedFrom,
|
|
265931
|
-
account: resolved.account
|
|
265932
|
-
};
|
|
265933
|
-
});
|
|
265934
|
-
const keypair3 = await step("Loading keypair", async () => createAccountFromSource(auth.source, auth.isKeyUri));
|
|
265935
|
-
const evmAddress = await step("Resolving EVM address", async () => clientWrapper.getEvmAddress(keypair3.address));
|
|
265936
|
-
console.log(source_default.gray(`
|
|
265937
|
-
RPC: `) + source_default.white(rpc));
|
|
265938
|
-
console.log(source_default.gray(" Account: ") + source_default.white(keypair3.address));
|
|
265939
|
-
return { clientWrapper, account: { address: keypair3.address }, rpc, evmAddress };
|
|
265940
|
-
}
|
|
265941
|
-
async function resolveRecipientByKind(clientWrapper, substrateAddress, destination) {
|
|
265942
|
-
const kind = classifyTransferDestination(destination);
|
|
265943
|
-
switch (kind) {
|
|
265944
|
-
case "evm":
|
|
265945
|
-
return destination;
|
|
265946
|
-
case "substrate":
|
|
265947
|
-
return clientWrapper.getEvmAddress(destination);
|
|
265948
|
-
case "label":
|
|
265949
|
-
return resolveTransferRecipient(clientWrapper, substrateAddress, destination);
|
|
265950
|
-
}
|
|
265951
|
-
}
|
|
265952
|
-
function attachLookupCommands(root) {
|
|
265953
|
-
const lookupCommand = root.command("lookup").description("Lookup domain information");
|
|
265954
|
-
addAuthOptions(lookupCommand);
|
|
265955
|
-
const lookupNameCommand = lookupCommand.command("name [label]").description("Lookup comprehensive domain information").option("-n, --name <label>", "Domain label to lookup (alternative to positional argument)").option("--json", "Output result as JSON (suppresses all other output)", false);
|
|
265956
|
-
addAuthOptions(lookupNameCommand).action(async (positionalLabel, options2, cmd) => {
|
|
265377
|
+
function attachBulletinCommands(root) {
|
|
265378
|
+
const bulletinCommand = addReporterOption(root.command("bulletin").description("Bulletin storage utilities")).option("--json", "Write machine-readable JSON to stdout", false);
|
|
265379
|
+
addAuthOptions(bulletinCommand);
|
|
265380
|
+
const authorizeCommand = addReporterOption(bulletinCommand.command("authorize [address]").description("Authorize an account for Bulletin TransactionStorage").option("--bulletin-rpc <wsUrl>", "Bulletin WebSocket RPC endpoint", DEFAULT_BULLETIN_RPC).option("--transactions <count>", "Number of transactions to authorize", String(DEFAULT_AUTHORIZATION_TRANSACTIONS)).option("--bytes <count>", "Number of bytes to authorize", String(DEFAULT_AUTHORIZATION_BYTES)).option("--force", "Force re-authorization even if account appears already authorized", false).option("--json", "Write machine-readable JSON to stdout", false));
|
|
265381
|
+
addAuthOptions(authorizeCommand).action(async (positionalAddress, options2, command) => {
|
|
265957
265382
|
try {
|
|
265958
|
-
const
|
|
265959
|
-
|
|
265960
|
-
|
|
265961
|
-
|
|
265962
|
-
|
|
265963
|
-
const
|
|
265964
|
-
const
|
|
265965
|
-
|
|
265966
|
-
|
|
265967
|
-
|
|
265968
|
-
|
|
265969
|
-
|
|
265970
|
-
|
|
265971
|
-
|
|
265972
|
-
`));
|
|
265973
|
-
console.log(source_default.gray("
|
|
265974
|
-
console.log(source_default.gray("
|
|
265975
|
-
console.log(source_default.gray(
|
|
265976
|
-
|
|
265977
|
-
|
|
265383
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
265384
|
+
const jsonOutput = getJsonFlag(command);
|
|
265385
|
+
const reporterMode = resolveReporterMode(mergedOptions.reporter);
|
|
265386
|
+
const reporter = createCliReporter(mergedOptions.reporter);
|
|
265387
|
+
const onPhase = createPhaseHandler(reporter);
|
|
265388
|
+
const bulletinRpc = String(mergedOptions.bulletinRpc || DEFAULT_BULLETIN_RPC);
|
|
265389
|
+
const transactions = Number(mergedOptions.transactions || DEFAULT_AUTHORIZATION_TRANSACTIONS);
|
|
265390
|
+
const bytes = BigInt(mergedOptions.bytes || DEFAULT_AUTHORIZATION_BYTES);
|
|
265391
|
+
const force = Boolean(options2.force);
|
|
265392
|
+
const signerKeyUri = String(mergedOptions.keyUri || DEFAULT_SUDO_KEY_URI);
|
|
265393
|
+
const targetAddress = await resolveTargetAddress(positionalAddress, mergedOptions, reporterMode);
|
|
265394
|
+
const signerContext = await withBulletinHumanOutput(reporterMode, () => prepareContext({ keyUri: signerKeyUri, useBulletin: true }));
|
|
265395
|
+
if (!jsonOutput) {
|
|
265396
|
+
console.log(source_default.blue(`
|
|
265397
|
+
▶ Bulletin Authorize`));
|
|
265398
|
+
console.log(source_default.gray(" target: ") + source_default.cyan(targetAddress));
|
|
265399
|
+
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
265400
|
+
console.log(source_default.gray(" transactions: ") + source_default.white(transactions.toLocaleString()));
|
|
265401
|
+
console.log(source_default.gray(" bytes: ") + source_default.white(formatBytes(bytes)));
|
|
265402
|
+
console.log(source_default.gray(" signer: ") + source_default.yellow(signerKeyUri));
|
|
265978
265403
|
}
|
|
265979
|
-
|
|
265980
|
-
|
|
265981
|
-
|
|
265982
|
-
|
|
265983
|
-
|
|
265984
|
-
|
|
265404
|
+
await withBulletinHumanOutput(reporterMode, () => authorizeAccount({
|
|
265405
|
+
rpc: bulletinRpc,
|
|
265406
|
+
signer: signerContext.signer,
|
|
265407
|
+
targetAddress,
|
|
265408
|
+
transactions,
|
|
265409
|
+
bytes,
|
|
265410
|
+
force,
|
|
265411
|
+
onPhase
|
|
265412
|
+
}));
|
|
265985
265413
|
if (jsonOutput) {
|
|
265986
|
-
|
|
265414
|
+
const authStatus = await checkAuthorization(bulletinRpc, targetAddress);
|
|
265415
|
+
const expiresAt = expirationToISOString(authStatus.currentBlock, authStatus.expiration);
|
|
265416
|
+
writeBulletinJson({
|
|
265417
|
+
ok: true,
|
|
265418
|
+
target: targetAddress,
|
|
265419
|
+
rpc: bulletinRpc,
|
|
265420
|
+
transactions,
|
|
265421
|
+
bytes: bytes.toString(),
|
|
265422
|
+
expiresAt
|
|
265423
|
+
});
|
|
265987
265424
|
} else {
|
|
265988
265425
|
console.log(source_default.green(`
|
|
265989
|
-
✓ Complete
|
|
265426
|
+
✓ Authorization Complete`));
|
|
265427
|
+
console.log(source_default.gray(` The account can now upload to Bulletin.
|
|
265990
265428
|
`));
|
|
265991
265429
|
}
|
|
265992
265430
|
process.exit(0);
|
|
265993
265431
|
} catch (error2) {
|
|
265994
265432
|
const errorMessage = formatErrorMessage(error2);
|
|
265995
|
-
const jsonOutput = getJsonFlag(
|
|
265433
|
+
const jsonOutput = getJsonFlag(command);
|
|
265996
265434
|
if (jsonOutput) {
|
|
265997
|
-
|
|
265998
|
-
process.exit(1);
|
|
265435
|
+
writeBulletinJsonError(errorMessage);
|
|
265999
265436
|
}
|
|
266000
|
-
|
|
266001
|
-
|
|
266002
|
-
|
|
266003
|
-
process.exit(1);
|
|
266004
|
-
}
|
|
266005
|
-
});
|
|
266006
|
-
lookupCommand.option("-n, --name <label>", "Domain label to lookup").option("--json", "Output result as JSON (suppresses all other output)", false).action(async (options2, cmd) => {
|
|
266007
|
-
const subcommand = cmd.args?.[0];
|
|
266008
|
-
if (["name", "owner-of", "oo", "transfer"].includes(subcommand))
|
|
266009
|
-
return;
|
|
266010
|
-
if (options2.name) {
|
|
266011
|
-
try {
|
|
266012
|
-
const merged = { ...options2 ?? {}, ...getAuthOptions(cmd) };
|
|
266013
|
-
const jsonOutput = getJsonFlag(cmd);
|
|
266014
|
-
const { clientWrapper, account } = await maybeQuiet(jsonOutput, () => prepareReadOnlyContext(merged));
|
|
266015
|
-
if (!jsonOutput)
|
|
266016
|
-
console.log(source_default.bold(`
|
|
266017
|
-
▶ Domain Lookup
|
|
266018
|
-
`));
|
|
266019
|
-
const result = await maybeQuiet(jsonOutput, () => performDomainLookup(merged.name, account.address, clientWrapper));
|
|
266020
|
-
if (jsonOutput) {
|
|
266021
|
-
console.log(JSON.stringify(result));
|
|
266022
|
-
} else {
|
|
266023
|
-
console.log(source_default.green(`
|
|
266024
|
-
✓ Complete
|
|
265437
|
+
if (errorMessage.includes("AlreadyAuthorized")) {
|
|
265438
|
+
console.log(source_default.yellow(`
|
|
265439
|
+
⚠ Account is already authorized
|
|
266025
265440
|
`));
|
|
266026
|
-
}
|
|
266027
265441
|
process.exit(0);
|
|
266028
|
-
}
|
|
266029
|
-
|
|
266030
|
-
const jsonOutput = getJsonFlag(cmd);
|
|
266031
|
-
if (jsonOutput) {
|
|
266032
|
-
console.error(JSON.stringify({ error: errorMessage }));
|
|
266033
|
-
process.exit(1);
|
|
266034
|
-
}
|
|
265442
|
+
}
|
|
265443
|
+
if (errorMessage.includes("BadOrigin")) {
|
|
266035
265444
|
console.error(source_default.red(`
|
|
266036
|
-
✗
|
|
265445
|
+
✗ Authorization failed — insufficient privileges`));
|
|
265446
|
+
console.error(source_default.yellow(" The signer does not have Authorizer privileges on this chain."));
|
|
265447
|
+
console.error(source_default.gray(` Override with --key-uri if needed.
|
|
265448
|
+
`));
|
|
265449
|
+
process.exit(1);
|
|
265450
|
+
}
|
|
265451
|
+
if (errorMessage.includes("not applied")) {
|
|
265452
|
+
console.error(source_default.red(`
|
|
265453
|
+
✗ ${errorMessage}`));
|
|
265454
|
+
console.error(source_default.gray(` Override with --key-uri if needed.
|
|
266037
265455
|
`));
|
|
266038
265456
|
process.exit(1);
|
|
266039
265457
|
}
|
|
265458
|
+
console.error(source_default.red(`
|
|
265459
|
+
✗ Error: ${errorMessage}
|
|
265460
|
+
`));
|
|
265461
|
+
process.exit(1);
|
|
266040
265462
|
}
|
|
266041
265463
|
});
|
|
266042
|
-
const
|
|
266043
|
-
addAuthOptions(
|
|
265464
|
+
const uploadCommand = addReporterOption(bulletinCommand.command("upload <path>").description("Upload a file or directory to Bulletin and print the resulting CID").option("--bulletin-rpc <wsUrl>", "Bulletin WebSocket RPC endpoint", DEFAULT_BULLETIN_RPC).option("--chunk-size <bytes>", "Chunk size for large uploads (clamped to 256 KB–2 MB)", String(DEFAULT_CHUNK_SIZE_BYTES)).option("--max-retries <n>", "Retry transient upload failures (default: 5, capped at 20)", String(DEFAULT_UPLOAD_MAX_RETRIES)).option("--force-chunked", "Force chunked upload (DAG-PB)", false).option("--concurrency <n>", "Adaptive scheduler max window (default: 16, max: 64)", "16").option("--print-contenthash", "Also print 0x-prefixed IPFS contenthash for the CID", false).option("--resume", "Resume a previously interrupted upload", false).option("--profile-upload", "Enable upload profiling and write a JSON report", false).option("--profile-output <path>", "Path to write upload profiling JSON report").option("--no-history", "Do not save upload to history", true).option("--cache", "Write the CID to the user's on-chain Store after upload", false).option("--json", "Write machine-readable JSON to stdout", false));
|
|
265465
|
+
addAuthOptions(uploadCommand).action(async (inputPath, options2, command) => {
|
|
266044
265466
|
try {
|
|
266045
|
-
const
|
|
266046
|
-
const jsonOutput = getJsonFlag(
|
|
266047
|
-
const
|
|
266048
|
-
|
|
266049
|
-
|
|
266050
|
-
|
|
266051
|
-
|
|
266052
|
-
|
|
266053
|
-
if (jsonOutput) {
|
|
266054
|
-
console.log(JSON.stringify(result));
|
|
266055
|
-
} else {
|
|
266056
|
-
console.log(source_default.green(`
|
|
266057
|
-
✓ Complete
|
|
266058
|
-
`));
|
|
266059
|
-
}
|
|
266060
|
-
process.exit(0);
|
|
266061
|
-
} catch (error2) {
|
|
266062
|
-
const errorMessage = formatErrorMessage(error2);
|
|
266063
|
-
const jsonOutput = getJsonFlag(cmd);
|
|
266064
|
-
if (jsonOutput) {
|
|
266065
|
-
console.error(JSON.stringify({ error: errorMessage }));
|
|
266066
|
-
process.exit(1);
|
|
265467
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
265468
|
+
const jsonOutput = getJsonFlag(command);
|
|
265469
|
+
const reporterMode = resolveReporterMode(mergedOptions.reporter);
|
|
265470
|
+
const reporter = createCliReporter(mergedOptions.reporter);
|
|
265471
|
+
const onPhase = createPhaseHandler(reporter);
|
|
265472
|
+
const onRetry = createRetryHandler(reporter);
|
|
265473
|
+
if (mergedOptions.mnemonic && mergedOptions.keyUri) {
|
|
265474
|
+
throw new Error("Cannot specify both --mnemonic and --key-uri");
|
|
266067
265475
|
}
|
|
266068
|
-
|
|
266069
|
-
|
|
266070
|
-
|
|
266071
|
-
|
|
266072
|
-
|
|
266073
|
-
|
|
266074
|
-
|
|
266075
|
-
|
|
266076
|
-
|
|
266077
|
-
const
|
|
266078
|
-
const
|
|
266079
|
-
|
|
266080
|
-
if (
|
|
266081
|
-
|
|
265476
|
+
await cleanupStaleManifests();
|
|
265477
|
+
const validatedPath = await withBulletinHumanOutput(reporterMode, () => validateAndReadPath(inputPath, onPhase));
|
|
265478
|
+
const { bytes, isDirectory, resolvedPath, fileSize, fileMtimeMs } = validatedPath;
|
|
265479
|
+
const bulletinRpc = String(mergedOptions.bulletinRpc || DEFAULT_BULLETIN_RPC);
|
|
265480
|
+
const chunkSizeBytes = clampChunkSizeBytes(Number(mergedOptions.chunkSize || DEFAULT_CHUNK_SIZE_BYTES));
|
|
265481
|
+
const maxRetries = normalizeUploadMaxRetries(mergedOptions.maxRetries);
|
|
265482
|
+
const concurrency = Math.max(1, Math.min(64, Math.floor(Number(mergedOptions.concurrency || 16))));
|
|
265483
|
+
const resume = Boolean(mergedOptions.resume);
|
|
265484
|
+
const profileUpload = Boolean(mergedOptions.profileUpload);
|
|
265485
|
+
const shouldUseChunkedUpload = !isDirectory;
|
|
265486
|
+
const effectiveFileSize = isDirectory ? 0 : fileSize ?? bytes.length;
|
|
265487
|
+
let resumedBlocks;
|
|
265488
|
+
if (resume && shouldUseChunkedUpload) {
|
|
265489
|
+
const resolvedFileMtimeMs = fileMtimeMs ?? (await filesystem2.stat(resolvedPath)).mtimeMs;
|
|
265490
|
+
const manifestLoadResult = await loadManifestForResume({
|
|
265491
|
+
inputPath: resolvedPath,
|
|
265492
|
+
fileSize: effectiveFileSize,
|
|
265493
|
+
fileMtimeMs: resolvedFileMtimeMs,
|
|
265494
|
+
chunkSize: chunkSizeBytes
|
|
265495
|
+
});
|
|
265496
|
+
if (manifestLoadResult.manifest && manifestLoadResult.manifest.completedBlocks.length > 0) {
|
|
265497
|
+
resumedBlocks = completedBlocksFromManifest(manifestLoadResult.manifest);
|
|
265498
|
+
reporter.warn(`resuming: ${manifestLoadResult.manifest.completedBlocks.length} blocks already uploaded`);
|
|
265499
|
+
} else if (manifestLoadResult.staleManifest) {
|
|
265500
|
+
reporter.warn("resume notice: file fingerprint changed, starting a fresh upload manifest");
|
|
265501
|
+
await deleteManifest(manifestLoadResult.staleManifest);
|
|
265502
|
+
}
|
|
266082
265503
|
}
|
|
266083
|
-
const
|
|
266084
|
-
|
|
266085
|
-
|
|
265504
|
+
const context = await withBulletinHumanOutput(reporterMode, () => prepareContext({ ...mergedOptions, useBulletin: true }));
|
|
265505
|
+
const authInfo = await withBulletinHumanOutput(reporterMode, () => ensureAccountAuthorized(bulletinRpc, context.substrateAddress));
|
|
265506
|
+
const profileOutputOverride = mergedOptions.profileOutput ? String(mergedOptions.profileOutput) : undefined;
|
|
265507
|
+
const profiler = profileUpload ? createUploadProfiler({
|
|
265508
|
+
sourcePath: resolvedPath,
|
|
265509
|
+
sourceSizeBytes: effectiveFileSize,
|
|
265510
|
+
chunkSizeBytes: shouldUseChunkedUpload ? chunkSizeBytes : Math.max(1, effectiveFileSize),
|
|
265511
|
+
rpc: bulletinRpc,
|
|
265512
|
+
initialConcurrency: shouldUseChunkedUpload ? 1 : 1,
|
|
265513
|
+
maxConcurrency: shouldUseChunkedUpload ? concurrency : 1,
|
|
265514
|
+
outputPath: profileOutputOverride,
|
|
265515
|
+
jsonOutput
|
|
265516
|
+
}) : undefined;
|
|
265517
|
+
const totalChunks = shouldUseChunkedUpload ? Math.ceil(effectiveFileSize / chunkSizeBytes) : undefined;
|
|
265518
|
+
const chunkedMonitor = shouldUseChunkedUpload && totalChunks ? createChunkedUploadMonitor(reporter, onPhase, effectiveFileSize, chunkSizeBytes, totalChunks) : null;
|
|
265519
|
+
const performUpload = async () => {
|
|
265520
|
+
if (isDirectory) {
|
|
265521
|
+
const result2 = await storeDirectory(bulletinRpc, context.signer, resolvedPath, {
|
|
265522
|
+
concurrency,
|
|
265523
|
+
accountAddress: context.substrateAddress,
|
|
265524
|
+
maxRetries,
|
|
265525
|
+
onPhase,
|
|
265526
|
+
onRetry,
|
|
265527
|
+
waitForFinalization: false
|
|
265528
|
+
});
|
|
265529
|
+
return { cid: result2.cid, size: 0 };
|
|
265530
|
+
}
|
|
265531
|
+
if (shouldUseChunkedUpload) {
|
|
265532
|
+
const result2 = await uploadChunkedBlocks(bulletinRpc, context.signer, resolvedPath, chunkSizeBytes, effectiveFileSize, context.substrateAddress, {
|
|
265533
|
+
completedBlocks: resumedBlocks,
|
|
265534
|
+
concurrency,
|
|
265535
|
+
maxRetries,
|
|
265536
|
+
onPhase,
|
|
265537
|
+
onRetry,
|
|
265538
|
+
onSchedulerState: (state3) => {
|
|
265539
|
+
profiler?.onSchedulerState(state3);
|
|
265540
|
+
chunkedMonitor?.onSchedulerState(state3);
|
|
265541
|
+
},
|
|
265542
|
+
onWave: (wave) => {
|
|
265543
|
+
profiler?.onWave(wave);
|
|
265544
|
+
chunkedMonitor?.onWave(wave);
|
|
265545
|
+
}
|
|
265546
|
+
});
|
|
265547
|
+
return { cid: result2, size: effectiveFileSize };
|
|
265548
|
+
}
|
|
265549
|
+
const result = await uploadSingleBlock(bulletinRpc, context.signer, bytes, {
|
|
265550
|
+
maxRetries,
|
|
265551
|
+
onPhase,
|
|
265552
|
+
onRetry
|
|
265553
|
+
});
|
|
265554
|
+
return { cid: result, size: bytes.length };
|
|
265555
|
+
};
|
|
265556
|
+
let cid;
|
|
265557
|
+
let uploadSize;
|
|
265558
|
+
let profileReportPath;
|
|
265559
|
+
let profileReport;
|
|
265560
|
+
const uploadStartedAtMs = Date.now();
|
|
265561
|
+
const uploadStartedAtIso = new Date(uploadStartedAtMs).toISOString();
|
|
265562
|
+
const pathBasename = resolvedPath.split("/").pop() ?? resolvedPath;
|
|
265563
|
+
if (authInfo?.expiration && authInfo.currentBlock) {
|
|
265564
|
+
reporter.detail(`auth: valid (expires ${formatExpirationDisplay(authInfo.currentBlock, authInfo.expiration)})`);
|
|
266086
265565
|
}
|
|
266087
|
-
const context = await maybeQuiet(jsonOutput, () => prepareAssetHubContext(merged));
|
|
266088
|
-
const { clientWrapper, substrateAddress, signer, evmAddress } = context;
|
|
266089
265566
|
if (!jsonOutput) {
|
|
266090
|
-
|
|
266091
|
-
|
|
266092
|
-
`));
|
|
266093
|
-
|
|
266094
|
-
|
|
265567
|
+
if (isDirectory) {
|
|
265568
|
+
console.log(source_default.blue(`
|
|
265569
|
+
▶ Uploading directory: ${pathBasename}`));
|
|
265570
|
+
console.log(source_default.gray(" path: ") + source_default.white(resolvedPath));
|
|
265571
|
+
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
265572
|
+
console.log(source_default.gray(" concurrency: ") + source_default.white(`${concurrency}x parallel waves`));
|
|
265573
|
+
} else if (shouldUseChunkedUpload) {
|
|
265574
|
+
console.log(source_default.blue(`
|
|
265575
|
+
▶ Uploading file: ${pathBasename} (${formatBytes(effectiveFileSize)})`));
|
|
265576
|
+
console.log(source_default.gray(" path: ") + source_default.white(resolvedPath));
|
|
265577
|
+
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
265578
|
+
console.log(source_default.gray(" mode: ") + source_default.white(`chunked (${totalChunks} × ${formatBytes(chunkSizeBytes)}, adaptive window 1..${concurrency})`));
|
|
265579
|
+
} else {
|
|
265580
|
+
console.log(source_default.blue(`
|
|
265581
|
+
▶ Uploading file: ${pathBasename} (${formatBytes(bytes.length)})`));
|
|
265582
|
+
console.log(source_default.gray(" path: ") + source_default.white(resolvedPath));
|
|
265583
|
+
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
265584
|
+
console.log(source_default.gray(" mode: ") + source_default.white("single block"));
|
|
265585
|
+
}
|
|
266095
265586
|
}
|
|
266096
|
-
|
|
266097
|
-
|
|
266098
|
-
|
|
266099
|
-
|
|
265587
|
+
try {
|
|
265588
|
+
const uploadResult = await withBulletinHumanOutput(reporterMode, performUpload);
|
|
265589
|
+
cid = uploadResult.cid;
|
|
265590
|
+
uploadSize = uploadResult.size;
|
|
265591
|
+
} finally {
|
|
265592
|
+
chunkedMonitor?.stop();
|
|
265593
|
+
}
|
|
265594
|
+
const uploadFinishedAtMs = Date.now();
|
|
265595
|
+
const uploadFinishedAtIso = new Date(uploadFinishedAtMs).toISOString();
|
|
265596
|
+
const totalUploadTimeMs = Math.max(1, uploadFinishedAtMs - uploadStartedAtMs);
|
|
265597
|
+
const totalUploadTimeSeconds = totalUploadTimeMs / 1000;
|
|
265598
|
+
if (profiler) {
|
|
265599
|
+
const finalizedProfile = await profiler.finalize(cid, profileOutputOverride);
|
|
265600
|
+
profileReport = finalizedProfile.report;
|
|
265601
|
+
profileReportPath = finalizedProfile.outputPath;
|
|
265602
|
+
}
|
|
265603
|
+
onPhase({
|
|
265604
|
+
phase: "verify",
|
|
265605
|
+
state: "start",
|
|
265606
|
+
message: "Verifying content on Bulletin P2P..."
|
|
265607
|
+
});
|
|
265608
|
+
let verified = false;
|
|
265609
|
+
try {
|
|
265610
|
+
const p2pResult = await verifyCidViaP2P(cid);
|
|
265611
|
+
if (p2pResult.resolvable) {
|
|
265612
|
+
onPhase({ phase: "verify", state: "success", message: "Content verified via P2P" });
|
|
265613
|
+
verified = true;
|
|
265614
|
+
}
|
|
265615
|
+
} catch {}
|
|
265616
|
+
if (!verified) {
|
|
265617
|
+
onPhase({
|
|
265618
|
+
phase: "verify",
|
|
265619
|
+
state: "update",
|
|
265620
|
+
message: "P2P unavailable, checking IPFS gateways..."
|
|
265621
|
+
});
|
|
265622
|
+
const gatewayResults = await verifyCidWithMultipleGateways(cid);
|
|
265623
|
+
const resolvable = Array.from(gatewayResults.values()).some((r2) => r2.resolvable);
|
|
265624
|
+
if (resolvable) {
|
|
265625
|
+
onPhase({
|
|
265626
|
+
phase: "verify",
|
|
265627
|
+
state: "success",
|
|
265628
|
+
message: "Content verified via IPFS gateway"
|
|
265629
|
+
});
|
|
265630
|
+
} else {
|
|
265631
|
+
onPhase({
|
|
265632
|
+
phase: "verify",
|
|
265633
|
+
state: "warning",
|
|
265634
|
+
message: "Content not yet resolvable — it may still be propagating"
|
|
265635
|
+
});
|
|
265636
|
+
}
|
|
265637
|
+
}
|
|
265638
|
+
const contenthash = generateContenthash(cid);
|
|
265639
|
+
const previewUrl = getPreviewUrl({
|
|
265640
|
+
cid,
|
|
265641
|
+
path: resolvedPath,
|
|
265642
|
+
type: isDirectory ? "directory" : "file",
|
|
265643
|
+
size: uploadSize,
|
|
265644
|
+
timestamp: ""
|
|
265645
|
+
});
|
|
266100
265646
|
if (jsonOutput) {
|
|
266101
|
-
|
|
266102
|
-
|
|
266103
|
-
|
|
266104
|
-
|
|
266105
|
-
|
|
266106
|
-
|
|
266107
|
-
|
|
265647
|
+
const authExpiresAt = expirationToISOString(authInfo?.currentBlock, authInfo?.expiration);
|
|
265648
|
+
writeBulletinJson({
|
|
265649
|
+
cid,
|
|
265650
|
+
contenthash: `0x${contenthash}`,
|
|
265651
|
+
preview: previewUrl,
|
|
265652
|
+
path: resolvedPath,
|
|
265653
|
+
type: isDirectory ? "directory" : "file",
|
|
265654
|
+
size: uploadSize,
|
|
265655
|
+
authorizationExpiresAt: authExpiresAt,
|
|
265656
|
+
uploadStartedAtIso,
|
|
265657
|
+
uploadFinishedAtIso,
|
|
265658
|
+
totalUploadTimeMs,
|
|
265659
|
+
totalUploadTimeSeconds
|
|
265660
|
+
});
|
|
266108
265661
|
} else {
|
|
265662
|
+
console.log(source_default.gray(`
|
|
265663
|
+
cid: `) + source_default.cyan(cid));
|
|
265664
|
+
console.log(source_default.gray(" preview: ") + source_default.blue(previewUrl));
|
|
265665
|
+
console.log(source_default.gray(" total time: ") + source_default.white(formatDuration(totalUploadTimeSeconds)));
|
|
265666
|
+
if (mergedOptions.printContenthash) {
|
|
265667
|
+
console.log(source_default.gray(" contenthash: ") + source_default.white(`0x${contenthash}`));
|
|
265668
|
+
}
|
|
265669
|
+
if (profileReportPath && profileReport) {
|
|
265670
|
+
console.log(source_default.gray(" profile: ") + source_default.white(profileReportPath));
|
|
265671
|
+
console.log(source_default.gray(" throughput: ") + source_default.white(`${formatBytes(profileReport.summary.throughputBytesPerSecond)}/s`));
|
|
265672
|
+
console.log(source_default.gray(" peak heap: ") + source_default.white(formatBytes(profileReport.summary.peakHeapUsed)));
|
|
265673
|
+
}
|
|
266109
265674
|
console.log(source_default.green(`
|
|
266110
|
-
✓ Complete
|
|
265675
|
+
✓ Upload Complete
|
|
266111
265676
|
`));
|
|
266112
265677
|
}
|
|
266113
|
-
|
|
266114
|
-
|
|
266115
|
-
|
|
266116
|
-
|
|
266117
|
-
|
|
266118
|
-
|
|
266119
|
-
|
|
266120
|
-
|
|
266121
|
-
|
|
266122
|
-
|
|
265678
|
+
if (options2.cache) {
|
|
265679
|
+
onPhase({
|
|
265680
|
+
phase: "cache",
|
|
265681
|
+
state: "start",
|
|
265682
|
+
message: "Saving CID to on-chain Store..."
|
|
265683
|
+
});
|
|
265684
|
+
try {
|
|
265685
|
+
const { cacheCidToStore: cacheCidToStore2 } = await Promise.resolve().then(() => (init_storeManagement(), exports_storeManagement));
|
|
265686
|
+
const { createClient: createClient4 } = await Promise.resolve().then(() => (init_esm10(), exports_esm2));
|
|
265687
|
+
const { getWsProvider: getWsProvider2 } = await Promise.resolve().then(() => (init_ws_provider(), exports_ws_provider));
|
|
265688
|
+
const { paseo } = await Promise.resolve().then(() => (init_dist(), exports_dist));
|
|
265689
|
+
const { ReviveClientWrapper: ReviveClientWrapper2 } = await Promise.resolve().then(() => (init_polkadotClient(), exports_polkadotClient));
|
|
265690
|
+
const { resolveRpc: resolveRpc2 } = await Promise.resolve().then(() => (init_env(), exports_env));
|
|
265691
|
+
const rpc = resolveRpc2(process.env.DOTNS_RPC);
|
|
265692
|
+
const typedApi = createClient4(getWsProvider2(rpc)).getTypedApi(paseo);
|
|
265693
|
+
const clientWrapper = new ReviveClientWrapper2(typedApi);
|
|
265694
|
+
const evmAddress = await clientWrapper.getEvmAddress(context.substrateAddress);
|
|
265695
|
+
await cacheCidToStore2({
|
|
265696
|
+
cid,
|
|
265697
|
+
clientWrapper,
|
|
265698
|
+
signer: context.signer,
|
|
265699
|
+
substrateAddress: context.substrateAddress,
|
|
265700
|
+
evmAddress
|
|
265701
|
+
});
|
|
265702
|
+
onPhase({ phase: "cache", state: "success", message: "CID cached to Store" });
|
|
265703
|
+
} catch (cacheError) {
|
|
265704
|
+
const msg = formatErrorMessage(cacheError);
|
|
265705
|
+
let reason;
|
|
265706
|
+
if (/insufficient|balance/i.test(msg)) {
|
|
265707
|
+
reason = "insufficient PAS balance on Asset Hub — fund the account and retry with --cache";
|
|
265708
|
+
} else if (/no store deployed|store not deployed/i.test(msg)) {
|
|
265709
|
+
reason = "no Store deployed — register a domain first or deploy a Store manually";
|
|
265710
|
+
} else if (/not authorized|unauthorized/i.test(msg)) {
|
|
265711
|
+
reason = "Store not authorised for writes — run dotns store ensure-auth";
|
|
265712
|
+
} else {
|
|
265713
|
+
reason = msg;
|
|
265714
|
+
}
|
|
265715
|
+
onPhase({
|
|
265716
|
+
phase: "cache",
|
|
265717
|
+
state: "warning",
|
|
265718
|
+
message: `Store caching skipped: ${reason}`
|
|
265719
|
+
});
|
|
265720
|
+
}
|
|
265721
|
+
}
|
|
265722
|
+
if (mergedOptions.history !== false) {
|
|
265723
|
+
await addUploadRecord({
|
|
265724
|
+
cid,
|
|
265725
|
+
path: resolvedPath,
|
|
265726
|
+
type: isDirectory ? "directory" : "file",
|
|
265727
|
+
size: uploadSize
|
|
265728
|
+
});
|
|
265729
|
+
}
|
|
265730
|
+
process.exit(0);
|
|
265731
|
+
} catch (error2) {
|
|
265732
|
+
const errorMessage = formatErrorMessage(error2);
|
|
265733
|
+
const jsonOutput = getJsonFlag(command);
|
|
265734
|
+
if (jsonOutput) {
|
|
265735
|
+
writeBulletinJsonError(errorMessage);
|
|
265736
|
+
}
|
|
265737
|
+
console.error(source_default.red(`
|
|
265738
|
+
✗ Error: ${errorMessage}
|
|
266123
265739
|
`));
|
|
266124
265740
|
process.exit(1);
|
|
266125
265741
|
}
|
|
266126
265742
|
});
|
|
266127
|
-
|
|
266128
|
-
|
|
266129
|
-
|
|
266130
|
-
|
|
266131
|
-
|
|
266132
|
-
|
|
266133
|
-
|
|
266134
|
-
|
|
266135
|
-
|
|
266136
|
-
|
|
266137
|
-
|
|
266138
|
-
|
|
266139
|
-
|
|
266140
|
-
|
|
266141
|
-
|
|
266142
|
-
|
|
266143
|
-
|
|
266144
|
-
|
|
265743
|
+
const statusCommand = addReporterOption(bulletinCommand.command("status [address]").description("Check authorization status for an account on Bulletin").option("--bulletin-rpc <wsUrl>", "Bulletin WebSocket RPC endpoint", DEFAULT_BULLETIN_RPC).option("--json", "Write machine-readable JSON to stdout", false));
|
|
265744
|
+
addAuthOptions(statusCommand).action(async (positionalAddress, options2, command) => {
|
|
265745
|
+
try {
|
|
265746
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
265747
|
+
const jsonOutput = getJsonFlag(command);
|
|
265748
|
+
const reporterMode = resolveReporterMode(mergedOptions.reporter);
|
|
265749
|
+
const reporter = createCliReporter(mergedOptions.reporter);
|
|
265750
|
+
const bulletinRpc = String(mergedOptions.bulletinRpc || DEFAULT_BULLETIN_RPC);
|
|
265751
|
+
const targetAddress = await resolveTargetAddress(positionalAddress, mergedOptions, reporterMode);
|
|
265752
|
+
const statusTask = reporter.task("Checking authorization");
|
|
265753
|
+
const authStatus = await checkAuthorization(bulletinRpc, targetAddress);
|
|
265754
|
+
statusTask.succeed("Authorization status read");
|
|
265755
|
+
if (jsonOutput) {
|
|
265756
|
+
writeBulletinJson({
|
|
265757
|
+
address: targetAddress,
|
|
265758
|
+
rpc: bulletinRpc,
|
|
265759
|
+
authorized: authStatus.authorized,
|
|
265760
|
+
expired: authStatus.expired ?? false,
|
|
265761
|
+
transactions: authStatus.transactions ?? 0,
|
|
265762
|
+
bytes: (authStatus.bytes ?? BigInt(0)).toString(),
|
|
265763
|
+
expiresAt: expirationToISOString(authStatus.currentBlock, authStatus.expiration)
|
|
265764
|
+
});
|
|
265765
|
+
} else {
|
|
265766
|
+
console.log(source_default.blue(`
|
|
265767
|
+
▶ Bulletin Authorization Status`));
|
|
265768
|
+
console.log(source_default.gray(" account: ") + source_default.cyan(targetAddress));
|
|
265769
|
+
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
265770
|
+
if (!authStatus.authorized) {
|
|
265771
|
+
console.log(source_default.gray(" status: ") + source_default.red("not authorized"));
|
|
265772
|
+
console.log(source_default.gray(`
|
|
265773
|
+
Authorize with: dotns bulletin authorize ` + targetAddress + `
|
|
265774
|
+
`));
|
|
265775
|
+
} else {
|
|
265776
|
+
const isExpired = authStatus.expired;
|
|
265777
|
+
const dateDisplay = formatExpirationDisplay(authStatus.currentBlock, authStatus.expiration);
|
|
265778
|
+
console.log(source_default.gray(" status: ") + (isExpired ? source_default.red("expired") : source_default.green("authorized")));
|
|
265779
|
+
console.log(source_default.gray(isExpired ? " expired: " : " expires: ") + (isExpired ? source_default.red(dateDisplay) : source_default.white(dateDisplay)));
|
|
265780
|
+
console.log(source_default.gray(" transactions: ") + source_default.white((authStatus.transactions ?? 0).toLocaleString()));
|
|
265781
|
+
console.log(source_default.gray(" bytes: ") + source_default.white(formatBytes(authStatus.bytes ?? BigInt(0))));
|
|
265782
|
+
if (isExpired) {
|
|
265783
|
+
console.log(source_default.gray(`
|
|
265784
|
+
Re-authorize with: dotns bulletin authorize ` + targetAddress + `
|
|
265785
|
+
`));
|
|
265786
|
+
} else {
|
|
265787
|
+
console.log();
|
|
265788
|
+
}
|
|
266145
265789
|
}
|
|
266146
265790
|
}
|
|
266147
|
-
|
|
266148
|
-
|
|
266149
|
-
|
|
266150
|
-
|
|
266151
|
-
|
|
266152
|
-
|
|
266153
|
-
|
|
266154
|
-
|
|
266155
|
-
}
|
|
266156
|
-
|
|
266157
|
-
|
|
266158
|
-
}
|
|
266159
|
-
function buildDefaultProfileOutputPath(sourcePath, fingerprint) {
|
|
266160
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
266161
|
-
const basename = path9.basename(sourcePath).replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
266162
|
-
return path9.join(os11.homedir(), ".dotns", "upload-profiles", `${timestamp}-${basename}-${fingerprint}.json`);
|
|
266163
|
-
}
|
|
266164
|
-
function createUploadProfiler(options2) {
|
|
266165
|
-
const startedAtMs = Date.now();
|
|
266166
|
-
const startedAtIso = new Date(startedAtMs).toISOString();
|
|
266167
|
-
let latestSchedulerState = {
|
|
266168
|
-
timestampMs: startedAtMs,
|
|
266169
|
-
window: Math.max(1, options2.initialConcurrency),
|
|
266170
|
-
inFlightBytes: 0,
|
|
266171
|
-
inFlightChunks: 0,
|
|
266172
|
-
completedChunks: 0,
|
|
266173
|
-
retries: 0
|
|
266174
|
-
};
|
|
266175
|
-
const samples = [];
|
|
266176
|
-
const waves = [];
|
|
266177
|
-
const captureSample = () => {
|
|
266178
|
-
const usage = process.memoryUsage();
|
|
266179
|
-
samples.push({
|
|
266180
|
-
timestampMs: Date.now(),
|
|
266181
|
-
heapUsed: usage.heapUsed,
|
|
266182
|
-
rss: usage.rss,
|
|
266183
|
-
arrayBuffers: usage.arrayBuffers,
|
|
266184
|
-
external: usage.external,
|
|
266185
|
-
inFlightBytes: latestSchedulerState.inFlightBytes,
|
|
266186
|
-
inFlightChunks: latestSchedulerState.inFlightChunks,
|
|
266187
|
-
window: latestSchedulerState.window,
|
|
266188
|
-
completed: latestSchedulerState.completedChunks,
|
|
266189
|
-
retries: latestSchedulerState.retries
|
|
266190
|
-
});
|
|
266191
|
-
};
|
|
266192
|
-
captureSample();
|
|
266193
|
-
const timer4 = setInterval(captureSample, PROFILE_SAMPLE_INTERVAL_MS);
|
|
266194
|
-
timer4.unref?.();
|
|
266195
|
-
const summarizeAndWrite = async (finalCid, overrideOutputPath) => {
|
|
266196
|
-
clearInterval(timer4);
|
|
266197
|
-
captureSample();
|
|
266198
|
-
const finishedAtMs = Date.now();
|
|
266199
|
-
const finishedAtIso = new Date(finishedAtMs).toISOString();
|
|
266200
|
-
const totalUploadTimeMs = Math.max(1, finishedAtMs - startedAtMs);
|
|
266201
|
-
const throughputBytesPerSecond = options2.sourceSizeBytes / totalUploadTimeMs * 1000;
|
|
266202
|
-
const peakHeapUsed = Math.max(...samples.map((sample) => sample.heapUsed));
|
|
266203
|
-
const peakRss = Math.max(...samples.map((sample) => sample.rss));
|
|
266204
|
-
const peakArrayBuffers = Math.max(...samples.map((sample) => sample.arrayBuffers));
|
|
266205
|
-
const peakExternal = Math.max(...samples.map((sample) => sample.external));
|
|
266206
|
-
const maxWindowReached = Math.max(...samples.map((sample) => sample.window));
|
|
266207
|
-
const report = {
|
|
266208
|
-
meta: {
|
|
266209
|
-
sourcePath: options2.sourcePath,
|
|
266210
|
-
sourceSizeBytes: options2.sourceSizeBytes,
|
|
266211
|
-
chunkSizeBytes: options2.chunkSizeBytes,
|
|
266212
|
-
rpc: options2.rpc,
|
|
266213
|
-
startedAtIso,
|
|
266214
|
-
finishedAtIso,
|
|
266215
|
-
heapLimitBytes: v8.getHeapStatistics().heap_size_limit,
|
|
266216
|
-
initialConcurrency: options2.initialConcurrency,
|
|
266217
|
-
maxConcurrency: options2.maxConcurrency
|
|
266218
|
-
},
|
|
266219
|
-
samples,
|
|
266220
|
-
waves,
|
|
266221
|
-
summary: {
|
|
266222
|
-
totalUploadTimeMs,
|
|
266223
|
-
totalUploadTimeSeconds: totalUploadTimeMs / 1000,
|
|
266224
|
-
elapsedMs: totalUploadTimeMs,
|
|
266225
|
-
throughputBytesPerSecond,
|
|
266226
|
-
peakHeapUsed,
|
|
266227
|
-
peakRss,
|
|
266228
|
-
peakArrayBuffers,
|
|
266229
|
-
peakExternal,
|
|
266230
|
-
retryCount: latestSchedulerState.retries,
|
|
266231
|
-
maxWindowReached,
|
|
266232
|
-
finalCid
|
|
265791
|
+
process.exit(0);
|
|
265792
|
+
} catch (error2) {
|
|
265793
|
+
const errorMessage = formatErrorMessage(error2);
|
|
265794
|
+
const jsonOutput = getJsonFlag(command);
|
|
265795
|
+
if (jsonOutput) {
|
|
265796
|
+
writeBulletinJsonError(errorMessage);
|
|
265797
|
+
} else {
|
|
265798
|
+
console.error(source_default.red(`
|
|
265799
|
+
✗ Error: ${errorMessage}
|
|
265800
|
+
`));
|
|
265801
|
+
process.exit(1);
|
|
266233
265802
|
}
|
|
266234
|
-
};
|
|
266235
|
-
const outputPath = overrideOutputPath ?? options2.outputPath ?? buildDefaultProfileOutputPath(options2.sourcePath, createProfileFingerprint(`${options2.sourcePath}:${options2.sourceSizeBytes}:${options2.chunkSizeBytes}:${startedAtIso}`));
|
|
266236
|
-
const resolvedOutputPath = path9.resolve(outputPath);
|
|
266237
|
-
await filesystem2.mkdir(path9.dirname(resolvedOutputPath), { recursive: true });
|
|
266238
|
-
await filesystem2.writeFile(resolvedOutputPath, JSON.stringify(report, null, 2), "utf8");
|
|
266239
|
-
return { report, outputPath: resolvedOutputPath };
|
|
266240
|
-
};
|
|
266241
|
-
return {
|
|
266242
|
-
onSchedulerState: (state3) => {
|
|
266243
|
-
latestSchedulerState = state3;
|
|
266244
|
-
captureSample();
|
|
266245
|
-
},
|
|
266246
|
-
onWave: (wave) => {
|
|
266247
|
-
waves.push(wave);
|
|
266248
|
-
captureSample();
|
|
266249
|
-
},
|
|
266250
|
-
finalize: summarizeAndWrite
|
|
266251
|
-
};
|
|
266252
|
-
}
|
|
266253
|
-
async function withCapturedConsole(callback) {
|
|
266254
|
-
const MAX_CAPTURED_ENTRIES = 400;
|
|
266255
|
-
const captured = [];
|
|
266256
|
-
const pushCaptured = (value3) => {
|
|
266257
|
-
captured.push(value3);
|
|
266258
|
-
if (captured.length > MAX_CAPTURED_ENTRIES) {
|
|
266259
|
-
captured.splice(0, captured.length - MAX_CAPTURED_ENTRIES);
|
|
266260
265803
|
}
|
|
266261
|
-
};
|
|
266262
|
-
const
|
|
266263
|
-
|
|
266264
|
-
};
|
|
266265
|
-
const captureWrite = (chunk) => {
|
|
266266
|
-
pushCaptured(String(chunk));
|
|
266267
|
-
return true;
|
|
266268
|
-
};
|
|
266269
|
-
const saved = {
|
|
266270
|
-
log: console.log,
|
|
266271
|
-
error: console.error,
|
|
266272
|
-
warn: console.warn,
|
|
266273
|
-
info: console.info,
|
|
266274
|
-
stdoutWrite: process.stdout.write.bind(process.stdout),
|
|
266275
|
-
stderrWrite: process.stderr.write.bind(process.stderr)
|
|
266276
|
-
};
|
|
266277
|
-
console.log = capture;
|
|
266278
|
-
console.error = capture;
|
|
266279
|
-
console.warn = capture;
|
|
266280
|
-
console.info = capture;
|
|
266281
|
-
process.stdout.write = captureWrite;
|
|
266282
|
-
process.stderr.write = captureWrite;
|
|
266283
|
-
try {
|
|
266284
|
-
return await callback();
|
|
266285
|
-
} catch (error2) {
|
|
266286
|
-
saved.error(`[captured output before failure]
|
|
266287
|
-
` + captured.join(`
|
|
266288
|
-
`));
|
|
266289
|
-
throw error2;
|
|
266290
|
-
} finally {
|
|
266291
|
-
console.log = saved.log;
|
|
266292
|
-
console.error = saved.error;
|
|
266293
|
-
console.warn = saved.warn;
|
|
266294
|
-
console.info = saved.info;
|
|
266295
|
-
process.stdout.write = saved.stdoutWrite;
|
|
266296
|
-
process.stderr.write = saved.stderrWrite;
|
|
266297
|
-
}
|
|
266298
|
-
}
|
|
266299
|
-
function maybeQuiet(jsonOutput, callback) {
|
|
266300
|
-
return jsonOutput ? withCapturedConsole(callback) : callback();
|
|
266301
|
-
}
|
|
266302
|
-
async function withBulletinHumanOutput(reporterMode, callback) {
|
|
266303
|
-
if (reporterMode === "quiet") {
|
|
266304
|
-
return withCapturedConsole(callback);
|
|
266305
|
-
}
|
|
266306
|
-
return withConsoleToStderr(callback);
|
|
266307
|
-
}
|
|
266308
|
-
async function resolveTargetAddress(positionalAddress, mergedOptions, reporterMode) {
|
|
266309
|
-
if (positionalAddress)
|
|
266310
|
-
return positionalAddress;
|
|
266311
|
-
const context = await withBulletinHumanOutput(reporterMode, () => prepareContext({ ...mergedOptions, useBulletin: true }));
|
|
266312
|
-
return context.substrateAddress;
|
|
266313
|
-
}
|
|
266314
|
-
function writeBulletinJson(payload) {
|
|
266315
|
-
process.stdout.write(`${JSON.stringify(payload)}
|
|
266316
|
-
`);
|
|
266317
|
-
}
|
|
266318
|
-
function writeBulletinJsonError(error2) {
|
|
266319
|
-
writeBulletinJson({ error: formatErrorMessage(error2) });
|
|
266320
|
-
process.exit(1);
|
|
266321
|
-
}
|
|
266322
|
-
function createPhaseHandler(reporter) {
|
|
266323
|
-
const tasks = new Map;
|
|
266324
|
-
return (event) => {
|
|
266325
|
-
const key = event.phase;
|
|
266326
|
-
const activeTask = tasks.get(key);
|
|
266327
|
-
if (event.state === "start") {
|
|
266328
|
-
activeTask?.stop();
|
|
266329
|
-
tasks.set(key, reporter.task(event.message));
|
|
266330
|
-
return;
|
|
266331
|
-
}
|
|
266332
|
-
if (event.state === "update") {
|
|
266333
|
-
if (activeTask) {
|
|
266334
|
-
activeTask.update(event.message);
|
|
266335
|
-
} else {
|
|
266336
|
-
tasks.set(key, reporter.task(event.message));
|
|
266337
|
-
}
|
|
266338
|
-
return;
|
|
266339
|
-
}
|
|
266340
|
-
if (event.state === "success") {
|
|
266341
|
-
if (activeTask) {
|
|
266342
|
-
activeTask.succeed(event.message);
|
|
266343
|
-
tasks.delete(key);
|
|
266344
|
-
} else {
|
|
266345
|
-
reporter.success(event.message);
|
|
266346
|
-
}
|
|
266347
|
-
return;
|
|
266348
|
-
}
|
|
266349
|
-
if (event.state === "warning") {
|
|
266350
|
-
if (activeTask) {
|
|
266351
|
-
activeTask.warn(event.message);
|
|
266352
|
-
tasks.delete(key);
|
|
266353
|
-
} else {
|
|
266354
|
-
reporter.warn(event.message);
|
|
266355
|
-
}
|
|
266356
|
-
return;
|
|
266357
|
-
}
|
|
266358
|
-
if (activeTask) {
|
|
266359
|
-
activeTask.fail(event.message);
|
|
266360
|
-
tasks.delete(key);
|
|
266361
|
-
return;
|
|
266362
|
-
}
|
|
266363
|
-
reporter.fail(event.message);
|
|
266364
|
-
};
|
|
266365
|
-
}
|
|
266366
|
-
function createRetryHandler(reporter) {
|
|
266367
|
-
return ({ label, retry, totalAttempts, delayMs, errorMessage }) => {
|
|
266368
|
-
reporter.warn(`${label} attempt ${retry + 1}/${totalAttempts} failed: ${errorMessage}`);
|
|
266369
|
-
reporter.detail(`retrying in ${(delayMs / 1000).toFixed(delayMs >= 1000 ? 1 : 0)}s`);
|
|
266370
|
-
};
|
|
266371
|
-
}
|
|
266372
|
-
function createChunkedUploadMonitor(reporter, phaseHandler, fileSize, chunkSizeBytes, totalChunks) {
|
|
266373
|
-
const heartbeatIntervalMs = 15000;
|
|
266374
|
-
let latestState = null;
|
|
266375
|
-
let heartbeatTimer;
|
|
266376
|
-
const startedAtMs = Date.now();
|
|
266377
|
-
const stopHeartbeat = () => {
|
|
266378
|
-
if (heartbeatTimer) {
|
|
266379
|
-
clearInterval(heartbeatTimer);
|
|
266380
|
-
heartbeatTimer = undefined;
|
|
266381
|
-
}
|
|
266382
|
-
};
|
|
266383
|
-
const emitHeartbeat = () => {
|
|
266384
|
-
if (!latestState || latestState.inFlightChunks === 0) {
|
|
266385
|
-
stopHeartbeat();
|
|
266386
|
-
return;
|
|
266387
|
-
}
|
|
266388
|
-
reporter.detail(`heartbeat | ${latestState.completedChunks}/${totalChunks} chunks | window=${latestState.window} | in-flight=${latestState.inFlightChunks} | bytes=${formatBytes(latestState.inFlightBytes)} | retries=${latestState.retries} | elapsed=${formatDuration((Date.now() - startedAtMs) / 1000)}`);
|
|
266389
|
-
};
|
|
266390
|
-
return {
|
|
266391
|
-
onSchedulerState(state3) {
|
|
266392
|
-
latestState = state3;
|
|
266393
|
-
if (reporter.mode !== "stream") {
|
|
266394
|
-
return;
|
|
266395
|
-
}
|
|
266396
|
-
if (state3.inFlightChunks > 0 && !heartbeatTimer) {
|
|
266397
|
-
heartbeatTimer = setInterval(emitHeartbeat, heartbeatIntervalMs);
|
|
266398
|
-
heartbeatTimer.unref?.();
|
|
266399
|
-
} else if (state3.inFlightChunks === 0) {
|
|
266400
|
-
stopHeartbeat();
|
|
266401
|
-
}
|
|
266402
|
-
},
|
|
266403
|
-
onWave(wave) {
|
|
266404
|
-
const completedChunks = latestState?.completedChunks ?? 0;
|
|
266405
|
-
const bytesUploaded = Math.min(fileSize, completedChunks * chunkSizeBytes);
|
|
266406
|
-
const throughputBytesPerSecond = wave.durationMs > 0 ? wave.succeeded * chunkSizeBytes * 1000 / wave.durationMs : 0;
|
|
266407
|
-
const message2 = `wave #${wave.wave} complete | ${completedChunks}/${totalChunks} chunks | ${formatBytes(bytesUploaded)}/${formatBytes(fileSize)} | ${(wave.durationMs / 1000).toFixed(1)}s | window=${wave.window} | retries=${wave.retries} | ${formatBytes(throughputBytesPerSecond)}/s`;
|
|
266408
|
-
if (reporter.mode === "interactive") {
|
|
266409
|
-
phaseHandler({ phase: "upload", state: "update", message: message2 });
|
|
266410
|
-
} else {
|
|
266411
|
-
reporter.line(message2);
|
|
266412
|
-
}
|
|
266413
|
-
},
|
|
266414
|
-
stop() {
|
|
266415
|
-
stopHeartbeat();
|
|
266416
|
-
}
|
|
266417
|
-
};
|
|
266418
|
-
}
|
|
266419
|
-
function attachBulletinCommands(root) {
|
|
266420
|
-
const bulletinCommand = addReporterOption(root.command("bulletin").description("Bulletin storage utilities")).option("--json", "Write machine-readable JSON to stdout", false);
|
|
266421
|
-
addAuthOptions(bulletinCommand);
|
|
266422
|
-
const authorizeCommand = addReporterOption(bulletinCommand.command("authorize [address]").description("Authorize an account for Bulletin TransactionStorage").option("--bulletin-rpc <wsUrl>", "Bulletin WebSocket RPC endpoint", DEFAULT_BULLETIN_RPC).option("--transactions <count>", "Number of transactions to authorize", String(DEFAULT_AUTHORIZATION_TRANSACTIONS)).option("--bytes <count>", "Number of bytes to authorize", String(DEFAULT_AUTHORIZATION_BYTES)).option("--force", "Force re-authorization even if account appears already authorized", false).option("--json", "Write machine-readable JSON to stdout", false));
|
|
266423
|
-
addAuthOptions(authorizeCommand).action(async (positionalAddress, options2, command) => {
|
|
265804
|
+
});
|
|
265805
|
+
const historyCommand = addReporterOption(bulletinCommand.command("history").alias("list").description("List all uploaded CIDs").option("--json", "Write machine-readable JSON to stdout", false));
|
|
265806
|
+
historyCommand.action(async (_options, command) => {
|
|
266424
265807
|
try {
|
|
266425
|
-
const mergedOptions = getMergedOptions2(command, options2);
|
|
266426
|
-
const jsonOutput = getJsonFlag(command);
|
|
266427
|
-
const reporterMode = resolveReporterMode(mergedOptions.reporter);
|
|
266428
|
-
const reporter = createCliReporter(mergedOptions.reporter);
|
|
266429
|
-
const onPhase = createPhaseHandler(reporter);
|
|
266430
|
-
const bulletinRpc = String(mergedOptions.bulletinRpc || DEFAULT_BULLETIN_RPC);
|
|
266431
|
-
const transactions = Number(mergedOptions.transactions || DEFAULT_AUTHORIZATION_TRANSACTIONS);
|
|
266432
|
-
const bytes = BigInt(mergedOptions.bytes || DEFAULT_AUTHORIZATION_BYTES);
|
|
266433
|
-
const force = Boolean(options2.force);
|
|
266434
|
-
const signerKeyUri = String(mergedOptions.keyUri || DEFAULT_SUDO_KEY_URI);
|
|
266435
|
-
const targetAddress = await resolveTargetAddress(positionalAddress, mergedOptions, reporterMode);
|
|
266436
|
-
const signerContext = await withBulletinHumanOutput(reporterMode, () => prepareContext({ keyUri: signerKeyUri, useBulletin: true }));
|
|
266437
|
-
if (!jsonOutput) {
|
|
266438
|
-
console.log(source_default.blue(`
|
|
266439
|
-
▶ Bulletin Authorize`));
|
|
266440
|
-
console.log(source_default.gray(" target: ") + source_default.cyan(targetAddress));
|
|
266441
|
-
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
266442
|
-
console.log(source_default.gray(" transactions: ") + source_default.white(transactions.toLocaleString()));
|
|
266443
|
-
console.log(source_default.gray(" bytes: ") + source_default.white(formatBytes(bytes)));
|
|
266444
|
-
console.log(source_default.gray(" signer: ") + source_default.yellow(signerKeyUri));
|
|
266445
|
-
}
|
|
266446
|
-
await withBulletinHumanOutput(reporterMode, () => authorizeAccount({
|
|
266447
|
-
rpc: bulletinRpc,
|
|
266448
|
-
signer: signerContext.signer,
|
|
266449
|
-
targetAddress,
|
|
266450
|
-
transactions,
|
|
266451
|
-
bytes,
|
|
266452
|
-
force,
|
|
266453
|
-
onPhase
|
|
266454
|
-
}));
|
|
266455
|
-
if (jsonOutput) {
|
|
266456
|
-
const authStatus = await checkAuthorization(bulletinRpc, targetAddress);
|
|
266457
|
-
const expiresAt = expirationToISOString(authStatus.currentBlock, authStatus.expiration);
|
|
266458
|
-
writeBulletinJson({
|
|
266459
|
-
ok: true,
|
|
266460
|
-
target: targetAddress,
|
|
266461
|
-
rpc: bulletinRpc,
|
|
266462
|
-
transactions,
|
|
266463
|
-
bytes: bytes.toString(),
|
|
266464
|
-
expiresAt
|
|
266465
|
-
});
|
|
266466
|
-
} else {
|
|
266467
|
-
console.log(source_default.green(`
|
|
266468
|
-
✓ Authorization Complete`));
|
|
266469
|
-
console.log(source_default.gray(` The account can now upload to Bulletin.
|
|
266470
|
-
`));
|
|
266471
|
-
}
|
|
266472
|
-
process.exit(0);
|
|
266473
|
-
} catch (error2) {
|
|
266474
|
-
const errorMessage = formatErrorMessage(error2);
|
|
266475
265808
|
const jsonOutput = getJsonFlag(command);
|
|
265809
|
+
const history = await readHistory();
|
|
266476
265810
|
if (jsonOutput) {
|
|
266477
|
-
|
|
265811
|
+
writeBulletinJson(history);
|
|
265812
|
+
process.exit(0);
|
|
266478
265813
|
}
|
|
266479
|
-
if (
|
|
265814
|
+
if (history.length === 0) {
|
|
266480
265815
|
console.log(source_default.yellow(`
|
|
266481
|
-
|
|
265816
|
+
No uploads in history.
|
|
265817
|
+
`));
|
|
265818
|
+
console.log(source_default.gray(` Upload files with: dotns bulletin upload <path>
|
|
266482
265819
|
`));
|
|
266483
265820
|
process.exit(0);
|
|
266484
265821
|
}
|
|
266485
|
-
|
|
266486
|
-
|
|
266487
|
-
✗ Authorization failed — insufficient privileges`));
|
|
266488
|
-
console.error(source_default.yellow(" The signer does not have Authorizer privileges on this chain."));
|
|
266489
|
-
console.error(source_default.gray(` Override with --key-uri if needed.
|
|
265822
|
+
console.log(source_default.blue(`
|
|
265823
|
+
▶ Upload History
|
|
266490
265824
|
`));
|
|
266491
|
-
|
|
266492
|
-
}
|
|
266493
|
-
if (errorMessage.includes("not applied")) {
|
|
266494
|
-
console.error(source_default.red(`
|
|
266495
|
-
✗ ${errorMessage}`));
|
|
266496
|
-
console.error(source_default.gray(` Override with --key-uri if needed.
|
|
265825
|
+
console.log(source_default.gray(` ${history.length} upload(s) found
|
|
266497
265826
|
`));
|
|
266498
|
-
|
|
265827
|
+
history.forEach((record2, index) => {
|
|
265828
|
+
const num = (index + 1).toString().padStart(2, " ");
|
|
265829
|
+
console.log(source_default.yellow(` ${num}.`) + source_default.white(` ${formatRecordTimestamp(record2)}`));
|
|
265830
|
+
console.log(source_default.gray(" cid: ") + source_default.cyan(record2.cid));
|
|
265831
|
+
console.log(source_default.gray(" path: ") + source_default.white(record2.path));
|
|
265832
|
+
console.log(source_default.gray(" type: ") + source_default.white(record2.type));
|
|
265833
|
+
if (record2.size > 0) {
|
|
265834
|
+
console.log(source_default.gray(" size: ") + source_default.white(formatBytes(record2.size)));
|
|
265835
|
+
}
|
|
265836
|
+
console.log(source_default.gray(" preview: ") + source_default.blue(getPreviewUrl(record2)));
|
|
265837
|
+
console.log();
|
|
265838
|
+
});
|
|
265839
|
+
process.exit(0);
|
|
265840
|
+
} catch (error2) {
|
|
265841
|
+
const jsonOutput = getJsonFlag(command);
|
|
265842
|
+
if (jsonOutput) {
|
|
265843
|
+
writeBulletinJsonError(error2);
|
|
266499
265844
|
}
|
|
266500
265845
|
console.error(source_default.red(`
|
|
266501
|
-
✗ Error: ${
|
|
265846
|
+
✗ Error: ${formatErrorMessage(error2)}
|
|
266502
265847
|
`));
|
|
266503
265848
|
process.exit(1);
|
|
266504
265849
|
}
|
|
266505
265850
|
});
|
|
266506
|
-
|
|
266507
|
-
addAuthOptions(uploadCommand).action(async (inputPath, options2, command) => {
|
|
265851
|
+
bulletinCommand.command("history:remove <cid>").description("Remove an upload from history by CID").action(async (cid) => {
|
|
266508
265852
|
try {
|
|
266509
|
-
const
|
|
266510
|
-
|
|
266511
|
-
|
|
266512
|
-
|
|
266513
|
-
|
|
266514
|
-
|
|
266515
|
-
|
|
266516
|
-
|
|
265853
|
+
const removed = await removeUploadRecord(cid);
|
|
265854
|
+
if (removed) {
|
|
265855
|
+
console.log(source_default.green(`
|
|
265856
|
+
✓ Removed ${cid} from history
|
|
265857
|
+
`));
|
|
265858
|
+
} else {
|
|
265859
|
+
console.log(source_default.yellow(`
|
|
265860
|
+
⚠ CID not found in history: ${cid}
|
|
265861
|
+
`));
|
|
266517
265862
|
}
|
|
266518
|
-
|
|
266519
|
-
|
|
266520
|
-
|
|
266521
|
-
|
|
266522
|
-
|
|
266523
|
-
|
|
266524
|
-
|
|
266525
|
-
|
|
266526
|
-
|
|
266527
|
-
|
|
266528
|
-
const
|
|
266529
|
-
|
|
266530
|
-
|
|
266531
|
-
|
|
266532
|
-
|
|
266533
|
-
|
|
266534
|
-
|
|
266535
|
-
|
|
266536
|
-
|
|
266537
|
-
|
|
266538
|
-
|
|
266539
|
-
|
|
266540
|
-
|
|
266541
|
-
|
|
266542
|
-
|
|
266543
|
-
|
|
266544
|
-
|
|
265863
|
+
process.exit(0);
|
|
265864
|
+
} catch (error2) {
|
|
265865
|
+
console.error(source_default.red(`
|
|
265866
|
+
✗ Error: ${formatErrorMessage(error2)}
|
|
265867
|
+
`));
|
|
265868
|
+
process.exit(1);
|
|
265869
|
+
}
|
|
265870
|
+
});
|
|
265871
|
+
addReporterOption(bulletinCommand.command("history:clear").description("Clear all upload history")).action(async () => {
|
|
265872
|
+
try {
|
|
265873
|
+
const count2 = await clearHistory();
|
|
265874
|
+
const historyPath = getHistoryPath();
|
|
265875
|
+
console.log(source_default.green(`
|
|
265876
|
+
✓ Cleared ${count2} upload(s) from history`));
|
|
265877
|
+
console.log(source_default.gray(` ${historyPath}
|
|
265878
|
+
`));
|
|
265879
|
+
process.exit(0);
|
|
265880
|
+
} catch (error2) {
|
|
265881
|
+
console.error(source_default.red(`
|
|
265882
|
+
✗ Error: ${formatErrorMessage(error2)}
|
|
265883
|
+
`));
|
|
265884
|
+
process.exit(1);
|
|
265885
|
+
}
|
|
265886
|
+
});
|
|
265887
|
+
addReporterOption(bulletinCommand.command("verify <cid>").description("Verify a CID is resolvable via IPFS gateways").option("--json", "Write machine-readable JSON to stdout", false)).action(async (cid, options2, command) => {
|
|
265888
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
265889
|
+
const jsonOutput = getJsonFlag(command) || Boolean(options2.json);
|
|
265890
|
+
const reporter = createCliReporter(mergedOptions.reporter);
|
|
265891
|
+
const p2pTask = reporter.task("Connecting to Bulletin P2P");
|
|
265892
|
+
try {
|
|
265893
|
+
if (!jsonOutput) {
|
|
265894
|
+
console.log(source_default.blue(`
|
|
265895
|
+
▶ Verifying CID`));
|
|
265896
|
+
console.log(source_default.gray(" cid: ") + source_default.cyan(cid));
|
|
266545
265897
|
}
|
|
266546
|
-
const
|
|
266547
|
-
|
|
266548
|
-
|
|
266549
|
-
|
|
266550
|
-
|
|
266551
|
-
|
|
266552
|
-
|
|
266553
|
-
|
|
266554
|
-
|
|
266555
|
-
maxConcurrency: shouldUseChunkedUpload ? concurrency : 1,
|
|
266556
|
-
outputPath: profileOutputOverride,
|
|
266557
|
-
jsonOutput
|
|
266558
|
-
}) : undefined;
|
|
266559
|
-
const totalChunks = shouldUseChunkedUpload ? Math.ceil(effectiveFileSize / chunkSizeBytes) : undefined;
|
|
266560
|
-
const chunkedMonitor = shouldUseChunkedUpload && totalChunks ? createChunkedUploadMonitor(reporter, onPhase, effectiveFileSize, chunkSizeBytes, totalChunks) : null;
|
|
266561
|
-
const performUpload = async () => {
|
|
266562
|
-
if (isDirectory) {
|
|
266563
|
-
const result2 = await storeDirectory(bulletinRpc, context.signer, resolvedPath, {
|
|
266564
|
-
concurrency,
|
|
266565
|
-
accountAddress: context.substrateAddress,
|
|
266566
|
-
maxRetries,
|
|
266567
|
-
onPhase,
|
|
266568
|
-
onRetry,
|
|
266569
|
-
waitForFinalization: false
|
|
266570
|
-
});
|
|
266571
|
-
return { cid: result2.cid, size: 0 };
|
|
266572
|
-
}
|
|
266573
|
-
if (shouldUseChunkedUpload) {
|
|
266574
|
-
const result2 = await uploadChunkedBlocks(bulletinRpc, context.signer, resolvedPath, chunkSizeBytes, effectiveFileSize, context.substrateAddress, {
|
|
266575
|
-
completedBlocks: resumedBlocks,
|
|
266576
|
-
concurrency,
|
|
266577
|
-
maxRetries,
|
|
266578
|
-
onPhase,
|
|
266579
|
-
onRetry,
|
|
266580
|
-
onSchedulerState: (state3) => {
|
|
266581
|
-
profiler?.onSchedulerState(state3);
|
|
266582
|
-
chunkedMonitor?.onSchedulerState(state3);
|
|
266583
|
-
},
|
|
266584
|
-
onWave: (wave) => {
|
|
266585
|
-
profiler?.onWave(wave);
|
|
266586
|
-
chunkedMonitor?.onWave(wave);
|
|
266587
|
-
}
|
|
265898
|
+
const p2pResult = await verifyCidViaP2P(cid);
|
|
265899
|
+
if (p2pResult.resolvable) {
|
|
265900
|
+
p2pTask.succeed("CID verified via P2P (bitswap)");
|
|
265901
|
+
if (jsonOutput) {
|
|
265902
|
+
writeBulletinJson({
|
|
265903
|
+
cid,
|
|
265904
|
+
resolvable: true,
|
|
265905
|
+
method: "p2p",
|
|
265906
|
+
gateways: [{ gateway: "p2p/bitswap", resolvable: true }]
|
|
266588
265907
|
});
|
|
266589
|
-
return { cid: result2, size: effectiveFileSize };
|
|
266590
|
-
}
|
|
266591
|
-
const result = await uploadSingleBlock(bulletinRpc, context.signer, bytes, {
|
|
266592
|
-
maxRetries,
|
|
266593
|
-
onPhase,
|
|
266594
|
-
onRetry
|
|
266595
|
-
});
|
|
266596
|
-
return { cid: result, size: bytes.length };
|
|
266597
|
-
};
|
|
266598
|
-
let cid;
|
|
266599
|
-
let uploadSize;
|
|
266600
|
-
let profileReportPath;
|
|
266601
|
-
let profileReport;
|
|
266602
|
-
const uploadStartedAtMs = Date.now();
|
|
266603
|
-
const uploadStartedAtIso = new Date(uploadStartedAtMs).toISOString();
|
|
266604
|
-
const pathBasename = resolvedPath.split("/").pop() ?? resolvedPath;
|
|
266605
|
-
if (authInfo?.expiration && authInfo.currentBlock) {
|
|
266606
|
-
reporter.detail(`auth: valid (expires ${formatExpirationDisplay(authInfo.currentBlock, authInfo.expiration)})`);
|
|
266607
|
-
}
|
|
266608
|
-
if (!jsonOutput) {
|
|
266609
|
-
if (isDirectory) {
|
|
266610
|
-
console.log(source_default.blue(`
|
|
266611
|
-
▶ Uploading directory: ${pathBasename}`));
|
|
266612
|
-
console.log(source_default.gray(" path: ") + source_default.white(resolvedPath));
|
|
266613
|
-
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
266614
|
-
console.log(source_default.gray(" concurrency: ") + source_default.white(`${concurrency}x parallel waves`));
|
|
266615
|
-
} else if (shouldUseChunkedUpload) {
|
|
266616
|
-
console.log(source_default.blue(`
|
|
266617
|
-
▶ Uploading file: ${pathBasename} (${formatBytes(effectiveFileSize)})`));
|
|
266618
|
-
console.log(source_default.gray(" path: ") + source_default.white(resolvedPath));
|
|
266619
|
-
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
266620
|
-
console.log(source_default.gray(" mode: ") + source_default.white(`chunked (${totalChunks} × ${formatBytes(chunkSizeBytes)}, adaptive window 1..${concurrency})`));
|
|
266621
265908
|
} else {
|
|
266622
|
-
console.log(source_default.
|
|
266623
|
-
|
|
266624
|
-
console.log(source_default.gray(" path: ") + source_default.white(resolvedPath));
|
|
266625
|
-
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
266626
|
-
console.log(source_default.gray(" mode: ") + source_default.white("single block"));
|
|
265909
|
+
console.log(source_default.gray(" ✓ ") + source_default.white("p2p/bitswap"));
|
|
265910
|
+
console.log();
|
|
266627
265911
|
}
|
|
265912
|
+
cleanupHeliaAndExit(0);
|
|
266628
265913
|
}
|
|
266629
|
-
|
|
266630
|
-
|
|
266631
|
-
|
|
266632
|
-
|
|
266633
|
-
|
|
266634
|
-
|
|
266635
|
-
|
|
266636
|
-
|
|
266637
|
-
const uploadFinishedAtIso = new Date(uploadFinishedAtMs).toISOString();
|
|
266638
|
-
const totalUploadTimeMs = Math.max(1, uploadFinishedAtMs - uploadStartedAtMs);
|
|
266639
|
-
const totalUploadTimeSeconds = totalUploadTimeMs / 1000;
|
|
266640
|
-
if (profiler) {
|
|
266641
|
-
const finalizedProfile = await profiler.finalize(cid, profileOutputOverride);
|
|
266642
|
-
profileReport = finalizedProfile.report;
|
|
266643
|
-
profileReportPath = finalizedProfile.outputPath;
|
|
266644
|
-
}
|
|
266645
|
-
onPhase({
|
|
266646
|
-
phase: "verify",
|
|
266647
|
-
state: "start",
|
|
266648
|
-
message: "Verifying content on Bulletin P2P..."
|
|
266649
|
-
});
|
|
266650
|
-
let verified = false;
|
|
266651
|
-
try {
|
|
266652
|
-
const p2pResult = await verifyCidViaP2P(cid);
|
|
266653
|
-
if (p2pResult.resolvable) {
|
|
266654
|
-
onPhase({ phase: "verify", state: "success", message: "Content verified via P2P" });
|
|
266655
|
-
verified = true;
|
|
266656
|
-
}
|
|
266657
|
-
} catch {}
|
|
266658
|
-
if (!verified) {
|
|
266659
|
-
onPhase({
|
|
266660
|
-
phase: "verify",
|
|
266661
|
-
state: "update",
|
|
266662
|
-
message: "P2P unavailable, checking IPFS gateways..."
|
|
266663
|
-
});
|
|
266664
|
-
const gatewayResults = await verifyCidWithMultipleGateways(cid);
|
|
266665
|
-
const resolvable = Array.from(gatewayResults.values()).some((r2) => r2.resolvable);
|
|
266666
|
-
if (resolvable) {
|
|
266667
|
-
onPhase({
|
|
266668
|
-
phase: "verify",
|
|
266669
|
-
state: "success",
|
|
266670
|
-
message: "Content verified via IPFS gateway"
|
|
266671
|
-
});
|
|
265914
|
+
p2pTask.warn("P2P verification failed, falling back to gateways");
|
|
265915
|
+
const gatewayTask = reporter.task("Checking IPFS gateways");
|
|
265916
|
+
const results = await verifyCidWithMultipleGateways(cid);
|
|
265917
|
+
const resolvableGateways = [];
|
|
265918
|
+
const failedGateways = [];
|
|
265919
|
+
for (const [gateway, result] of results) {
|
|
265920
|
+
if (result.resolvable) {
|
|
265921
|
+
resolvableGateways.push(gateway);
|
|
266672
265922
|
} else {
|
|
266673
|
-
|
|
266674
|
-
phase: "verify",
|
|
266675
|
-
state: "warning",
|
|
266676
|
-
message: "Content not yet resolvable — it may still be propagating"
|
|
266677
|
-
});
|
|
265923
|
+
failedGateways.push(gateway);
|
|
266678
265924
|
}
|
|
266679
265925
|
}
|
|
266680
|
-
const contenthash = generateContenthash(cid);
|
|
266681
|
-
const previewUrl = getPreviewUrl({
|
|
266682
|
-
cid,
|
|
266683
|
-
path: resolvedPath,
|
|
266684
|
-
type: isDirectory ? "directory" : "file",
|
|
266685
|
-
size: uploadSize,
|
|
266686
|
-
timestamp: ""
|
|
266687
|
-
});
|
|
266688
265926
|
if (jsonOutput) {
|
|
266689
|
-
const
|
|
265927
|
+
const entries = Array.from(results.entries()).map(([gateway, result]) => ({
|
|
265928
|
+
gateway,
|
|
265929
|
+
resolvable: result.resolvable,
|
|
265930
|
+
statusCode: result.statusCode,
|
|
265931
|
+
errorMessage: result.errorMessage
|
|
265932
|
+
}));
|
|
266690
265933
|
writeBulletinJson({
|
|
266691
265934
|
cid,
|
|
266692
|
-
|
|
266693
|
-
|
|
266694
|
-
|
|
266695
|
-
type: isDirectory ? "directory" : "file",
|
|
266696
|
-
size: uploadSize,
|
|
266697
|
-
authorizationExpiresAt: authExpiresAt,
|
|
266698
|
-
uploadStartedAtIso,
|
|
266699
|
-
uploadFinishedAtIso,
|
|
266700
|
-
totalUploadTimeMs,
|
|
266701
|
-
totalUploadTimeSeconds
|
|
265935
|
+
resolvable: resolvableGateways.length > 0,
|
|
265936
|
+
method: resolvableGateways.length > 0 ? "gateway" : "none",
|
|
265937
|
+
gateways: entries
|
|
266702
265938
|
});
|
|
265939
|
+
cleanupHeliaAndExit(resolvableGateways.length > 0 ? 0 : 1);
|
|
265940
|
+
}
|
|
265941
|
+
if (resolvableGateways.length > 0) {
|
|
265942
|
+
gatewayTask.succeed(`CID resolvable on ${resolvableGateways.length} gateway(s)`);
|
|
265943
|
+
for (const gw of resolvableGateways) {
|
|
265944
|
+
console.log(source_default.gray(" ✓ ") + source_default.white(gw));
|
|
265945
|
+
}
|
|
266703
265946
|
} else {
|
|
266704
|
-
|
|
266705
|
-
|
|
266706
|
-
|
|
266707
|
-
|
|
266708
|
-
|
|
266709
|
-
console.log(source_default.gray(" contenthash: ") + source_default.white(`0x${contenthash}`));
|
|
266710
|
-
}
|
|
266711
|
-
if (profileReportPath && profileReport) {
|
|
266712
|
-
console.log(source_default.gray(" profile: ") + source_default.white(profileReportPath));
|
|
266713
|
-
console.log(source_default.gray(" throughput: ") + source_default.white(`${formatBytes(profileReport.summary.throughputBytesPerSecond)}/s`));
|
|
266714
|
-
console.log(source_default.gray(" peak heap: ") + source_default.white(formatBytes(profileReport.summary.peakHeapUsed)));
|
|
265947
|
+
gatewayTask.fail("CID not resolvable on any gateway");
|
|
265948
|
+
}
|
|
265949
|
+
if (failedGateways.length > 0 && resolvableGateways.length > 0) {
|
|
265950
|
+
for (const gw of failedGateways) {
|
|
265951
|
+
console.log(source_default.gray(" ✗ ") + source_default.dim(gw));
|
|
266715
265952
|
}
|
|
266716
|
-
|
|
266717
|
-
|
|
265953
|
+
}
|
|
265954
|
+
console.log();
|
|
265955
|
+
cleanupHeliaAndExit(resolvableGateways.length > 0 ? 0 : 1);
|
|
265956
|
+
} catch (error2) {
|
|
265957
|
+
p2pTask.fail("Verification failed");
|
|
265958
|
+
const errorMessage = formatErrorMessage(error2);
|
|
265959
|
+
if (jsonOutput) {
|
|
265960
|
+
writeBulletinJsonError(errorMessage);
|
|
265961
|
+
} else {
|
|
265962
|
+
console.error(source_default.red(`
|
|
265963
|
+
✗ Error: ${errorMessage}
|
|
266718
265964
|
`));
|
|
265965
|
+
cleanupHeliaAndExit(1);
|
|
266719
265966
|
}
|
|
266720
|
-
|
|
266721
|
-
|
|
266722
|
-
|
|
266723
|
-
|
|
266724
|
-
|
|
266725
|
-
|
|
266726
|
-
|
|
266727
|
-
|
|
266728
|
-
|
|
266729
|
-
|
|
266730
|
-
|
|
266731
|
-
|
|
266732
|
-
|
|
266733
|
-
|
|
266734
|
-
|
|
266735
|
-
|
|
266736
|
-
|
|
266737
|
-
|
|
266738
|
-
|
|
266739
|
-
|
|
266740
|
-
|
|
266741
|
-
|
|
266742
|
-
|
|
266743
|
-
|
|
266744
|
-
|
|
266745
|
-
|
|
266746
|
-
|
|
266747
|
-
|
|
266748
|
-
|
|
266749
|
-
|
|
266750
|
-
|
|
266751
|
-
|
|
266752
|
-
|
|
266753
|
-
|
|
266754
|
-
|
|
266755
|
-
|
|
266756
|
-
|
|
266757
|
-
|
|
266758
|
-
|
|
266759
|
-
|
|
266760
|
-
|
|
266761
|
-
|
|
265967
|
+
}
|
|
265968
|
+
});
|
|
265969
|
+
}
|
|
265970
|
+
|
|
265971
|
+
// src/cli/commands/content.ts
|
|
265972
|
+
init_source();
|
|
265973
|
+
|
|
265974
|
+
// src/commands/contentHash.ts
|
|
265975
|
+
init_source();
|
|
265976
|
+
init__esm();
|
|
265977
|
+
init_constants();
|
|
265978
|
+
init_contractInteractions();
|
|
265979
|
+
|
|
265980
|
+
// src/commands/resolverAuth.ts
|
|
265981
|
+
init__esm();
|
|
265982
|
+
init_constants();
|
|
265983
|
+
init_contractInteractions();
|
|
265984
|
+
async function getResolverNodeInfo(clientWrapper, originSubstrateAddress, namehashNode) {
|
|
265985
|
+
const exists2 = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "recordExists", [namehashNode]);
|
|
265986
|
+
const owner = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "owner", [namehashNode]);
|
|
265987
|
+
const caller = await clientWrapper.getEvmAddress(originSubstrateAddress);
|
|
265988
|
+
return { exists: exists2 && owner !== zeroAddress, owner, caller };
|
|
265989
|
+
}
|
|
265990
|
+
async function requireResolverAuthorization(clientWrapper, originSubstrateAddress, owner, caller) {
|
|
265991
|
+
const isOwner = checksumAddress(owner) === checksumAddress(caller);
|
|
265992
|
+
const isApproved = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "isApprovedForAll", [owner, caller]);
|
|
265993
|
+
if (!isOwner && !isApproved) {
|
|
265994
|
+
throw new Error(`You do not own this domain. Owner is ${owner}, but you are ${caller}`);
|
|
265995
|
+
}
|
|
265996
|
+
}
|
|
265997
|
+
|
|
265998
|
+
// src/commands/contentHash.ts
|
|
265999
|
+
function decodeContenthashToCid(contenthash) {
|
|
266000
|
+
if (contenthash === "0x" || contenthash === "0x0" || contenthash.length < 6) {
|
|
266001
|
+
return "No CID set";
|
|
266002
|
+
}
|
|
266003
|
+
const cid = decodeIpfsContenthash(contenthash);
|
|
266004
|
+
return cid ?? `Unable to decode: ${contenthash}`;
|
|
266005
|
+
}
|
|
266006
|
+
function encodeCidToContenthash(cidString) {
|
|
266007
|
+
const encoded = encodeIpfsContenthash(cidString);
|
|
266008
|
+
return `0x${encoded}`;
|
|
266009
|
+
}
|
|
266010
|
+
async function viewDomainContentHash(clientWrapper, originSubstrateAddress, label, spinner) {
|
|
266011
|
+
const namehashNode = namehash(`${label}.dot`);
|
|
266012
|
+
spinner.start("Querying registry");
|
|
266013
|
+
const recordExists = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "recordExists", [namehashNode]);
|
|
266014
|
+
const ownerAddress = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "owner", [namehashNode]);
|
|
266015
|
+
spinner.succeed("Registry read");
|
|
266016
|
+
console.log(source_default.gray(" registry: ") + source_default.white(CONTRACTS.DOTNS_REGISTRY));
|
|
266017
|
+
console.log(source_default.gray(" domain: ") + source_default.cyan(`${label}.dot`));
|
|
266018
|
+
console.log(source_default.gray(" node: ") + source_default.white(namehashNode));
|
|
266019
|
+
console.log(source_default.gray(" exists: ") + source_default.white(String(recordExists)));
|
|
266020
|
+
console.log(source_default.gray(" owner: ") + source_default.white(ownerAddress));
|
|
266021
|
+
console.log();
|
|
266022
|
+
if (!recordExists || ownerAddress === zeroAddress) {
|
|
266023
|
+
console.log(source_default.yellow(" status: Domain not registered"));
|
|
266024
|
+
return { domain: `${label}.dot`, contenthash: null, cid: null };
|
|
266025
|
+
}
|
|
266026
|
+
const contentHashBytes = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [namehashNode]);
|
|
266027
|
+
const decodedCid = decodeContenthashToCid(contentHashBytes);
|
|
266028
|
+
console.log(source_default.gray(" resolver: ") + source_default.white(CONTRACTS.DOTNS_CONTENT_RESOLVER));
|
|
266029
|
+
console.log(source_default.gray(" contenthash: ") + source_default.white(contentHashBytes));
|
|
266030
|
+
console.log(source_default.gray(" cid: ") + source_default.cyan(decodedCid));
|
|
266031
|
+
const hasContent = decodedCid !== "No CID set";
|
|
266032
|
+
const cidResolved = hasContent && !decodedCid.startsWith("Unable to decode:") ? decodedCid : null;
|
|
266033
|
+
return {
|
|
266034
|
+
domain: `${label}.dot`,
|
|
266035
|
+
contenthash: hasContent ? contentHashBytes : null,
|
|
266036
|
+
cid: cidResolved
|
|
266037
|
+
};
|
|
266038
|
+
}
|
|
266039
|
+
async function setDomainContentHash(clientWrapper, originSubstrateAddress, signer, label, contentId, spinner) {
|
|
266040
|
+
const namehashNode = namehash(`${label}.dot`);
|
|
266041
|
+
console.log(source_default.gray(" domain: ") + source_default.cyan(`${label}.dot`));
|
|
266042
|
+
console.log(source_default.gray(" node: ") + source_default.white(namehashNode));
|
|
266043
|
+
console.log();
|
|
266044
|
+
const { exists: exists2, owner, caller } = await getResolverNodeInfo(clientWrapper, originSubstrateAddress, namehashNode);
|
|
266045
|
+
console.log(source_default.gray(" exists: ") + source_default.white(String(exists2)));
|
|
266046
|
+
console.log(source_default.gray(" owner: ") + source_default.white(owner));
|
|
266047
|
+
console.log(source_default.gray(" caller: ") + source_default.white(caller));
|
|
266048
|
+
console.log();
|
|
266049
|
+
if (!exists2) {
|
|
266050
|
+
throw new Error(`Domain ${label}.dot is not registered`);
|
|
266051
|
+
}
|
|
266052
|
+
await requireResolverAuthorization(clientWrapper, originSubstrateAddress, owner, caller);
|
|
266053
|
+
console.log(source_default.gray(" status: ") + source_default.green("Ownership verified"));
|
|
266054
|
+
console.log();
|
|
266055
|
+
try {
|
|
266056
|
+
const currentContentHash = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [namehashNode]);
|
|
266057
|
+
const currentCid = decodeContenthashToCid(currentContentHash);
|
|
266058
|
+
console.log(source_default.gray(" current: ") + source_default.cyan(currentCid));
|
|
266059
|
+
} catch {
|
|
266060
|
+
console.log(source_default.gray(" current: ") + source_default.yellow("Not set or error reading"));
|
|
266061
|
+
}
|
|
266062
|
+
console.log();
|
|
266063
|
+
const contentBytes = encodeCidToContenthash(contentId);
|
|
266064
|
+
console.log(source_default.gray(" resolver: ") + source_default.white(CONTRACTS.DOTNS_CONTENT_RESOLVER));
|
|
266065
|
+
console.log(source_default.gray(" node: ") + source_default.white(namehashNode));
|
|
266066
|
+
console.log(source_default.gray(" cid: ") + source_default.cyan(contentId));
|
|
266067
|
+
console.log(source_default.gray(" bytes: ") + source_default.white(contentBytes));
|
|
266068
|
+
spinner.start("Submitting setContenthash");
|
|
266069
|
+
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_CONTENT_RESOLVER, 0n, DOTNS_CONTENT_RESOLVER_ABI, "setContenthash", [namehashNode, contentBytes], originSubstrateAddress, signer, spinner, "setContenthash");
|
|
266070
|
+
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
266071
|
+
const updatedContentHash = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [namehashNode]);
|
|
266072
|
+
const updatedCid = decodeContenthashToCid(updatedContentHash);
|
|
266073
|
+
console.log();
|
|
266074
|
+
console.log(source_default.gray(" new: ") + source_default.cyan(updatedCid));
|
|
266075
|
+
return {
|
|
266076
|
+
ok: true,
|
|
266077
|
+
domain: `${label}.dot`,
|
|
266078
|
+
cid: contentId,
|
|
266079
|
+
contenthash: contentBytes,
|
|
266080
|
+
txHash: transactionHash
|
|
266081
|
+
};
|
|
266082
|
+
}
|
|
266083
|
+
|
|
266084
|
+
// src/cli/commands/lookup.ts
|
|
266085
|
+
init_source();
|
|
266086
|
+
init_esm10();
|
|
266087
|
+
init_ws_provider();
|
|
266088
|
+
init_dist();
|
|
266089
|
+
init_polkadotClient();
|
|
266090
|
+
|
|
266091
|
+
// src/commands/lookup.ts
|
|
266092
|
+
init_source();
|
|
266093
|
+
init_ora();
|
|
266094
|
+
init__esm();
|
|
266095
|
+
init_constants();
|
|
266096
|
+
|
|
266097
|
+
// src/utils/validation.ts
|
|
266098
|
+
init__esm();
|
|
266099
|
+
function countTrailingDigits(label) {
|
|
266100
|
+
let count2 = 0;
|
|
266101
|
+
for (let characterIndex = label.length - 1;characterIndex >= 0; characterIndex--) {
|
|
266102
|
+
const asciiCode = label.charCodeAt(characterIndex);
|
|
266103
|
+
if (asciiCode >= 48 && asciiCode <= 57) {
|
|
266104
|
+
count2++;
|
|
266105
|
+
} else {
|
|
266106
|
+
break;
|
|
266107
|
+
}
|
|
266108
|
+
}
|
|
266109
|
+
return count2;
|
|
266110
|
+
}
|
|
266111
|
+
function stripTrailingDigits(label) {
|
|
266112
|
+
return label.replace(/\d+$/, "");
|
|
266113
|
+
}
|
|
266114
|
+
function validateDomainLabel(label) {
|
|
266115
|
+
if (!/^[a-z0-9-]{3,}$/.test(label)) {
|
|
266116
|
+
throw new Error("Invalid domain label: must contain only lowercase letters, digits, and hyphens, with minimum length of 3 characters");
|
|
266117
|
+
}
|
|
266118
|
+
if (label.startsWith("-") || label.endsWith("-")) {
|
|
266119
|
+
throw new Error("Invalid domain label: cannot start or end with hyphen");
|
|
266120
|
+
}
|
|
266121
|
+
const trailingDigitCount = countTrailingDigits(label);
|
|
266122
|
+
if (trailingDigitCount > 2) {
|
|
266123
|
+
throw new Error(`Invalid domain label: maximum 2 trailing digits allowed, found ${trailingDigitCount}`);
|
|
266124
|
+
}
|
|
266125
|
+
}
|
|
266126
|
+
function validateGovernanceLabel(label) {
|
|
266127
|
+
validateDomainLabel(label);
|
|
266128
|
+
const baseName = stripTrailingDigits(label);
|
|
266129
|
+
if (baseName.length > 5) {
|
|
266130
|
+
throw new Error(`Invalid governance label: base name must be 5 characters or fewer (got ${baseName.length})`);
|
|
266131
|
+
}
|
|
266132
|
+
}
|
|
266133
|
+
var isValidSubstrateAddress = (address, ss58Format = 42) => {
|
|
266134
|
+
try {
|
|
266135
|
+
if (isHex(address))
|
|
266136
|
+
return false;
|
|
266137
|
+
const decoded = decodeAddress2(address);
|
|
266138
|
+
const checksummed = encodeAddress2(decoded, ss58Format);
|
|
266139
|
+
return address === checksummed;
|
|
266140
|
+
} catch {
|
|
266141
|
+
return false;
|
|
266142
|
+
}
|
|
266143
|
+
};
|
|
266144
|
+
|
|
266145
|
+
// src/commands/lookup.ts
|
|
266146
|
+
init_contractInteractions();
|
|
266147
|
+
init_formatting();
|
|
266148
|
+
async function performDomainLookup(label, originSubstrateAddress, clientWrapper) {
|
|
266149
|
+
const fullyQualifiedDomainName = `${label}.dot`;
|
|
266150
|
+
const namehashNode = namehash(fullyQualifiedDomainName);
|
|
266151
|
+
const result = {
|
|
266152
|
+
domain: fullyQualifiedDomainName,
|
|
266153
|
+
node: namehashNode,
|
|
266154
|
+
exists: false,
|
|
266155
|
+
owner: zeroAddress,
|
|
266156
|
+
resolver: zeroAddress,
|
|
266157
|
+
store: null,
|
|
266158
|
+
resolvedAddress: null,
|
|
266159
|
+
ownerBalance: null,
|
|
266160
|
+
baseNameReservation: null
|
|
266161
|
+
};
|
|
266162
|
+
const spinner = ora("Reading registry").start();
|
|
266163
|
+
result.exists = Boolean(await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "recordExists", [namehashNode]));
|
|
266164
|
+
result.owner = getAddress(await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "owner", [namehashNode]));
|
|
266165
|
+
result.resolver = getAddress(await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "resolver", [namehashNode]));
|
|
266166
|
+
spinner.succeed("Registry read");
|
|
266167
|
+
console.log(`
|
|
266168
|
+
▶ DotNS Domain Lookup`);
|
|
266169
|
+
console.log(source_default.gray(" domain: ") + source_default.cyan(fullyQualifiedDomainName));
|
|
266170
|
+
console.log(source_default.gray(" node: ") + source_default.white(namehashNode));
|
|
266171
|
+
console.log();
|
|
266172
|
+
console.log("▶ Registry (DotnsRegistry)");
|
|
266173
|
+
console.log(source_default.gray(" registry: ") + source_default.white(CONTRACTS.DOTNS_REGISTRY));
|
|
266174
|
+
console.log(source_default.gray(" exists: ") + source_default.white(String(result.exists)));
|
|
266175
|
+
console.log(source_default.gray(" owner: ") + source_default.white(result.owner));
|
|
266176
|
+
console.log(source_default.gray(" resolver: ") + source_default.white(result.resolver));
|
|
266177
|
+
console.log();
|
|
266178
|
+
if (!result.exists || result.owner === zeroAddress) {
|
|
266179
|
+
console.log("▶ Status");
|
|
266180
|
+
console.log(source_default.gray(" status: ") + source_default.yellow("not registered (no record)"));
|
|
266181
|
+
console.log();
|
|
266182
|
+
const baseName2 = stripTrailingDigits(label);
|
|
266183
|
+
if (baseName2 !== label) {
|
|
266184
|
+
result.baseNameReservation = await lookupBaseNameReservation(clientWrapper, originSubstrateAddress, baseName2);
|
|
266185
|
+
displayBaseNameReservation(result.baseNameReservation);
|
|
266186
|
+
}
|
|
266187
|
+
return result;
|
|
266188
|
+
}
|
|
266189
|
+
console.log("▶ User Store (StoreFactory)");
|
|
266190
|
+
console.log(source_default.gray(" factory: ") + source_default.white(CONTRACTS.STORE_FACTORY));
|
|
266191
|
+
const storeAddress = getAddress(await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.STORE_FACTORY, STORE_FACTORY_ABI, "getDeployedStore", [result.owner]));
|
|
266192
|
+
result.store = storeAddress === zeroAddress ? null : storeAddress;
|
|
266193
|
+
console.log(source_default.gray(" store: ") + source_default.white(storeAddress));
|
|
266194
|
+
console.log(source_default.gray(" status: ") + source_default.white(storeAddress === zeroAddress ? "no store deployed" : "store exists"));
|
|
266195
|
+
console.log();
|
|
266196
|
+
console.log("▶ Forward Resolution (DotnsResolver)");
|
|
266197
|
+
console.log(source_default.gray(" expectedResolver: ") + source_default.white(CONTRACTS.DOTNS_RESOLVER));
|
|
266198
|
+
if (checksumAddress(result.resolver) !== checksumAddress(CONTRACTS.DOTNS_RESOLVER)) {
|
|
266199
|
+
console.log(source_default.gray(" note: ") + source_default.yellow("registry resolver is not DotnsResolver, skipping address lookup"));
|
|
266200
|
+
} else {
|
|
266201
|
+
try {
|
|
266202
|
+
const resolvedAddress = getAddress(await performContractCall(clientWrapper, originSubstrateAddress, result.resolver, DOTNS_RESOLVER_ABI, "addressOf", [namehashNode]));
|
|
266203
|
+
result.resolvedAddress = resolvedAddress === zeroAddress ? null : resolvedAddress;
|
|
266204
|
+
console.log(source_default.gray(" resolvedAddress: ") + source_default.white(resolvedAddress === zeroAddress ? "(not set)" : resolvedAddress));
|
|
266205
|
+
} catch {
|
|
266206
|
+
console.log(source_default.gray(" resolvedAddress: ") + source_default.yellow("lookup failed"));
|
|
266207
|
+
}
|
|
266208
|
+
}
|
|
266209
|
+
console.log();
|
|
266210
|
+
console.log("▶ Owner Balance");
|
|
266211
|
+
try {
|
|
266212
|
+
const ownerSubstrateAddress = await clientWrapper.getSubstrateAddress(result.owner);
|
|
266213
|
+
const accountInfo = await clientWrapper.client.query.System.Account.getValue(ownerSubstrateAddress);
|
|
266214
|
+
const freeBalance = accountInfo.data.free;
|
|
266215
|
+
result.ownerBalance = {
|
|
266216
|
+
substrate: ownerSubstrateAddress,
|
|
266217
|
+
free: formatNativeBalance(freeBalance)
|
|
266218
|
+
};
|
|
266219
|
+
console.log(source_default.gray(" substrate: ") + source_default.white(ownerSubstrateAddress));
|
|
266220
|
+
console.log(source_default.gray(" free: ") + source_default.white(formatNativeBalance(freeBalance) + " PAS"));
|
|
266221
|
+
} catch {
|
|
266222
|
+
console.log(source_default.gray(" balance: ") + source_default.yellow("unavailable"));
|
|
266223
|
+
}
|
|
266224
|
+
console.log();
|
|
266225
|
+
const baseName = stripTrailingDigits(label);
|
|
266226
|
+
if (baseName !== label) {
|
|
266227
|
+
result.baseNameReservation = await lookupBaseNameReservation(clientWrapper, originSubstrateAddress, baseName);
|
|
266228
|
+
displayBaseNameReservation(result.baseNameReservation);
|
|
266229
|
+
}
|
|
266230
|
+
console.log("▶ Lookup completed");
|
|
266231
|
+
return result;
|
|
266232
|
+
}
|
|
266233
|
+
async function lookupBaseNameReservation(clientWrapper, originSubstrateAddress, baseName) {
|
|
266234
|
+
try {
|
|
266235
|
+
const reservationInfo = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "isBaseNameReserved", [baseName]);
|
|
266236
|
+
const [isReserved, reservationOwner, expirationTimestamp] = reservationInfo;
|
|
266237
|
+
return {
|
|
266238
|
+
baseName,
|
|
266239
|
+
isReserved,
|
|
266240
|
+
reservedBy: getAddress(reservationOwner),
|
|
266241
|
+
expires: expirationTimestamp > 0n ? new Date(Number(expirationTimestamp) * 1000).toISOString() : null
|
|
266242
|
+
};
|
|
266243
|
+
} catch {
|
|
266244
|
+
return {
|
|
266245
|
+
expires: null,
|
|
266246
|
+
baseName,
|
|
266247
|
+
isReserved: false,
|
|
266248
|
+
reservedBy: zeroAddress
|
|
266249
|
+
};
|
|
266250
|
+
}
|
|
266251
|
+
}
|
|
266252
|
+
function displayBaseNameReservation(reservation) {
|
|
266253
|
+
console.log("▶ Base Name Reservation (PopRules)");
|
|
266254
|
+
console.log(source_default.gray(" oracle: ") + source_default.white(CONTRACTS.DOTNS_RULES));
|
|
266255
|
+
console.log(source_default.gray(" baseName: ") + source_default.cyan(reservation.baseName));
|
|
266256
|
+
console.log(source_default.gray(" isReserved: ") + source_default.white(String(reservation.isReserved)));
|
|
266257
|
+
console.log(source_default.gray(" owner: ") + source_default.white(reservation.reservedBy));
|
|
266258
|
+
if (reservation.expires) {
|
|
266259
|
+
console.log(source_default.gray(" expires: ") + source_default.white(reservation.expires));
|
|
266260
|
+
}
|
|
266261
|
+
console.log();
|
|
266262
|
+
}
|
|
266263
|
+
async function performOwnerOfLookup(name10, substrateAddress, clientWrapper) {
|
|
266264
|
+
if (!name10 || name10.trim().length === 0) {
|
|
266265
|
+
throw new Error("--owner-of requires a <label>");
|
|
266266
|
+
}
|
|
266267
|
+
const label = name10.trim();
|
|
266268
|
+
console.log(source_default.bold(`
|
|
266269
|
+
\uD83D\uDD0E Ownership lookup
|
|
266270
|
+
`));
|
|
266271
|
+
console.log(source_default.gray(" Label: ") + source_default.cyan(label));
|
|
266272
|
+
console.log(source_default.gray(" Domain: ") + source_default.cyan(label + ".dot"));
|
|
266273
|
+
const tokenId = computeDomainTokenId(label);
|
|
266274
|
+
let actualOwner;
|
|
266275
|
+
let isRegistered;
|
|
266276
|
+
try {
|
|
266277
|
+
actualOwner = await withTimeout(performContractCall(clientWrapper, substrateAddress, CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 30000, "ownerOf");
|
|
266278
|
+
isRegistered = actualOwner !== zeroAddress;
|
|
266279
|
+
} catch (error2) {
|
|
266280
|
+
const errorMessage = formatErrorMessage(error2);
|
|
266281
|
+
if (errorMessage.includes("Contract reverted") || errorMessage.includes("does not exist")) {
|
|
266282
|
+
actualOwner = zeroAddress;
|
|
266283
|
+
isRegistered = false;
|
|
266284
|
+
} else {
|
|
266285
|
+
throw error2;
|
|
266286
|
+
}
|
|
266287
|
+
}
|
|
266288
|
+
const ownerSubstrateAddress = isRegistered ? await clientWrapper.getSubstrateAddress(actualOwner) : "(none)";
|
|
266289
|
+
console.log(source_default.gray(`
|
|
266290
|
+
Registered: `) + source_default.white(String(isRegistered)));
|
|
266291
|
+
console.log(source_default.gray(" Owner (EVM): ") + source_default.white(isRegistered ? actualOwner : "(none)"));
|
|
266292
|
+
console.log(source_default.gray(" Owner (Substrate): ") + source_default.white(ownerSubstrateAddress));
|
|
266293
|
+
return {
|
|
266294
|
+
label,
|
|
266295
|
+
domain: `${label}.dot`,
|
|
266296
|
+
registered: isRegistered,
|
|
266297
|
+
ownerEvm: isRegistered ? actualOwner : zeroAddress,
|
|
266298
|
+
ownerSubstrate: ownerSubstrateAddress
|
|
266299
|
+
};
|
|
266300
|
+
}
|
|
266301
|
+
|
|
266302
|
+
// src/commands/register.ts
|
|
266303
|
+
init_source();
|
|
266304
|
+
init_ora();
|
|
266305
|
+
init__esm();
|
|
266306
|
+
init_formatting();
|
|
266307
|
+
import crypto16 from "crypto";
|
|
266308
|
+
|
|
266309
|
+
// src/types/types.ts
|
|
266310
|
+
var ProofOfPersonhoodStatus;
|
|
266311
|
+
((ProofOfPersonhoodStatus2) => {
|
|
266312
|
+
ProofOfPersonhoodStatus2[ProofOfPersonhoodStatus2["NoStatus"] = 0] = "NoStatus";
|
|
266313
|
+
ProofOfPersonhoodStatus2[ProofOfPersonhoodStatus2["ProofOfPersonhoodLite"] = 1] = "ProofOfPersonhoodLite";
|
|
266314
|
+
ProofOfPersonhoodStatus2[ProofOfPersonhoodStatus2["ProofOfPersonhoodFull"] = 2] = "ProofOfPersonhoodFull";
|
|
266315
|
+
ProofOfPersonhoodStatus2[ProofOfPersonhoodStatus2["Reserved"] = 3] = "Reserved";
|
|
266316
|
+
})(ProofOfPersonhoodStatus ||= {});
|
|
266317
|
+
|
|
266318
|
+
// src/commands/register.ts
|
|
266319
|
+
init_constants();
|
|
266320
|
+
init_contractInteractions();
|
|
266321
|
+
init_formatting();
|
|
266322
|
+
function redactSecret(secret) {
|
|
266323
|
+
if (secret.length <= 10)
|
|
266324
|
+
return "0x" + "*".repeat(secret.length - 2);
|
|
266325
|
+
const prefix = secret.slice(0, 6);
|
|
266326
|
+
const suffix = secret.slice(-4);
|
|
266327
|
+
const redacted = "*".repeat(secret.length - 10);
|
|
266328
|
+
return `${prefix}${redacted}${suffix}`;
|
|
266329
|
+
}
|
|
266330
|
+
function convertToProofOfPersonhoodStatus(value3) {
|
|
266331
|
+
if (typeof value3 === "number")
|
|
266332
|
+
return value3;
|
|
266333
|
+
if (typeof value3 === "bigint")
|
|
266334
|
+
return Number(value3);
|
|
266335
|
+
throw new Error(`Unexpected ProofOfPersonhoodStatus type: ${typeof value3}`);
|
|
266336
|
+
}
|
|
266337
|
+
async function classifyDomainName(clientWrapper, originSubstrateAddress, label) {
|
|
266338
|
+
const spinner = ora("Classifying name via PopRules").start();
|
|
266339
|
+
try {
|
|
266340
|
+
const classificationResult = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "classifyName", [label]), 30000, "classifyName");
|
|
266341
|
+
const requiredStatus = convertToProofOfPersonhoodStatus(classificationResult[0]);
|
|
266342
|
+
const message2 = classificationResult[1];
|
|
266343
|
+
spinner.succeed("Name classification");
|
|
266344
|
+
console.log(source_default.gray(" required: ") + source_default.white(ProofOfPersonhoodStatus[requiredStatus]));
|
|
266345
|
+
console.log(source_default.gray(" message: ") + source_default.white(message2));
|
|
266346
|
+
return { requiredStatus, message: message2 };
|
|
266347
|
+
} catch (error2) {
|
|
266348
|
+
spinner.fail("Name classification failed");
|
|
266349
|
+
throw error2;
|
|
266350
|
+
}
|
|
266351
|
+
}
|
|
266352
|
+
async function ensureDomainNotRegistered(clientWrapper, originSubstrateAddress, label) {
|
|
266353
|
+
const spinner = ora(`Checking availability of ${source_default.cyan(label + ".dot")}`).start();
|
|
266354
|
+
const tokenId = computeDomainTokenId(label);
|
|
266355
|
+
try {
|
|
266356
|
+
const owner = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 30000, "Availability check");
|
|
266357
|
+
if (owner !== zeroAddress) {
|
|
266358
|
+
spinner.fail(`Name ${source_default.cyan(label + ".dot")} already owned by ${source_default.yellow(owner)}`);
|
|
266359
|
+
throw new Error(`Domain already owned by ${owner}`);
|
|
266360
|
+
}
|
|
266361
|
+
} catch (error2) {
|
|
266362
|
+
const errorMessage = formatErrorMessage(error2);
|
|
266363
|
+
if (errorMessage.includes("already owned"))
|
|
266364
|
+
throw error2;
|
|
266365
|
+
}
|
|
266366
|
+
spinner.succeed(`Name ${source_default.cyan(label + ".dot")} is available`);
|
|
266367
|
+
}
|
|
266368
|
+
async function generateCommitment(clientWrapper, originSubstrateAddress, label, ownerAddress, includeReverse) {
|
|
266369
|
+
const spinner = ora("Generating commitment hash").start();
|
|
266370
|
+
try {
|
|
266371
|
+
validateDomainLabel(label);
|
|
266372
|
+
const secret = `0x${crypto16.randomBytes(32).toString("hex")}`;
|
|
266373
|
+
const registration = {
|
|
266374
|
+
label,
|
|
266375
|
+
owner: ownerAddress,
|
|
266376
|
+
secret,
|
|
266377
|
+
reserved: includeReverse
|
|
266378
|
+
};
|
|
266379
|
+
const commitment = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, DOTNS_REGISTRAR_CONTROLLER_ABI, "makeCommitment", [registration]), 30000, "Commitment generation");
|
|
266380
|
+
spinner.succeed("Commitment hash generated");
|
|
266381
|
+
console.log(source_default.gray(" commitment: ") + source_default.blue(commitment));
|
|
266382
|
+
console.log(source_default.gray(" hash: ") + source_default.dim("label + owner + secret + reserved"));
|
|
266383
|
+
console.log(source_default.gray(" secret: ") + source_default.yellow(redactSecret(secret)));
|
|
266384
|
+
console.log(source_default.gray(" reserved: ") + (includeReverse ? source_default.green("true") : source_default.white("false")));
|
|
266385
|
+
return { commitment, registration };
|
|
266386
|
+
} catch (error2) {
|
|
266387
|
+
spinner.fail("Failed to create commitment");
|
|
266388
|
+
throw error2;
|
|
266389
|
+
}
|
|
266390
|
+
}
|
|
266391
|
+
async function submitCommitment(clientWrapper, substrateAddress, signer, commitment) {
|
|
266392
|
+
const spinner = ora("Submitting commitment to controller").start();
|
|
266393
|
+
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, 0n, DOTNS_REGISTRAR_CONTROLLER_ABI, "commit", [commitment], substrateAddress, signer, spinner, "Commitment");
|
|
266394
|
+
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
266395
|
+
console.log(source_default.gray(" committed: ") + source_default.white(new Date().toISOString()));
|
|
266396
|
+
}
|
|
266397
|
+
async function waitForMinimumCommitmentAge(clientWrapper, originSubstrateAddress, commitment, commitmentBuffer) {
|
|
266398
|
+
const buffer2 = commitmentBuffer ?? DEFAULT_COMMITMENT_BUFFER_SECONDS;
|
|
266399
|
+
const checkSpinner = ora("Reading minimum commitment age").start();
|
|
266400
|
+
const [minimumAge, initialCommitTimestamp] = await Promise.all([
|
|
266401
|
+
withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, DOTNS_REGISTRAR_CONTROLLER_ABI, "minCommitmentAge", []), 30000, "minCommitmentAge"),
|
|
266402
|
+
withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, DOTNS_REGISTRAR_CONTROLLER_ABI, "commitments", [commitment]), 30000, "commitments")
|
|
266403
|
+
]);
|
|
266404
|
+
const minimumAgeSeconds = typeof minimumAge === "bigint" ? Number(minimumAge) : minimumAge;
|
|
266405
|
+
const initialCommitTime = typeof initialCommitTimestamp === "bigint" ? Number(initialCommitTimestamp) : initialCommitTimestamp;
|
|
266406
|
+
if (initialCommitTime === 0) {
|
|
266407
|
+
checkSpinner.fail("Commitment not found on-chain");
|
|
266408
|
+
throw new Error("Commitment not found on-chain. It may not have been included in a block yet.");
|
|
266409
|
+
}
|
|
266410
|
+
const waitSeconds = minimumAgeSeconds + buffer2;
|
|
266411
|
+
checkSpinner.succeed(`Minimum commitment age: ${source_default.yellow(waitSeconds.toString() + "s")}`);
|
|
266412
|
+
const waitSpinner = ora(`Waiting for commitment age (${waitSeconds}s)`).start();
|
|
266413
|
+
let elapsedSeconds = 0;
|
|
266414
|
+
const intervalId = setInterval(() => {
|
|
266415
|
+
elapsedSeconds++;
|
|
266416
|
+
const remainingSeconds = waitSeconds - elapsedSeconds;
|
|
266417
|
+
waitSpinner.text = `Waiting for commitment age (${source_default.yellow(remainingSeconds + "s")} remaining)`;
|
|
266418
|
+
}, 1000);
|
|
266419
|
+
await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1000));
|
|
266420
|
+
clearInterval(intervalId);
|
|
266421
|
+
waitSpinner.text = "Verifying commitment age on-chain";
|
|
266422
|
+
const pollDeadline = Date.now() + COMMITMENT_POLL_TIMEOUT_MS;
|
|
266423
|
+
while (Date.now() < pollDeadline) {
|
|
266424
|
+
const polledTimestamp = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, DOTNS_REGISTRAR_CONTROLLER_ABI, "commitments", [commitment]);
|
|
266425
|
+
const polledCommitTime = typeof polledTimestamp === "bigint" ? Number(polledTimestamp) : polledTimestamp;
|
|
266426
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
266427
|
+
if (polledCommitTime > 0 && nowSeconds - polledCommitTime >= minimumAgeSeconds) {
|
|
266428
|
+
waitSpinner.succeed("Commitment age requirement met (verified on-chain)");
|
|
266429
|
+
return;
|
|
266430
|
+
}
|
|
266431
|
+
waitSpinner.text = `Commitment still too new, polling (${Math.ceil((pollDeadline - Date.now()) / 1000)}s remaining)`;
|
|
266432
|
+
await new Promise((resolve) => setTimeout(resolve, COMMITMENT_POLL_INTERVAL_MS));
|
|
266433
|
+
}
|
|
266434
|
+
waitSpinner.fail("Commitment age verification timed out");
|
|
266435
|
+
throw new Error(`Commitment still too new after ${waitSeconds + COMMITMENT_POLL_TIMEOUT_MS / 1000}s. The chain's block timestamps may be advancing slower than expected. Try increasing --commitment-buffer or DOTNS_COMMITMENT_BUFFER.`);
|
|
266436
|
+
}
|
|
266437
|
+
async function getUserProofOfPersonhoodStatus(clientWrapper, originSubstrateAddress, ownerAddress) {
|
|
266438
|
+
const userStatusRaw = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "userPopStatus", [ownerAddress]), 30000, "userPopStatus");
|
|
266439
|
+
return convertToProofOfPersonhoodStatus(userStatusRaw);
|
|
266440
|
+
}
|
|
266441
|
+
async function getPriceAndValidateEligibility(clientWrapper, originSubstrateAddress, label, ownerAddress) {
|
|
266442
|
+
const spinner = ora("Pricing via PopRules.price").start();
|
|
266443
|
+
try {
|
|
266444
|
+
validateDomainLabel(label);
|
|
266445
|
+
const baseName = stripTrailingDigits(label);
|
|
266446
|
+
const reservationInfo = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "isBaseNameReserved", [baseName]), 30000, "isBaseNameReserved");
|
|
266447
|
+
const [isReserved, reservationOwner] = reservationInfo;
|
|
266448
|
+
if (isReserved && checksumAddress(reservationOwner) !== checksumAddress(ownerAddress)) {
|
|
266449
|
+
spinner.fail("Eligibility failed");
|
|
266450
|
+
throw new Error("Base name reserved for original Lite registrant");
|
|
266451
|
+
}
|
|
266452
|
+
const classificationResult = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_RULES, POP_RULES_ABI, "priceWithoutCheck", [label, ownerAddress]), 30000, "priceWithoutCheck");
|
|
266453
|
+
const requiredStatus = convertToProofOfPersonhoodStatus(classificationResult.status);
|
|
266454
|
+
const message2 = classificationResult.message;
|
|
266455
|
+
const userStatus = await getUserProofOfPersonhoodStatus(clientWrapper, originSubstrateAddress, ownerAddress);
|
|
266456
|
+
if (requiredStatus === 3 /* Reserved */) {
|
|
266457
|
+
spinner.fail("Eligibility failed");
|
|
266458
|
+
throw new Error(message2);
|
|
266459
|
+
}
|
|
266460
|
+
if (requiredStatus === 2 /* ProofOfPersonhoodFull */) {
|
|
266461
|
+
if (userStatus !== 2 /* ProofOfPersonhoodFull */) {
|
|
266462
|
+
spinner.fail("Eligibility failed");
|
|
266463
|
+
throw new Error("Requires Full Personhood verification");
|
|
266464
|
+
}
|
|
266465
|
+
} else if (requiredStatus === 1 /* ProofOfPersonhoodLite */) {
|
|
266466
|
+
if (userStatus !== 1 /* ProofOfPersonhoodLite */ && userStatus !== 2 /* ProofOfPersonhoodFull */) {
|
|
266467
|
+
spinner.fail("Eligibility failed");
|
|
266468
|
+
throw new Error("Requires Personhood Lite verification");
|
|
266469
|
+
}
|
|
266470
|
+
} else {
|
|
266471
|
+
const trailingDigitCount = countTrailingDigits(label);
|
|
266472
|
+
if (trailingDigitCount === 0 || userStatus === 1 /* ProofOfPersonhoodLite */) {
|
|
266473
|
+
spinner.fail("Eligibility failed");
|
|
266474
|
+
throw new Error(`Personhood Lite cannot register base names
|
|
266475
|
+
This means another user already owns the name without digits`);
|
|
266476
|
+
}
|
|
266477
|
+
}
|
|
266478
|
+
spinner.succeed("Eligibility and price");
|
|
266479
|
+
console.log(source_default.gray(" required: ") + source_default.white(ProofOfPersonhoodStatus[requiredStatus]));
|
|
266480
|
+
console.log(source_default.gray(" user: ") + source_default.white(ProofOfPersonhoodStatus[userStatus]));
|
|
266481
|
+
console.log(source_default.gray(" message: ") + source_default.white(message2));
|
|
266482
|
+
console.log(source_default.gray(" price: ") + source_default.green(`${classificationResult.priceWei > 0n ? formatWeiAsEther(classificationResult.priceWei) : 0n} PAS`));
|
|
266483
|
+
return {
|
|
266484
|
+
priceWei: classificationResult.price ?? classificationResult.priceWei,
|
|
266485
|
+
requiredStatus,
|
|
266486
|
+
userStatus,
|
|
266487
|
+
message: message2,
|
|
266488
|
+
status: requiredStatus,
|
|
266489
|
+
price: classificationResult.price ?? classificationResult.priceWei
|
|
266490
|
+
};
|
|
266491
|
+
} catch (error2) {
|
|
266492
|
+
if (!spinner.isSpinning)
|
|
266493
|
+
throw error2;
|
|
266494
|
+
spinner.fail("Pricing failed");
|
|
266495
|
+
throw error2;
|
|
266496
|
+
}
|
|
266497
|
+
}
|
|
266498
|
+
async function finalizeRegularRegistration(clientWrapper, substrateAddress, signer, registration, priceWei) {
|
|
266499
|
+
const spinner = ora(`Registering ${source_default.cyan(registration.label + ".dot")}`).start();
|
|
266500
|
+
try {
|
|
266501
|
+
const bufferedPaymentWei = priceWei * 110n / 100n;
|
|
266502
|
+
const bufferedPaymentNative = convertWeiToNative(bufferedPaymentWei);
|
|
266503
|
+
console.log(source_default.gray(" oracle: ") + source_default.green(formatWeiAsEther(priceWei) + " PAS"));
|
|
266504
|
+
console.log(source_default.gray(" paying: ") + source_default.green(formatWeiAsEther(bufferedPaymentWei) + " PAS"));
|
|
266505
|
+
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, bufferedPaymentNative, DOTNS_REGISTRAR_CONTROLLER_ABI, "register", [registration], substrateAddress, signer, spinner, "Registration");
|
|
266506
|
+
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
266507
|
+
console.log(source_default.gray(" paid: ") + source_default.green(formatWeiAsEther(bufferedPaymentWei) + " PAS"));
|
|
266508
|
+
} catch (error2) {
|
|
266509
|
+
spinner.fail("Registration failed");
|
|
266510
|
+
throw error2;
|
|
266511
|
+
}
|
|
266512
|
+
}
|
|
266513
|
+
async function finalizeGovernanceRegistration(clientWrapper, substrateAddress, signer, registration) {
|
|
266514
|
+
const spinner = ora(`Registering governance name ${source_default.cyan(registration.label + ".dot")}`).start();
|
|
266515
|
+
try {
|
|
266516
|
+
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRAR_CONTROLLER, 0n, DOTNS_REGISTRAR_CONTROLLER_ABI, "registerReserved", [registration], substrateAddress, signer, spinner, "Governance Registration");
|
|
266517
|
+
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
266518
|
+
} catch (error2) {
|
|
266519
|
+
spinner.fail("Governance registration failed");
|
|
266520
|
+
throw error2;
|
|
266521
|
+
}
|
|
266522
|
+
}
|
|
266523
|
+
async function registerSubnode(clientWrapper, substrateAddress, signer, sublabel, parentLabel, ownerAddress) {
|
|
266524
|
+
const fullName = `${sublabel}.${parentLabel}.dot`;
|
|
266525
|
+
const spinner = ora(`Registering subname ${source_default.cyan(fullName)}`).start();
|
|
266526
|
+
try {
|
|
266527
|
+
const parentNode = namehash(`${parentLabel}.dot`);
|
|
266528
|
+
const subnodeRecord = {
|
|
266529
|
+
parentNode,
|
|
266530
|
+
subLabel: sublabel,
|
|
266531
|
+
parentLabel,
|
|
266532
|
+
owner: ownerAddress
|
|
266533
|
+
};
|
|
266534
|
+
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRY, 0n, DOTNS_REGISTRY_ABI, "setSubnodeOwner", [subnodeRecord], substrateAddress, signer, spinner, "Subname registration");
|
|
266535
|
+
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
266536
|
+
return transactionHash;
|
|
266537
|
+
} catch (error2) {
|
|
266538
|
+
spinner.fail("Subname registration failed");
|
|
266539
|
+
throw error2;
|
|
266540
|
+
}
|
|
266541
|
+
}
|
|
266542
|
+
async function verifyDomainOwnership(clientWrapper, originSubstrateAddress, label, expectedOwner) {
|
|
266543
|
+
const spinner = ora("Verifying minted ownership").start();
|
|
266544
|
+
try {
|
|
266545
|
+
const tokenId = computeDomainTokenId(label);
|
|
266546
|
+
const actualOwner = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]), 30000, "ownerOf");
|
|
266547
|
+
if (checksumAddress(actualOwner) !== checksumAddress(expectedOwner)) {
|
|
266548
|
+
spinner.fail("Ownership verification failed");
|
|
266549
|
+
console.log(source_default.gray(" expected: ") + source_default.white(expectedOwner));
|
|
266550
|
+
console.log(source_default.gray(" actual: ") + source_default.white(actualOwner));
|
|
266551
|
+
throw new Error(`Owner mismatch for ${label}.dot`);
|
|
266552
|
+
}
|
|
266553
|
+
spinner.succeed("Ownership verified");
|
|
266554
|
+
console.log(source_default.gray(" owner: ") + source_default.white(actualOwner));
|
|
266555
|
+
return actualOwner;
|
|
266556
|
+
} catch (error2) {
|
|
266557
|
+
spinner.fail("Ownership verification failed");
|
|
266558
|
+
throw error2;
|
|
266559
|
+
}
|
|
266560
|
+
}
|
|
266561
|
+
async function displayDeployedStore(clientWrapper, originSubstrateAddress, ownerAddress) {
|
|
266562
|
+
const spinner = ora("Reading deployed Store address").start();
|
|
266563
|
+
try {
|
|
266564
|
+
const storeAddress = await withTimeout(performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.STORE_FACTORY, STORE_FACTORY_ABI, "getDeployedStore", [ownerAddress]), 30000, "getDeployedStore");
|
|
266565
|
+
spinner.succeed("Store");
|
|
266566
|
+
console.log(source_default.gray(" store: ") + (storeAddress === zeroAddress ? source_default.yellow("not deployed") : source_default.cyan(storeAddress)));
|
|
266567
|
+
} catch (error2) {
|
|
266568
|
+
spinner.fail("Failed to read Store address");
|
|
266569
|
+
throw error2;
|
|
266570
|
+
}
|
|
266571
|
+
}
|
|
266572
|
+
async function ensureStoreAuthorizations2(clientWrapper, substrateAddress, signer, evmAddress) {
|
|
266573
|
+
const storeAddress = getAddress(await withTimeout(performContractCall(clientWrapper, substrateAddress, CONTRACTS.STORE_FACTORY, STORE_FACTORY_ABI, "getDeployedStore", [evmAddress]), 30000, "getDeployedStore"));
|
|
266574
|
+
if (storeAddress === zeroAddress)
|
|
266575
|
+
return;
|
|
266576
|
+
const spinner = ora("Checking Store authorizations").start();
|
|
266577
|
+
const [controllerAuthorized, registryAuthorized] = await Promise.all([
|
|
266578
|
+
Boolean(await performContractCall(clientWrapper, substrateAddress, storeAddress, STORE_ABI, "isAuthorized", [CONTRACTS.DOTNS_REGISTRAR_CONTROLLER])),
|
|
266579
|
+
Boolean(await performContractCall(clientWrapper, substrateAddress, storeAddress, STORE_ABI, "isAuthorized", [CONTRACTS.DOTNS_REGISTRY]))
|
|
266580
|
+
]);
|
|
266581
|
+
if (controllerAuthorized && registryAuthorized) {
|
|
266582
|
+
spinner.succeed("Store authorizations verified");
|
|
266583
|
+
console.log(source_default.gray(" controller: ") + source_default.white(CONTRACTS.DOTNS_REGISTRAR_CONTROLLER));
|
|
266584
|
+
console.log(source_default.gray(" registry: ") + source_default.white(CONTRACTS.DOTNS_REGISTRY));
|
|
266585
|
+
return;
|
|
266586
|
+
}
|
|
266587
|
+
spinner.warn("Store authorizations need update");
|
|
266588
|
+
if (!controllerAuthorized) {
|
|
266589
|
+
const controllerSpinner = ora("Authorizing registrar controller as Store writer").start();
|
|
266590
|
+
const tx = await submitContractTransaction(clientWrapper, storeAddress, 0n, STORE_ABI, "authorizeStore", [CONTRACTS.DOTNS_REGISTRAR_CONTROLLER], substrateAddress, signer, controllerSpinner, "Authorize controller");
|
|
266591
|
+
console.log(source_default.gray(" tx: ") + source_default.blue(tx));
|
|
266592
|
+
console.log(source_default.gray(" controller: ") + source_default.white(CONTRACTS.DOTNS_REGISTRAR_CONTROLLER));
|
|
266593
|
+
}
|
|
266594
|
+
if (!registryAuthorized) {
|
|
266595
|
+
const registrySpinner = ora("Authorizing registry as Store writer").start();
|
|
266596
|
+
const tx = await submitContractTransaction(clientWrapper, storeAddress, 0n, STORE_ABI, "authorizeStore", [CONTRACTS.DOTNS_REGISTRY], substrateAddress, signer, registrySpinner, "Authorize registry");
|
|
266597
|
+
console.log(source_default.gray(" tx: ") + source_default.blue(tx));
|
|
266598
|
+
console.log(source_default.gray(" registry: ") + source_default.white(CONTRACTS.DOTNS_REGISTRY));
|
|
266599
|
+
}
|
|
266600
|
+
}
|
|
266601
|
+
async function setUserProofOfPersonhoodStatus(clientWrapper, substrateAddress, signer, ownerAddress, label, status) {
|
|
266602
|
+
const displayName = label ? source_default.cyan(label) : "account";
|
|
266603
|
+
const checkSpinner = ora(`Checking current PoP status for ${displayName}`).start();
|
|
266604
|
+
try {
|
|
266605
|
+
const currentStatus = await getUserProofOfPersonhoodStatus(clientWrapper, substrateAddress, ownerAddress);
|
|
266606
|
+
checkSpinner.succeed("Current PoP status");
|
|
266607
|
+
console.log(source_default.gray(" current: ") + source_default.white(ProofOfPersonhoodStatus[currentStatus]));
|
|
266608
|
+
console.log(source_default.gray(" desired: ") + source_default.white(ProofOfPersonhoodStatus[status]));
|
|
266609
|
+
if (currentStatus === status) {
|
|
266610
|
+
console.log(source_default.yellow(` ↳ Status already set to ${ProofOfPersonhoodStatus[status]}, skipping update`));
|
|
266611
|
+
return;
|
|
266612
|
+
}
|
|
266613
|
+
const updateSpinner = ora(`Setting PoP status for ${displayName} to ${source_default.yellow(ProofOfPersonhoodStatus[status])}`).start();
|
|
266614
|
+
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_RULES, 0n, POP_RULES_ABI, "setUserPopStatus", [status], substrateAddress, signer, updateSpinner, "PoP status update");
|
|
266615
|
+
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
266616
|
+
} catch (error2) {
|
|
266617
|
+
if (checkSpinner.isSpinning)
|
|
266618
|
+
checkSpinner.fail("Failed to check PoP status");
|
|
266619
|
+
throw error2;
|
|
266620
|
+
}
|
|
266621
|
+
}
|
|
266622
|
+
|
|
266623
|
+
// src/cli/commands/lookup.ts
|
|
266624
|
+
init_env();
|
|
266625
|
+
init_formatting();
|
|
266626
|
+
|
|
266627
|
+
// src/cli/transfer.ts
|
|
266628
|
+
init_source();
|
|
266629
|
+
init_ora();
|
|
266630
|
+
init__esm();
|
|
266631
|
+
init_constants();
|
|
266632
|
+
init_formatting();
|
|
266633
|
+
init_contractInteractions();
|
|
266634
|
+
function toChecksummed(a2) {
|
|
266635
|
+
return checksumAddress(a2);
|
|
266636
|
+
}
|
|
266637
|
+
function isLabelLike(input) {
|
|
266638
|
+
return /^[a-z0-9-]{3,}$/.test(input);
|
|
266639
|
+
}
|
|
266640
|
+
function asDotLabel(input) {
|
|
266641
|
+
const raw = input.trim().toLowerCase();
|
|
266642
|
+
if (raw.endsWith(".dot"))
|
|
266643
|
+
return raw.slice(0, -4);
|
|
266644
|
+
return raw;
|
|
266645
|
+
}
|
|
266646
|
+
async function ownerOfLabel(clientWrapper, originSubstrateAddress, label) {
|
|
266647
|
+
const tokenId = computeDomainTokenId(label);
|
|
266648
|
+
return await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRAR, DOTNS_REGISTRAR_ABI, "ownerOf", [tokenId]);
|
|
266649
|
+
}
|
|
266650
|
+
async function resolveTransferRecipient(clientWrapper, originSubstrateAddress, recipientIdentifier) {
|
|
266651
|
+
const input = recipientIdentifier.trim();
|
|
266652
|
+
if (isAddress(input))
|
|
266653
|
+
return toChecksummed(input);
|
|
266654
|
+
const label = asDotLabel(input);
|
|
266655
|
+
if (isLabelLike(label)) {
|
|
266656
|
+
const spinner2 = ora(`Resolving ${source_default.cyan(label + ".dot")} to owner address`).start();
|
|
266657
|
+
const ownerAddress = await ownerOfLabel(clientWrapper, originSubstrateAddress, label);
|
|
266658
|
+
if (ownerAddress === zeroAddress) {
|
|
266659
|
+
spinner2.fail(`No owner found for ${source_default.cyan(label + ".dot")} (unregistered)`);
|
|
266660
|
+
throw new Error(`Domain ${label}.dot has no owner`);
|
|
266661
|
+
}
|
|
266662
|
+
spinner2.succeed(`${source_default.cyan(label + ".dot")} → ${source_default.white(toChecksummed(ownerAddress))}`);
|
|
266663
|
+
return toChecksummed(ownerAddress);
|
|
266664
|
+
}
|
|
266665
|
+
const spinner = ora(`Resolving recipient address`).start();
|
|
266666
|
+
const evmAddress = await clientWrapper.getEvmAddress(input);
|
|
266667
|
+
spinner.succeed(`${source_default.white(input)} → ${source_default.white(toChecksummed(evmAddress))}`);
|
|
266668
|
+
return toChecksummed(evmAddress);
|
|
266669
|
+
}
|
|
266670
|
+
async function transferDomain(clientWrapper, originSubstrateAddress, signer, fromAddress, toAddress, label) {
|
|
266671
|
+
const spinner = ora().start();
|
|
266672
|
+
const normLabel = asDotLabel(label);
|
|
266673
|
+
spinner.text = `Validating ${source_default.cyan(normLabel + ".dot")}`;
|
|
266674
|
+
validateDomainLabel(normLabel);
|
|
266675
|
+
spinner.succeed(`Valid: ${source_default.cyan(normLabel + ".dot")}`);
|
|
266676
|
+
spinner.start(`Checking owner of ${source_default.cyan(normLabel + ".dot")}`);
|
|
266677
|
+
const tokenId = computeDomainTokenId(normLabel);
|
|
266678
|
+
const currentOwner = await ownerOfLabel(clientWrapper, originSubstrateAddress, normLabel);
|
|
266679
|
+
const currentOwnerC = toChecksummed(currentOwner);
|
|
266680
|
+
spinner.succeed(`Owner: ${source_default.cyan(normLabel + ".dot")} → ${source_default.white(currentOwnerC)}`);
|
|
266681
|
+
const fromC = toChecksummed(fromAddress);
|
|
266682
|
+
const toC = toChecksummed(toAddress);
|
|
266683
|
+
if (currentOwner === zeroAddress) {
|
|
266684
|
+
spinner.fail(`${source_default.cyan(normLabel + ".dot")} is not registered`);
|
|
266685
|
+
throw new Error(`Cannot transfer: ${normLabel}.dot is not registered`);
|
|
266686
|
+
}
|
|
266687
|
+
if (currentOwnerC !== fromC) {
|
|
266688
|
+
spinner.fail(`Not authorized to transfer ${source_default.cyan(normLabel + ".dot")}`);
|
|
266689
|
+
console.log(source_default.gray(" expected owner: ") + source_default.white(fromC));
|
|
266690
|
+
console.log(source_default.gray(" on-chain owner: ") + source_default.white(currentOwnerC));
|
|
266691
|
+
throw new Error(`Cannot transfer: ${normLabel}.dot owned by ${currentOwnerC}`);
|
|
266692
|
+
}
|
|
266693
|
+
try {
|
|
266694
|
+
const syncSpinner = ora(`Syncing label ${source_default.cyan(normLabel)} with registrar`).start();
|
|
266695
|
+
await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRAR, 0n, DOTNS_REGISTRAR_ABI, "syncLabel", [tokenId, normLabel], originSubstrateAddress, signer, syncSpinner, "Label sync");
|
|
266696
|
+
syncSpinner.succeed("Label synced");
|
|
266697
|
+
} catch (error2) {
|
|
266698
|
+
const errorMessage = formatErrorMessage(error2);
|
|
266699
|
+
if (!errorMessage.includes("LabelAlreadySet")) {
|
|
266700
|
+
console.log(source_default.yellow(" Label sync skipped: " + errorMessage.split(`
|
|
266701
|
+
`)[0]));
|
|
266702
|
+
}
|
|
266703
|
+
}
|
|
266704
|
+
spinner.start(`Submitting transfer ${source_default.cyan(normLabel + ".dot")} → ${source_default.green(toC)}`);
|
|
266705
|
+
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_REGISTRAR, 0n, DOTNS_REGISTRAR_ABI, "transferFrom", [fromC, toC, tokenId], originSubstrateAddress, signer, spinner, "Transfer");
|
|
266706
|
+
spinner.succeed(`Transfer finalized`);
|
|
266707
|
+
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
266708
|
+
console.log(source_default.gray(" from: ") + source_default.yellow(fromC));
|
|
266709
|
+
console.log(source_default.gray(" to: ") + source_default.green(toC));
|
|
266710
|
+
console.log(source_default.gray(" name: ") + source_default.cyan(normLabel + ".dot"));
|
|
266711
|
+
}
|
|
266712
|
+
|
|
266713
|
+
// src/cli/commands/register.ts
|
|
266714
|
+
init_source();
|
|
266715
|
+
init__esm();
|
|
266716
|
+
|
|
266717
|
+
// src/cli/labels.ts
|
|
266718
|
+
function generateRandomLabel(status) {
|
|
266719
|
+
const alphabet4 = "abcdefghijklmnopqrstuvwxyz";
|
|
266720
|
+
const alphanumeric = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
266721
|
+
const randomInteger = (maxExclusive) => Math.floor(Math.random() * maxExclusive);
|
|
266722
|
+
const randomCharacters = (characterSet, count2) => {
|
|
266723
|
+
let result = "";
|
|
266724
|
+
for (let i2 = 0;i2 < count2; i2++)
|
|
266725
|
+
result += characterSet[randomInteger(characterSet.length)];
|
|
266726
|
+
return result;
|
|
266727
|
+
};
|
|
266728
|
+
const twoDigits = () => String(randomInteger(99) + 1).padStart(2, "0");
|
|
266729
|
+
const baseEndingWithLetter = (length5) => {
|
|
266730
|
+
if (length5 <= 0)
|
|
266731
|
+
throw new Error("Invalid base length");
|
|
266732
|
+
if (length5 === 1)
|
|
266733
|
+
return randomCharacters(alphabet4, 1);
|
|
266734
|
+
return randomCharacters(alphanumeric, length5 - 1) + randomCharacters(alphabet4, 1);
|
|
266735
|
+
};
|
|
266736
|
+
if (status === 1 /* ProofOfPersonhoodLite */) {
|
|
266737
|
+
const baseLength = 6 + randomInteger(3);
|
|
266738
|
+
return baseEndingWithLetter(baseLength) + twoDigits();
|
|
266739
|
+
}
|
|
266740
|
+
if (status === 0 /* NoStatus */) {
|
|
266741
|
+
const baseLength = 9 + randomInteger(6);
|
|
266742
|
+
return baseEndingWithLetter(baseLength) + twoDigits();
|
|
266743
|
+
}
|
|
266744
|
+
if (status === 2 /* ProofOfPersonhoodFull */) {
|
|
266745
|
+
const baseLength = randomInteger(2) === 0 ? 6 + randomInteger(3) : 9 + randomInteger(6);
|
|
266746
|
+
return baseEndingWithLetter(baseLength);
|
|
266747
|
+
}
|
|
266748
|
+
throw new Error("Cannot auto-generate Reserved names");
|
|
266749
|
+
}
|
|
266750
|
+
function parseProofOfPersonhoodStatus(statusString) {
|
|
266751
|
+
const normalized = statusString.toLowerCase();
|
|
266752
|
+
if (normalized === "none" || normalized === "nostatus")
|
|
266753
|
+
return 0 /* NoStatus */;
|
|
266754
|
+
if (normalized === "lite" || normalized === "poplite")
|
|
266755
|
+
return 1 /* ProofOfPersonhoodLite */;
|
|
266756
|
+
if (normalized === "full" || normalized === "popfull")
|
|
266757
|
+
return 2 /* ProofOfPersonhoodFull */;
|
|
266758
|
+
throw new Error("Invalid status: use none, lite, or full");
|
|
266759
|
+
}
|
|
266760
|
+
|
|
266761
|
+
// src/cli/commands/register.ts
|
|
266762
|
+
function resolveTransferDestination(options2) {
|
|
266763
|
+
const legacy = options2.transferTo;
|
|
266764
|
+
const modern = options2.to;
|
|
266765
|
+
const destination = legacy ?? modern;
|
|
266766
|
+
if (options2.transfer === true && !destination) {
|
|
266767
|
+
throw new Error("Missing transfer destination: use --to <evm|ss58|label>");
|
|
266768
|
+
}
|
|
266769
|
+
if (options2.transfer === false && legacy) {
|
|
266770
|
+
return legacy;
|
|
266771
|
+
}
|
|
266772
|
+
return destination;
|
|
266773
|
+
}
|
|
266774
|
+
function classifyTransferDestination(destination) {
|
|
266775
|
+
if (isAddress(destination))
|
|
266776
|
+
return "evm";
|
|
266777
|
+
if (isValidSubstrateAddress(destination))
|
|
266778
|
+
return "substrate";
|
|
266779
|
+
return "label";
|
|
266780
|
+
}
|
|
266781
|
+
function isValidTransferDestination(destination) {
|
|
266782
|
+
const kind = classifyTransferDestination(destination);
|
|
266783
|
+
if (kind === "evm" || kind === "substrate")
|
|
266784
|
+
return true;
|
|
266785
|
+
const domainLabelPattern = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
266786
|
+
return domainLabelPattern.test(destination) && destination.length >= 3 && destination.length <= 63;
|
|
266787
|
+
}
|
|
266788
|
+
async function executeRegistration(options2 = {}) {
|
|
266789
|
+
if (options2.mnemonic && options2.keyUri) {
|
|
266790
|
+
throw new Error("Cannot specify both --mnemonic and --key-uri");
|
|
266791
|
+
}
|
|
266792
|
+
if (options2.parent) {
|
|
266793
|
+
return executeSubnameRegistration(options2);
|
|
266794
|
+
}
|
|
266795
|
+
const transferDestination = resolveTransferDestination(options2);
|
|
266796
|
+
if (transferDestination && !isValidTransferDestination(transferDestination)) {
|
|
266797
|
+
throw new Error("Invalid transfer destination: must be valid EVM address, Substrate address, or domain label");
|
|
266798
|
+
}
|
|
266799
|
+
const context = await prepareAssetHubContext(options2);
|
|
266800
|
+
const { clientWrapper, substrateAddress, signer, evmAddress } = context;
|
|
266801
|
+
const statusWasProvided = options2.__statusProvided === true;
|
|
266802
|
+
const popStatusConfig = statusWasProvided ? { mode: "set", status: parseProofOfPersonhoodStatus(options2.status ?? "none") } : { mode: "unchanged" };
|
|
266803
|
+
const label = options2.name ?? generateRandomLabel(popStatusConfig.mode === "set" ? popStatusConfig.status : 0 /* NoStatus */);
|
|
266804
|
+
console.log(source_default.gray(" Mode: ") + source_default.yellow(options2.governance ? "Governance registration" : "Regular registration"));
|
|
266805
|
+
console.log(source_default.gray(" Label: ") + source_default.cyan(label));
|
|
266806
|
+
console.log(source_default.gray(" Domain: ") + source_default.cyan(label + ".dot"));
|
|
266807
|
+
console.log(source_default.gray(" Transfer: ") + (transferDestination ? source_default.green("post-mint") : source_default.gray("none")));
|
|
266808
|
+
await step("Ensuring account mapped", async () => clientWrapper.ensureAccountMapped(substrateAddress, signer));
|
|
266809
|
+
if (options2.governance) {
|
|
266810
|
+
await executeGovernanceRegistration(clientWrapper, substrateAddress, signer, evmAddress, label, transferDestination, options2.commitmentBuffer);
|
|
266811
|
+
} else {
|
|
266812
|
+
await executeRegularRegistration(clientWrapper, substrateAddress, signer, evmAddress, label, popStatusConfig, options2.reverse ?? false, transferDestination, options2.commitmentBuffer);
|
|
266813
|
+
}
|
|
266814
|
+
console.log(`
|
|
266815
|
+
${source_default.bold.green("═══════════════════════════════════════")}`);
|
|
266816
|
+
console.log(`${source_default.bold.green(" ✓ Operation Complete ")}`);
|
|
266817
|
+
console.log(`${source_default.bold.green("═══════════════════════════════════════")}
|
|
266818
|
+
`);
|
|
266819
|
+
console.log(source_default.gray(" Domain: ") + source_default.cyan(label + ".dot"));
|
|
266820
|
+
return { ok: true, label, domain: `${label}.dot`, owner: evmAddress };
|
|
266821
|
+
}
|
|
266822
|
+
async function executeSubnameRegistration(options2) {
|
|
266823
|
+
if (!options2.name) {
|
|
266824
|
+
throw new Error("Missing subname: use --name <sublabel>");
|
|
266825
|
+
}
|
|
266826
|
+
if (!options2.parent) {
|
|
266827
|
+
throw new Error("Missing parent: use --parent <parentlabel>");
|
|
266828
|
+
}
|
|
266829
|
+
const context = await prepareAssetHubContext(options2);
|
|
266830
|
+
const { clientWrapper, substrateAddress, signer, evmAddress } = context;
|
|
266831
|
+
const sublabel = options2.name;
|
|
266832
|
+
const parentLabel = options2.parent;
|
|
266833
|
+
const ownerAddress = options2.owner ?? evmAddress;
|
|
266834
|
+
const fullName = `${sublabel}.${parentLabel}.dot`;
|
|
266835
|
+
console.log(source_default.bold(`
|
|
266836
|
+
▶ Subname Registration
|
|
266837
|
+
`));
|
|
266838
|
+
console.log(source_default.gray(" Subname: ") + source_default.cyan(fullName));
|
|
266839
|
+
console.log(source_default.gray(" Parent: ") + source_default.white(`${parentLabel}.dot`));
|
|
266840
|
+
console.log(source_default.gray(" Owner: ") + source_default.white(ownerAddress));
|
|
266841
|
+
await step("Ensuring account mapped", async () => clientWrapper.ensureAccountMapped(substrateAddress, signer));
|
|
266842
|
+
await registerSubnode(clientWrapper, substrateAddress, signer, sublabel, parentLabel, ownerAddress);
|
|
266843
|
+
console.log(`
|
|
266844
|
+
${source_default.bold.green("═══════════════════════════════════════")}`);
|
|
266845
|
+
console.log(`${source_default.bold.green(" ✓ Subname Registered ")}`);
|
|
266846
|
+
console.log(`${source_default.bold.green("═══════════════════════════════════════")}
|
|
266847
|
+
`);
|
|
266848
|
+
console.log(source_default.gray(" Domain: ") + source_default.cyan(fullName));
|
|
266849
|
+
return {
|
|
266850
|
+
ok: true,
|
|
266851
|
+
label: sublabel,
|
|
266852
|
+
parent: parentLabel,
|
|
266853
|
+
domain: fullName,
|
|
266854
|
+
owner: ownerAddress
|
|
266855
|
+
};
|
|
266856
|
+
}
|
|
266857
|
+
async function executeGovernanceRegistration(clientWrapper, substrateAddress, signer, evmAddress, label, transferDestination, commitmentBuffer) {
|
|
266858
|
+
console.log(source_default.bold(`
|
|
266859
|
+
\uD83C\uDFDB Governance registration (commit-reveal)
|
|
266860
|
+
`));
|
|
266861
|
+
validateGovernanceLabel(label);
|
|
266862
|
+
const classification = await step("Classifying name", async () => classifyDomainName(clientWrapper, substrateAddress, label));
|
|
266863
|
+
if (classification.requiredStatus !== 3 /* Reserved */) {
|
|
266864
|
+
throw new Error(`Governance name must classify as Reserved; got ${ProofOfPersonhoodStatus[classification.requiredStatus]}`);
|
|
266865
|
+
}
|
|
266866
|
+
await step("Checking availability", async () => ensureDomainNotRegistered(clientWrapper, substrateAddress, label));
|
|
266867
|
+
const { commitment, registration } = await step("Generating commitment", async () => generateCommitment(clientWrapper, substrateAddress, label, evmAddress, true));
|
|
266868
|
+
await step("Submitting commitment", async () => submitCommitment(clientWrapper, substrateAddress, signer, commitment));
|
|
266869
|
+
await step("Waiting commitment age", async () => waitForMinimumCommitmentAge(clientWrapper, substrateAddress, commitment, commitmentBuffer));
|
|
266870
|
+
await step("Finalizing registration", async () => finalizeGovernanceRegistration(clientWrapper, substrateAddress, signer, registration));
|
|
266871
|
+
await step("Verifying ownership", async () => verifyDomainOwnership(clientWrapper, substrateAddress, label, evmAddress));
|
|
266872
|
+
await step("Displaying store", async () => displayDeployedStore(clientWrapper, substrateAddress, evmAddress));
|
|
266873
|
+
await step("Ensuring store authorizations", async () => ensureStoreAuthorizations2(clientWrapper, substrateAddress, signer, evmAddress));
|
|
266874
|
+
if (transferDestination) {
|
|
266875
|
+
const recipient = await step("Resolving recipient", async () => resolveTransferRecipient(clientWrapper, substrateAddress, transferDestination));
|
|
266876
|
+
await step("Transferring domain", async () => transferDomain(clientWrapper, substrateAddress, signer, evmAddress, recipient, label));
|
|
266877
|
+
await step("Verifying ownership", async () => verifyDomainOwnership(clientWrapper, substrateAddress, label, recipient));
|
|
266878
|
+
}
|
|
266879
|
+
}
|
|
266880
|
+
async function executeRegularRegistration(clientWrapper, substrateAddress, signer, evmAddress, label, popStatusConfig, enableReverseRecord, transferDestination, commitmentBuffer) {
|
|
266881
|
+
console.log(source_default.bold(`
|
|
266882
|
+
\uD83E\uDDFE Regular registration (commit-reveal)
|
|
266883
|
+
`));
|
|
266884
|
+
validateDomainLabel(label);
|
|
266885
|
+
const classification = await step("Classifying name", async () => classifyDomainName(clientWrapper, substrateAddress, label));
|
|
266886
|
+
if (popStatusConfig.mode === "set") {
|
|
266887
|
+
await step("Setting PoP status", async () => setUserProofOfPersonhoodStatus(clientWrapper, substrateAddress, signer, evmAddress, label, popStatusConfig.status));
|
|
266888
|
+
}
|
|
266889
|
+
await step("Checking availability", async () => ensureDomainNotRegistered(clientWrapper, substrateAddress, label));
|
|
266890
|
+
const { commitment, registration } = await step("Generating commitment", async () => generateCommitment(clientWrapper, substrateAddress, label, evmAddress, enableReverseRecord));
|
|
266891
|
+
await step("Submitting commitment", async () => submitCommitment(clientWrapper, substrateAddress, signer, commitment));
|
|
266892
|
+
await step("Waiting commitment age", async () => waitForMinimumCommitmentAge(clientWrapper, substrateAddress, commitment, commitmentBuffer));
|
|
266893
|
+
const pricing = await step("Pricing and eligibility", async () => getPriceAndValidateEligibility(clientWrapper, substrateAddress, label, evmAddress));
|
|
266894
|
+
await step("Finalizing registration", async () => finalizeRegularRegistration(clientWrapper, substrateAddress, signer, registration, pricing.priceWei));
|
|
266895
|
+
await step("Verifying ownership", async () => verifyDomainOwnership(clientWrapper, substrateAddress, label, evmAddress));
|
|
266896
|
+
await step("Displaying store", async () => displayDeployedStore(clientWrapper, substrateAddress, evmAddress));
|
|
266897
|
+
await step("Ensuring store authorizations", async () => ensureStoreAuthorizations2(clientWrapper, substrateAddress, signer, evmAddress));
|
|
266898
|
+
if (transferDestination) {
|
|
266899
|
+
const recipient = await step("Resolving recipient", async () => resolveTransferRecipient(clientWrapper, substrateAddress, transferDestination));
|
|
266900
|
+
await step("Transferring domain", async () => transferDomain(clientWrapper, substrateAddress, signer, evmAddress, recipient, label));
|
|
266901
|
+
await step("Verifying ownership", async () => verifyDomainOwnership(clientWrapper, substrateAddress, label, recipient));
|
|
266902
|
+
}
|
|
266903
|
+
}
|
|
266904
|
+
|
|
266905
|
+
// src/cli/commands/lookup.ts
|
|
266906
|
+
function createClientWrapper(rpc) {
|
|
266907
|
+
const client = createClient3(getWsProvider(rpc)).getTypedApi(paseo_default);
|
|
266908
|
+
return new ReviveClientWrapper(client);
|
|
266909
|
+
}
|
|
266910
|
+
function hasAnyAuthHint(opts) {
|
|
266911
|
+
return opts.mnemonic != null && String(opts.mnemonic).length > 0 || opts.keyUri != null && String(opts.keyUri).length > 0 || opts.keystorePath != null && String(opts.keystorePath).length > 0 || opts.account != null && String(opts.account).length > 0 || opts.password != null && String(opts.password).length > 0;
|
|
266912
|
+
}
|
|
266913
|
+
function withReadOnlyPasswordFallback(opts) {
|
|
266914
|
+
const passwordEnv = process.env.DOTNS_KEYSTORE_PASSWORD;
|
|
266915
|
+
if ((opts.password == null || String(opts.password).length === 0) && passwordEnv && passwordEnv.length > 0) {
|
|
266916
|
+
return { ...opts, password: passwordEnv };
|
|
266917
|
+
}
|
|
266918
|
+
return opts;
|
|
266919
|
+
}
|
|
266920
|
+
async function prepareReadOnlyContext(options2) {
|
|
266921
|
+
const rpc = resolveRpc(options2.rpc);
|
|
266922
|
+
const clientWrapper = await step(`Connecting RPC ${rpc}`, async () => createClientWrapper(rpc));
|
|
266923
|
+
const auth = await step("Resolving read-only account", async () => {
|
|
266924
|
+
if (hasAnyAuthHint(options2)) {
|
|
266925
|
+
const merged = withReadOnlyPasswordFallback(options2);
|
|
266926
|
+
const resolved2 = await resolveAuthSource(merged);
|
|
266927
|
+
return {
|
|
266928
|
+
source: resolved2.source,
|
|
266929
|
+
isKeyUri: resolved2.isKeyUri,
|
|
266930
|
+
resolvedFrom: resolved2.resolvedFrom,
|
|
266931
|
+
account: resolved2.account
|
|
266932
|
+
};
|
|
266933
|
+
}
|
|
266934
|
+
const resolved = await resolveAuthSourceReadOnly();
|
|
266935
|
+
return {
|
|
266936
|
+
source: resolved.source,
|
|
266937
|
+
isKeyUri: resolved.isKeyUri,
|
|
266938
|
+
resolvedFrom: resolved.resolvedFrom,
|
|
266939
|
+
account: resolved.account
|
|
266940
|
+
};
|
|
266941
|
+
});
|
|
266942
|
+
const keypair3 = await step("Loading keypair", async () => createAccountFromSource(auth.source, auth.isKeyUri));
|
|
266943
|
+
const evmAddress = await step("Resolving EVM address", async () => clientWrapper.getEvmAddress(keypair3.address));
|
|
266944
|
+
console.log(source_default.gray(`
|
|
266945
|
+
RPC: `) + source_default.white(rpc));
|
|
266946
|
+
console.log(source_default.gray(" Account: ") + source_default.white(keypair3.address));
|
|
266947
|
+
return { clientWrapper, account: { address: keypair3.address }, rpc, evmAddress };
|
|
266948
|
+
}
|
|
266949
|
+
async function resolveRecipientByKind(clientWrapper, substrateAddress, destination) {
|
|
266950
|
+
const kind = classifyTransferDestination(destination);
|
|
266951
|
+
switch (kind) {
|
|
266952
|
+
case "evm":
|
|
266953
|
+
return destination;
|
|
266954
|
+
case "substrate":
|
|
266955
|
+
return clientWrapper.getEvmAddress(destination);
|
|
266956
|
+
case "label":
|
|
266957
|
+
return resolveTransferRecipient(clientWrapper, substrateAddress, destination);
|
|
266958
|
+
}
|
|
266959
|
+
}
|
|
266960
|
+
function attachLookupCommands(root) {
|
|
266961
|
+
const lookupCommand = root.command("lookup").description("Lookup domain information");
|
|
266962
|
+
addAuthOptions(lookupCommand);
|
|
266963
|
+
const lookupNameCommand = lookupCommand.command("name [label]").description("Lookup comprehensive domain information").option("-n, --name <label>", "Domain label to lookup (alternative to positional argument)").option("--json", "Output result as JSON (suppresses all other output)", false);
|
|
266964
|
+
addAuthOptions(lookupNameCommand).action(async (positionalLabel, options2, cmd) => {
|
|
266965
|
+
try {
|
|
266966
|
+
const merged = {
|
|
266967
|
+
...options2 ?? {},
|
|
266968
|
+
...getAuthOptions(cmd),
|
|
266969
|
+
__positionalLabel: positionalLabel
|
|
266970
|
+
};
|
|
266971
|
+
const label = merged.name || merged.__positionalLabel;
|
|
266972
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
266973
|
+
if (!label) {
|
|
266974
|
+
if (jsonOutput) {
|
|
266975
|
+
console.error(JSON.stringify({ error: "Domain label is required" }));
|
|
266976
|
+
process.exit(1);
|
|
266762
266977
|
}
|
|
266978
|
+
console.error(source_default.red(`
|
|
266979
|
+
Error: Domain label is required
|
|
266980
|
+
`));
|
|
266981
|
+
console.log(source_default.gray("Usage: dotns lookup name <label>"));
|
|
266982
|
+
console.log(source_default.gray(" or: dotns lookup name --name <label>"));
|
|
266983
|
+
console.log(source_default.gray(` or: dotns lookup --name <label>
|
|
266984
|
+
`));
|
|
266985
|
+
process.exit(1);
|
|
266763
266986
|
}
|
|
266764
|
-
|
|
266765
|
-
|
|
266766
|
-
|
|
266767
|
-
|
|
266768
|
-
|
|
266769
|
-
|
|
266770
|
-
|
|
266987
|
+
const { clientWrapper, account } = await maybeQuiet(jsonOutput, () => prepareReadOnlyContext(merged));
|
|
266988
|
+
if (!jsonOutput)
|
|
266989
|
+
console.log(source_default.bold(`
|
|
266990
|
+
▶ Domain Lookup
|
|
266991
|
+
`));
|
|
266992
|
+
const result = await maybeQuiet(jsonOutput, () => performDomainLookup(label, account.address, clientWrapper));
|
|
266993
|
+
if (jsonOutput) {
|
|
266994
|
+
console.log(JSON.stringify(result));
|
|
266995
|
+
} else {
|
|
266996
|
+
console.log(source_default.green(`
|
|
266997
|
+
✓ Complete
|
|
266998
|
+
`));
|
|
266771
266999
|
}
|
|
266772
267000
|
process.exit(0);
|
|
266773
267001
|
} catch (error2) {
|
|
266774
267002
|
const errorMessage = formatErrorMessage(error2);
|
|
266775
|
-
const jsonOutput = getJsonFlag(
|
|
267003
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
266776
267004
|
if (jsonOutput) {
|
|
266777
|
-
|
|
267005
|
+
console.error(JSON.stringify({ error: errorMessage }));
|
|
267006
|
+
process.exit(1);
|
|
266778
267007
|
}
|
|
266779
267008
|
console.error(source_default.red(`
|
|
266780
267009
|
✗ Error: ${errorMessage}
|
|
@@ -266782,61 +267011,35 @@ function attachBulletinCommands(root) {
|
|
|
266782
267011
|
process.exit(1);
|
|
266783
267012
|
}
|
|
266784
267013
|
});
|
|
266785
|
-
|
|
266786
|
-
|
|
266787
|
-
|
|
266788
|
-
|
|
266789
|
-
|
|
266790
|
-
|
|
266791
|
-
|
|
266792
|
-
|
|
266793
|
-
|
|
266794
|
-
|
|
266795
|
-
|
|
266796
|
-
|
|
266797
|
-
if (jsonOutput) {
|
|
266798
|
-
writeBulletinJson({
|
|
266799
|
-
address: targetAddress,
|
|
266800
|
-
rpc: bulletinRpc,
|
|
266801
|
-
authorized: authStatus.authorized,
|
|
266802
|
-
expired: authStatus.expired ?? false,
|
|
266803
|
-
transactions: authStatus.transactions ?? 0,
|
|
266804
|
-
bytes: (authStatus.bytes ?? BigInt(0)).toString(),
|
|
266805
|
-
expiresAt: expirationToISOString(authStatus.currentBlock, authStatus.expiration)
|
|
266806
|
-
});
|
|
266807
|
-
} else {
|
|
266808
|
-
console.log(source_default.blue(`
|
|
266809
|
-
▶ Bulletin Authorization Status`));
|
|
266810
|
-
console.log(source_default.gray(" account: ") + source_default.cyan(targetAddress));
|
|
266811
|
-
console.log(source_default.gray(" rpc: ") + source_default.white(bulletinRpc));
|
|
266812
|
-
if (!authStatus.authorized) {
|
|
266813
|
-
console.log(source_default.gray(" status: ") + source_default.red("not authorized"));
|
|
266814
|
-
console.log(source_default.gray(`
|
|
266815
|
-
Authorize with: dotns bulletin authorize ` + targetAddress + `
|
|
267014
|
+
lookupCommand.option("-n, --name <label>", "Domain label to lookup").option("--json", "Output result as JSON (suppresses all other output)", false).action(async (options2, cmd) => {
|
|
267015
|
+
const subcommand = cmd.args?.[0];
|
|
267016
|
+
if (["name", "owner-of", "oo", "transfer"].includes(subcommand))
|
|
267017
|
+
return;
|
|
267018
|
+
if (options2.name) {
|
|
267019
|
+
try {
|
|
267020
|
+
const merged = { ...options2 ?? {}, ...getAuthOptions(cmd) };
|
|
267021
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
267022
|
+
const { clientWrapper, account } = await maybeQuiet(jsonOutput, () => prepareReadOnlyContext(merged));
|
|
267023
|
+
if (!jsonOutput)
|
|
267024
|
+
console.log(source_default.bold(`
|
|
267025
|
+
▶ Domain Lookup
|
|
266816
267026
|
`));
|
|
267027
|
+
const result = await maybeQuiet(jsonOutput, () => performDomainLookup(merged.name, account.address, clientWrapper));
|
|
267028
|
+
if (jsonOutput) {
|
|
267029
|
+
console.log(JSON.stringify(result));
|
|
266817
267030
|
} else {
|
|
266818
|
-
|
|
266819
|
-
|
|
266820
|
-
console.log(source_default.gray(" status: ") + (isExpired ? source_default.red("expired") : source_default.green("authorized")));
|
|
266821
|
-
console.log(source_default.gray(isExpired ? " expired: " : " expires: ") + (isExpired ? source_default.red(dateDisplay) : source_default.white(dateDisplay)));
|
|
266822
|
-
console.log(source_default.gray(" transactions: ") + source_default.white((authStatus.transactions ?? 0).toLocaleString()));
|
|
266823
|
-
console.log(source_default.gray(" bytes: ") + source_default.white(formatBytes(authStatus.bytes ?? BigInt(0))));
|
|
266824
|
-
if (isExpired) {
|
|
266825
|
-
console.log(source_default.gray(`
|
|
266826
|
-
Re-authorize with: dotns bulletin authorize ` + targetAddress + `
|
|
267031
|
+
console.log(source_default.green(`
|
|
267032
|
+
✓ Complete
|
|
266827
267033
|
`));
|
|
266828
|
-
} else {
|
|
266829
|
-
console.log();
|
|
266830
|
-
}
|
|
266831
267034
|
}
|
|
266832
|
-
|
|
266833
|
-
|
|
266834
|
-
|
|
266835
|
-
|
|
266836
|
-
|
|
266837
|
-
|
|
266838
|
-
|
|
266839
|
-
|
|
267035
|
+
process.exit(0);
|
|
267036
|
+
} catch (error2) {
|
|
267037
|
+
const errorMessage = formatErrorMessage(error2);
|
|
267038
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
267039
|
+
if (jsonOutput) {
|
|
267040
|
+
console.error(JSON.stringify({ error: errorMessage }));
|
|
267041
|
+
process.exit(1);
|
|
267042
|
+
}
|
|
266840
267043
|
console.error(source_default.red(`
|
|
266841
267044
|
✗ Error: ${errorMessage}
|
|
266842
267045
|
`));
|
|
@@ -266844,336 +267047,143 @@ function attachBulletinCommands(root) {
|
|
|
266844
267047
|
}
|
|
266845
267048
|
}
|
|
266846
267049
|
});
|
|
266847
|
-
const
|
|
266848
|
-
|
|
267050
|
+
const ownerOfCommand = lookupCommand.command("owner-of <label>").description("Show whether a name is registered and who owns it").alias("oo").option("--json", "Output result as JSON (suppresses all other output)", false);
|
|
267051
|
+
addAuthOptions(ownerOfCommand).action(async (label, options2, cmd) => {
|
|
266849
267052
|
try {
|
|
266850
|
-
const
|
|
266851
|
-
const
|
|
266852
|
-
|
|
266853
|
-
|
|
266854
|
-
|
|
266855
|
-
|
|
266856
|
-
if (history.length === 0) {
|
|
266857
|
-
console.log(source_default.yellow(`
|
|
266858
|
-
No uploads in history.
|
|
266859
|
-
`));
|
|
266860
|
-
console.log(source_default.gray(` Upload files with: dotns bulletin upload <path>
|
|
266861
|
-
`));
|
|
266862
|
-
process.exit(0);
|
|
266863
|
-
}
|
|
266864
|
-
console.log(source_default.blue(`
|
|
266865
|
-
▶ Upload History
|
|
266866
|
-
`));
|
|
266867
|
-
console.log(source_default.gray(` ${history.length} upload(s) found
|
|
267053
|
+
const merged = { ...options2 ?? {}, ...getAuthOptions(cmd) };
|
|
267054
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
267055
|
+
const { clientWrapper, account } = await maybeQuiet(jsonOutput, () => prepareReadOnlyContext(merged));
|
|
267056
|
+
if (!jsonOutput)
|
|
267057
|
+
console.log(source_default.bold(`
|
|
267058
|
+
▶ Ownership Lookup
|
|
266868
267059
|
`));
|
|
266869
|
-
|
|
266870
|
-
const num = (index + 1).toString().padStart(2, " ");
|
|
266871
|
-
console.log(source_default.yellow(` ${num}.`) + source_default.white(` ${formatRecordTimestamp(record2)}`));
|
|
266872
|
-
console.log(source_default.gray(" cid: ") + source_default.cyan(record2.cid));
|
|
266873
|
-
console.log(source_default.gray(" path: ") + source_default.white(record2.path));
|
|
266874
|
-
console.log(source_default.gray(" type: ") + source_default.white(record2.type));
|
|
266875
|
-
if (record2.size > 0) {
|
|
266876
|
-
console.log(source_default.gray(" size: ") + source_default.white(formatBytes(record2.size)));
|
|
266877
|
-
}
|
|
266878
|
-
console.log(source_default.gray(" preview: ") + source_default.blue(getPreviewUrl(record2)));
|
|
266879
|
-
console.log();
|
|
266880
|
-
});
|
|
266881
|
-
process.exit(0);
|
|
266882
|
-
} catch (error2) {
|
|
266883
|
-
const jsonOutput = getJsonFlag(command);
|
|
267060
|
+
const result = await maybeQuiet(jsonOutput, () => performOwnerOfLookup(label, account.address, clientWrapper));
|
|
266884
267061
|
if (jsonOutput) {
|
|
266885
|
-
|
|
266886
|
-
}
|
|
266887
|
-
console.error(source_default.red(`
|
|
266888
|
-
✗ Error: ${formatErrorMessage(error2)}
|
|
266889
|
-
`));
|
|
266890
|
-
process.exit(1);
|
|
266891
|
-
}
|
|
266892
|
-
});
|
|
266893
|
-
bulletinCommand.command("history:remove <cid>").description("Remove an upload from history by CID").action(async (cid) => {
|
|
266894
|
-
try {
|
|
266895
|
-
const removed = await removeUploadRecord(cid);
|
|
266896
|
-
if (removed) {
|
|
266897
|
-
console.log(source_default.green(`
|
|
266898
|
-
✓ Removed ${cid} from history
|
|
266899
|
-
`));
|
|
267062
|
+
console.log(JSON.stringify(result));
|
|
266900
267063
|
} else {
|
|
266901
|
-
console.log(source_default.
|
|
266902
|
-
|
|
267064
|
+
console.log(source_default.green(`
|
|
267065
|
+
✓ Complete
|
|
266903
267066
|
`));
|
|
266904
267067
|
}
|
|
266905
267068
|
process.exit(0);
|
|
266906
267069
|
} catch (error2) {
|
|
267070
|
+
const errorMessage = formatErrorMessage(error2);
|
|
267071
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
267072
|
+
if (jsonOutput) {
|
|
267073
|
+
console.error(JSON.stringify({ error: errorMessage }));
|
|
267074
|
+
process.exit(1);
|
|
267075
|
+
}
|
|
266907
267076
|
console.error(source_default.red(`
|
|
266908
|
-
✗ Error: ${
|
|
266909
|
-
`));
|
|
266910
|
-
process.exit(1);
|
|
266911
|
-
}
|
|
266912
|
-
});
|
|
266913
|
-
addReporterOption(bulletinCommand.command("history:clear").description("Clear all upload history")).action(async () => {
|
|
266914
|
-
try {
|
|
266915
|
-
const count2 = await clearHistory();
|
|
266916
|
-
const historyPath = getHistoryPath();
|
|
266917
|
-
console.log(source_default.green(`
|
|
266918
|
-
✓ Cleared ${count2} upload(s) from history`));
|
|
266919
|
-
console.log(source_default.gray(` ${historyPath}
|
|
266920
|
-
`));
|
|
266921
|
-
process.exit(0);
|
|
266922
|
-
} catch (error2) {
|
|
266923
|
-
console.error(source_default.red(`
|
|
266924
|
-
✗ Error: ${formatErrorMessage(error2)}
|
|
267077
|
+
✗ Error: ${errorMessage}
|
|
266925
267078
|
`));
|
|
266926
267079
|
process.exit(1);
|
|
266927
267080
|
}
|
|
266928
267081
|
});
|
|
266929
|
-
|
|
266930
|
-
|
|
266931
|
-
const jsonOutput = getJsonFlag(command) || Boolean(options2.json);
|
|
266932
|
-
const reporter = createCliReporter(mergedOptions.reporter);
|
|
266933
|
-
const p2pTask = reporter.task("Connecting to Bulletin P2P");
|
|
267082
|
+
const transferCommand = lookupCommand.command("transfer [label]").description("Transfer domain ownership to another address or label").requiredOption("-d, --destination <destination>", "Transfer destination (EVM address, SS58 address, or domain label)").option("--json", "Output result as JSON (suppresses all other output)", false);
|
|
267083
|
+
addAuthOptions(transferCommand).action(async (positionalLabel, options2, cmd) => {
|
|
266934
267084
|
try {
|
|
266935
|
-
|
|
266936
|
-
|
|
266937
|
-
|
|
266938
|
-
|
|
267085
|
+
const merged = { ...options2 ?? {}, ...getAuthOptions(cmd) };
|
|
267086
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
267087
|
+
const label = positionalLabel || merged.name || cmd.parent?.opts()?.name;
|
|
267088
|
+
if (!label) {
|
|
267089
|
+
throw new Error("Domain label is required: dotns lookup transfer <label> -d <destination>");
|
|
266939
267090
|
}
|
|
266940
|
-
const
|
|
266941
|
-
if (
|
|
266942
|
-
|
|
266943
|
-
if (jsonOutput) {
|
|
266944
|
-
writeBulletinJson({
|
|
266945
|
-
cid,
|
|
266946
|
-
resolvable: true,
|
|
266947
|
-
method: "p2p",
|
|
266948
|
-
gateways: [{ gateway: "p2p/bitswap", resolvable: true }]
|
|
266949
|
-
});
|
|
266950
|
-
} else {
|
|
266951
|
-
console.log(source_default.gray(" ✓ ") + source_default.white("p2p/bitswap"));
|
|
266952
|
-
console.log();
|
|
266953
|
-
}
|
|
266954
|
-
cleanupHeliaAndExit(0);
|
|
267091
|
+
const destination = merged.destination;
|
|
267092
|
+
if (!isValidTransferDestination(destination)) {
|
|
267093
|
+
throw new Error("Invalid transfer destination: must be a valid EVM address, Substrate address, or domain label");
|
|
266955
267094
|
}
|
|
266956
|
-
|
|
266957
|
-
const
|
|
266958
|
-
|
|
266959
|
-
|
|
266960
|
-
|
|
266961
|
-
|
|
266962
|
-
|
|
266963
|
-
|
|
266964
|
-
} else {
|
|
266965
|
-
failedGateways.push(gateway);
|
|
266966
|
-
}
|
|
267095
|
+
const context = await maybeQuiet(jsonOutput, () => prepareAssetHubContext(merged));
|
|
267096
|
+
const { clientWrapper, substrateAddress, signer, evmAddress } = context;
|
|
267097
|
+
if (!jsonOutput) {
|
|
267098
|
+
console.log(source_default.bold(`
|
|
267099
|
+
▶ Transfer
|
|
267100
|
+
`));
|
|
267101
|
+
console.log(source_default.gray(" domain: ") + source_default.cyan(`${label}.dot`));
|
|
267102
|
+
console.log(source_default.gray(" to: ") + source_default.white(destination));
|
|
266967
267103
|
}
|
|
267104
|
+
await maybeQuiet(jsonOutput, () => step("Ensuring account mapped", async () => clientWrapper.ensureAccountMapped(substrateAddress, signer)));
|
|
267105
|
+
const recipient = await maybeQuiet(jsonOutput, () => step("Resolving recipient", async () => resolveRecipientByKind(clientWrapper, substrateAddress, destination)));
|
|
267106
|
+
await maybeQuiet(jsonOutput, () => step("Transferring domain", async () => transferDomain(clientWrapper, substrateAddress, signer, evmAddress, recipient, label)));
|
|
267107
|
+
await maybeQuiet(jsonOutput, () => step("Verifying ownership", async () => verifyDomainOwnership(clientWrapper, substrateAddress, label, recipient)));
|
|
266968
267108
|
if (jsonOutput) {
|
|
266969
|
-
|
|
266970
|
-
|
|
266971
|
-
|
|
266972
|
-
|
|
266973
|
-
|
|
267109
|
+
console.log(JSON.stringify({
|
|
267110
|
+
label,
|
|
267111
|
+
domain: `${label}.dot`,
|
|
267112
|
+
destination,
|
|
267113
|
+
recipient,
|
|
267114
|
+
transferred: true
|
|
266974
267115
|
}));
|
|
266975
|
-
writeBulletinJson({
|
|
266976
|
-
cid,
|
|
266977
|
-
resolvable: resolvableGateways.length > 0,
|
|
266978
|
-
method: resolvableGateways.length > 0 ? "gateway" : "none",
|
|
266979
|
-
gateways: entries
|
|
266980
|
-
});
|
|
266981
|
-
cleanupHeliaAndExit(resolvableGateways.length > 0 ? 0 : 1);
|
|
266982
|
-
}
|
|
266983
|
-
if (resolvableGateways.length > 0) {
|
|
266984
|
-
gatewayTask.succeed(`CID resolvable on ${resolvableGateways.length} gateway(s)`);
|
|
266985
|
-
for (const gw of resolvableGateways) {
|
|
266986
|
-
console.log(source_default.gray(" ✓ ") + source_default.white(gw));
|
|
266987
|
-
}
|
|
266988
267116
|
} else {
|
|
266989
|
-
|
|
266990
|
-
|
|
266991
|
-
|
|
266992
|
-
for (const gw of failedGateways) {
|
|
266993
|
-
console.log(source_default.gray(" ✗ ") + source_default.dim(gw));
|
|
266994
|
-
}
|
|
267117
|
+
console.log(source_default.green(`
|
|
267118
|
+
✓ Complete
|
|
267119
|
+
`));
|
|
266995
267120
|
}
|
|
266996
|
-
|
|
266997
|
-
cleanupHeliaAndExit(resolvableGateways.length > 0 ? 0 : 1);
|
|
267121
|
+
process.exit(0);
|
|
266998
267122
|
} catch (error2) {
|
|
266999
|
-
p2pTask.fail("Verification failed");
|
|
267000
267123
|
const errorMessage = formatErrorMessage(error2);
|
|
267124
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
267001
267125
|
if (jsonOutput) {
|
|
267002
|
-
|
|
267003
|
-
|
|
267004
|
-
|
|
267126
|
+
console.error(JSON.stringify({ error: errorMessage }));
|
|
267127
|
+
process.exit(1);
|
|
267128
|
+
}
|
|
267129
|
+
console.error(source_default.red(`
|
|
267005
267130
|
✗ Error: ${errorMessage}
|
|
267006
267131
|
`));
|
|
267007
|
-
|
|
267008
|
-
}
|
|
267132
|
+
process.exit(1);
|
|
267009
267133
|
}
|
|
267010
267134
|
});
|
|
267011
267135
|
}
|
|
267012
267136
|
|
|
267013
267137
|
// src/cli/commands/content.ts
|
|
267014
|
-
init_source();
|
|
267015
|
-
|
|
267016
|
-
// src/commands/contentHash.ts
|
|
267017
|
-
init_source();
|
|
267018
|
-
init__esm();
|
|
267019
|
-
init_constants();
|
|
267020
|
-
init_contractInteractions();
|
|
267021
|
-
|
|
267022
|
-
// src/commands/resolverAuth.ts
|
|
267023
|
-
init__esm();
|
|
267024
|
-
init_constants();
|
|
267025
|
-
init_contractInteractions();
|
|
267026
|
-
async function getResolverNodeInfo(clientWrapper, originSubstrateAddress, namehashNode) {
|
|
267027
|
-
const exists2 = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "recordExists", [namehashNode]);
|
|
267028
|
-
const owner = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "owner", [namehashNode]);
|
|
267029
|
-
const caller = await clientWrapper.getEvmAddress(originSubstrateAddress);
|
|
267030
|
-
return { exists: exists2 && owner !== zeroAddress, owner, caller };
|
|
267031
|
-
}
|
|
267032
|
-
async function requireResolverAuthorization(clientWrapper, originSubstrateAddress, owner, caller) {
|
|
267033
|
-
const isOwner = checksumAddress(owner) === checksumAddress(caller);
|
|
267034
|
-
const isApproved = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "isApprovedForAll", [owner, caller]);
|
|
267035
|
-
if (!isOwner && !isApproved) {
|
|
267036
|
-
throw new Error(`You do not own this domain. Owner is ${owner}, but you are ${caller}`);
|
|
267037
|
-
}
|
|
267038
|
-
}
|
|
267039
|
-
|
|
267040
|
-
// src/commands/contentHash.ts
|
|
267041
|
-
function decodeContenthashToCid(contenthash) {
|
|
267042
|
-
if (contenthash === "0x" || contenthash === "0x0" || contenthash.length < 6) {
|
|
267043
|
-
return "No CID set";
|
|
267044
|
-
}
|
|
267045
|
-
const cid = decodeIpfsContenthash(contenthash);
|
|
267046
|
-
return cid ?? `Unable to decode: ${contenthash}`;
|
|
267047
|
-
}
|
|
267048
|
-
function encodeCidToContenthash(cidString) {
|
|
267049
|
-
const encoded = encodeIpfsContenthash(cidString);
|
|
267050
|
-
return `0x${encoded}`;
|
|
267051
|
-
}
|
|
267052
|
-
async function viewDomainContentHash(clientWrapper, originSubstrateAddress, label, spinner) {
|
|
267053
|
-
const namehashNode = namehash(`${label}.dot`);
|
|
267054
|
-
spinner.start("Querying registry");
|
|
267055
|
-
const recordExists = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "recordExists", [namehashNode]);
|
|
267056
|
-
const ownerAddress = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "owner", [namehashNode]);
|
|
267057
|
-
spinner.succeed("Registry read");
|
|
267058
|
-
console.log(source_default.gray(" registry: ") + source_default.white(CONTRACTS.DOTNS_REGISTRY));
|
|
267059
|
-
console.log(source_default.gray(" domain: ") + source_default.cyan(`${label}.dot`));
|
|
267060
|
-
console.log(source_default.gray(" node: ") + source_default.white(namehashNode));
|
|
267061
|
-
console.log(source_default.gray(" exists: ") + source_default.white(String(recordExists)));
|
|
267062
|
-
console.log(source_default.gray(" owner: ") + source_default.white(ownerAddress));
|
|
267063
|
-
console.log();
|
|
267064
|
-
if (!recordExists || ownerAddress === zeroAddress) {
|
|
267065
|
-
console.log(source_default.yellow(" status: Domain not registered"));
|
|
267066
|
-
return;
|
|
267067
|
-
}
|
|
267068
|
-
const contentHashBytes = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [namehashNode]);
|
|
267069
|
-
const decodedCid = decodeContenthashToCid(contentHashBytes);
|
|
267070
|
-
console.log(source_default.gray(" resolver: ") + source_default.white(CONTRACTS.DOTNS_CONTENT_RESOLVER));
|
|
267071
|
-
console.log(source_default.gray(" contenthash: ") + source_default.white(contentHashBytes));
|
|
267072
|
-
console.log(source_default.gray(" cid: ") + source_default.cyan(decodedCid));
|
|
267073
|
-
}
|
|
267074
|
-
async function setDomainContentHash(clientWrapper, originSubstrateAddress, signer, label, contentId, spinner) {
|
|
267075
|
-
const namehashNode = namehash(`${label}.dot`);
|
|
267076
|
-
console.log(source_default.gray(" domain: ") + source_default.cyan(`${label}.dot`));
|
|
267077
|
-
console.log(source_default.gray(" node: ") + source_default.white(namehashNode));
|
|
267078
|
-
console.log();
|
|
267079
|
-
const { exists: exists2, owner, caller } = await getResolverNodeInfo(clientWrapper, originSubstrateAddress, namehashNode);
|
|
267080
|
-
console.log(source_default.gray(" exists: ") + source_default.white(String(exists2)));
|
|
267081
|
-
console.log(source_default.gray(" owner: ") + source_default.white(owner));
|
|
267082
|
-
console.log(source_default.gray(" caller: ") + source_default.white(caller));
|
|
267083
|
-
console.log();
|
|
267084
|
-
if (!exists2) {
|
|
267085
|
-
throw new Error(`Domain ${label}.dot is not registered`);
|
|
267086
|
-
}
|
|
267087
|
-
await requireResolverAuthorization(clientWrapper, originSubstrateAddress, owner, caller);
|
|
267088
|
-
console.log(source_default.gray(" status: ") + source_default.green("Ownership verified"));
|
|
267089
|
-
console.log();
|
|
267090
|
-
try {
|
|
267091
|
-
const currentContentHash = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [namehashNode]);
|
|
267092
|
-
const currentCid = decodeContenthashToCid(currentContentHash);
|
|
267093
|
-
console.log(source_default.gray(" current: ") + source_default.cyan(currentCid));
|
|
267094
|
-
} catch {
|
|
267095
|
-
console.log(source_default.gray(" current: ") + source_default.yellow("Not set or error reading"));
|
|
267096
|
-
}
|
|
267097
|
-
console.log();
|
|
267098
|
-
const contentBytes = encodeCidToContenthash(contentId);
|
|
267099
|
-
console.log(source_default.gray(" resolver: ") + source_default.white(CONTRACTS.DOTNS_CONTENT_RESOLVER));
|
|
267100
|
-
console.log(source_default.gray(" node: ") + source_default.white(namehashNode));
|
|
267101
|
-
console.log(source_default.gray(" cid: ") + source_default.cyan(contentId));
|
|
267102
|
-
console.log(source_default.gray(" bytes: ") + source_default.white(contentBytes));
|
|
267103
|
-
spinner.start("Submitting setContenthash");
|
|
267104
|
-
const transactionHash = await submitContractTransaction(clientWrapper, CONTRACTS.DOTNS_CONTENT_RESOLVER, 0n, DOTNS_CONTENT_RESOLVER_ABI, "setContenthash", [namehashNode, contentBytes], originSubstrateAddress, signer, spinner, "setContenthash");
|
|
267105
|
-
console.log(source_default.gray(" tx: ") + source_default.blue(transactionHash));
|
|
267106
|
-
const updatedContentHash = await performContractCall(clientWrapper, originSubstrateAddress, CONTRACTS.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [namehashNode]);
|
|
267107
|
-
const updatedCid = decodeContenthashToCid(updatedContentHash);
|
|
267108
|
-
console.log();
|
|
267109
|
-
console.log(source_default.gray(" new: ") + source_default.cyan(updatedCid));
|
|
267110
|
-
}
|
|
267111
|
-
|
|
267112
|
-
// src/cli/commands/content.ts
|
|
267113
|
-
init_formatting();
|
|
267114
267138
|
init_ora();
|
|
267115
|
-
function getMergedOptions3(command, fallback) {
|
|
267116
|
-
const mergedOptions = { ...fallback ?? {} };
|
|
267117
|
-
let currentCommand = command?.parent;
|
|
267118
|
-
while (currentCommand) {
|
|
267119
|
-
if (typeof currentCommand.opts === "function") {
|
|
267120
|
-
const parentOptions = currentCommand.opts();
|
|
267121
|
-
for (const key in parentOptions) {
|
|
267122
|
-
if (!(key in mergedOptions) && parentOptions[key] !== undefined) {
|
|
267123
|
-
mergedOptions[key] = parentOptions[key];
|
|
267124
|
-
}
|
|
267125
|
-
}
|
|
267126
|
-
}
|
|
267127
|
-
currentCommand = currentCommand.parent;
|
|
267128
|
-
}
|
|
267129
|
-
return mergedOptions;
|
|
267130
|
-
}
|
|
267131
267139
|
function attachContentCommands(root) {
|
|
267132
267140
|
const contentCommand = root.command("content").description("Manage domain content hashes");
|
|
267133
267141
|
addAuthOptions(contentCommand);
|
|
267134
|
-
const viewContentCommand = contentCommand.command("view <name>").description("View domain content hash");
|
|
267142
|
+
const viewContentCommand = contentCommand.command("view <name>").description("View domain content hash").option("--json", "Output result as JSON (suppresses all other output)", false);
|
|
267135
267143
|
addAuthOptions(viewContentCommand).action(async (name10, options2, command) => {
|
|
267144
|
+
const jsonOutput = getJsonFlag(command);
|
|
267136
267145
|
try {
|
|
267137
|
-
const mergedOptions =
|
|
267138
|
-
const context = await prepareReadOnlyContext(mergedOptions);
|
|
267139
|
-
|
|
267146
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
267147
|
+
const context = await maybeQuiet(jsonOutput, () => prepareReadOnlyContext(mergedOptions));
|
|
267148
|
+
if (!jsonOutput)
|
|
267149
|
+
console.log(source_default.bold(`
|
|
267140
267150
|
▶ Content View
|
|
267141
267151
|
`));
|
|
267142
267152
|
const spinner = ora();
|
|
267143
|
-
await viewDomainContentHash(context.clientWrapper, context.account.address, name10, spinner);
|
|
267144
|
-
|
|
267153
|
+
const result = await maybeQuiet(jsonOutput, () => viewDomainContentHash(context.clientWrapper, context.account.address, name10, spinner));
|
|
267154
|
+
if (!emitJsonResult(jsonOutput, result)) {
|
|
267155
|
+
console.log(source_default.green(`
|
|
267145
267156
|
✓ Complete
|
|
267146
267157
|
`));
|
|
267158
|
+
}
|
|
267147
267159
|
process.exit(0);
|
|
267148
267160
|
} catch (error2) {
|
|
267149
|
-
|
|
267150
|
-
✗ Error: ${formatErrorMessage(error2)}
|
|
267151
|
-
`));
|
|
267152
|
-
process.exit(1);
|
|
267161
|
+
handleCommandError(jsonOutput, error2);
|
|
267153
267162
|
}
|
|
267154
267163
|
});
|
|
267155
|
-
const setContentCommand = contentCommand.command("set <name> <cid>").description("Set domain content hash (IPFS CID)");
|
|
267164
|
+
const setContentCommand = contentCommand.command("set <name> <cid>").description("Set domain content hash (IPFS CID)").option("--json", "Output result as JSON (suppresses all other output)", false);
|
|
267156
267165
|
addAuthOptions(setContentCommand).action(async (name10, cid, options2, command) => {
|
|
267166
|
+
const jsonOutput = getJsonFlag(command);
|
|
267157
267167
|
try {
|
|
267158
|
-
const mergedOptions =
|
|
267168
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
267159
267169
|
if (mergedOptions.mnemonic && mergedOptions.keyUri) {
|
|
267160
267170
|
throw new Error("Cannot specify both --mnemonic and --key-uri");
|
|
267161
267171
|
}
|
|
267162
|
-
const context = await prepareContext({ ...mergedOptions, useRevive: true });
|
|
267163
|
-
|
|
267172
|
+
const context = await maybeQuiet(jsonOutput, () => prepareContext({ ...mergedOptions, useRevive: true }));
|
|
267173
|
+
if (!jsonOutput)
|
|
267174
|
+
console.log(source_default.bold(`
|
|
267164
267175
|
▶ Content Set
|
|
267165
267176
|
`));
|
|
267166
267177
|
const spinner = ora();
|
|
267167
|
-
await setDomainContentHash(context.clientWrapper, context.substrateAddress, context.signer, name10, cid, spinner);
|
|
267168
|
-
|
|
267178
|
+
const result = await maybeQuiet(jsonOutput, () => setDomainContentHash(context.clientWrapper, context.substrateAddress, context.signer, name10, cid, spinner));
|
|
267179
|
+
if (!emitJsonResult(jsonOutput, result)) {
|
|
267180
|
+
console.log(source_default.green(`
|
|
267169
267181
|
✓ Complete
|
|
267170
267182
|
`));
|
|
267183
|
+
}
|
|
267171
267184
|
process.exit(0);
|
|
267172
267185
|
} catch (error2) {
|
|
267173
|
-
|
|
267174
|
-
✗ Error: ${formatErrorMessage(error2)}
|
|
267175
|
-
`));
|
|
267176
|
-
process.exit(1);
|
|
267186
|
+
handleCommandError(jsonOutput, error2);
|
|
267177
267187
|
}
|
|
267178
267188
|
});
|
|
267179
267189
|
}
|
|
@@ -267246,22 +267256,6 @@ async function setDomainText(clientWrapper, originSubstrateAddress, signer, labe
|
|
|
267246
267256
|
// src/cli/commands/text.ts
|
|
267247
267257
|
init_formatting();
|
|
267248
267258
|
init_ora();
|
|
267249
|
-
function getMergedOptions4(command, fallback) {
|
|
267250
|
-
const mergedOptions = { ...fallback ?? {} };
|
|
267251
|
-
let currentCommand = command?.parent;
|
|
267252
|
-
while (currentCommand) {
|
|
267253
|
-
if (typeof currentCommand.opts === "function") {
|
|
267254
|
-
const parentOptions = currentCommand.opts();
|
|
267255
|
-
for (const key in parentOptions) {
|
|
267256
|
-
if (!(key in mergedOptions) && parentOptions[key] !== undefined) {
|
|
267257
|
-
mergedOptions[key] = parentOptions[key];
|
|
267258
|
-
}
|
|
267259
|
-
}
|
|
267260
|
-
}
|
|
267261
|
-
currentCommand = currentCommand.parent;
|
|
267262
|
-
}
|
|
267263
|
-
return mergedOptions;
|
|
267264
|
-
}
|
|
267265
267259
|
function attachTextCommands(root) {
|
|
267266
267260
|
const textCommand = root.command("text").description("Manage domain text records");
|
|
267267
267261
|
addAuthOptions(textCommand);
|
|
@@ -267274,7 +267268,7 @@ function attachTextCommands(root) {
|
|
|
267274
267268
|
process.stdout.write = process.stderr.write.bind(process.stderr);
|
|
267275
267269
|
}
|
|
267276
267270
|
try {
|
|
267277
|
-
const mergedOptions =
|
|
267271
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
267278
267272
|
const context = await prepareReadOnlyContext(mergedOptions);
|
|
267279
267273
|
console.error(source_default.bold(`
|
|
267280
267274
|
▶ Text View
|
|
@@ -267298,7 +267292,7 @@ function attachTextCommands(root) {
|
|
|
267298
267292
|
const setTextCommand = textCommand.command("set <name> <key> [value]").description("Set a domain text record (reads from stdin if value omitted)");
|
|
267299
267293
|
addAuthOptions(setTextCommand).action(async (name10, key, value3, options2, command) => {
|
|
267300
267294
|
try {
|
|
267301
|
-
const mergedOptions =
|
|
267295
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
267302
267296
|
if (!value3) {
|
|
267303
267297
|
if (process.stdin.isTTY) {
|
|
267304
267298
|
throw new Error("No value provided. Pass a value argument or pipe via stdin.");
|
|
@@ -267333,24 +267327,6 @@ function attachTextCommands(root) {
|
|
|
267333
267327
|
|
|
267334
267328
|
// src/cli/commands/pop.ts
|
|
267335
267329
|
init_source();
|
|
267336
|
-
init_formatting();
|
|
267337
|
-
function getMergedOptions5(command, fallback) {
|
|
267338
|
-
const mergedOptions = { ...fallback ?? {} };
|
|
267339
|
-
let currentCommand = command?.parent;
|
|
267340
|
-
while (currentCommand) {
|
|
267341
|
-
if (typeof currentCommand.opts === "function") {
|
|
267342
|
-
const parentOptions = currentCommand.opts();
|
|
267343
|
-
for (const key in parentOptions) {
|
|
267344
|
-
const optionKey = key;
|
|
267345
|
-
if (!(optionKey in mergedOptions) && parentOptions[optionKey] !== undefined) {
|
|
267346
|
-
mergedOptions[optionKey] = parentOptions[optionKey];
|
|
267347
|
-
}
|
|
267348
|
-
}
|
|
267349
|
-
}
|
|
267350
|
-
currentCommand = currentCommand.parent;
|
|
267351
|
-
}
|
|
267352
|
-
return mergedOptions;
|
|
267353
|
-
}
|
|
267354
267330
|
async function readPopInfo(options2) {
|
|
267355
267331
|
const context = await prepareReadOnlyContext(options2);
|
|
267356
267332
|
const status = await getUserProofOfPersonhoodStatus(context.clientWrapper, context.account.address, context.evmAddress);
|
|
@@ -267363,51 +267339,58 @@ async function readPopInfo(options2) {
|
|
|
267363
267339
|
function attachPopCommands(root) {
|
|
267364
267340
|
const popCommand = root.command("pop").description("ProofOfPersonhood status management");
|
|
267365
267341
|
addAuthOptions(popCommand);
|
|
267366
|
-
const setPopCommand = popCommand.command("set <status>").description("Set ProofOfPersonhood status (none, lite, or full)");
|
|
267342
|
+
const setPopCommand = popCommand.command("set <status>").description("Set ProofOfPersonhood status (none, lite, or full)").option("--json", "Output result as JSON (suppresses all other output)", false);
|
|
267367
267343
|
addAuthOptions(setPopCommand).action(async (status, options2, command) => {
|
|
267344
|
+
const jsonOutput = getJsonFlag(command);
|
|
267368
267345
|
try {
|
|
267369
|
-
const mergedOptions =
|
|
267370
|
-
const context = await prepareContext(mergedOptions);
|
|
267346
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
267347
|
+
const context = await maybeQuiet(jsonOutput, () => prepareContext(mergedOptions));
|
|
267371
267348
|
const parsedStatus = parseProofOfPersonhoodStatus(status);
|
|
267372
|
-
await setUserProofOfPersonhoodStatus(context.clientWrapper, context.substrateAddress, context.signer, context.evmAddress, "", parsedStatus);
|
|
267373
|
-
|
|
267349
|
+
await maybeQuiet(jsonOutput, () => setUserProofOfPersonhoodStatus(context.clientWrapper, context.substrateAddress, context.signer, context.evmAddress, "", parsedStatus));
|
|
267350
|
+
if (!emitJsonResult(jsonOutput, {
|
|
267351
|
+
ok: true,
|
|
267352
|
+
status: ProofOfPersonhoodStatus[parsedStatus].toLowerCase(),
|
|
267353
|
+
statusCode: parsedStatus
|
|
267354
|
+
})) {
|
|
267355
|
+
console.log(source_default.green(`
|
|
267374
267356
|
✓ PoP Status Updated
|
|
267375
267357
|
`));
|
|
267358
|
+
}
|
|
267376
267359
|
process.exit(0);
|
|
267377
267360
|
} catch (error2) {
|
|
267378
|
-
|
|
267379
|
-
✗ Error: ${formatErrorMessage(error2)}
|
|
267380
|
-
`));
|
|
267381
|
-
process.exit(1);
|
|
267361
|
+
handleCommandError(jsonOutput, error2);
|
|
267382
267362
|
}
|
|
267383
267363
|
});
|
|
267384
|
-
const infoCommand = popCommand.command("info").description("Display ProofOfPersonhood status");
|
|
267364
|
+
const infoCommand = popCommand.command("info").description("Display ProofOfPersonhood status").option("--json", "Output result as JSON (suppresses all other output)", false);
|
|
267385
267365
|
addAuthOptions(infoCommand).action(async (options2, command) => {
|
|
267366
|
+
const jsonOutput = getJsonFlag(command);
|
|
267386
267367
|
try {
|
|
267387
|
-
const mergedOptions =
|
|
267388
|
-
const info2 = await readPopInfo(mergedOptions);
|
|
267389
|
-
|
|
267368
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
267369
|
+
const info2 = await maybeQuiet(jsonOutput, () => readPopInfo(mergedOptions));
|
|
267370
|
+
if (!emitJsonResult(jsonOutput, {
|
|
267371
|
+
substrate: info2.substrate,
|
|
267372
|
+
evm: info2.evm,
|
|
267373
|
+
status: ProofOfPersonhoodStatus[info2.status].toLowerCase(),
|
|
267374
|
+
statusCode: info2.status
|
|
267375
|
+
})) {
|
|
267376
|
+
console.log(source_default.bold(`
|
|
267390
267377
|
\uD83D\uDCCB ProofOfPersonhood Status
|
|
267391
267378
|
`));
|
|
267392
|
-
|
|
267393
|
-
|
|
267394
|
-
|
|
267395
|
-
|
|
267379
|
+
console.log(source_default.gray(" substrate: ") + source_default.white(info2.substrate));
|
|
267380
|
+
console.log(source_default.gray(" evm: ") + source_default.white(info2.evm));
|
|
267381
|
+
console.log(source_default.gray(" status: ") + source_default.white(ProofOfPersonhoodStatus[info2.status]));
|
|
267382
|
+
console.log(source_default.green(`
|
|
267396
267383
|
✓ PoP Status Retrieved
|
|
267397
267384
|
`));
|
|
267385
|
+
}
|
|
267398
267386
|
process.exit(0);
|
|
267399
267387
|
} catch (error2) {
|
|
267400
|
-
|
|
267401
|
-
✗ Error: ${formatErrorMessage(error2)}
|
|
267402
|
-
`));
|
|
267403
|
-
process.exit(1);
|
|
267388
|
+
handleCommandError(jsonOutput, error2);
|
|
267404
267389
|
}
|
|
267405
267390
|
});
|
|
267406
267391
|
}
|
|
267407
267392
|
|
|
267408
267393
|
// src/cli/commands/registerCommand.ts
|
|
267409
|
-
init_source();
|
|
267410
|
-
init_formatting();
|
|
267411
267394
|
init_constants();
|
|
267412
267395
|
function resolveCommitmentBuffer(cliValue) {
|
|
267413
267396
|
const raw = cliValue ?? process.env.DOTNS_COMMITMENT_BUFFER;
|
|
@@ -267421,7 +267404,8 @@ function resolveCommitmentBuffer(cliValue) {
|
|
|
267421
267404
|
}
|
|
267422
267405
|
function attachRegisterCommand(root) {
|
|
267423
267406
|
const registerCommand = root.command("register").description("Domain registration commands");
|
|
267424
|
-
const domainCommand = registerCommand.command("domain").description("Register a new base domain").option("-n, --name <label>", "Domain label to register (without .dot)").option("-s, --status <level>", "ProofOfPersonhood status: none, lite, or full").option("-r, --reverse", "Enable reverse record registration", false).option("-g, --governance", "Use governance registration path", false).option("-o, --owner <address>", "Owner address (EVM or Substrate, or label)").option("--transfer", "Transfer domain after registration", false).option("--to <destination>", "Transfer destination (EVM address, SS58, or domain label)").option("--cb, --commitment-buffer <seconds>", `Extra seconds to wait after minCommitmentAge (default: ${DEFAULT_COMMITMENT_BUFFER_SECONDS}, env: DOTNS_COMMITMENT_BUFFER)`).action(async (options2, cmd) => {
|
|
267407
|
+
const domainCommand = registerCommand.command("domain").description("Register a new base domain").option("-n, --name <label>", "Domain label to register (without .dot)").option("-s, --status <level>", "ProofOfPersonhood status: none, lite, or full").option("-r, --reverse", "Enable reverse record registration", false).option("-g, --governance", "Use governance registration path", false).option("-o, --owner <address>", "Owner address (EVM or Substrate, or label)").option("--transfer", "Transfer domain after registration", false).option("--to <destination>", "Transfer destination (EVM address, SS58, or domain label)").option("--cb, --commitment-buffer <seconds>", `Extra seconds to wait after minCommitmentAge (default: ${DEFAULT_COMMITMENT_BUFFER_SECONDS}, env: DOTNS_COMMITMENT_BUFFER)`).option("--json", "Output result as JSON (suppresses all other output)", false).action(async (options2, cmd) => {
|
|
267408
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
267425
267409
|
try {
|
|
267426
267410
|
const merged = { ...options2, ...getAuthOptions(cmd) };
|
|
267427
267411
|
const allOpts = typeof cmd.optsWithGlobals === "function" ? cmd.optsWithGlobals() : cmd.opts();
|
|
@@ -267430,26 +267414,23 @@ function attachRegisterCommand(root) {
|
|
|
267430
267414
|
if (merged.transfer === true && !merged.to) {
|
|
267431
267415
|
throw new Error("Missing transfer destination: use --to <evm|ss58|label>");
|
|
267432
267416
|
}
|
|
267433
|
-
await executeRegistration(merged);
|
|
267417
|
+
const result = await maybeQuiet(jsonOutput, () => executeRegistration(merged));
|
|
267418
|
+
emitJsonResult(jsonOutput, result);
|
|
267434
267419
|
process.exit(0);
|
|
267435
267420
|
} catch (error2) {
|
|
267436
|
-
|
|
267437
|
-
${source_default.red.bold("✗ Error:")} ${formatErrorMessage(error2)}
|
|
267438
|
-
`);
|
|
267439
|
-
process.exit(1);
|
|
267421
|
+
handleCommandError(jsonOutput, error2);
|
|
267440
267422
|
}
|
|
267441
267423
|
});
|
|
267442
267424
|
addAuthOptions(domainCommand);
|
|
267443
|
-
const subnameCommand = registerCommand.command("subname").description("Register a subname under an existing domain").requiredOption("-n, --name <label>", "Subname label to register").requiredOption("-p, --parent <label>", "Parent domain label (without .dot)").option("-o, --owner <address>", "Owner address (EVM or Substrate, or label)").action(async (options2, cmd) => {
|
|
267425
|
+
const subnameCommand = registerCommand.command("subname").description("Register a subname under an existing domain").requiredOption("-n, --name <label>", "Subname label to register").requiredOption("-p, --parent <label>", "Parent domain label (without .dot)").option("-o, --owner <address>", "Owner address (EVM or Substrate, or label)").option("--json", "Output result as JSON (suppresses all other output)", false).action(async (options2, cmd) => {
|
|
267426
|
+
const jsonOutput = getJsonFlag(cmd);
|
|
267444
267427
|
try {
|
|
267445
267428
|
const merged = { ...options2, ...getAuthOptions(cmd) };
|
|
267446
|
-
await executeSubnameRegistration(merged);
|
|
267429
|
+
const result = await maybeQuiet(jsonOutput, () => executeSubnameRegistration(merged));
|
|
267430
|
+
emitJsonResult(jsonOutput, result);
|
|
267447
267431
|
process.exit(0);
|
|
267448
267432
|
} catch (error2) {
|
|
267449
|
-
|
|
267450
|
-
${source_default.red.bold("✗ Error:")} ${formatErrorMessage(error2)}
|
|
267451
|
-
`);
|
|
267452
|
-
process.exit(1);
|
|
267433
|
+
handleCommandError(jsonOutput, error2);
|
|
267453
267434
|
}
|
|
267454
267435
|
});
|
|
267455
267436
|
addAuthOptions(subnameCommand);
|
|
@@ -267521,29 +267502,13 @@ async function whitelistAddress(clientWrapper, originAddress, signer, targetAddr
|
|
|
267521
267502
|
}
|
|
267522
267503
|
|
|
267523
267504
|
// src/cli/commands/info.ts
|
|
267524
|
-
function getMergedOptions6(command, fallback) {
|
|
267525
|
-
const mergedOptions = { ...fallback ?? {} };
|
|
267526
|
-
let currentCommand = command?.parent;
|
|
267527
|
-
while (currentCommand) {
|
|
267528
|
-
if (typeof currentCommand.opts === "function") {
|
|
267529
|
-
const parentOptions = currentCommand.opts();
|
|
267530
|
-
for (const key in parentOptions) {
|
|
267531
|
-
if (!(key in mergedOptions) && parentOptions[key] !== undefined) {
|
|
267532
|
-
mergedOptions[key] = parentOptions[key];
|
|
267533
|
-
}
|
|
267534
|
-
}
|
|
267535
|
-
}
|
|
267536
|
-
currentCommand = currentCommand.parent;
|
|
267537
|
-
}
|
|
267538
|
-
return mergedOptions;
|
|
267539
|
-
}
|
|
267540
267505
|
function attachAccountCommands(root) {
|
|
267541
267506
|
const accountCommand = root.command("account").description("Account management utilities");
|
|
267542
267507
|
addAuthOptions(accountCommand);
|
|
267543
267508
|
const addressCommand = accountCommand.command("address").description("Print the substrate address for the configured account (offline, no RPC)");
|
|
267544
267509
|
addAuthOptions(addressCommand).action(async (options2, command) => {
|
|
267545
267510
|
try {
|
|
267546
|
-
const mergedOptions =
|
|
267511
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
267547
267512
|
const keystorePath = resolveKeystorePath(mergedOptions.keystorePath);
|
|
267548
267513
|
const auth = await resolveAuthSource({
|
|
267549
267514
|
mnemonic: mergedOptions.mnemonic,
|
|
@@ -267563,7 +267528,7 @@ function attachAccountCommands(root) {
|
|
|
267563
267528
|
const infoCommand = accountCommand.command("info").description("Display account information including balances");
|
|
267564
267529
|
addAuthOptions(infoCommand).action(async (options2, command) => {
|
|
267565
267530
|
try {
|
|
267566
|
-
const mergedOptions =
|
|
267531
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
267567
267532
|
const rpc = resolveRpc(mergedOptions.rpc);
|
|
267568
267533
|
const keystorePath = resolveKeystorePath(mergedOptions.keystorePath);
|
|
267569
267534
|
const client = await step(`Connecting RPC ${rpc}`, async () => createClient3(getWsProvider(rpc)).getTypedApi(paseo_default));
|
|
@@ -267595,7 +267560,7 @@ function attachAccountCommands(root) {
|
|
|
267595
267560
|
const mapCommand = accountCommand.command("map").description("Map Substrate account to EVM address");
|
|
267596
267561
|
addAuthOptions(mapCommand).action(async (options2, command) => {
|
|
267597
267562
|
try {
|
|
267598
|
-
const mergedOptions =
|
|
267563
|
+
const mergedOptions = getMergedOptions(command, options2);
|
|
267599
267564
|
const rpc = resolveRpc(mergedOptions.rpc);
|
|
267600
267565
|
const client = await step(`Connecting RPC ${rpc}`, async () => createClient3(getWsProvider(rpc)).getTypedApi(paseo_default));
|
|
267601
267566
|
const clientWrapper = new ReviveClientWrapper(client);
|
|
@@ -267628,7 +267593,7 @@ function attachAccountCommands(root) {
|
|
|
267628
267593
|
addAuthOptions(isMappedCommand).action(async (address, options2, cmd) => {
|
|
267629
267594
|
const jsonOutput = getJsonFlag(cmd);
|
|
267630
267595
|
try {
|
|
267631
|
-
const mergedOptions =
|
|
267596
|
+
const mergedOptions = getMergedOptions(cmd, options2);
|
|
267632
267597
|
const { clientWrapper } = await maybeQuiet(jsonOutput, () => prepareReadOnlyContext(mergedOptions));
|
|
267633
267598
|
const result = await maybeQuiet(jsonOutput, () => checkAccountMapped(clientWrapper, address));
|
|
267634
267599
|
if (jsonOutput)
|
|
@@ -267652,7 +267617,7 @@ function attachAccountCommands(root) {
|
|
|
267652
267617
|
addAuthOptions(isWhitelistedCommand).action(async (address, options2, cmd) => {
|
|
267653
267618
|
const jsonOutput = getJsonFlag(cmd);
|
|
267654
267619
|
try {
|
|
267655
|
-
const mergedOptions =
|
|
267620
|
+
const mergedOptions = getMergedOptions(cmd, options2);
|
|
267656
267621
|
const { clientWrapper, account } = await maybeQuiet(jsonOutput, () => prepareReadOnlyContext(mergedOptions));
|
|
267657
267622
|
const result = await maybeQuiet(jsonOutput, () => checkWhitelisted(clientWrapper, account.address, address));
|
|
267658
267623
|
if (jsonOutput)
|
|
@@ -267676,7 +267641,7 @@ function attachAccountCommands(root) {
|
|
|
267676
267641
|
addAuthOptions(whitelistCommand).action(async (address, options2, cmd) => {
|
|
267677
267642
|
const jsonOutput = getJsonFlag(cmd);
|
|
267678
267643
|
try {
|
|
267679
|
-
const mergedOptions =
|
|
267644
|
+
const mergedOptions = getMergedOptions(cmd, options2);
|
|
267680
267645
|
const enable = !mergedOptions.remove;
|
|
267681
267646
|
const context = await maybeQuiet(jsonOutput, () => prepareAssetHubContext(mergedOptions));
|
|
267682
267647
|
const result = await maybeQuiet(jsonOutput, () => whitelistAddress(context.clientWrapper, context.substrateAddress, context.signer, address, enable));
|
|
@@ -267712,7 +267677,7 @@ function validateEvmAddress(raw) {
|
|
|
267712
267677
|
}
|
|
267713
267678
|
return getAddress(raw);
|
|
267714
267679
|
}
|
|
267715
|
-
function
|
|
267680
|
+
function handleCommandError2(error2, cmd) {
|
|
267716
267681
|
const jsonOutput = getJsonFlag(cmd);
|
|
267717
267682
|
const message2 = formatErrorMessage(error2);
|
|
267718
267683
|
if (jsonOutput) {
|
|
@@ -267742,7 +267707,7 @@ function attachStoreCommands(root) {
|
|
|
267742
267707
|
}
|
|
267743
267708
|
process.exit(0);
|
|
267744
267709
|
} catch (error2) {
|
|
267745
|
-
|
|
267710
|
+
handleCommandError2(error2, cmd);
|
|
267746
267711
|
}
|
|
267747
267712
|
});
|
|
267748
267713
|
const listCommand = storeCommand.command("list").description("List all values in your Store").option("--json", "Output result as JSON", false);
|
|
@@ -267761,7 +267726,7 @@ function attachStoreCommands(root) {
|
|
|
267761
267726
|
}
|
|
267762
267727
|
process.exit(0);
|
|
267763
267728
|
} catch (error2) {
|
|
267764
|
-
|
|
267729
|
+
handleCommandError2(error2, cmd);
|
|
267765
267730
|
}
|
|
267766
267731
|
});
|
|
267767
267732
|
const namesCommand = storeCommand.command("names").description("List all .dot names in your Store").option("--json", "Output result as JSON", false);
|
|
@@ -267790,7 +267755,7 @@ function attachStoreCommands(root) {
|
|
|
267790
267755
|
}
|
|
267791
267756
|
process.exit(0);
|
|
267792
267757
|
} catch (error2) {
|
|
267793
|
-
|
|
267758
|
+
handleCommandError2(error2, cmd);
|
|
267794
267759
|
}
|
|
267795
267760
|
});
|
|
267796
267761
|
const cidsCommand = storeCommand.command("cids").description("List all uploaded CIDs in your Store").option("--json", "Output result as JSON", false);
|
|
@@ -267819,7 +267784,7 @@ function attachStoreCommands(root) {
|
|
|
267819
267784
|
}
|
|
267820
267785
|
process.exit(0);
|
|
267821
267786
|
} catch (error2) {
|
|
267822
|
-
|
|
267787
|
+
handleCommandError2(error2, cmd);
|
|
267823
267788
|
}
|
|
267824
267789
|
});
|
|
267825
267790
|
const getCommand = storeCommand.command("get <key>").description("Get a value by key (hex bytes32 or string, hashed via keccak256)").option("--json", "Output result as JSON", false);
|
|
@@ -267838,7 +267803,7 @@ function attachStoreCommands(root) {
|
|
|
267838
267803
|
}
|
|
267839
267804
|
process.exit(0);
|
|
267840
267805
|
} catch (error2) {
|
|
267841
|
-
|
|
267806
|
+
handleCommandError2(error2, cmd);
|
|
267842
267807
|
}
|
|
267843
267808
|
});
|
|
267844
267809
|
const setCommand = storeCommand.command("set <key> <value>").description("Set a key-value pair in your Store").option("--json", "Output result as JSON", false);
|
|
@@ -267858,7 +267823,7 @@ function attachStoreCommands(root) {
|
|
|
267858
267823
|
}
|
|
267859
267824
|
process.exit(0);
|
|
267860
267825
|
} catch (error2) {
|
|
267861
|
-
|
|
267826
|
+
handleCommandError2(error2, cmd);
|
|
267862
267827
|
}
|
|
267863
267828
|
});
|
|
267864
267829
|
const deleteCommand = storeCommand.command("delete <key>").description("Delete a value from your Store by key").option("--json", "Output result as JSON", false);
|
|
@@ -267878,7 +267843,7 @@ function attachStoreCommands(root) {
|
|
|
267878
267843
|
}
|
|
267879
267844
|
process.exit(0);
|
|
267880
267845
|
} catch (error2) {
|
|
267881
|
-
|
|
267846
|
+
handleCommandError2(error2, cmd);
|
|
267882
267847
|
}
|
|
267883
267848
|
});
|
|
267884
267849
|
const checkCommand = storeCommand.command("check <address>").description("Check whether an address is authorized or a DotNS controller on your Store").option("--json", "Output result as JSON", false);
|
|
@@ -267898,7 +267863,7 @@ function attachStoreCommands(root) {
|
|
|
267898
267863
|
}
|
|
267899
267864
|
process.exit(0);
|
|
267900
267865
|
} catch (error2) {
|
|
267901
|
-
|
|
267866
|
+
handleCommandError2(error2, cmd);
|
|
267902
267867
|
}
|
|
267903
267868
|
});
|
|
267904
267869
|
const authorizeCommand = storeCommand.command("authorize <address>").description("Authorize an address to write to your Store (setValueFor)").option("--json", "Output result as JSON", false);
|
|
@@ -267919,7 +267884,7 @@ function attachStoreCommands(root) {
|
|
|
267919
267884
|
}
|
|
267920
267885
|
process.exit(0);
|
|
267921
267886
|
} catch (error2) {
|
|
267922
|
-
|
|
267887
|
+
handleCommandError2(error2, cmd);
|
|
267923
267888
|
}
|
|
267924
267889
|
});
|
|
267925
267890
|
const unauthorizeCommand = storeCommand.command("unauthorize <address>").description("Revoke write access from an address on your Store").option("--json", "Output result as JSON", false);
|
|
@@ -267940,7 +267905,7 @@ function attachStoreCommands(root) {
|
|
|
267940
267905
|
}
|
|
267941
267906
|
process.exit(0);
|
|
267942
267907
|
} catch (error2) {
|
|
267943
|
-
|
|
267908
|
+
handleCommandError2(error2, cmd);
|
|
267944
267909
|
}
|
|
267945
267910
|
});
|
|
267946
267911
|
const authorizeControllerCommand = storeCommand.command("authorize-controller <address>").description("Authorize an address as a DotNS controller (locks keys permanently on write)").option("--json", "Output result as JSON", false);
|
|
@@ -267961,7 +267926,7 @@ function attachStoreCommands(root) {
|
|
|
267961
267926
|
}
|
|
267962
267927
|
process.exit(0);
|
|
267963
267928
|
} catch (error2) {
|
|
267964
|
-
|
|
267929
|
+
handleCommandError2(error2, cmd);
|
|
267965
267930
|
}
|
|
267966
267931
|
});
|
|
267967
267932
|
const unauthorizeControllerCommand = storeCommand.command("unauthorize-controller <address>").description("Revoke DotNS controller authorization from an address on your Store").option("--json", "Output result as JSON", false);
|
|
@@ -267982,7 +267947,7 @@ function attachStoreCommands(root) {
|
|
|
267982
267947
|
}
|
|
267983
267948
|
process.exit(0);
|
|
267984
267949
|
} catch (error2) {
|
|
267985
|
-
|
|
267950
|
+
handleCommandError2(error2, cmd);
|
|
267986
267951
|
}
|
|
267987
267952
|
});
|
|
267988
267953
|
const ensureAuthCommand = storeCommand.command("ensure-auth").description("Ensure DotNS system contracts are authorized on your Store").option("--json", "Output result as JSON", false);
|
|
@@ -267992,7 +267957,7 @@ function attachStoreCommands(root) {
|
|
|
267992
267957
|
const jsonOutput = getJsonFlag(cmd);
|
|
267993
267958
|
const context = await maybeQuiet(jsonOutput, () => prepareAssetHubContext(merged));
|
|
267994
267959
|
const { clientWrapper, substrateAddress, signer, evmAddress } = context;
|
|
267995
|
-
const result = await maybeQuiet(jsonOutput, () =>
|
|
267960
|
+
const result = await maybeQuiet(jsonOutput, () => ensureStoreAuthorizations(clientWrapper, substrateAddress, signer, evmAddress));
|
|
267996
267961
|
if (jsonOutput) {
|
|
267997
267962
|
console.log(JSON.stringify(result));
|
|
267998
267963
|
} else {
|
|
@@ -268002,7 +267967,7 @@ function attachStoreCommands(root) {
|
|
|
268002
267967
|
}
|
|
268003
267968
|
process.exit(0);
|
|
268004
267969
|
} catch (error2) {
|
|
268005
|
-
|
|
267970
|
+
handleCommandError2(error2, cmd);
|
|
268006
267971
|
}
|
|
268007
267972
|
});
|
|
268008
267973
|
}
|