bulletin-deploy 0.6.3 → 0.6.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/{chunk-ECOC6TV4.js → chunk-3J3S6JLX.js} +1 -1
- package/dist/{chunk-TITCVJJF.js → chunk-MXMJJURQ.js} +12 -12
- package/dist/{chunk-IPTNRVHY.js → chunk-YNBJATGK.js} +64 -31
- package/dist/deploy.js +3 -3
- package/dist/dotns.js +2 -2
- package/dist/index.js +3 -3
- package/dist/telemetry.js +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
captureWarning,
|
|
3
3
|
withSpan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3J3S6JLX.js";
|
|
5
5
|
|
|
6
6
|
// src/dotns.ts
|
|
7
7
|
import crypto from "crypto";
|
|
@@ -51,13 +51,18 @@ var _rpcIdCounter = 0;
|
|
|
51
51
|
async function fetchNonce(rpc, ss58Address) {
|
|
52
52
|
const WS = globalThis.WebSocket ?? (await import("./wrapper-IFSKR7DG.js")).default;
|
|
53
53
|
return new Promise((resolve, reject) => {
|
|
54
|
-
|
|
54
|
+
let done = false;
|
|
55
|
+
const settle = (fn, ...args) => {
|
|
56
|
+
if (done) return;
|
|
57
|
+
done = true;
|
|
58
|
+
clearTimeout(timer);
|
|
55
59
|
try {
|
|
56
60
|
ws.close();
|
|
57
61
|
} catch {
|
|
58
62
|
}
|
|
59
|
-
|
|
60
|
-
}
|
|
63
|
+
fn(...args);
|
|
64
|
+
};
|
|
65
|
+
const timer = setTimeout(() => settle(reject, new Error(`fetchNonce timed out after 8s for ${rpc}`)), 8e3);
|
|
61
66
|
const ws = new WS(rpc);
|
|
62
67
|
const id = ++_rpcIdCounter;
|
|
63
68
|
ws.onopen = () => ws.send(JSON.stringify({ jsonrpc: "2.0", id, method: "system_accountNextIndex", params: [ss58Address] }));
|
|
@@ -65,16 +70,11 @@ async function fetchNonce(rpc, ss58Address) {
|
|
|
65
70
|
const d = typeof e.data === "string" ? e.data : e.data.toString();
|
|
66
71
|
const r = JSON.parse(d);
|
|
67
72
|
if (r.id === id) {
|
|
68
|
-
|
|
69
|
-
ws.close();
|
|
70
|
-
r.error ? reject(new Error(r.error.message)) : resolve(r.result);
|
|
73
|
+
r.error ? settle(reject, new Error(r.error.message)) : settle(resolve, r.result);
|
|
71
74
|
}
|
|
72
75
|
};
|
|
73
|
-
ws.onerror = () => {
|
|
74
|
-
|
|
75
|
-
ws.close();
|
|
76
|
-
reject(new Error(`WebSocket to ${rpc} failed`));
|
|
77
|
-
};
|
|
76
|
+
ws.onerror = () => settle(reject, new Error(`WebSocket to ${rpc} failed`));
|
|
77
|
+
ws.onclose = () => settle(reject, new Error(`WebSocket to ${rpc} closed before response`));
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
var ProofOfPersonhoodStatus = {
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
TX_TIMEOUT_MS,
|
|
5
5
|
fetchNonce,
|
|
6
6
|
validateDomainLabel
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MXMJJURQ.js";
|
|
8
8
|
import {
|
|
9
9
|
derivePoolAccounts,
|
|
10
10
|
ensureAuthorized,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
setDeployAttribute,
|
|
19
19
|
withDeploySpan,
|
|
20
20
|
withSpan
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-3J3S6JLX.js";
|
|
22
22
|
|
|
23
23
|
// src/deploy.ts
|
|
24
24
|
import { Buffer } from "buffer";
|
|
@@ -280,8 +280,10 @@ var BULLETIN_RPC = DEFAULT_BULLETIN_RPC;
|
|
|
280
280
|
var POOL_SIZE = DEFAULT_POOL_SIZE;
|
|
281
281
|
var CHUNK_SIZE = 1 * 1024 * 1024;
|
|
282
282
|
var MAX_FILE_SIZE = 8 * 1024 * 1024;
|
|
283
|
-
var MAX_RECONNECTIONS = parseInt(process.env.BULLETIN_MAX_RECONNECTIONS ?? "
|
|
283
|
+
var MAX_RECONNECTIONS = parseInt(process.env.BULLETIN_MAX_RECONNECTIONS ?? "3", 10);
|
|
284
284
|
var CHUNK_TIMEOUT_MS = 3e4;
|
|
285
|
+
var RETRY_BASE_DELAY_MS = 2e3;
|
|
286
|
+
var RETRY_MAX_DELAY_MS = 15e3;
|
|
285
287
|
function isConnectionError(error) {
|
|
286
288
|
const msg = error?.message || String(error);
|
|
287
289
|
return /heartbeat timeout|WS halt|Unable to connect/i.test(msg);
|
|
@@ -362,7 +364,7 @@ function toHashingEnum(mhCode) {
|
|
|
362
364
|
}
|
|
363
365
|
async function getProvider() {
|
|
364
366
|
console.log(` Connecting to Bulletin: ${BULLETIN_RPC}`);
|
|
365
|
-
const client = createPolkadotClient(withPolkadotSdkCompat(getWsProvider(BULLETIN_RPC)));
|
|
367
|
+
const client = createPolkadotClient(withPolkadotSdkCompat(getWsProvider([BULLETIN_RPC])));
|
|
366
368
|
const unsafeApi = client.getUnsafeApi();
|
|
367
369
|
try {
|
|
368
370
|
await cryptoWaitReady();
|
|
@@ -390,7 +392,7 @@ async function getProvider() {
|
|
|
390
392
|
}
|
|
391
393
|
async function getDirectProvider(mnemonic) {
|
|
392
394
|
console.log(` Connecting to Bulletin: ${BULLETIN_RPC}`);
|
|
393
|
-
const client = createPolkadotClient(withPolkadotSdkCompat(getWsProvider(BULLETIN_RPC)));
|
|
395
|
+
const client = createPolkadotClient(withPolkadotSdkCompat(getWsProvider([BULLETIN_RPC])));
|
|
394
396
|
const unsafeApi = client.getUnsafeApi();
|
|
395
397
|
const { signer, ss58 } = deriveRootSigner(mnemonic);
|
|
396
398
|
console.log(` Using direct signer: ${ss58}`);
|
|
@@ -408,39 +410,46 @@ async function getDirectProvider(mnemonic) {
|
|
|
408
410
|
setDeployAttribute("deploy.signer.address", ss58);
|
|
409
411
|
return { client, unsafeApi, signer, ss58 };
|
|
410
412
|
}
|
|
413
|
+
var MAX_BEST_CHAIN_DROPS = 5;
|
|
411
414
|
function watchTransaction(tx, signer, txOpts, onSuccess, { label = "transaction", rpc, senderSS58, expectedNonce, timeoutMs } = {}) {
|
|
412
415
|
const timeout = timeoutMs ?? TX_TIMEOUT_MS;
|
|
413
416
|
return new Promise((resolve2, reject) => {
|
|
414
417
|
let settled = false;
|
|
418
|
+
let sub;
|
|
419
|
+
let dropCount = 0;
|
|
415
420
|
const settle = (fn) => (...args) => {
|
|
416
|
-
if (
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
421
|
+
if (settled) return;
|
|
422
|
+
settled = true;
|
|
423
|
+
clearTimeout(timer);
|
|
424
|
+
try {
|
|
425
|
+
sub?.unsubscribe();
|
|
426
|
+
} catch {
|
|
427
|
+
}
|
|
428
|
+
fn(...args);
|
|
429
|
+
};
|
|
430
|
+
const tryNonceFallback = async () => {
|
|
431
|
+
if (!rpc || !senderSS58 || expectedNonce == null) return false;
|
|
432
|
+
try {
|
|
433
|
+
const currentNonce = await fetchNonce(rpc, senderSS58);
|
|
434
|
+
if (settled) return true;
|
|
435
|
+
if (currentNonce > expectedNonce) {
|
|
436
|
+
console.log(` ${label}: nonce advanced (${expectedNonce} -> ${currentNonce}), tx was included`);
|
|
437
|
+
settle(resolve2)({ value: onSuccess(), viaFallback: true });
|
|
438
|
+
return true;
|
|
422
439
|
}
|
|
423
|
-
|
|
440
|
+
} catch (e) {
|
|
441
|
+
if (settled) return true;
|
|
442
|
+
console.log(` ${label}: nonce fallback failed: ${e.message?.slice(0, 80)}`);
|
|
424
443
|
}
|
|
444
|
+
return false;
|
|
425
445
|
};
|
|
426
446
|
const timer = setTimeout(async () => {
|
|
427
447
|
if (settled) return;
|
|
428
|
-
if (
|
|
429
|
-
try {
|
|
430
|
-
const currentNonce = await fetchNonce(rpc, senderSS58);
|
|
431
|
-
if (currentNonce > expectedNonce) {
|
|
432
|
-
console.log(` ${label}: subscription timed out but nonce advanced (${expectedNonce} -> ${currentNonce}), tx was included`);
|
|
433
|
-
settle(resolve2)({ value: onSuccess(), viaFallback: true });
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
} catch (e) {
|
|
437
|
-
console.log(` ${label}: nonce check failed: ${e.message}`);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
448
|
+
if (await tryNonceFallback()) return;
|
|
440
449
|
settle(reject)(new Error(`${label} timed out after ${timeout / 1e3}s waiting for block confirmation`));
|
|
441
450
|
}, timeout);
|
|
442
|
-
|
|
443
|
-
next: (event) => {
|
|
451
|
+
sub = tx.signSubmitAndWatch(signer, txOpts).subscribe({
|
|
452
|
+
next: async (event) => {
|
|
444
453
|
if (event.type === "txBestBlocksState") {
|
|
445
454
|
if (event.found) {
|
|
446
455
|
if (event.ok) {
|
|
@@ -449,7 +458,14 @@ function watchTransaction(tx, signer, txOpts, onSuccess, { label = "transaction"
|
|
|
449
458
|
settle(reject)(new Error(`${label} dispatch error`));
|
|
450
459
|
}
|
|
451
460
|
} else {
|
|
452
|
-
|
|
461
|
+
dropCount++;
|
|
462
|
+
if (dropCount >= MAX_BEST_CHAIN_DROPS) {
|
|
463
|
+
console.log(` ${label}: tx dropped ${dropCount} times, checking nonce...`);
|
|
464
|
+
if (await tryNonceFallback()) return;
|
|
465
|
+
settle(reject)(new Error(`${label} tx dropped from best chain ${dropCount} times`));
|
|
466
|
+
} else {
|
|
467
|
+
console.log(` ${label}: tx dropped from best chain (${dropCount}/${MAX_BEST_CHAIN_DROPS}), waiting...`);
|
|
468
|
+
}
|
|
453
469
|
}
|
|
454
470
|
}
|
|
455
471
|
},
|
|
@@ -531,13 +547,15 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
|
|
|
531
547
|
throw new Error(`Connection lost and max reconnections (${MAX_RECONNECTIONS}) exhausted`);
|
|
532
548
|
}
|
|
533
549
|
reconnectionsUsed++;
|
|
550
|
+
const delay = Math.min(RETRY_BASE_DELAY_MS * Math.pow(2, reconnectionsUsed - 1), RETRY_MAX_DELAY_MS);
|
|
534
551
|
console.log(`
|
|
535
|
-
Connection lost, reconnecting to Bulletin (${reconnectionsUsed}/${MAX_RECONNECTIONS})...`);
|
|
552
|
+
Connection lost, reconnecting to Bulletin in ${(delay / 1e3).toFixed(0)}s (${reconnectionsUsed}/${MAX_RECONNECTIONS})...`);
|
|
536
553
|
captureWarning("WebSocket connection lost, reconnecting", { reconnection: reconnectionsUsed, maxReconnections: MAX_RECONNECTIONS });
|
|
537
554
|
try {
|
|
538
555
|
client.destroy();
|
|
539
556
|
} catch {
|
|
540
557
|
}
|
|
558
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
541
559
|
const fresh = await reconnect();
|
|
542
560
|
client = fresh.client;
|
|
543
561
|
unsafeApi = fresh.unsafeApi;
|
|
@@ -589,10 +607,19 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
|
|
|
589
607
|
captureWarning("Chunk upload failed, retrying", { chunkIndex: fail.index + 1, maxRetries: MAX_CHUNK_RETRIES, error: fail.error?.message?.slice(0, 200) });
|
|
590
608
|
let retried = false;
|
|
591
609
|
for (let attempt = 1; attempt <= MAX_CHUNK_RETRIES; attempt++) {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
610
|
+
const retryDelay = Math.min(RETRY_BASE_DELAY_MS * Math.pow(2, attempt - 1), RETRY_MAX_DELAY_MS);
|
|
611
|
+
console.log(` Retrying chunk ${fail.index + 1} (attempt ${attempt}/${MAX_CHUNK_RETRIES}) in ${(retryDelay / 1e3).toFixed(0)}s...`);
|
|
612
|
+
await new Promise((r) => setTimeout(r, retryDelay));
|
|
613
|
+
if (isConnectionError(fail.error) && reconnect && reconnectionsUsed < MAX_RECONNECTIONS) {
|
|
614
|
+
try {
|
|
615
|
+
await doReconnect();
|
|
616
|
+
} catch (reconnectErr) {
|
|
617
|
+
console.log(` Reconnect failed: ${reconnectErr.message?.slice(0, 80)}`);
|
|
618
|
+
break;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
595
621
|
try {
|
|
622
|
+
const freshNonce = await fetchNonce(BULLETIN_RPC, ss58);
|
|
596
623
|
const result2 = await storeChunk(unsafeApi, signer, fail.chunkData, freshNonce, ss58);
|
|
597
624
|
stored[fail.index] = result2;
|
|
598
625
|
retried = true;
|
|
@@ -600,6 +627,12 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
|
|
|
600
627
|
} catch (e) {
|
|
601
628
|
captureWarning("Chunk retry failed", { chunkIndex: fail.index + 1, attempt, maxRetries: MAX_CHUNK_RETRIES, error: e.message?.slice(0, 200) });
|
|
602
629
|
console.log(` Retry ${attempt} failed: ${e.message?.slice(0, 80)}`);
|
|
630
|
+
if (isConnectionError(e) && reconnect && reconnectionsUsed < MAX_RECONNECTIONS) {
|
|
631
|
+
try {
|
|
632
|
+
await doReconnect();
|
|
633
|
+
} catch {
|
|
634
|
+
}
|
|
635
|
+
}
|
|
603
636
|
}
|
|
604
637
|
}
|
|
605
638
|
if (!retried) {
|
package/dist/deploy.js
CHANGED
|
@@ -19,10 +19,10 @@ import {
|
|
|
19
19
|
storeChunkedContent,
|
|
20
20
|
storeDirectory,
|
|
21
21
|
storeFile
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-YNBJATGK.js";
|
|
23
|
+
import "./chunk-MXMJJURQ.js";
|
|
24
24
|
import "./chunk-AIHW2WLO.js";
|
|
25
|
-
import "./chunk-
|
|
25
|
+
import "./chunk-3J3S6JLX.js";
|
|
26
26
|
import "./chunk-QGM4M3NI.js";
|
|
27
27
|
export {
|
|
28
28
|
DEFAULT_BULLETIN_RPC,
|
package/dist/dotns.js
CHANGED
|
@@ -19,8 +19,8 @@ import {
|
|
|
19
19
|
sanitizeDomainLabel,
|
|
20
20
|
stripTrailingDigits,
|
|
21
21
|
validateDomainLabel
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-MXMJJURQ.js";
|
|
23
|
+
import "./chunk-3J3S6JLX.js";
|
|
24
24
|
import "./chunk-QGM4M3NI.js";
|
|
25
25
|
export {
|
|
26
26
|
CONNECTION_TIMEOUT_MS,
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deploy
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YNBJATGK.js";
|
|
4
4
|
import {
|
|
5
5
|
DotNS
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MXMJJURQ.js";
|
|
7
7
|
import {
|
|
8
8
|
bootstrapPool,
|
|
9
9
|
derivePoolAccounts,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
fetchPoolAuthorizations,
|
|
12
12
|
selectAccount
|
|
13
13
|
} from "./chunk-AIHW2WLO.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-3J3S6JLX.js";
|
|
15
15
|
import "./chunk-QGM4M3NI.js";
|
|
16
16
|
export {
|
|
17
17
|
DotNS,
|
package/dist/telemetry.js
CHANGED