bulletin-deploy 0.7.6 → 0.7.7

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.
@@ -24,6 +24,8 @@ for (let i = 0; i < args.length; i++) {
24
24
  else if (args[i] === "--password") { flags.password = args[++i]; }
25
25
  else if (args[i] === "--js-merkle") { flags.jsMerkle = true; }
26
26
  else if (args[i] === "--tag") { flags.tag = args[++i]; }
27
+ else if (args[i] === "--name") { flags.name = args[++i]; }
28
+ else if (args[i] === "--description") { flags.description = args[++i]; }
27
29
  else if (args[i] === "--gh-pages-mirror") { flags.ghPagesMirror = true; }
28
30
  else if (args[i] === "--version" || args[i] === "-V") { flags.version = true; }
29
31
  else if (args[i] === "--help" || args[i] === "-h") { flags.help = true; }
@@ -54,6 +56,8 @@ Options:
54
56
  --password "..." Encrypt SPA content (users will be prompted to decrypt)
55
57
  --js-merkle Use pure-JS merkleization (no IPFS Kubo binary required)
56
58
  --tag "..." Label deploy in telemetry (or set DEPLOY_TAG env var); see Telemetry in README
59
+ --name "..." Optional. Sets the "name" text record on the domain.
60
+ --description "..." Optional. Sets the "description" text record (≤100 chars recommended).
57
61
  --gh-pages-mirror After deploy, push the CAR to the current repo's gh-pages branch
58
62
  at bulletin/<domain>.dot.car (opt-in; also set GH_PAGES_MIRROR=1)
59
63
  --version Show version
@@ -185,6 +189,8 @@ try {
185
189
  jsMerkle: flags.jsMerkle,
186
190
  tag: flags.tag,
187
191
  ghPagesMirror: flags.ghPagesMirror,
192
+ name: flags.name,
193
+ description: flags.description,
188
194
  });
189
195
 
190
196
  const output = process.env.GITHUB_OUTPUT;
@@ -9,10 +9,10 @@ import {
9
9
  offerBugReport,
10
10
  scrubSecrets,
11
11
  setDeployContext
12
- } from "./chunk-YX62STIA.js";
13
- import "./chunk-EECNTEAE.js";
14
- import "./chunk-Y6CTPQS2.js";
15
- import "./chunk-HHY32NGJ.js";
12
+ } from "./chunk-D3SJZTE2.js";
13
+ import "./chunk-BEAOHOTJ.js";
14
+ import "./chunk-LNFD7QP6.js";
15
+ import "./chunk-VKADME5F.js";
16
16
  import "./chunk-QGM4M3NI.js";
17
17
  export {
18
18
  buildCliFlagsSummary,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  setDeployContext
3
- } from "./chunk-YX62STIA.js";
3
+ } from "./chunk-D3SJZTE2.js";
4
4
  import {
5
5
  DotNS,
6
6
  TX_TIMEOUT_MS,
@@ -8,12 +8,12 @@ import {
8
8
  parseDomainName,
9
9
  popStatusName,
10
10
  verifyNonceAdvanced
11
- } from "./chunk-G6CVI6U2.js";
11
+ } from "./chunk-EOCLCWCS.js";
12
12
  import {
13
13
  MirrorSkipped,
14
14
  mirrorToGitHubPages,
15
15
  pollMirrorFreshness
16
- } from "./chunk-2Q2WSKFD.js";
16
+ } from "./chunk-HOTQDYHD.js";
17
17
  import {
18
18
  VERSION,
19
19
  captureWarning,
@@ -27,7 +27,7 @@ import {
27
27
  truncateAddress,
28
28
  withDeploySpan,
29
29
  withSpan
30
- } from "./chunk-Y6CTPQS2.js";
30
+ } from "./chunk-LNFD7QP6.js";
31
31
  import {
32
32
  merkleizeJS
33
33
  } from "./chunk-B7GUYYAN.js";
@@ -38,7 +38,7 @@ import {
38
38
  fetchPoolAuthorizations,
39
39
  selectAccount,
40
40
  topUpBy
41
- } from "./chunk-WIBZPZSY.js";
41
+ } from "./chunk-RP4YJYNB.js";
42
42
 
43
43
  // src/deploy.ts
44
44
  import { Buffer } from "buffer";
@@ -648,6 +648,12 @@ async function storeDirectory(directoryPath, providerOrOptions = {}, password, j
648
648
  }
649
649
  return { storageCid, ipfsCid, carBytes: carContent };
650
650
  }
651
+ function resolveDotnsConnectOptions(options) {
652
+ if (options.signer && options.signerAddress) {
653
+ return { signer: options.signer, signerAddress: options.signerAddress };
654
+ }
655
+ return { mnemonic: options.mnemonic, derivationPath: options.derivationPath };
656
+ }
651
657
  async function estimateUploadBytes(content) {
652
658
  try {
653
659
  if (Array.isArray(content)) {
@@ -702,14 +708,13 @@ async function deploy(content, domainName = null, options = {}) {
702
708
  if (options.password) console.log(` Encrypted: yes`);
703
709
  let provider;
704
710
  const reconnect = options.mnemonic ? () => getDirectProvider(options.mnemonic, options.derivationPath) : () => getProvider();
711
+ let dotnsPreflight = null;
705
712
  try {
706
713
  console.log("\n" + "=".repeat(60));
707
714
  console.log("Preflight");
708
715
  console.log("=".repeat(60));
709
716
  const preflight = new DotNS();
710
- await preflight.connect(
711
- options.signer && options.signerAddress ? { signer: options.signer, signerAddress: options.signerAddress } : options.mnemonic ? { mnemonic: options.mnemonic, derivationPath: options.derivationPath } : {}
712
- );
717
+ await preflight.connect(resolveDotnsConnectOptions(options));
713
718
  if (parsed?.isSubdomain) {
714
719
  try {
715
720
  const { owned: subOwned } = await preflight.checkSubdomainOwnership(parsed.sublabel, parsed.parentLabel);
@@ -726,7 +731,6 @@ async function deploy(content, domainName = null, options = {}) {
726
731
  }
727
732
  console.log(` Mode: subdomain (parent ${parsed.parentLabel}.dot owned by signer)`);
728
733
  } else {
729
- let dotnsPreflight;
730
734
  try {
731
735
  dotnsPreflight = await preflight.preflight(name);
732
736
  } finally {
@@ -859,9 +863,7 @@ async function deploy(content, domainName = null, options = {}) {
859
863
  console.log("=".repeat(60));
860
864
  await withSpan("deploy.dotns", "2. dotns", { "deploy.domain": name, "deploy.subdomain": String(parsed?.isSubdomain ?? false) }, async () => {
861
865
  const dotns = new DotNS();
862
- await dotns.connect(
863
- options.signer && options.signerAddress ? { signer: options.signer, signerAddress: options.signerAddress } : options.mnemonic ? { mnemonic: options.mnemonic, derivationPath: options.derivationPath } : {}
864
- );
866
+ await dotns.connect(resolveDotnsConnectOptions(options));
865
867
  if (parsed?.isSubdomain) {
866
868
  const { owned, owner } = await dotns.checkSubdomainOwnership(parsed.sublabel, parsed.parentLabel);
867
869
  if (owned) {
@@ -879,12 +881,18 @@ async function deploy(content, domainName = null, options = {}) {
879
881
  if (owned) {
880
882
  console.log(` Status: Already owned`);
881
883
  } else {
884
+ if (dotnsPreflight !== null && dotnsPreflight.needsPopUpgrade && dotnsPreflight.targetPopStatus !== void 0 && dotnsPreflight.isTestnet) {
885
+ await dotns.setUserPopStatus(dotnsPreflight.targetPopStatus);
886
+ }
882
887
  console.log(` Status: Registering...`);
883
888
  await dotns.register(name);
884
889
  }
885
890
  }
886
891
  const contenthashHex = `0x${encodeContenthash(cid)}`;
887
892
  await dotns.setContenthash(name, contenthashHex);
893
+ const textRecordTarget = parsed?.isSubdomain && parsed.sublabel && parsed.parentLabel ? `${parsed.sublabel}.${parsed.parentLabel}` : name;
894
+ if (options.name !== void 0) await dotns.setTextRecord(textRecordTarget, "name", options.name);
895
+ if (options.description !== void 0) await dotns.setTextRecord(textRecordTarget, "description", options.description);
888
896
  dotns.disconnect();
889
897
  });
890
898
  if (options.ghPagesMirror) {
@@ -961,6 +969,7 @@ export {
961
969
  merkleize,
962
970
  computeStorageCid,
963
971
  storeDirectory,
972
+ resolveDotnsConnectOptions,
964
973
  estimateUploadBytes,
965
974
  deploy
966
975
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-Y6CTPQS2.js";
3
+ } from "./chunk-LNFD7QP6.js";
4
4
 
5
5
  // src/version-check.ts
6
6
  import { execSync, execFileSync } from "child_process";
@@ -2,11 +2,11 @@ import {
2
2
  classifyErrorArea,
3
3
  isInteractive,
4
4
  promptYesNo
5
- } from "./chunk-EECNTEAE.js";
5
+ } from "./chunk-BEAOHOTJ.js";
6
6
  import {
7
7
  VERSION,
8
8
  getCurrentSentryTraceId
9
- } from "./chunk-Y6CTPQS2.js";
9
+ } from "./chunk-LNFD7QP6.js";
10
10
 
11
11
  // src/bug-report.ts
12
12
  import { execSync, execFileSync } from "child_process";
@@ -2,16 +2,16 @@ import {
2
2
  captureWarning,
3
3
  setDeployAttribute,
4
4
  withSpan
5
- } from "./chunk-Y6CTPQS2.js";
5
+ } from "./chunk-LNFD7QP6.js";
6
6
  import {
7
7
  isTestnetSpecName
8
- } from "./chunk-WIBZPZSY.js";
8
+ } from "./chunk-RP4YJYNB.js";
9
9
 
10
10
  // src/dotns.ts
11
11
  import { spawn } from "child_process";
12
12
  import { readFileSync } from "fs";
13
13
  import { dirname, join } from "path";
14
- import { createClient } from "polkadot-api";
14
+ import { createClient, Enum } from "polkadot-api";
15
15
  import { getPolkadotSigner } from "polkadot-api/signer";
16
16
  import { getWsProvider } from "polkadot-api/ws-provider";
17
17
  import { Keyring } from "@polkadot/keyring";
@@ -45,6 +45,19 @@ try {
45
45
  _dotnsCliPath = "dotns";
46
46
  console.warn(`[bulletin-deploy] @parity/dotns-cli not found in node_modules \u2014 falling back to "dotns" in PATH. Install with: npm install @parity/dotns-cli. Underlying: ${err.message}`);
47
47
  }
48
+ var ONE_PAS = 10000000000n;
49
+ var FEE_FLOOR_OWNED = ONE_PAS / 100n;
50
+ var FEE_FLOOR_REGISTER = ONE_PAS / 10n;
51
+ var TOP_UP_TARGET = ONE_PAS / 2n;
52
+ var SOURCE_BUFFER = ONE_PAS;
53
+ var TOP_UP_TRANSFER_TIMEOUT_MS = 6e4;
54
+ var PASEO_FAUCET_URL = "https://faucet.polkadot.io";
55
+ function fmtPas(plancks) {
56
+ return (Number(plancks) / Number(ONE_PAS)).toFixed(4);
57
+ }
58
+ function feeFloorFor(plannedAction) {
59
+ return plannedAction === "already-owned-by-us" ? FEE_FLOOR_OWNED : FEE_FLOOR_REGISTER;
60
+ }
48
61
  var RPC_ENDPOINTS = [
49
62
  "wss://asset-hub-paseo.dotters.network",
50
63
  "wss://sys.ibp.network/asset-hub-paseo",
@@ -282,12 +295,13 @@ function canRegister(requiredStatus, userStatus, trailingDigits) {
282
295
  function simulateUserStatus(currentStatus, requiredStatus, options) {
283
296
  const max = (a, b) => a > b ? a : b;
284
297
  if (options.explicitStatus !== void 0) {
285
- return max(currentStatus, options.explicitStatus);
298
+ if (options.isTestnet) return max(currentStatus, options.explicitStatus);
299
+ return currentStatus;
286
300
  }
287
301
  if (requiredStatus === ProofOfPersonhoodStatus.NoStatus && currentStatus === ProofOfPersonhoodStatus.ProofOfPersonhoodLite && options.isTestnet) {
288
302
  return ProofOfPersonhoodStatus.ProofOfPersonhoodFull;
289
303
  }
290
- if (requiredStatus !== ProofOfPersonhoodStatus.NoStatus) {
304
+ if (requiredStatus !== ProofOfPersonhoodStatus.NoStatus && options.isTestnet) {
291
305
  return max(currentStatus, requiredStatus);
292
306
  }
293
307
  return currentStatus;
@@ -520,6 +534,129 @@ var DotNS = class {
520
534
  this._testnetCache = isTestnetSpecName(rpc) || rpc.includes("paseo") || rpc.includes("westend") || rpc.includes("rococo");
521
535
  return this._testnetCache;
522
536
  }
537
+ // Free PAS balance for a substrate address on the connected DotNS chain.
538
+ // Used by preflight to gate the deploy on whether the signer can pay tx
539
+ // fees before the chunk upload runs. Returns 0n if the account doesn't
540
+ // exist on chain.
541
+ async readFreeBalance(ss58) {
542
+ this.ensureConnected();
543
+ if (!this.clientWrapper) throw new Error("readFreeBalance: polkadot-api client not available");
544
+ const acc = await this.clientWrapper.client.query.System.Account.getValue(ss58);
545
+ return BigInt(acc?.data?.free ?? 0n);
546
+ }
547
+ // Testnet-only: try to top the deploy signer up from the well-known dev
548
+ // phrase's Alice (root) or Bob (//Bob) account. Each candidate is read,
549
+ // skipped if it can't spare the transfer, and otherwise used to send
550
+ // `targetAmount` to `recipientSs58`. Returns the source label + amount on
551
+ // success, or null if neither candidate had the funds. The dev phrase is
552
+ // hardcoded on purpose — this only fires on testnet (gated by caller) and
553
+ // runs against accounts every Substrate-Polkadot tester can fund.
554
+ async attemptTestnetTopUp(recipientSs58, targetAmount) {
555
+ this.ensureConnected();
556
+ if (!this.clientWrapper) throw new Error("attemptTestnetTopUp: polkadot-api client not available");
557
+ await cryptoWaitReady();
558
+ const keyring = new Keyring({ type: "sr25519" });
559
+ const sources = [
560
+ { label: "Alice", uri: DEFAULT_MNEMONIC },
561
+ { label: "Bob", uri: `${DEFAULT_MNEMONIC}//Bob` }
562
+ ];
563
+ for (const src of sources) {
564
+ const account = keyring.addFromUri(src.uri);
565
+ if (account.address === recipientSs58) continue;
566
+ const sourceBalance = await this.readFreeBalance(account.address);
567
+ if (sourceBalance < targetAmount + SOURCE_BUFFER) {
568
+ console.log(` ${src.label} (${account.address.slice(0, 8)}...) low: ${fmtPas(sourceBalance)} PAS \u2014 skipping`);
569
+ captureWarning(`DotNS auto-top-up: ${src.label} insufficient`, {
570
+ source: src.label,
571
+ sourceAddress: account.address,
572
+ free: sourceBalance.toString(),
573
+ required: (targetAmount + SOURCE_BUFFER).toString()
574
+ });
575
+ continue;
576
+ }
577
+ const signer = getPolkadotSigner(
578
+ account.publicKey,
579
+ "Sr25519",
580
+ async (input) => account.sign(input)
581
+ );
582
+ console.log(` Trying ${src.label} (${account.address.slice(0, 8)}...): transferring ${fmtPas(targetAmount)} PAS to ${recipientSs58.slice(0, 8)}...`);
583
+ try {
584
+ await withTimeout(
585
+ this.submitTransfer(signer, recipientSs58, targetAmount),
586
+ TOP_UP_TRANSFER_TIMEOUT_MS,
587
+ `Balances.transfer_allow_death from ${src.label}`
588
+ );
589
+ return { source: src.label, transferred: targetAmount };
590
+ } catch (e) {
591
+ console.log(` Top-up via ${src.label} failed: ${e.message?.slice(0, 200)}`);
592
+ }
593
+ }
594
+ return null;
595
+ }
596
+ // Helper: submit a Balances.transfer_allow_death tx and resolve only after
597
+ // GRANDPA finalization (not best-block inclusion). Auto-top-up writes to
598
+ // the deploy signer's balance; if a re-org rolls back a best-block credit
599
+ // before the deploy's next tx, preflight reports success but setContenthash
600
+ // / register fail with Insufficient funds again. Waiting for finalization
601
+ // adds ~18s on Asset Hub Paseo but eliminates the re-org window.
602
+ // Logs a per-block-progress line so the operator sees the wait isn't a hang.
603
+ // Note: Enum("Id", ss58) is required to decode the SS58 to AccountId32;
604
+ // the structural literal { type: "Id", value } encodes wrong.
605
+ // Companion in tools/setup-e2e-derivation-signers.mjs uses best-block only;
606
+ // that's a one-time setup script, not a runtime gate, so the trade-off there
607
+ // is different.
608
+ submitTransfer(signer, destSubstrate, valueRaw) {
609
+ const api = this.clientWrapper.client;
610
+ const tx = api.tx.Balances.transfer_allow_death({
611
+ dest: Enum("Id", destSubstrate),
612
+ value: valueRaw
613
+ });
614
+ return new Promise((resolve, reject) => {
615
+ let settled = false;
616
+ let bestBlockSeen = false;
617
+ const sub = tx.signSubmitAndWatch(signer).subscribe({
618
+ next: (event) => {
619
+ if (settled) return;
620
+ if (event.type === "txBestBlocksState" && event.found && !bestBlockSeen) {
621
+ bestBlockSeen = true;
622
+ if (!event.ok) {
623
+ settled = true;
624
+ try {
625
+ sub.unsubscribe();
626
+ } catch {
627
+ }
628
+ reject(new Error("Balances.transfer_allow_death dispatch error"));
629
+ return;
630
+ }
631
+ console.log(` Tx in best block \u2014 waiting for finalization...`);
632
+ return;
633
+ }
634
+ if (event.type === "finalized") {
635
+ settled = true;
636
+ try {
637
+ sub.unsubscribe();
638
+ } catch {
639
+ }
640
+ if (event.ok === false) reject(new Error("Balances.transfer_allow_death finalization error"));
641
+ else resolve();
642
+ }
643
+ },
644
+ error: (e) => {
645
+ if (settled) return;
646
+ settled = true;
647
+ reject(e instanceof Error ? e : new Error(String(e)));
648
+ },
649
+ // Defensive: papi can complete the stream after a network drop without
650
+ // emitting finalized. Without this, the promise hangs forever and
651
+ // preflight stalls. Reject so the caller falls back to Bob.
652
+ complete: () => {
653
+ if (settled) return;
654
+ settled = true;
655
+ reject(new Error("transfer subscription closed without finalization"));
656
+ }
657
+ });
658
+ });
659
+ }
523
660
  async contractCall(contractAddress, contractAbi, functionName, args = []) {
524
661
  this.ensureConnected();
525
662
  if (!this.clientWrapper) throw new Error("contractCall: polkadot-api client not available");
@@ -650,6 +787,30 @@ var DotNS = class {
650
787
  return { node };
651
788
  });
652
789
  }
790
+ async setTextRecord(domainName, key, value, _cli = runDotnsCli) {
791
+ return withSpan("deploy.dotns.set-text", `2c. set-text ${key}`, {}, async () => {
792
+ this.ensureConnected();
793
+ console.log(` Setting text[${key}]: ${value}`);
794
+ const authEnv = buildAuthEnv({ mnemonic: this._mnemonic ?? void 0, keyUri: this._keyUri ?? void 0 });
795
+ const setResult = await _cli(
796
+ ["text", "set", domainName, key, value, "--json", ...rpcFlag(this.rpc)],
797
+ authEnv
798
+ );
799
+ console.log(` Tx: ${setResult.txHash}`);
800
+ const viewResult = await _cli(
801
+ ["text", "view", domainName, key, "--json", ...rpcFlag(this.rpc)]
802
+ );
803
+ const onChain = viewResult.value ?? "";
804
+ if (onChain !== value) {
805
+ throw new Error(
806
+ `Post-set verification failed for text[${key}] on ${domainName}.dot: on-chain value is ${JSON.stringify(onChain)}, not ${JSON.stringify(value)} we just wrote. The setText tx may have silently failed, or another writer overwrote the record.`
807
+ );
808
+ }
809
+ console.log(` Verified text[${key}]: ${onChain}
810
+ `);
811
+ return { value, txHash: setResult.txHash };
812
+ });
813
+ }
653
814
  async getContenthash(domainName) {
654
815
  this.ensureConnected();
655
816
  const result = await runDotnsCli(
@@ -687,11 +848,12 @@ var DotNS = class {
687
848
  };
688
849
  }
689
850
  const baseName = stripTrailingDigits(validated);
690
- const [userStatus, baseReservation, ownership, isTestnet] = await Promise.all([
851
+ const [userStatus, baseReservation, ownership, isTestnet, signerFreeBalance] = await Promise.all([
691
852
  this.getUserPopStatus(),
692
853
  withTimeout(this.contractCall(CONTRACTS.POP_RULES, POP_RULES_ABI, "isBaseNameReserved", [baseName]), 3e4, "isBaseNameReserved"),
693
854
  this.checkOwnership(validated),
694
- this.isTestnet()
855
+ this.isTestnet(),
856
+ this.readFreeBalance(this.substrateAddress)
695
857
  ]);
696
858
  const [isReserved, reservationOwnerRaw] = baseReservation;
697
859
  const reservationOwner = isReserved ? reservationOwnerRaw.toLowerCase() : null;
@@ -713,11 +875,12 @@ var DotNS = class {
713
875
  canProceed: false,
714
876
  reason: `Domain ${validated}.dot is already owned by ${existingOwner}.`,
715
877
  plannedAction: "abort",
716
- needsPopUpgrade: false
878
+ needsPopUpgrade: false,
879
+ signerFreeBalance
717
880
  };
718
881
  }
719
882
  if (existingOwner !== null && existingOwner === selfAddress) {
720
- return {
883
+ return await this.gateOnFeeBalance({
721
884
  label: validated,
722
885
  classification,
723
886
  userStatus,
@@ -731,7 +894,7 @@ var DotNS = class {
731
894
  canProceed: true,
732
895
  plannedAction: "already-owned-by-us",
733
896
  needsPopUpgrade: false
734
- };
897
+ }, signerFreeBalance, isTestnet);
735
898
  }
736
899
  if (isReserved && reservationOwner !== selfAddress) {
737
900
  return {
@@ -748,7 +911,8 @@ var DotNS = class {
748
911
  canProceed: false,
749
912
  reason: `Base name ${baseName} is reserved for ${reservationOwner}.`,
750
913
  plannedAction: "abort",
751
- needsPopUpgrade: false
914
+ needsPopUpgrade: false,
915
+ signerFreeBalance
752
916
  };
753
917
  }
754
918
  const explicitStatus = explicitStatusOverride ?? process.env.DOTNS_STATUS;
@@ -771,10 +935,11 @@ var DotNS = class {
771
935
  reason: `${validated}.dot classifies as ${className}; this signer cannot register it (PopRules.priceWithCheck gate). Remediations: use a signer with Full PoP, or pick a base name of 6-8 chars + trailing 00 (which classifies as PopLite).`,
772
936
  plannedAction: "abort",
773
937
  needsPopUpgrade: false,
774
- targetPopStatus
938
+ targetPopStatus,
939
+ signerFreeBalance
775
940
  };
776
941
  }
777
- return {
942
+ return await this.gateOnFeeBalance({
778
943
  label: validated,
779
944
  classification,
780
945
  userStatus,
@@ -789,9 +954,55 @@ var DotNS = class {
789
954
  plannedAction: "register",
790
955
  needsPopUpgrade: targetPopStatus !== userStatus,
791
956
  targetPopStatus
792
- };
957
+ }, signerFreeBalance, isTestnet);
793
958
  });
794
959
  }
960
+ // Final preflight stage: check the DotNS signer can pay tx fees on the
961
+ // connected fee chain (Asset Hub Paseo for testnet, Asset Hub Polkadot for
962
+ // mainnet). On testnet, attempts a one-shot auto-top-up from the dev
963
+ // phrase's Alice or Bob if the signer is short. Replaces the original
964
+ // canProceed:true result with an actionable canProceed:false when even the
965
+ // top-up can't get the signer above the threshold.
966
+ async gateOnFeeBalance(candidate, signerFreeBalance, isTestnet) {
967
+ const feeFloor = feeFloorFor(candidate.plannedAction);
968
+ let effectiveBalance = signerFreeBalance;
969
+ let toppedUp;
970
+ if (effectiveBalance < feeFloor && isTestnet) {
971
+ setDeployAttribute("deploy.dotns.signer_below_floor", "true");
972
+ console.log(` DotNS signer ${this.substrateAddress?.slice(0, 8)}... balance ${fmtPas(effectiveBalance)} PAS < ${fmtPas(feeFloor)} PAS floor \u2014 attempting testnet auto top-up...`);
973
+ const result = await this.attemptTestnetTopUp(this.substrateAddress, TOP_UP_TARGET);
974
+ if (result) {
975
+ console.log(` Topped up ${fmtPas(result.transferred)} PAS from ${result.source}`);
976
+ effectiveBalance += result.transferred;
977
+ toppedUp = result;
978
+ setDeployAttribute("deploy.dotns.toppedup", "true");
979
+ setDeployAttribute("deploy.dotns.toppedup_source", result.source);
980
+ }
981
+ } else if (effectiveBalance < feeFloor) {
982
+ setDeployAttribute("deploy.dotns.signer_below_floor", "true");
983
+ }
984
+ if (effectiveBalance < feeFloor) {
985
+ const op = candidate.plannedAction === "already-owned-by-us" ? "setContenthash" : "register";
986
+ const tail = isTestnet ? ` Testnet auto-top-up via Alice/Bob failed (both also low). Top up at ${PASEO_FAUCET_URL}.` : ` Top up the signer's balance and re-deploy.`;
987
+ captureWarning("DotNS preflight balance gate: signer cannot pay fees", {
988
+ signer: this.substrateAddress,
989
+ free: effectiveBalance.toString(),
990
+ floor: feeFloor.toString(),
991
+ plannedAction: candidate.plannedAction,
992
+ isTestnet: String(isTestnet),
993
+ autoTopUpAttempted: String(isTestnet)
994
+ });
995
+ return {
996
+ ...candidate,
997
+ canProceed: false,
998
+ plannedAction: "abort",
999
+ reason: `DotNS signer ${this.substrateAddress} has ${fmtPas(effectiveBalance)} PAS free; needs \u2265${fmtPas(feeFloor)} PAS for ${op}.${tail}`,
1000
+ signerFreeBalance: effectiveBalance,
1001
+ feeFloor
1002
+ };
1003
+ }
1004
+ return { ...candidate, signerFreeBalance: effectiveBalance, feeFloor, toppedUp };
1005
+ }
795
1006
  async register(label, options = {}) {
796
1007
  return withSpan("deploy.dotns.register", `2a. register ${label}.dot`, {}, async () => {
797
1008
  if (!this.connected) await this.connect(options);
@@ -859,6 +1070,8 @@ var DotNS = class {
859
1070
  var dotns = new DotNS();
860
1071
 
861
1072
  export {
1073
+ fmtPas,
1074
+ feeFloorFor,
862
1075
  RPC_ENDPOINTS,
863
1076
  CONTRACTS,
864
1077
  DECIMALS,
@@ -108,6 +108,14 @@ function runGit(args, cwd, extraEnv = {}) {
108
108
  env: { ...process.env, ...extraEnv }
109
109
  }).trim();
110
110
  }
111
+ var MIRROR_BOT_GIT_OVERRIDES = [
112
+ "-c",
113
+ "user.email=bulletin-deploy@noreply.github.com",
114
+ "-c",
115
+ "user.name=bulletin-deploy",
116
+ "-c",
117
+ "commit.gpgsign=false"
118
+ ];
111
119
  function pushRemoteUrl(owner, repo, token) {
112
120
  const authedOwner = token ? `x-access-token:${token}@github.com` : "github.com";
113
121
  return `https://${authedOwner}/${owner}/${repo}.git`;
@@ -154,7 +162,7 @@ async function mirrorToGitHubPages(input) {
154
162
  const manifestPath = path.join(mirrorDir, `${domainFilename}.json`);
155
163
  fs.writeFileSync(carPath, input.carBytes);
156
164
  fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
157
- runGit(["-c", `user.email=bulletin-deploy@noreply.github.com`, "-c", "user.name=bulletin-deploy", "add", GH_PAGES_MIRROR_DIR], workTree);
165
+ runGit([...MIRROR_BOT_GIT_OVERRIDES, "add", GH_PAGES_MIRROR_DIR], workTree);
158
166
  const status = runGit(["status", "--porcelain"], workTree);
159
167
  if (status.length === 0) {
160
168
  return {
@@ -167,10 +175,7 @@ async function mirrorToGitHubPages(input) {
167
175
  }
168
176
  runGit(
169
177
  [
170
- "-c",
171
- "user.email=bulletin-deploy@noreply.github.com",
172
- "-c",
173
- "user.name=bulletin-deploy",
178
+ ...MIRROR_BOT_GIT_OVERRIDES,
174
179
  "commit",
175
180
  "-m",
176
181
  `"mirror(bulletin): ${domainFilename} @ ${input.cid.slice(0, 12)}"`
@@ -209,5 +214,6 @@ export {
209
214
  normalizeDomainFilename,
210
215
  mirrorUrl,
211
216
  buildManifest,
217
+ MIRROR_BOT_GIT_OVERRIDES,
212
218
  mirrorToGitHubPages
213
219
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  package_default,
3
3
  writeRunState
4
- } from "./chunk-HHY32NGJ.js";
4
+ } from "./chunk-VKADME5F.js";
5
5
 
6
6
  // src/memory-report.ts
7
7
  import * as fs2 from "fs";
@@ -203,7 +203,12 @@ function getDeployAttributes(domain) {
203
203
  // Seed "false" so every span carries the attribute (boolean-both-values rule).
204
204
  // Flipped to "true" by getWsProvider's onStatusChanged when papi connects to a
205
205
  // non-primary endpoint, and flushed again in deploy()'s finally block.
206
- "deploy.rpc.failed_over": "false"
206
+ "deploy.rpc.failed_over": "false",
207
+ // DotNS preflight balance gate. Seeded "false" so successful spans form the
208
+ // denominator for "% of deploys hitting the floor" and "% recovered via
209
+ // testnet auto-top-up" metrics. Flipped by gateOnFeeBalance.
210
+ "deploy.dotns.signer_below_floor": "false",
211
+ "deploy.dotns.toppedup": "false"
207
212
  };
208
213
  if (hostApp) attrs["deploy.host_app"] = hostApp;
209
214
  return attrs;
@@ -7,6 +7,10 @@ import { getWsProvider } from "polkadot-api/ws-provider";
7
7
  import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat";
8
8
  import { Keyring } from "@polkadot/keyring";
9
9
  import { cryptoWaitReady } from "@polkadot/util-crypto";
10
+ var PAS_DECIMALS_DIVISOR = 1e10;
11
+ function formatPasBalance(plancks) {
12
+ return (Number(plancks) / PAS_DECIMALS_DIVISOR).toFixed(4);
13
+ }
10
14
  var DEPLOY_PATH_PREFIX = "//deploy";
11
15
  var TOPUP_TRANSACTIONS = 1e3;
12
16
  var TOPUP_BYTES = 100000000n;
@@ -198,7 +202,7 @@ async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic) {
198
202
  const aliceSigner = getPolkadotSigner(alice.publicKey, "Sr25519", (data) => alice.sign(data));
199
203
  const aliceAccount = await api.query.System.Account.getValue(alice.address);
200
204
  const aliceBalance = BigInt(aliceAccount.data.free);
201
- console.log(`Alice balance: ${(Number(aliceBalance) / 1e12).toFixed(4)} PAS
205
+ console.log(`Alice balance: ${formatPasBalance(aliceBalance)} PAS
202
206
  `);
203
207
  for (const account of accounts) {
204
208
  console.log(`Account ${account.index}: ${account.address}`);
@@ -239,6 +243,7 @@ async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic) {
239
243
  }
240
244
 
241
245
  export {
246
+ formatPasBalance,
242
247
  derivePoolAccounts,
243
248
  selectAccount,
244
249
  fetchPoolAuthorizations,
@@ -6,7 +6,7 @@ import * as path from "path";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "bulletin-deploy",
9
- version: "0.7.6",
9
+ version: "0.7.7",
10
10
  private: false,
11
11
  repository: {
12
12
  type: "git",
@@ -48,7 +48,7 @@ var package_default = {
48
48
  "@ipld/car": "^5.4.3",
49
49
  "@ipld/dag-pb": "^4.1.3",
50
50
  "@noble/hashes": "^1.7.2",
51
- "@parity/dotns-cli": "0.5.6",
51
+ "@parity/dotns-cli": "^0.6.0",
52
52
  "@polkadot-api/substrate-bindings": "^0.16.5",
53
53
  "@polkadot-labs/hdkd": "^0.0.25",
54
54
  "@polkadot-labs/hdkd-helpers": "^0.0.26",
package/dist/deploy.d.ts CHANGED
@@ -101,8 +101,18 @@ interface DeployOptions {
101
101
  * caveat.
102
102
  */
103
103
  ghPagesMirror?: boolean;
104
+ /** When set, writes the "name" text record on the domain after contenthash. */
105
+ name?: string;
106
+ /** When set, writes the "description" text record. ≤100 chars recommended for host-app cards. */
107
+ description?: string;
104
108
  }
109
+ declare function resolveDotnsConnectOptions(options: Pick<DeployOptions, "mnemonic" | "derivationPath" | "signer" | "signerAddress">): {
110
+ signer?: PolkadotSigner;
111
+ signerAddress?: string;
112
+ mnemonic?: string;
113
+ derivationPath?: string;
114
+ };
105
115
  declare function estimateUploadBytes(content: DeployContent): Promise<number | null>;
106
116
  declare function deploy(content: DeployContent, domainName?: string | null, options?: DeployOptions): Promise<DeployResult>;
107
117
 
108
- export { CHUNK_MORTALITY_PERIOD, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, type DeployContent, type DeployOptions, type DeployResult, ENCRYPT_KEY_LEN, ENCRYPT_MAGIC, ENCRYPT_NONCE_LEN, ENCRYPT_PBKDF2_ITERATIONS, ENCRYPT_SALT_LEN, ENCRYPT_TAG_LEN, EXIT_CODE_NO_RETRY, NonRetryableError, type StoreDirectoryOptions, chunk, computeStorageCid, createCID, deploy, deriveRootSigner, encodeContenthash, encryptContent, estimateUploadBytes, friendlyChainError, hasIPFS, isConnectionError, merkleize, storeChunkedContent, storeDirectory, storeFile };
118
+ export { CHUNK_MORTALITY_PERIOD, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, type DeployContent, type DeployOptions, type DeployResult, ENCRYPT_KEY_LEN, ENCRYPT_MAGIC, ENCRYPT_NONCE_LEN, ENCRYPT_PBKDF2_ITERATIONS, ENCRYPT_SALT_LEN, ENCRYPT_TAG_LEN, EXIT_CODE_NO_RETRY, NonRetryableError, type StoreDirectoryOptions, chunk, computeStorageCid, createCID, deploy, deriveRootSigner, encodeContenthash, encryptContent, estimateUploadBytes, friendlyChainError, hasIPFS, isConnectionError, merkleize, resolveDotnsConnectOptions, storeChunkedContent, storeDirectory, storeFile };
package/dist/deploy.js CHANGED
@@ -22,18 +22,19 @@ import {
22
22
  hasIPFS,
23
23
  isConnectionError,
24
24
  merkleize,
25
+ resolveDotnsConnectOptions,
25
26
  storeChunkedContent,
26
27
  storeDirectory,
27
28
  storeFile
28
- } from "./chunk-A2J6R5PD.js";
29
- import "./chunk-YX62STIA.js";
30
- import "./chunk-EECNTEAE.js";
31
- import "./chunk-G6CVI6U2.js";
32
- import "./chunk-2Q2WSKFD.js";
33
- import "./chunk-Y6CTPQS2.js";
34
- import "./chunk-HHY32NGJ.js";
29
+ } from "./chunk-77SWQOPW.js";
30
+ import "./chunk-D3SJZTE2.js";
31
+ import "./chunk-BEAOHOTJ.js";
32
+ import "./chunk-EOCLCWCS.js";
33
+ import "./chunk-HOTQDYHD.js";
34
+ import "./chunk-LNFD7QP6.js";
35
+ import "./chunk-VKADME5F.js";
35
36
  import "./chunk-B7GUYYAN.js";
36
- import "./chunk-WIBZPZSY.js";
37
+ import "./chunk-RP4YJYNB.js";
37
38
  import "./chunk-QGM4M3NI.js";
38
39
  export {
39
40
  CHUNK_MORTALITY_PERIOD,
@@ -59,6 +60,7 @@ export {
59
60
  hasIPFS,
60
61
  isConnectionError,
61
62
  merkleize,
63
+ resolveDotnsConnectOptions,
62
64
  storeChunkedContent,
63
65
  storeDirectory,
64
66
  storeFile
package/dist/dotns.d.ts CHANGED
@@ -44,7 +44,19 @@ interface DotnsPreflightResult {
44
44
  plannedAction: "register" | "already-owned-by-us" | "abort";
45
45
  needsPopUpgrade: boolean;
46
46
  targetPopStatus?: number;
47
+ /** Free PAS balance of the DotNS signer at preflight time, in plancks (10 decimals). */
48
+ signerFreeBalance?: bigint;
49
+ /** Threshold the signer must clear; depends on plannedAction. */
50
+ feeFloor?: bigint;
51
+ /** Set when an auto-top-up was attempted on testnet; describes the source and amount. */
52
+ toppedUp?: {
53
+ source: "Alice" | "Bob";
54
+ transferred: bigint;
55
+ };
47
56
  }
57
+ declare function fmtPas(plancks: bigint): string;
58
+ type DotnsSuccessAction = Exclude<DotnsPreflightResult["plannedAction"], "abort">;
59
+ declare function feeFloorFor(plannedAction: DotnsSuccessAction): bigint;
48
60
  declare const RPC_ENDPOINTS: string[];
49
61
  declare const CONTRACTS: {
50
62
  readonly DOTNS_REGISTRAR: "0x329aAA5b6bEa94E750b2dacBa74Bf41291E6c2BD";
@@ -130,6 +142,12 @@ declare class DotNS {
130
142
  ensureConnected(): void;
131
143
  private _testnetCache;
132
144
  isTestnet(): Promise<boolean>;
145
+ readFreeBalance(ss58: string): Promise<bigint>;
146
+ attemptTestnetTopUp(recipientSs58: string, targetAmount: bigint): Promise<{
147
+ source: "Alice" | "Bob";
148
+ transferred: bigint;
149
+ } | null>;
150
+ private submitTransfer;
133
151
  contractCall(contractAddress: string, contractAbi: readonly any[], functionName: string, args?: any[]): Promise<any>;
134
152
  checkOwnership(label: string, ownerAddress?: string | null): Promise<OwnershipResult>;
135
153
  getUserPopStatus(ownerAddress?: string | null): Promise<number>;
@@ -143,8 +161,13 @@ declare class DotNS {
143
161
  setContenthash(domainName: string, contenthashHex: string): Promise<{
144
162
  node: string;
145
163
  }>;
164
+ setTextRecord(domainName: string, key: string, value: string, _cli?: (argv: string[], env?: Record<string, string>) => Promise<unknown>): Promise<{
165
+ value: string;
166
+ txHash: string;
167
+ }>;
146
168
  getContenthash(domainName: string): Promise<string>;
147
169
  preflight(label: string, explicitStatusOverride?: string): Promise<DotnsPreflightResult>;
170
+ private gateOnFeeBalance;
148
171
  register(label: string, options?: DotNSConnectOptions & {
149
172
  status?: string;
150
173
  reverse?: boolean;
@@ -156,4 +179,4 @@ declare class DotNS {
156
179
  }
157
180
  declare const dotns: DotNS;
158
181
 
159
- export { CONNECTION_TIMEOUT_MS, CONTRACTS, DECIMALS, DEFAULT_MNEMONIC, DOTNS_TX_MAX_ATTEMPTS, DOT_NODE, DotNS, type DotNSConnectOptions, type DotnsPreflightResult, NATIVE_TO_ETH_RATIO, OPERATION_TIMEOUT_MS, type OwnershipResult, type ParsedDomainName, type PriceValidationResult, ProofOfPersonhoodStatus, RPC_ENDPOINTS, TX_CHAIN_TIME_BUDGET_MS, TX_TIMEOUT_MS, TX_WALL_CLOCK_CEILING_MS, WS_HEARTBEAT_TIMEOUT_MS, canRegister, classifyDotnsLabel, classifyTxRetryDecision, computeDomainTokenId, convertWeiToNative, countTrailingDigits, dotns, fetchNonce, isCommitmentMature, isExplicitCommitmentBuffer, parseDomainName, parseProofOfPersonhoodStatus, popStatusName, runDotnsCli, sanitizeDomainLabel, simulateUserStatus, stripTrailingDigits, validateDomainLabel, verifyNonceAdvanced };
182
+ export { CONNECTION_TIMEOUT_MS, CONTRACTS, DECIMALS, DEFAULT_MNEMONIC, DOTNS_TX_MAX_ATTEMPTS, DOT_NODE, DotNS, type DotNSConnectOptions, type DotnsPreflightResult, type DotnsSuccessAction, NATIVE_TO_ETH_RATIO, OPERATION_TIMEOUT_MS, type OwnershipResult, type ParsedDomainName, type PriceValidationResult, ProofOfPersonhoodStatus, RPC_ENDPOINTS, TX_CHAIN_TIME_BUDGET_MS, TX_TIMEOUT_MS, TX_WALL_CLOCK_CEILING_MS, WS_HEARTBEAT_TIMEOUT_MS, canRegister, classifyDotnsLabel, classifyTxRetryDecision, computeDomainTokenId, convertWeiToNative, countTrailingDigits, dotns, feeFloorFor, fetchNonce, fmtPas, isCommitmentMature, isExplicitCommitmentBuffer, parseDomainName, parseProofOfPersonhoodStatus, popStatusName, runDotnsCli, sanitizeDomainLabel, simulateUserStatus, stripTrailingDigits, validateDomainLabel, verifyNonceAdvanced };
package/dist/dotns.js CHANGED
@@ -21,7 +21,9 @@ import {
21
21
  convertWeiToNative,
22
22
  countTrailingDigits,
23
23
  dotns,
24
+ feeFloorFor,
24
25
  fetchNonce,
26
+ fmtPas,
25
27
  isCommitmentMature,
26
28
  isExplicitCommitmentBuffer,
27
29
  parseDomainName,
@@ -33,10 +35,10 @@ import {
33
35
  stripTrailingDigits,
34
36
  validateDomainLabel,
35
37
  verifyNonceAdvanced
36
- } from "./chunk-G6CVI6U2.js";
37
- import "./chunk-Y6CTPQS2.js";
38
- import "./chunk-HHY32NGJ.js";
39
- import "./chunk-WIBZPZSY.js";
38
+ } from "./chunk-EOCLCWCS.js";
39
+ import "./chunk-LNFD7QP6.js";
40
+ import "./chunk-VKADME5F.js";
41
+ import "./chunk-RP4YJYNB.js";
40
42
  import "./chunk-QGM4M3NI.js";
41
43
  export {
42
44
  CONNECTION_TIMEOUT_MS,
@@ -61,7 +63,9 @@ export {
61
63
  convertWeiToNative,
62
64
  countTrailingDigits,
63
65
  dotns,
66
+ feeFloorFor,
64
67
  fetchNonce,
68
+ fmtPas,
65
69
  isCommitmentMature,
66
70
  isExplicitCommitmentBuffer,
67
71
  parseDomainName,
@@ -70,6 +70,7 @@ declare function resolveSourceCommit(repoPath: string): string | undefined;
70
70
  declare function normalizeDomainFilename(domain: string): string;
71
71
  declare function mirrorUrl(owner: string, repo: string, domainFilename: string): string;
72
72
  declare function buildManifest(input: Omit<MirrorInput, "carBytes" | "repoPath" | "githubToken">): MirrorManifest;
73
+ declare const MIRROR_BOT_GIT_OVERRIDES: readonly string[];
73
74
  declare function mirrorToGitHubPages(input: MirrorInput): Promise<MirrorResult>;
74
75
 
75
- export { type FreshnessPollResult, GH_PAGES_MIRROR_BRANCH, GH_PAGES_MIRROR_DIR, GH_PAGES_MIRROR_MAX_BYTES, type MirrorInput, type MirrorManifest, type MirrorResult, MirrorSkipped, buildManifest, mirrorToGitHubPages, mirrorUrl, normalizeDomainFilename, parseGitRemoteUrl, pollMirrorFreshness, resolveOwnerRepo, resolveSourceCommit };
76
+ export { type FreshnessPollResult, GH_PAGES_MIRROR_BRANCH, GH_PAGES_MIRROR_DIR, GH_PAGES_MIRROR_MAX_BYTES, MIRROR_BOT_GIT_OVERRIDES, type MirrorInput, type MirrorManifest, type MirrorResult, MirrorSkipped, buildManifest, mirrorToGitHubPages, mirrorUrl, normalizeDomainFilename, parseGitRemoteUrl, pollMirrorFreshness, resolveOwnerRepo, resolveSourceCommit };
@@ -2,6 +2,7 @@ import {
2
2
  GH_PAGES_MIRROR_BRANCH,
3
3
  GH_PAGES_MIRROR_DIR,
4
4
  GH_PAGES_MIRROR_MAX_BYTES,
5
+ MIRROR_BOT_GIT_OVERRIDES,
5
6
  MirrorSkipped,
6
7
  buildManifest,
7
8
  mirrorToGitHubPages,
@@ -11,12 +12,13 @@ import {
11
12
  pollMirrorFreshness,
12
13
  resolveOwnerRepo,
13
14
  resolveSourceCommit
14
- } from "./chunk-2Q2WSKFD.js";
15
+ } from "./chunk-HOTQDYHD.js";
15
16
  import "./chunk-QGM4M3NI.js";
16
17
  export {
17
18
  GH_PAGES_MIRROR_BRANCH,
18
19
  GH_PAGES_MIRROR_DIR,
19
20
  GH_PAGES_MIRROR_MAX_BYTES,
21
+ MIRROR_BOT_GIT_OVERRIDES,
20
22
  MirrorSkipped,
21
23
  buildManifest,
22
24
  mirrorToGitHubPages,
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  deploy
3
- } from "./chunk-A2J6R5PD.js";
4
- import "./chunk-YX62STIA.js";
5
- import "./chunk-EECNTEAE.js";
3
+ } from "./chunk-77SWQOPW.js";
4
+ import "./chunk-D3SJZTE2.js";
5
+ import "./chunk-BEAOHOTJ.js";
6
6
  import {
7
7
  DotNS,
8
8
  parseDomainName
9
- } from "./chunk-G6CVI6U2.js";
10
- import "./chunk-2Q2WSKFD.js";
11
- import "./chunk-Y6CTPQS2.js";
9
+ } from "./chunk-EOCLCWCS.js";
10
+ import "./chunk-HOTQDYHD.js";
11
+ import "./chunk-LNFD7QP6.js";
12
12
  import {
13
13
  VERSION,
14
14
  loadRunState,
@@ -18,7 +18,7 @@ import {
18
18
  shouldSkipStaleWarning,
19
19
  stateFilePath,
20
20
  writeRunState
21
- } from "./chunk-HHY32NGJ.js";
21
+ } from "./chunk-VKADME5F.js";
22
22
  import {
23
23
  merkleizeJS
24
24
  } from "./chunk-B7GUYYAN.js";
@@ -28,7 +28,7 @@ import {
28
28
  ensureAuthorized,
29
29
  fetchPoolAuthorizations,
30
30
  selectAccount
31
- } from "./chunk-WIBZPZSY.js";
31
+ } from "./chunk-RP4YJYNB.js";
32
32
  import "./chunk-QGM4M3NI.js";
33
33
  export {
34
34
  DotNS,
@@ -5,8 +5,8 @@ import {
5
5
  maybeWriteMemoryReport,
6
6
  safeHeap,
7
7
  sampleFromBytes
8
- } from "./chunk-Y6CTPQS2.js";
9
- import "./chunk-HHY32NGJ.js";
8
+ } from "./chunk-LNFD7QP6.js";
9
+ import "./chunk-VKADME5F.js";
10
10
  import "./chunk-QGM4M3NI.js";
11
11
  export {
12
12
  DEFAULT_THRESHOLD_MB,
package/dist/pool.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { PolkadotSigner } from 'polkadot-api';
2
2
 
3
+ declare function formatPasBalance(plancks: bigint): string;
3
4
  interface PoolAccount {
4
5
  index: number;
5
6
  path: string;
@@ -34,4 +35,4 @@ declare function ensureAuthorized(api: any, address: string, label?: string, min
34
35
  declare function topUpBy(api: any, address: string, needs: AuthorizationNeeds, label?: string): Promise<void>;
35
36
  declare function bootstrapPool(bulletinRpc: string, poolSize?: number, mnemonic?: string): Promise<void>;
36
37
 
37
- export { type AuthorizationNeeds, type PoolAccount, type PoolAuthorization, type TxRetryDecision, _resetTestnetCacheForTests, bootstrapPool, classifyAliceTxError, computeTopUpTarget, derivePoolAccounts, detectTestnet, ensureAuthorized, fetchPoolAuthorizations, isTestnetSpecName, selectAccount, topUpBy };
38
+ export { type AuthorizationNeeds, type PoolAccount, type PoolAuthorization, type TxRetryDecision, _resetTestnetCacheForTests, bootstrapPool, classifyAliceTxError, computeTopUpTarget, derivePoolAccounts, detectTestnet, ensureAuthorized, fetchPoolAuthorizations, formatPasBalance, isTestnetSpecName, selectAccount, topUpBy };
package/dist/pool.js CHANGED
@@ -7,10 +7,11 @@ import {
7
7
  detectTestnet,
8
8
  ensureAuthorized,
9
9
  fetchPoolAuthorizations,
10
+ formatPasBalance,
10
11
  isTestnetSpecName,
11
12
  selectAccount,
12
13
  topUpBy
13
- } from "./chunk-WIBZPZSY.js";
14
+ } from "./chunk-RP4YJYNB.js";
14
15
  import "./chunk-QGM4M3NI.js";
15
16
  export {
16
17
  _resetTestnetCacheForTests,
@@ -21,6 +22,7 @@ export {
21
22
  detectTestnet,
22
23
  ensureAuthorized,
23
24
  fetchPoolAuthorizations,
25
+ formatPasBalance,
24
26
  isTestnetSpecName,
25
27
  selectAccount,
26
28
  topUpBy
package/dist/run-state.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  shouldSkipStaleWarning,
8
8
  stateFilePath,
9
9
  writeRunState
10
- } from "./chunk-HHY32NGJ.js";
10
+ } from "./chunk-VKADME5F.js";
11
11
  import "./chunk-QGM4M3NI.js";
12
12
  export {
13
13
  VERSION,
package/dist/telemetry.js CHANGED
@@ -24,8 +24,8 @@ import {
24
24
  truncateAddress,
25
25
  withDeploySpan,
26
26
  withSpan
27
- } from "./chunk-Y6CTPQS2.js";
28
- import "./chunk-HHY32NGJ.js";
27
+ } from "./chunk-LNFD7QP6.js";
28
+ import "./chunk-VKADME5F.js";
29
29
  import "./chunk-QGM4M3NI.js";
30
30
  export {
31
31
  VERSION,
@@ -8,9 +8,9 @@ import {
8
8
  isPreReleaseVersion,
9
9
  preReleaseWarning,
10
10
  promptYesNo
11
- } from "./chunk-EECNTEAE.js";
12
- import "./chunk-Y6CTPQS2.js";
13
- import "./chunk-HHY32NGJ.js";
11
+ } from "./chunk-BEAOHOTJ.js";
12
+ import "./chunk-LNFD7QP6.js";
13
+ import "./chunk-VKADME5F.js";
14
14
  import "./chunk-QGM4M3NI.js";
15
15
  export {
16
16
  assessVersion,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulletin-deploy",
3
- "version": "0.7.6",
3
+ "version": "0.7.7",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -42,7 +42,7 @@
42
42
  "@ipld/car": "^5.4.3",
43
43
  "@ipld/dag-pb": "^4.1.3",
44
44
  "@noble/hashes": "^1.7.2",
45
- "@parity/dotns-cli": "0.5.6",
45
+ "@parity/dotns-cli": "^0.6.0",
46
46
  "@polkadot-api/substrate-bindings": "^0.16.5",
47
47
  "@polkadot-labs/hdkd": "^0.0.25",
48
48
  "@polkadot-labs/hdkd-helpers": "^0.0.26",