@parity/product-deploy 0.11.0 → 0.12.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/bin/bulletin-bootstrap +23 -1
  2. package/dist/auth-config.js +3 -3
  3. package/dist/bug-report.js +4 -4
  4. package/dist/{chunk-SES7CGNY.js → chunk-DDC6NKE3.js} +1 -1
  5. package/dist/{chunk-TE2YKRYY.js → chunk-F4O42MUQ.js} +2 -2
  6. package/dist/{chunk-HLXRVFKL.js → chunk-FGCBIUMT.js} +38 -1
  7. package/dist/{chunk-HTZGBUZA.js → chunk-IR5BHZ2S.js} +3 -3
  8. package/dist/{chunk-7RYEYWYO.js → chunk-JGS6QR5X.js} +1 -1
  9. package/dist/{chunk-53BU4X2R.js → chunk-LRJTODL2.js} +12 -2
  10. package/dist/{chunk-UUJFLJKY.js → chunk-N7KXNIH4.js} +158 -61
  11. package/dist/{chunk-JWMHCW74.js → chunk-NRSIBGBP.js} +1 -1
  12. package/dist/{chunk-O4I37F5K.js → chunk-S62H6TWE.js} +55 -12
  13. package/dist/{chunk-7E33R3OQ.js → chunk-UPA5PEQA.js} +1 -1
  14. package/dist/{chunk-QDHLTSEO.js → chunk-WVVRMGKN.js} +2 -2
  15. package/dist/{chunk-MRQPJLPS.js → chunk-XVQICFTB.js} +22 -1
  16. package/dist/chunk-probe.d.ts +43 -1
  17. package/dist/chunk-probe.js +11 -5
  18. package/dist/commands/login.js +11 -11
  19. package/dist/commands/logout.js +4 -4
  20. package/dist/commands/transfer.js +4 -4
  21. package/dist/commands/whoami.js +3 -3
  22. package/dist/deploy-actors.js +6 -6
  23. package/dist/deploy.d.ts +45 -1
  24. package/dist/deploy.js +17 -11
  25. package/dist/dotns.d.ts +33 -1
  26. package/dist/dotns.js +14 -4
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +18 -12
  29. package/dist/manifest/publish.js +12 -12
  30. package/dist/memory-report.js +2 -2
  31. package/dist/merkle.js +11 -11
  32. package/dist/personhood/bootstrap.js +4 -4
  33. package/dist/personhood/people-client.js +4 -4
  34. package/dist/personhood/reprove.js +19 -2
  35. package/dist/pool.d.ts +11 -1
  36. package/dist/pool.js +9 -1
  37. package/dist/run-state.js +1 -1
  38. package/dist/sss-allowance-cache.js +4 -4
  39. package/dist/storage-signer.d.ts +28 -3
  40. package/dist/storage-signer.js +13 -11
  41. package/dist/telemetry.js +2 -2
  42. package/dist/version-check.js +3 -3
  43. package/package.json +1 -1
  44. package/tools/release-retry-wrapper.mjs +6 -0
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-SI2ZUOYD.js";
4
4
  import {
5
5
  isTestnetSpecName
6
- } from "./chunk-MRQPJLPS.js";
6
+ } from "./chunk-XVQICFTB.js";
7
7
  import {
8
8
  captureWarning,
9
9
  markCodePath,
@@ -11,7 +11,7 @@ import {
11
11
  setDeploySentryTag,
12
12
  truncateAddress,
13
13
  withSpan
14
- } from "./chunk-53BU4X2R.js";
14
+ } from "./chunk-LRJTODL2.js";
15
15
  import {
16
16
  validateContractAddresses
17
17
  } from "./chunk-JSYQ3JQS.js";
@@ -50,6 +50,11 @@ var CODE_PATHS = {
50
50
  // true → automated mapping via EVM key derivation
51
51
  // false → standard check (already-mapped or manually register)
52
52
  DOTNS_AUTO_MAPPING: "dotns.auto-mapping",
53
+ // NOTE (issue #706): marked "exempt" in tools/check-code-path-coverage.py's
54
+ // CODE_PATHS mirror — it's a real fallback for external DotNS library
55
+ // callers, but Parity-internal telemetry never sees that population, so
56
+ // it always reads 0 hits here regardless of real-world usage. Confirmed
57
+ // non-dead in PR #756 and again for #706; keep the branch and the ID.
53
58
  DOTNS_MANUAL_MAPPING: "dotns.manual-mapping"
54
59
  };
55
60
 
@@ -126,7 +131,23 @@ var TX_WALL_CLOCK_CEILING_MS = 24e4;
126
131
  var TX_NO_PROGRESS_MS = 9e4;
127
132
  var WS_HEARTBEAT_TIMEOUT_MS = 3e5;
128
133
  var DOTNS_TX_MAX_ATTEMPTS = 3;
134
+ var WatcherSilentNoEventError = class extends Error {
135
+ constructor(silentMs) {
136
+ super(`transaction watcher silent for ${Math.floor(silentMs / 1e3)}s \u2014 no response received (did you approve on your phone?)`);
137
+ this.name = "WatcherSilentNoEventError";
138
+ }
139
+ };
129
140
  var VERIFY_EFFECT_CHAIN_SECONDS = 60;
141
+ var NONCE_ADVANCE_VERIFY_RETRIES = 3;
142
+ var NONCE_ADVANCE_VERIFY_RETRY_INTERVAL_MS = 2e3;
143
+ async function verifyEffectWithGrace(verifyEffect, { retries = NONCE_ADVANCE_VERIFY_RETRIES, intervalMs = NONCE_ADVANCE_VERIFY_RETRY_INTERVAL_MS } = {}) {
144
+ if (await verifyEffect()) return true;
145
+ for (let attempt = 0; attempt < retries; attempt++) {
146
+ await new Promise((r) => setTimeout(r, intervalMs));
147
+ if (await verifyEffect()) return true;
148
+ }
149
+ return false;
150
+ }
130
151
  function classifyTxRetryDecision(err) {
131
152
  const msg = err instanceof Error ? err.message : String(err);
132
153
  const lower = msg.toLowerCase();
@@ -138,6 +159,12 @@ function classifyTxRetryDecision(err) {
138
159
  if (lower.includes("transaction watcher silent")) return "retry";
139
160
  return "abort";
140
161
  }
162
+ function classifyWatcherSilentFastFail(err, isPhoneSigner) {
163
+ if (err instanceof WatcherSilentNoEventError && isPhoneSigner === true) {
164
+ return new NonRetryableError("No signature received from the phone \u2014 re-run when you can approve on your phone.");
165
+ }
166
+ return null;
167
+ }
141
168
  var DOTNS_RETRY_BASE_MS = 400;
142
169
  var DOTNS_RETRY_MAX_MS = 6e3;
143
170
  function dotnsRetryBackoffMs(attempt, rand = Math.random) {
@@ -696,7 +723,7 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
696
723
  if (nonce.advanced) {
697
724
  if (opts.verifyEffect) {
698
725
  statusCallback("verifying");
699
- const observed = await opts.verifyEffect();
726
+ const observed = await verifyEffectWithGrace(opts.verifyEffect);
700
727
  if (!observed) {
701
728
  statusCallback("failed");
702
729
  finish(reject)(new Error(`nonce-advance fallback: nonce moved past ${opts.nonceFallback.expectedNonce} but expected on-chain effect not observable (likely a different tx of ours consumed the nonce, or our tx was reorged out)`));
@@ -724,7 +751,11 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
724
751
  const silentMs = Date.now() - lastEventAt;
725
752
  if (silentMs > TX_NO_PROGRESS_MS) {
726
753
  statusCallback("failed");
727
- finish(reject)(new Error(`transaction watcher silent for ${Math.floor(silentMs / 1e3)}s after ${lastEventType}`));
754
+ if (lastEventType === "(none)") {
755
+ finish(reject)(new WatcherSilentNoEventError(silentMs));
756
+ } else {
757
+ finish(reject)(new Error(`transaction watcher silent for ${Math.floor(silentMs / 1e3)}s after ${lastEventType}`));
758
+ }
728
759
  return;
729
760
  }
730
761
  } catch {
@@ -794,6 +825,11 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
794
825
  return await this.signAndSubmitExtrinsic(buildExtrinsic(), signer, filter.callback, opts);
795
826
  } catch (e) {
796
827
  lastError = e;
828
+ const fastFail = classifyWatcherSilentFastFail(e, opts.isPhoneSigner);
829
+ if (fastFail) {
830
+ filter.flush();
831
+ throw fastFail;
832
+ }
797
833
  const decision = classifyTxRetryDecision(e);
798
834
  const msg = e?.message ?? String(e);
799
835
  if (!shouldRetryTxAttempt(attempt, DOTNS_TX_MAX_ATTEMPTS, decision)) {
@@ -1430,18 +1466,19 @@ var DotNS = class {
1430
1466
  if (rawData.length <= 2) {
1431
1467
  const hasCode = await this.clientWrapper.hasContractCode(contractAddress);
1432
1468
  const name = dotnsContractName(contractAddress, this._contracts);
1469
+ const env = this._environmentId ?? "(unset)";
1433
1470
  if (hasCode === false) {
1434
1471
  throw new Error(
1435
- `No contract deployed at ${contractAddress} (${name}) \u2014 the dry-run call to ${functionName} returned empty success data, which on pallet-revive means the target address has no contract code. Check environments.json / --contract config for this network.`
1472
+ `No contract deployed at ${contractAddress} (${name}) env=${env} \u2014 the dry-run call to ${functionName} returned empty success data, which on pallet-revive means the target address has no contract code. Check environments.json / --contract config for this network.`
1436
1473
  );
1437
1474
  }
1438
1475
  if (hasCode === null) {
1439
1476
  throw new Error(
1440
- `Contract call returned empty data \u2014 contract=${name} (${contractAddress}) functionName=${functionName}. Could not verify whether contract code exists at this address (runtime code-presence query failed); investigate the contract/ABI or the configured address.`
1477
+ `Contract call returned empty data \u2014 contract=${name} (${contractAddress}) env=${env} functionName=${functionName}. Could not verify whether contract code exists at this address (runtime code-presence query failed); investigate the contract/ABI or the configured address.`
1441
1478
  );
1442
1479
  }
1443
1480
  throw new Error(
1444
- `Contract call returned empty data \u2014 contract=${name} (${contractAddress}) functionName=${functionName}. The address has contract code but the call returned no bytes, which is unexpected for this read. Investigate the contract/ABI rather than masking it with a default.`
1481
+ `Contract call returned empty data \u2014 contract=${name} (${contractAddress}) env=${env} functionName=${functionName}. The address has contract code but the call returned no bytes, which is unexpected for this read. Investigate the contract/ABI rather than masking it with a default.`
1445
1482
  );
1446
1483
  }
1447
1484
  return decodeFunctionResult({ abi: contractAbi, functionName, data: rawData });
@@ -1819,7 +1856,7 @@ var DotNS = class {
1819
1856
  const target = this._contracts.DOTNS_CONTENT_RESOLVER;
1820
1857
  let current = null;
1821
1858
  try {
1822
- current = await this.contractCall(this._contracts.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "resolver", [node]);
1859
+ current = await this.contractCallNullable(this._contracts.DOTNS_REGISTRY, DOTNS_REGISTRY_ABI, "resolver", [node]);
1823
1860
  } catch {
1824
1861
  }
1825
1862
  if (typeof current === "string" && current.toLowerCase() === target.toLowerCase()) {
@@ -1833,7 +1870,7 @@ var DotNS = class {
1833
1870
  async getTextRecord(domainName, key) {
1834
1871
  this.ensureConnected();
1835
1872
  const node = namehash(`${domainName}.dot`);
1836
- const result = await this.contractCall(
1873
+ const result = await this.contractCallNullable(
1837
1874
  this._contracts.DOTNS_CONTENT_RESOLVER,
1838
1875
  DOTNS_TEXT_RESOLVER_ABI,
1839
1876
  "text",
@@ -1880,7 +1917,7 @@ var DotNS = class {
1880
1917
  let onChainValue = "";
1881
1918
  let lastPrintedElapsed = -1;
1882
1919
  while (true) {
1883
- const onChain = await withTimeout(this.contractCall(this._contracts.DOTNS_CONTENT_RESOLVER, DOTNS_TEXT_RESOLVER_ABI, "text", [node, key]), 3e4, "text");
1920
+ const onChain = await withTimeout(this.contractCallNullable(this._contracts.DOTNS_CONTENT_RESOLVER, DOTNS_TEXT_RESOLVER_ABI, "text", [node, key]), 3e4, "text");
1884
1921
  onChainValue = onChain ?? "";
1885
1922
  if (onChainValue === value) break;
1886
1923
  const nowChainMs = Number(await this.clientWrapper.client.query.Timestamp.Now.getValue());
@@ -1937,7 +1974,7 @@ var DotNS = class {
1937
1974
  const startChainMs = Number(await this.clientWrapper.client.query.Timestamp.Now.getValue());
1938
1975
  let lastResults = [];
1939
1976
  while (true) {
1940
- lastResults = await Promise.all(entries.map((e) => withTimeout(this.contractCall(this._contracts.DOTNS_CONTENT_RESOLVER, DOTNS_TEXT_RESOLVER_ABI, "text", [node, e.key]), 3e4, "text").then((onChain) => ({ key: e.key, expected: e.value, onChain: onChain ?? "" }))));
1977
+ lastResults = await Promise.all(entries.map((e) => withTimeout(this.contractCallNullable(this._contracts.DOTNS_CONTENT_RESOLVER, DOTNS_TEXT_RESOLVER_ABI, "text", [node, e.key]), 3e4, "text").then((onChain) => ({ key: e.key, expected: e.value, onChain: onChain ?? "" }))));
1941
1978
  if (lastResults.every((v) => v.onChain === v.expected)) break;
1942
1979
  const nowChainMs = Number(await this.clientWrapper.client.query.Timestamp.Now.getValue());
1943
1980
  const chainElapsed = (nowChainMs - startChainMs) / 1e3;
@@ -2102,10 +2139,11 @@ var DotNS = class {
2102
2139
  this.ensureConnected();
2103
2140
  const node = namehash(`${domainName}.dot`);
2104
2141
  const result = await withTimeout(
2105
- this.contractCall(this._contracts.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [node]),
2142
+ this.contractCallNullable(this._contracts.DOTNS_CONTENT_RESOLVER, DOTNS_CONTENT_RESOLVER_ABI, "contenthash", [node]),
2106
2143
  3e4,
2107
2144
  "contenthash"
2108
2145
  );
2146
+ if (result === null) return "0x";
2109
2147
  return typeof result === "string" ? result : result?.toString?.() ?? String(result);
2110
2148
  }
2111
2149
  async classifyName(label) {
@@ -2759,8 +2797,13 @@ export {
2759
2797
  TX_NO_PROGRESS_MS,
2760
2798
  WS_HEARTBEAT_TIMEOUT_MS,
2761
2799
  DOTNS_TX_MAX_ATTEMPTS,
2800
+ WatcherSilentNoEventError,
2762
2801
  VERIFY_EFFECT_CHAIN_SECONDS,
2802
+ NONCE_ADVANCE_VERIFY_RETRIES,
2803
+ NONCE_ADVANCE_VERIFY_RETRY_INTERVAL_MS,
2804
+ verifyEffectWithGrace,
2763
2805
  classifyTxRetryDecision,
2806
+ classifyWatcherSilentFastFail,
2764
2807
  dotnsRetryBackoffMs,
2765
2808
  shouldRetryTxAttempt,
2766
2809
  shouldRegateBeforeResign,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-53BU4X2R.js";
3
+ } from "./chunk-LRJTODL2.js";
4
4
 
5
5
  // src/version-check.ts
6
6
  import { execSync, execFileSync } from "child_process";
@@ -4,10 +4,10 @@ import {
4
4
  } from "./chunk-5FLTDWWP.js";
5
5
  import {
6
6
  DOT_PRODUCT_ID
7
- } from "./chunk-JWMHCW74.js";
7
+ } from "./chunk-NRSIBGBP.js";
8
8
  import {
9
9
  DEFAULT_MNEMONIC
10
- } from "./chunk-O4I37F5K.js";
10
+ } from "./chunk-S62H6TWE.js";
11
11
 
12
12
  // src/deploy-actors.ts
13
13
  var DEFAULT_WORKER_SURI = DEFAULT_MNEMONIC;
@@ -37,6 +37,15 @@ function isAuthorizationSufficient(auth, currentBlock) {
37
37
  function accountsNeedingAuthorization(auths, currentBlock) {
38
38
  return auths.filter((a) => !isAuthorizationSufficient(a, currentBlock));
39
39
  }
40
+ var BULLETIN_BLOCK_TIME_SECS = 6;
41
+ var BULLETIN_BLOCKS_PER_DAY = Math.floor(86400 / BULLETIN_BLOCK_TIME_SECS);
42
+ function accountsNeedingReauthorization(auths, currentBlock, bufferBlocks = BULLETIN_BLOCKS_PER_DAY) {
43
+ const deadline = currentBlock + bufferBlocks;
44
+ return auths.filter((a) => !isAuthorizationSufficient(a, deadline));
45
+ }
46
+ function isAutoReauthorizeAllowed(env) {
47
+ return env?.network !== "mainnet" && env?.bulletinAutoAuthorize === true;
48
+ }
40
49
  function selectAccount(authorizations, random = Math.random, pinnedIndex) {
41
50
  if (pinnedIndex != null) {
42
51
  const pinned = authorizations.find((a) => a.index === pinnedIndex);
@@ -164,13 +173,21 @@ async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic, opts = {}) {
164
173
  printAuthStatus(a, currentBlock);
165
174
  }
166
175
  console.log("");
167
- const needsAuth = accountsNeedingAuthorization(auths, currentBlock);
176
+ const reauthBufferBlocks = opts.reauthBufferBlocks ?? 0;
177
+ const needsAuth = accountsNeedingReauthorization(auths, currentBlock, reauthBufferBlocks);
168
178
  if (needsAuth.length === 0) {
169
179
  console.log("All pool accounts are authorized. Nothing to do.");
170
180
  return;
171
181
  }
172
182
  console.log(`${needsAuth.length} account(s) need authorization.
173
183
  `);
184
+ if (reauthBufferBlocks > 0 && !opts.allowAutoReauthorize) {
185
+ const details = needsAuth.map((a) => ` [${a.index}] ${a.address} \u2014 expires @${a.expiration} (current block ${currentBlock})`).join("\n");
186
+ throw new Error(
187
+ `Auto-reauthorize is testnet-only (see isAutoReauthorizeAllowed / environments.json bulletinAutoAuthorize) and this call was not cleared to write. ${needsAuth.length} account(s) need reauthorization within the ${reauthBufferBlocks}-block buffer:
188
+ ${details}`
189
+ );
190
+ }
174
191
  let authorizerSigner;
175
192
  const keyring = new Keyring({ type: "sr25519" });
176
193
  if (opts.authorizerMnemonic) {
@@ -228,6 +245,10 @@ export {
228
245
  derivePoolAccounts,
229
246
  isAuthorizationSufficient,
230
247
  accountsNeedingAuthorization,
248
+ BULLETIN_BLOCK_TIME_SECS,
249
+ BULLETIN_BLOCKS_PER_DAY,
250
+ accountsNeedingReauthorization,
251
+ isAutoReauthorizeAllowed,
231
252
  selectAccount,
232
253
  fetchPoolAuthorizations,
233
254
  isTestnetSpecName,
@@ -29,9 +29,51 @@ declare function _decodeStorageValue(hex: string | null | undefined): {
29
29
  index: number;
30
30
  } | null;
31
31
  declare function probeChunks(cids: string[], options: ChainProbeOptions): Promise<ChunkProbeResult[]>;
32
+ /**
33
+ * Splits cids that are missing at finalised head into two buckets, using a
34
+ * best-block probe result for each cid:
35
+ * - `lagging`: present at best-block. GRANDPA just hasn't caught up yet
36
+ * (#1049) — these were never lost and must NEVER be re-uploaded.
37
+ * - `reallyMissing`: absent at best-block too (or the best-block probe
38
+ * itself failed, `present === null`) — genuinely dropped, or we
39
+ * couldn't determine presence at all. Either way, re-upload is the
40
+ * safe default: treating an indeterminate result as "lagging" risks
41
+ * silently skipping a chunk that's actually gone.
42
+ *
43
+ * Pure function — no chain I/O — so it's directly unit-testable against a
44
+ * mocked ChunkProbeResult array without a client.
45
+ */
46
+ declare function classifyFinalityGap(missingAtFinalized: string[], bestBlockResults: ChunkProbeResult[]): {
47
+ reallyMissing: string[];
48
+ lagging: string[];
49
+ };
50
+ /**
51
+ * Composite, chain-touching version of classifyFinalityGap (#1049): probes
52
+ * `missingAtFinalized` at best-block, retries once on an indeterminate
53
+ * result (present === null), then classifies. Any caller that finds cids
54
+ * missing at finalised head should route through this — not re-implement
55
+ * the probe/retry/classify sequence inline — so the "finalised-head absence
56
+ * is not proof of loss" policy stays consistent everywhere it's checked
57
+ * (the GRANDPA finality-check phase and the pre-setContenthash root
58
+ * re-check both use it).
59
+ */
60
+ declare function probeFinalityGap(missingAtFinalized: string[], options: ChainProbeOptions): Promise<{
61
+ reallyMissing: string[];
62
+ lagging: string[];
63
+ }>;
64
+ /**
65
+ * Best (non-finalised) block height, via `chain_getHeader`. Used by the
66
+ * initial chunk-upload retry loop (#1051) to detect a frozen chain — no new
67
+ * blocks since the last check — so it can wait instead of resubmitting into
68
+ * a stall (which just manufactures same-nonce collisions once the chain
69
+ * resumes). Returns `null` on any RPC failure or malformed response; callers
70
+ * must treat `null` as "can't tell" and fail open (proceed as if live)
71
+ * rather than blocking forever on a single bad peer.
72
+ */
73
+ declare function getBestBlockNumber(client: any): Promise<number | null>;
32
74
  /** Reset session-level caches. Used in tests only. */
33
75
  declare function _resetProbeSession(): void;
34
76
  /** Pre-set metadataChecked so tests don't need a real metadata RPC mock. Used in tests only. */
35
77
  declare function _bypassMetadataCheckForTest(): void;
36
78
 
37
- export { ChainProbeCrossValidationError, ChainProbeMetadataError, type ChainProbeOptions, type ChunkProbeFailureReason, type ChunkProbeResult, _bypassMetadataCheckForTest, _decodeStorageValue, _resetProbeSession, probeChunks };
79
+ export { ChainProbeCrossValidationError, ChainProbeMetadataError, type ChainProbeOptions, type ChunkProbeFailureReason, type ChunkProbeResult, _bypassMetadataCheckForTest, _decodeStorageValue, _resetProbeSession, classifyFinalityGap, getBestBlockNumber, probeChunks, probeFinalityGap };
@@ -4,15 +4,21 @@ import {
4
4
  _bypassMetadataCheckForTest,
5
5
  _decodeStorageValue,
6
6
  _resetProbeSession,
7
- probeChunks
8
- } from "./chunk-HLXRVFKL.js";
9
- import "./chunk-53BU4X2R.js";
10
- import "./chunk-SES7CGNY.js";
7
+ classifyFinalityGap,
8
+ getBestBlockNumber,
9
+ probeChunks,
10
+ probeFinalityGap
11
+ } from "./chunk-FGCBIUMT.js";
12
+ import "./chunk-LRJTODL2.js";
13
+ import "./chunk-DDC6NKE3.js";
11
14
  export {
12
15
  ChainProbeCrossValidationError,
13
16
  ChainProbeMetadataError,
14
17
  _bypassMetadataCheckForTest,
15
18
  _decodeStorageValue,
16
19
  _resetProbeSession,
17
- probeChunks
20
+ classifyFinalityGap,
21
+ getBestBlockNumber,
22
+ probeChunks,
23
+ probeFinalityGap
18
24
  };
@@ -3,10 +3,10 @@ import {
3
3
  } from "../chunk-J7CYVTAW.js";
4
4
  import {
5
5
  waitForBulletinAuthorization
6
- } from "../chunk-UUJFLJKY.js";
6
+ } from "../chunk-N7KXNIH4.js";
7
7
  import {
8
8
  preflightSssAllowance
9
- } from "../chunk-7RYEYWYO.js";
9
+ } from "../chunk-JGS6QR5X.js";
10
10
  import {
11
11
  statementSigningAccount
12
12
  } from "../chunk-GRPLHUYC.js";
@@ -15,11 +15,11 @@ import "../chunk-IW3X2MJF.js";
15
15
  import "../chunk-KOSF5FDO.js";
16
16
  import "../chunk-J3NIXHZZ.js";
17
17
  import "../chunk-S7EM5VMW.js";
18
- import "../chunk-HTZGBUZA.js";
19
- import "../chunk-7E33R3OQ.js";
20
- import "../chunk-HLXRVFKL.js";
18
+ import "../chunk-IR5BHZ2S.js";
19
+ import "../chunk-UPA5PEQA.js";
20
+ import "../chunk-FGCBIUMT.js";
21
21
  import "../chunk-C2TS5MER.js";
22
- import "../chunk-QDHLTSEO.js";
22
+ import "../chunk-WVVRMGKN.js";
23
23
  import "../chunk-JQKKMUCT.js";
24
24
  import {
25
25
  BULLETIN_RESOURCE,
@@ -36,15 +36,15 @@ import {
36
36
  getAuthClient,
37
37
  getPeopleChainEndpoints,
38
38
  resolveBulletinEndpoints
39
- } from "../chunk-JWMHCW74.js";
39
+ } from "../chunk-NRSIBGBP.js";
40
40
  import {
41
41
  CLI_NAME
42
42
  } from "../chunk-TSPERKUS.js";
43
- import "../chunk-O4I37F5K.js";
43
+ import "../chunk-S62H6TWE.js";
44
44
  import "../chunk-SI2ZUOYD.js";
45
- import "../chunk-MRQPJLPS.js";
46
- import "../chunk-53BU4X2R.js";
47
- import "../chunk-SES7CGNY.js";
45
+ import "../chunk-XVQICFTB.js";
46
+ import "../chunk-LRJTODL2.js";
47
+ import "../chunk-DDC6NKE3.js";
48
48
  import {
49
49
  loadEnvironments
50
50
  } from "../chunk-JSYQ3JQS.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clearSssAllowanceCache
3
- } from "../chunk-7RYEYWYO.js";
3
+ } from "../chunk-JGS6QR5X.js";
4
4
  import "../chunk-GRPLHUYC.js";
5
5
  import "../chunk-JQKKMUCT.js";
6
6
  import "../chunk-5FLTDWWP.js";
@@ -9,10 +9,10 @@ import {
9
9
  } from "../chunk-RIRDBSBG.js";
10
10
  import {
11
11
  getAuthClient
12
- } from "../chunk-JWMHCW74.js";
12
+ } from "../chunk-NRSIBGBP.js";
13
13
  import "../chunk-TSPERKUS.js";
14
- import "../chunk-53BU4X2R.js";
15
- import "../chunk-SES7CGNY.js";
14
+ import "../chunk-LRJTODL2.js";
15
+ import "../chunk-DDC6NKE3.js";
16
16
  import "../chunk-JSYQ3JQS.js";
17
17
  import "../chunk-ZOC4GITL.js";
18
18
 
@@ -4,11 +4,11 @@ import {
4
4
  import {
5
5
  DEFAULT_MNEMONIC,
6
6
  DotNS
7
- } from "../chunk-O4I37F5K.js";
7
+ } from "../chunk-S62H6TWE.js";
8
8
  import "../chunk-SI2ZUOYD.js";
9
- import "../chunk-MRQPJLPS.js";
10
- import "../chunk-53BU4X2R.js";
11
- import "../chunk-SES7CGNY.js";
9
+ import "../chunk-XVQICFTB.js";
10
+ import "../chunk-LRJTODL2.js";
11
+ import "../chunk-DDC6NKE3.js";
12
12
  import {
13
13
  getPopSelfServeConfig,
14
14
  loadEnvironments,
@@ -2,12 +2,12 @@ import {
2
2
  STALE_SESSION_MESSAGE,
3
3
  getAuthClient,
4
4
  hasPersistedSession
5
- } from "../chunk-JWMHCW74.js";
5
+ } from "../chunk-NRSIBGBP.js";
6
6
  import {
7
7
  CLI_NAME
8
8
  } from "../chunk-TSPERKUS.js";
9
- import "../chunk-53BU4X2R.js";
10
- import "../chunk-SES7CGNY.js";
9
+ import "../chunk-LRJTODL2.js";
10
+ import "../chunk-DDC6NKE3.js";
11
11
  import "../chunk-JSYQ3JQS.js";
12
12
  import "../chunk-ZOC4GITL.js";
13
13
 
@@ -2,17 +2,17 @@ import {
2
2
  MainnetDefaultWorkerError,
3
3
  resolveDeployActors,
4
4
  resolveStorageSigner
5
- } from "./chunk-QDHLTSEO.js";
5
+ } from "./chunk-WVVRMGKN.js";
6
6
  import "./chunk-JQKKMUCT.js";
7
7
  import "./chunk-5FLTDWWP.js";
8
8
  import "./chunk-RIRDBSBG.js";
9
- import "./chunk-JWMHCW74.js";
9
+ import "./chunk-NRSIBGBP.js";
10
10
  import "./chunk-TSPERKUS.js";
11
- import "./chunk-O4I37F5K.js";
11
+ import "./chunk-S62H6TWE.js";
12
12
  import "./chunk-SI2ZUOYD.js";
13
- import "./chunk-MRQPJLPS.js";
14
- import "./chunk-53BU4X2R.js";
15
- import "./chunk-SES7CGNY.js";
13
+ import "./chunk-XVQICFTB.js";
14
+ import "./chunk-LRJTODL2.js";
15
+ import "./chunk-DDC6NKE3.js";
16
16
  import "./chunk-JSYQ3JQS.js";
17
17
  import "./chunk-ZOC4GITL.js";
18
18
  export {
package/dist/deploy.d.ts CHANGED
@@ -164,6 +164,50 @@ declare function formatTransferModeStorageSignerLine(workerAddress: string): str
164
164
  * Exported for unit testing.
165
165
  */
166
166
  declare function formatTransferModeDotnsLine(alreadyOwned: boolean, dotName: string, recipient: string): string;
167
+ /**
168
+ * Produce an actionable reason string for the pool-fallback warning + telemetry
169
+ * attribute. BulletinSlotAuthError carries a typed reason; other errors
170
+ * (WS/connection, still possible after withTransientRetry's bounded retries
171
+ * are exhausted — see storage-signer.ts) use their message. Extracted from
172
+ * selectStorageReconnect so it's unit-testable without a real WS connection
173
+ * (#1058: pool fallbacks must always carry an explicit, visible reason).
174
+ */
175
+ declare function describeSlotFallbackReason(e: unknown): string;
176
+ /**
177
+ * Reconcile-before-resubmit (#1051). Pure decision function — no chain I/O —
178
+ * so it's directly unit-testable. Decides whether a timed-out chunk tx
179
+ * should be treated as already included (skip the resubmit, avoid a
180
+ * duplicate content write) based on two independent signals:
181
+ * - nonce advance: the account's nonce moved past the chunk's assigned
182
+ * nonce. Only meaningful when `nonceHeuristicValid` — false after a pool
183
+ * account rotation, where the old nonce baseline belongs to a different
184
+ * account (#951).
185
+ * - CID presence at best-block: a direct probe of the chunk's own content
186
+ * hash, independent of account/nonce bookkeeping entirely. Catches
187
+ * inclusion the nonce heuristic can miss (e.g. the endpoint used for the
188
+ * nonce fetch is briefly behind a peer that already saw the tx land).
189
+ * Either signal alone is sufficient.
190
+ */
191
+ declare function reconcileTimedOutChunk(opts: {
192
+ originalNonce: number | undefined;
193
+ currentNonce: number;
194
+ nonceHeuristicValid: boolean;
195
+ cidPresentAtBest: boolean | null;
196
+ }): boolean;
197
+ /**
198
+ * Chain-liveness gate (#1051). Polls `getBestBlockNumber` every
199
+ * CHUNK_LIVENESS_POLL_MS until height advances past `lastHeight`, or until
200
+ * `timeoutMs` elapses. Returns the last-observed height either way — never
201
+ * throws. `lastHeight === null` (couldn't determine a baseline) returns
202
+ * immediately without waiting: there's nothing to compare against, so
203
+ * waiting would just delay a resubmit decision for no benefit. A `null`
204
+ * result from `getBestBlockNumber` mid-wait (RPC failure) also returns
205
+ * immediately — fail open toward resubmitting rather than hanging on a dead
206
+ * peer.
207
+ */
208
+ declare function waitForChainLiveness(client: any, lastHeight: number | null, timeoutMs: number, pollMs?: number): Promise<number | null>;
209
+ /** Test-only alias — exported for unit tests that inject a short timeout/poll. */
210
+ declare const __waitForChainLivenessForTest: typeof waitForChainLiveness;
167
211
  declare function storeFile(contentBytes: Uint8Array, { client: existingClient, unsafeApi: existingApi, signer: existingSigner, hashCode, }?: ExistingProvider & {
168
212
  hashCode?: number;
169
213
  }): Promise<string>;
@@ -474,4 +518,4 @@ declare function computePhoneSigningSteps(dotnsPreflight: {
474
518
  needsPopUpgrade: boolean;
475
519
  } | null, publishNeeded: boolean): string[];
476
520
 
477
- export { BLAKE2B_256_MULTIHASH_CODE, BULLETIN_ENDPOINTS, type BitswapErrorVariant, type BitswapProbeResult, 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, PhoneSignatureStep, SHA256_MULTIHASH_CODE, type SizeDecision, type StoreDirectoryOptions, WS_HEARTBEAT_TIMEOUT_MS, __assignDenseNoncesForTest, __selectStorageProviderModeForTest, applyManifestFetchAttributes, assertSubdomainOwnerMatchesSigner, browserUrlFor, buildFilesMap, checkDeploySize, chooseSignerInput, chunk, computePhoneSigningSteps, computeStorageCid, createCID, deploy, deriveRootSigner, detectFramework, encodeContenthash, encryptContent, estimateUploadBytes, formatStorageSignerLine, formatTransferModeDotnsLine, formatTransferModeStorageSignerLine, friendlyChainError, hasIPFS, interpretBitswapResult, isBenignTeardownError, isConnectionError, isPhoneSignerActive, makeBulletinStatusHandler, merkleize, probeP2pRetrieval, resolveDotnsConnectOptions, resolveReproducibleTimestamp, retryBudgetExhausted, setWsHaltCallback, shouldHandoverName, storeChunkedContent, storeDirectory, storeDirectoryV2, storeFile, unpublish };
521
+ export { BLAKE2B_256_MULTIHASH_CODE, BULLETIN_ENDPOINTS, type BitswapErrorVariant, type BitswapProbeResult, 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, PhoneSignatureStep, SHA256_MULTIHASH_CODE, type SizeDecision, type StoreDirectoryOptions, WS_HEARTBEAT_TIMEOUT_MS, __assignDenseNoncesForTest, __selectStorageProviderModeForTest, __waitForChainLivenessForTest, applyManifestFetchAttributes, assertSubdomainOwnerMatchesSigner, browserUrlFor, buildFilesMap, checkDeploySize, chooseSignerInput, chunk, computePhoneSigningSteps, computeStorageCid, createCID, deploy, deriveRootSigner, describeSlotFallbackReason, detectFramework, encodeContenthash, encryptContent, estimateUploadBytes, formatStorageSignerLine, formatTransferModeDotnsLine, formatTransferModeStorageSignerLine, friendlyChainError, hasIPFS, interpretBitswapResult, isBenignTeardownError, isConnectionError, isPhoneSignerActive, makeBulletinStatusHandler, merkleize, probeP2pRetrieval, reconcileTimedOutChunk, resolveDotnsConnectOptions, resolveReproducibleTimestamp, retryBudgetExhausted, setWsHaltCallback, shouldHandoverName, storeChunkedContent, storeDirectory, storeDirectoryV2, storeFile, unpublish };
package/dist/deploy.js CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  WS_HEARTBEAT_TIMEOUT_MS,
15
15
  __assignDenseNoncesForTest,
16
16
  __selectStorageProviderModeForTest,
17
+ __waitForChainLivenessForTest,
17
18
  applyManifestFetchAttributes,
18
19
  assertSubdomainOwnerMatchesSigner,
19
20
  browserUrlFor,
@@ -26,6 +27,7 @@ import {
26
27
  createCID,
27
28
  deploy,
28
29
  deriveRootSigner,
30
+ describeSlotFallbackReason,
29
31
  detectFramework,
30
32
  encodeContenthash,
31
33
  encryptContent,
@@ -42,6 +44,7 @@ import {
42
44
  makeBulletinStatusHandler,
43
45
  merkleize,
44
46
  probeP2pRetrieval,
47
+ reconcileTimedOutChunk,
45
48
  resolveDotnsConnectOptions,
46
49
  resolveReproducibleTimestamp,
47
50
  retryBudgetExhausted,
@@ -52,29 +55,29 @@ import {
52
55
  storeDirectoryV2,
53
56
  storeFile,
54
57
  unpublish
55
- } from "./chunk-UUJFLJKY.js";
56
- import "./chunk-7RYEYWYO.js";
58
+ } from "./chunk-N7KXNIH4.js";
59
+ import "./chunk-JGS6QR5X.js";
57
60
  import "./chunk-GRPLHUYC.js";
58
61
  import "./chunk-HOTQDYHD.js";
59
62
  import "./chunk-IW3X2MJF.js";
60
63
  import "./chunk-KOSF5FDO.js";
61
64
  import "./chunk-J3NIXHZZ.js";
62
65
  import "./chunk-S7EM5VMW.js";
63
- import "./chunk-HTZGBUZA.js";
64
- import "./chunk-7E33R3OQ.js";
65
- import "./chunk-HLXRVFKL.js";
66
+ import "./chunk-IR5BHZ2S.js";
67
+ import "./chunk-UPA5PEQA.js";
68
+ import "./chunk-FGCBIUMT.js";
66
69
  import "./chunk-C2TS5MER.js";
67
- import "./chunk-QDHLTSEO.js";
70
+ import "./chunk-WVVRMGKN.js";
68
71
  import "./chunk-JQKKMUCT.js";
69
72
  import "./chunk-5FLTDWWP.js";
70
73
  import "./chunk-RIRDBSBG.js";
71
- import "./chunk-JWMHCW74.js";
74
+ import "./chunk-NRSIBGBP.js";
72
75
  import "./chunk-TSPERKUS.js";
73
- import "./chunk-O4I37F5K.js";
76
+ import "./chunk-S62H6TWE.js";
74
77
  import "./chunk-SI2ZUOYD.js";
75
- import "./chunk-MRQPJLPS.js";
76
- import "./chunk-53BU4X2R.js";
77
- import "./chunk-SES7CGNY.js";
78
+ import "./chunk-XVQICFTB.js";
79
+ import "./chunk-LRJTODL2.js";
80
+ import "./chunk-DDC6NKE3.js";
78
81
  import "./chunk-JSYQ3JQS.js";
79
82
  import {
80
83
  EXIT_CODE_NO_RETRY,
@@ -98,6 +101,7 @@ export {
98
101
  WS_HEARTBEAT_TIMEOUT_MS,
99
102
  __assignDenseNoncesForTest,
100
103
  __selectStorageProviderModeForTest,
104
+ __waitForChainLivenessForTest,
101
105
  applyManifestFetchAttributes,
102
106
  assertSubdomainOwnerMatchesSigner,
103
107
  browserUrlFor,
@@ -110,6 +114,7 @@ export {
110
114
  createCID,
111
115
  deploy,
112
116
  deriveRootSigner,
117
+ describeSlotFallbackReason,
113
118
  detectFramework,
114
119
  encodeContenthash,
115
120
  encryptContent,
@@ -126,6 +131,7 @@ export {
126
131
  makeBulletinStatusHandler,
127
132
  merkleize,
128
133
  probeP2pRetrieval,
134
+ reconcileTimedOutChunk,
129
135
  resolveDotnsConnectOptions,
130
136
  resolveReproducibleTimestamp,
131
137
  retryBudgetExhausted,