bulletin-deploy 0.7.18-rc.1 → 0.7.19
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/assets/environments.json +23 -5
- package/bin/bulletin-bootstrap +38 -2
- package/bin/bulletin-deploy +8 -26
- package/dist/bug-report.js +4 -4
- package/dist/{chunk-IU6LUQFY.js → chunk-3BOARQQO.js} +1 -2
- package/dist/{chunk-V42LNJK5.js → chunk-4TS6R26J.js} +84 -31
- package/dist/{chunk-ARFDIRRZ.js → chunk-EFLBLRT5.js} +1 -1
- package/dist/{chunk-BVCNV2VK.js → chunk-I5ZGHKNT.js} +2 -2
- package/dist/{chunk-X7G2XUB6.js → chunk-KQ352MBU.js} +1 -1
- package/dist/{chunk-X3F7WHSF.js → chunk-O2HIPNUT.js} +15 -102
- package/dist/{chunk-L6N6LA3N.js → chunk-PBUI63YV.js} +92 -20
- package/dist/{chunk-5BHSSRH7.js → chunk-VQBSWH77.js} +1 -1
- package/dist/{chunk-765Q65E3.js → chunk-WX7MOC3Z.js} +98 -55
- package/dist/chunk-probe.js +3 -3
- package/dist/deploy.d.ts +11 -1
- package/dist/deploy.js +9 -9
- package/dist/dotns.d.ts +11 -0
- package/dist/dotns.js +4 -4
- package/dist/environments.d.ts +12 -12
- package/dist/environments.js +1 -11
- package/dist/index.js +9 -9
- package/dist/memory-report.js +2 -2
- package/dist/merkle.d.ts +2 -1
- package/dist/merkle.js +13 -11
- package/dist/pool.d.ts +7 -4
- package/dist/pool.js +1 -1
- package/dist/run-state.js +1 -1
- package/dist/telemetry.js +2 -2
- package/dist/version-check.js +3 -3
- package/docs/e2e-bootstrap.md +88 -3
- package/package.json +1 -2
package/assets/environments.json
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
"network": "testnet",
|
|
7
7
|
"description": "Product Preview net, used by Product Teams",
|
|
8
8
|
"backend": "https://polkadot-app-stg.parity.io/",
|
|
9
|
-
"ipfs": "https://previewnet.substrate.dev/ipfs/"
|
|
9
|
+
"ipfs": "https://previewnet.substrate.dev/ipfs/",
|
|
10
|
+
"autoAccountMapping": true,
|
|
11
|
+
"bulletinAuthorizeV2": true
|
|
10
12
|
},
|
|
11
13
|
{
|
|
12
14
|
"id": "paseo-next",
|
|
@@ -34,19 +36,35 @@
|
|
|
34
36
|
"description": "Next iteration of the Paseo Next testnet",
|
|
35
37
|
"backend": "https://identity-backend-next.parity-testnet.parity.io",
|
|
36
38
|
"ipfs": "https://paseo-bulletin-next-ipfs.polkadot.io",
|
|
37
|
-
"docsUrl": "https://sre.teleport.parity.io/environments/paseo-next/"
|
|
39
|
+
"docsUrl": "https://sre.teleport.parity.io/environments/paseo-next/",
|
|
40
|
+
"autoAccountMapping": true,
|
|
41
|
+
"bulletinAuthorizeV2": true,
|
|
42
|
+
"nativeToEthRatio": 100000000,
|
|
43
|
+
"contracts": {
|
|
44
|
+
"DOTNS_REGISTRAR": "0xE67B22B285912FFfaE23BdfAc8C80c779d99B3e0",
|
|
45
|
+
"DOTNS_REGISTRAR_CONTROLLER": "0x8403e49Ec12F4EA5788f7bc0C0c2F649205774cC",
|
|
46
|
+
"DOTNS_REGISTRY": "0xDeFE1AAE21eC2455bd04b213a51C16d4b426c7ef",
|
|
47
|
+
"DOTNS_RESOLVER": "0xB436A271Beff1DBa6abDf2dbCc7E6d723d505EE6",
|
|
48
|
+
"DOTNS_CONTENT_RESOLVER": "0xBcFa907Ff85dFc62a21b41d48F23D7A73aC42914",
|
|
49
|
+
"DOTNS_REVERSE_RESOLVER": "0x4Ca32Dd0233D8c1B1709e20D9E4edBF2a77D21c3",
|
|
50
|
+
"POP_RULES": "0xd3F059FA65dA566B294b5d755a06054d4bE7ce7C",
|
|
51
|
+
"STORE_FACTORY": "0x4f1885fB6e0b154dCf9C2A8661e578B94aD50775"
|
|
52
|
+
},
|
|
53
|
+
"skipDotnsCli": true
|
|
38
54
|
},
|
|
39
55
|
{
|
|
40
56
|
"id": "polkadot",
|
|
41
57
|
"name": "Polkadot",
|
|
42
58
|
"network": "mainnet",
|
|
43
|
-
"description": "Polkadot mainnet"
|
|
59
|
+
"description": "Polkadot mainnet",
|
|
60
|
+
"autoAccountMapping": true
|
|
44
61
|
},
|
|
45
62
|
{
|
|
46
63
|
"id": "kusama",
|
|
47
64
|
"name": "Kusama",
|
|
48
65
|
"network": "mainnet",
|
|
49
|
-
"description": "Kusama canary network"
|
|
66
|
+
"description": "Kusama canary network",
|
|
67
|
+
"autoAccountMapping": true
|
|
50
68
|
}
|
|
51
69
|
],
|
|
52
70
|
"chains": [
|
|
@@ -260,4 +278,4 @@
|
|
|
260
278
|
}
|
|
261
279
|
],
|
|
262
280
|
"source": "https://docs.google.com/document/d/1xQoAmWDpbjhuXKT79DTNKFzv7ZkFr5npjo0BvrxXDIw"
|
|
263
|
-
}
|
|
281
|
+
}
|
package/bin/bulletin-bootstrap
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import * as fs from "node:fs/promises";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
3
6
|
import { DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE } from "../dist/deploy.js";
|
|
4
7
|
import { bootstrapPool } from "../dist/pool.js";
|
|
5
8
|
import { VERSION } from "../dist/telemetry.js";
|
|
@@ -11,6 +14,7 @@ for (let i = 0; i < args.length; i++) {
|
|
|
11
14
|
if (args[i] === "--pool-size") { flags.poolSize = parseInt(args[++i], 10); }
|
|
12
15
|
else if (args[i] === "--mnemonic") { flags.mnemonic = args[++i]; }
|
|
13
16
|
else if (args[i] === "--rpc") { flags.rpc = args[++i]; }
|
|
17
|
+
else if (args[i] === "--env") { flags.env = args[++i]; }
|
|
14
18
|
else if (args[i] === "--version" || args[i] === "-V") { flags.version = true; }
|
|
15
19
|
else if (args[i] === "--help" || args[i] === "-h") { flags.help = true; }
|
|
16
20
|
else {
|
|
@@ -33,6 +37,7 @@ Usage:
|
|
|
33
37
|
Options:
|
|
34
38
|
--mnemonic "..." Pool root mnemonic (or set BULLETIN_POOL_MNEMONIC / MNEMONIC env var)
|
|
35
39
|
--rpc wss://... Bulletin RPC (or set BULLETIN_RPC env var)
|
|
40
|
+
--env <id> Load environment by id from environments.json (sets default RPC and V2 flag)
|
|
36
41
|
--pool-size N Number of pool accounts to initialize (default: 10)
|
|
37
42
|
--version Show version
|
|
38
43
|
--help Show this help
|
|
@@ -41,8 +46,39 @@ Initialize pool accounts for Bulletin storage authorization.`);
|
|
|
41
46
|
process.exit(0);
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
let rpc = flags.rpc ?? process.env.BULLETIN_RPC ?? DEFAULT_BULLETIN_RPC;
|
|
45
50
|
const poolSize = flags.poolSize ?? parseInt(process.env.BULLETIN_POOL_SIZE ?? String(DEFAULT_POOL_SIZE), 10);
|
|
46
51
|
const mnemonic = flags.mnemonic ?? process.env.BULLETIN_POOL_MNEMONIC ?? process.env.MNEMONIC;
|
|
47
52
|
|
|
48
|
-
|
|
53
|
+
const bootstrapOpts = {};
|
|
54
|
+
|
|
55
|
+
if (flags.env) {
|
|
56
|
+
const envJsonPath = fileURLToPath(new URL("../assets/environments.json", import.meta.url));
|
|
57
|
+
let envDoc;
|
|
58
|
+
try {
|
|
59
|
+
const raw = await fs.readFile(envJsonPath, "utf8");
|
|
60
|
+
envDoc = JSON.parse(raw);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.error(`Error: could not load environments.json: ${e.message}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const envEntry = envDoc.environments.find(e => e.id === flags.env);
|
|
67
|
+
if (!envEntry) {
|
|
68
|
+
const valid = envDoc.environments.map(e => e.id).join(", ");
|
|
69
|
+
console.error(`Error: unknown environment '${flags.env}'. Valid: ${valid}.`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!flags.rpc) {
|
|
74
|
+
const bulletinChain = envDoc.chains.find(c => c.id === "bulletin");
|
|
75
|
+
const ep = bulletinChain?.endpoints?.[flags.env];
|
|
76
|
+
if (ep?.wss) {
|
|
77
|
+
rpc = Array.isArray(ep.wss) ? ep.wss[0] : ep.wss;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
bootstrapOpts.bulletinAuthorizeV2 = envEntry.bulletinAuthorizeV2 ?? false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
await bootstrapPool(rpc, poolSize, mnemonic, bootstrapOpts);
|
package/bin/bulletin-deploy
CHANGED
|
@@ -5,7 +5,7 @@ import { VERSION, setDeployAttribute, captureWarning, closeTelemetry, setRunStat
|
|
|
5
5
|
import { handleFailedDeploy, preReleaseWarning, checkNodeVersion } from "../dist/version-check.js";
|
|
6
6
|
import { setDeployContext, installLogCapture, buildCliFlagsSummary } from "../dist/bug-report.js";
|
|
7
7
|
import { loadRunState, writeRunState, shouldSkipStaleWarning, shouldShowOomHint, probablyOomRssMb } from "../dist/run-state.js";
|
|
8
|
-
import { loadEnvironments, listEnvironments, formatEnvironmentTable, DEFAULT_ENV_ID
|
|
8
|
+
import { loadEnvironments, listEnvironments, formatEnvironmentTable, DEFAULT_ENV_ID } from "../dist/environments.js";
|
|
9
9
|
import { shouldMirrorToPaseoNextV2 } from "../dist/mirror.js";
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
|
|
@@ -33,7 +33,6 @@ for (let i = 0; i < args.length; i++) {
|
|
|
33
33
|
else if (args[i] === "--rpc") { flags.rpc = args[++i]; }
|
|
34
34
|
else if (args[i] === "--env") { flags.env = args[++i]; }
|
|
35
35
|
else if (args[i] === "--list-environments") { flags.listEnvironments = true; }
|
|
36
|
-
else if (args[i] === "--refresh-environments") { flags.refreshEnvironments = true; }
|
|
37
36
|
else if (args[i] === "--password") { flags.password = args[++i]; }
|
|
38
37
|
else if (args[i] === "--js-merkle") { flags.jsMerkle = true; }
|
|
39
38
|
else if (args[i] === "--input-car") { flags.inputCar = args[++i]; }
|
|
@@ -44,6 +43,7 @@ for (let i = 0; i < args.length; i++) {
|
|
|
44
43
|
else if (args[i] === "--allow-large-deploy") { flags.allowLargeDeploy = true; }
|
|
45
44
|
else if (args[i] === "--reproducible") { flags.reproducibleSource = "commit"; }
|
|
46
45
|
else if (args[i].startsWith("--reproducible=")) { flags.reproducibleSource = args[i].slice("--reproducible=".length); }
|
|
46
|
+
else if (args[i] === "--skip-dotns-cli") { flags.skipDotnsCli = true; }
|
|
47
47
|
else if (args[i] === "--skip-automated-deployment-to-paseo-next-v2") { flags.skipMirrorToPaseoNextV2 = true; }
|
|
48
48
|
else if (args[i] === "--fail-on-mirror-error") { flags.failOnMirrorError = true; }
|
|
49
49
|
else if (args[i] === "--version" || args[i] === "-V") { flags.version = true; }
|
|
@@ -74,18 +74,7 @@ if (flags.listEnvironments) {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
// positional args, refresh first, then deploy.
|
|
79
|
-
if (flags.refreshEnvironments && positional.length === 0) {
|
|
80
|
-
try {
|
|
81
|
-
const { doc } = await loadEnvironments({ forceRefresh: true });
|
|
82
|
-
console.log(`Refreshed ${doc.environments.length} environments from ${process.env.BULLETIN_ENVIRONMENTS_URL ?? DEFAULT_ENVIRONMENTS_URL}`);
|
|
83
|
-
process.exit(0);
|
|
84
|
-
} catch (e) {
|
|
85
|
-
console.error(`Error: failed to refresh environments: ${e?.message ?? e}`);
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
77
|
+
|
|
89
78
|
|
|
90
79
|
if (flags.help || positional.length === 0) {
|
|
91
80
|
console.log(`bulletin-deploy v${VERSION}
|
|
@@ -98,8 +87,6 @@ Options:
|
|
|
98
87
|
Drives both the bulletin RPC and the asset-hub RPC used
|
|
99
88
|
by DotNS. See --list-environments for valid ids.
|
|
100
89
|
--list-environments Print the environments table and exit.
|
|
101
|
-
--refresh-environments Bust the cache and re-fetch environments.json. Composes
|
|
102
|
-
with --env (refresh-then-deploy) or runs solo.
|
|
103
90
|
--mnemonic "..." DotNS owner mnemonic (or set MNEMONIC env var)
|
|
104
91
|
--derivation-path "..." Optional Substrate-style path applied to --mnemonic (e.g. //deploy/3)
|
|
105
92
|
--rpc wss://... Override the bulletin RPC for the chosen --env (or set BULLETIN_RPC).
|
|
@@ -114,6 +101,10 @@ Options:
|
|
|
114
101
|
--description "..." Optional. Sets the "description" text record (≤100 chars recommended).
|
|
115
102
|
--gh-pages-mirror After deploy, push the CAR to the current repo's gh-pages branch
|
|
116
103
|
at bulletin/<domain>.dot.car (opt-in; also set GH_PAGES_MIRROR=1)
|
|
104
|
+
--skip-dotns-cli Use direct contract calls for DotNS operations instead of
|
|
105
|
+
dotns-cli. Auto-set for envs with custom contract addresses
|
|
106
|
+
(e.g. paseo-next-v2). Use to override when dotns-cli lacks
|
|
107
|
+
support for the target chain.
|
|
117
108
|
--skip-automated-deployment-to-paseo-next-v2
|
|
118
109
|
Suppress the automatic mirror deploy to paseo-next-v2.
|
|
119
110
|
--fail-on-mirror-error
|
|
@@ -244,16 +235,6 @@ try {
|
|
|
244
235
|
if (!fs.existsSync(buildDir)) { console.error(`Error: ${buildDir} does not exist`); process.exit(1); }
|
|
245
236
|
}
|
|
246
237
|
|
|
247
|
-
// --refresh-environments composed with a deploy: bust the cache before
|
|
248
|
-
// deploy() loads it, so deploy() picks up fresh data on the next loadEnvironments().
|
|
249
|
-
if (flags.refreshEnvironments) {
|
|
250
|
-
try {
|
|
251
|
-
await loadEnvironments({ forceRefresh: true });
|
|
252
|
-
} catch (e) {
|
|
253
|
-
console.error(`Error: failed to refresh environments: ${e?.message ?? e}`);
|
|
254
|
-
process.exit(1);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
238
|
const effectiveRpc = flags.rpc ?? process.env.BULLETIN_RPC ?? DEFAULT_BULLETIN_RPC;
|
|
258
239
|
const deployTag = flags.tag ?? process.env.DEPLOY_TAG;
|
|
259
240
|
const ci = process.env.GITHUB_ACTIONS === "true" ? {
|
|
@@ -290,6 +271,7 @@ try {
|
|
|
290
271
|
description: flags.description,
|
|
291
272
|
allowLargeDeploy: flags.allowLargeDeploy,
|
|
292
273
|
reproducibleSource: flags.reproducibleSource,
|
|
274
|
+
skipDotnsCli: flags.skipDotnsCli,
|
|
293
275
|
});
|
|
294
276
|
|
|
295
277
|
const output = process.env.GITHUB_OUTPUT;
|
package/dist/bug-report.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
offerBugReport,
|
|
10
10
|
scrubSecrets,
|
|
11
11
|
setDeployContext
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-I5ZGHKNT.js";
|
|
13
|
+
import "./chunk-VQBSWH77.js";
|
|
14
|
+
import "./chunk-KQ352MBU.js";
|
|
15
|
+
import "./chunk-3BOARQQO.js";
|
|
16
16
|
import "./chunk-QGM4M3NI.js";
|
|
17
17
|
export {
|
|
18
18
|
buildCliFlagsSummary,
|
|
@@ -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.
|
|
9
|
+
version: "0.7.19",
|
|
10
10
|
private: false,
|
|
11
11
|
repository: {
|
|
12
12
|
type: "git",
|
|
@@ -36,7 +36,6 @@ var package_default = {
|
|
|
36
36
|
"assets"
|
|
37
37
|
],
|
|
38
38
|
scripts: {
|
|
39
|
-
prebuild: "node scripts/refresh-environments.mjs",
|
|
40
39
|
build: "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts src/memory-report.ts src/merkle.ts src/gh-pages-mirror.ts src/version-check.ts src/bug-report.ts src/run-state.ts src/environments.ts src/errors.ts src/manifest.ts src/chunk-probe.ts src/manifest-embed.ts src/manifest-fetch.ts src/manifest-roundtrip.ts src/incremental-stats.ts src/chunker.ts src/mirror.ts --format esm --dts --clean --target node22",
|
|
41
40
|
"refresh-environments": "node scripts/refresh-environments.mjs",
|
|
42
41
|
prepare: "npm run build",
|
|
@@ -133,7 +133,13 @@ function aliceKeyring() {
|
|
|
133
133
|
const signer = getPolkadotSigner(alice.publicKey, "Sr25519", (data) => alice.sign(data));
|
|
134
134
|
return { alice, signer };
|
|
135
135
|
}
|
|
136
|
-
|
|
136
|
+
var U32_MAX = 0xFFFFFFFFn;
|
|
137
|
+
function clampU32(n, name) {
|
|
138
|
+
if (n < 0n) throw new Error(`${name} must be non-negative`);
|
|
139
|
+
if (n > U32_MAX) throw new Error(`${name} (${n}) exceeds u32 max \u2014 split the deploy into smaller batches`);
|
|
140
|
+
return Number(n);
|
|
141
|
+
}
|
|
142
|
+
async function ensureAuthorized(api, address, label, bulletinAuthorizeV2) {
|
|
137
143
|
const [auth, currentBlock] = await Promise.all([
|
|
138
144
|
api.query.TransactionStorage.Authorizations.getValue(Enum("Account", address)),
|
|
139
145
|
api.query.System.Number.getValue()
|
|
@@ -141,18 +147,31 @@ async function ensureAuthorized(api, address, label) {
|
|
|
141
147
|
if (isAuthorizationActive(auth, currentBlock)) return;
|
|
142
148
|
console.log(` Auto-authorizing ${label ?? "account"} (${address.slice(0, 8)}...)...`);
|
|
143
149
|
const { signer } = aliceKeyring();
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
if (bulletinAuthorizeV2) {
|
|
151
|
+
await submitAliceTxWithRetry(
|
|
152
|
+
() => api.tx.TransactionStorage.authorize_account({
|
|
153
|
+
who: address,
|
|
154
|
+
transactions: clampU32(BigInt(TOPUP_TRANSACTIONS), "transactions"),
|
|
155
|
+
bytes: TOPUP_BYTES
|
|
156
|
+
}),
|
|
157
|
+
signer,
|
|
158
|
+
`authorize_account(${label ?? "account"})`
|
|
159
|
+
);
|
|
160
|
+
console.log(` Authorized: ${TOPUP_TRANSACTIONS} txs / ${Number(TOPUP_BYTES) / 1e6}MB`);
|
|
161
|
+
} else {
|
|
162
|
+
const newExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
|
|
163
|
+
await submitAliceTxWithRetry(
|
|
164
|
+
() => api.tx.TransactionStorage.authorize_account({
|
|
165
|
+
who: address,
|
|
166
|
+
expiration: newExpiration
|
|
167
|
+
}),
|
|
168
|
+
signer,
|
|
169
|
+
`authorize_account(${label ?? "account"})`
|
|
170
|
+
);
|
|
171
|
+
console.log(` Authorized: expires at block ${newExpiration} (current: ${currentBlock})`);
|
|
172
|
+
}
|
|
154
173
|
}
|
|
155
|
-
async function topUpBy(api, address, needs, label) {
|
|
174
|
+
async function topUpBy(api, address, needs, label, bulletinAuthorizeV2) {
|
|
156
175
|
const [currentAuth, currentBlock] = await Promise.all([
|
|
157
176
|
api.query.TransactionStorage.Authorizations.getValue(Enum("Account", address)),
|
|
158
177
|
api.query.System.Number.getValue()
|
|
@@ -165,20 +184,34 @@ async function topUpBy(api, address, needs, label) {
|
|
|
165
184
|
console.log(` Pre-auth skipped for ${label ?? "account"} (${address.slice(0, 8)}...): authorized until block ${expiration}, ${txsRemaining} txs / ${fmtMB(bytesRemaining)}MB remaining.`);
|
|
166
185
|
return;
|
|
167
186
|
}
|
|
168
|
-
const newExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
|
|
169
187
|
const { signer } = aliceKeyring();
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
188
|
+
if (bulletinAuthorizeV2) {
|
|
189
|
+
console.log(` Pre-authorizing ${label ?? "account"} (${address.slice(0, 8)}...): granting ${TOPUP_TRANSACTIONS} txs / ${Number(TOPUP_BYTES) / 1e6}MB...`);
|
|
190
|
+
await submitAliceTxWithRetry(
|
|
191
|
+
() => api.tx.TransactionStorage.authorize_account({
|
|
192
|
+
who: address,
|
|
193
|
+
transactions: clampU32(BigInt(TOPUP_TRANSACTIONS), "transactions"),
|
|
194
|
+
bytes: TOPUP_BYTES
|
|
195
|
+
}),
|
|
196
|
+
signer,
|
|
197
|
+
`topUpBy(${label ?? "account"})`
|
|
198
|
+
);
|
|
199
|
+
console.log(` Pre-authorized: ${TOPUP_TRANSACTIONS} txs / ${Number(TOPUP_BYTES) / 1e6}MB`);
|
|
200
|
+
} else {
|
|
201
|
+
const newExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
|
|
202
|
+
console.log(` Pre-authorizing ${label ?? "account"} (${address.slice(0, 8)}...): extending authorization to block ${newExpiration}...`);
|
|
203
|
+
await submitAliceTxWithRetry(
|
|
204
|
+
() => api.tx.TransactionStorage.authorize_account({
|
|
205
|
+
who: address,
|
|
206
|
+
expiration: newExpiration
|
|
207
|
+
}),
|
|
208
|
+
signer,
|
|
209
|
+
`topUpBy(${label ?? "account"})`
|
|
210
|
+
);
|
|
211
|
+
console.log(` Pre-authorized: expires at block ${newExpiration}`);
|
|
212
|
+
}
|
|
180
213
|
}
|
|
181
|
-
async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic) {
|
|
214
|
+
async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic, opts = {}) {
|
|
182
215
|
console.log(`Bootstrapping ${poolSize} pool accounts on ${bulletinRpc}...
|
|
183
216
|
`);
|
|
184
217
|
await cryptoWaitReady();
|
|
@@ -196,19 +229,39 @@ async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic) {
|
|
|
196
229
|
console.log(`Alice balance: ${formatPasBalance(aliceBalance)} PAS
|
|
197
230
|
`);
|
|
198
231
|
const currentBlock = await api.query.System.Number.getValue();
|
|
199
|
-
|
|
200
|
-
|
|
232
|
+
if (opts.bulletinAuthorizeV2) {
|
|
233
|
+
console.log(`Authorizing accounts with V2 (${TOPUP_TRANSACTIONS} txs / ${Number(TOPUP_BYTES) / 1e6}MB)
|
|
201
234
|
`);
|
|
235
|
+
} else {
|
|
236
|
+
const authExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
|
|
237
|
+
console.log(`Authorizing accounts until block ${authExpiration} (current: ${currentBlock})
|
|
238
|
+
`);
|
|
239
|
+
}
|
|
202
240
|
for (const account of accounts) {
|
|
203
241
|
console.log(`Account ${account.index}: ${account.address}`);
|
|
204
242
|
try {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
243
|
+
let tx;
|
|
244
|
+
if (opts.bulletinAuthorizeV2) {
|
|
245
|
+
tx = api.tx.TransactionStorage.authorize_account({
|
|
246
|
+
who: account.address,
|
|
247
|
+
transactions: clampU32(BigInt(TOPUP_TRANSACTIONS), "transactions"),
|
|
248
|
+
bytes: TOPUP_BYTES
|
|
249
|
+
});
|
|
250
|
+
} else {
|
|
251
|
+
const authExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
|
|
252
|
+
tx = api.tx.TransactionStorage.authorize_account({
|
|
253
|
+
who: account.address,
|
|
254
|
+
expiration: authExpiration
|
|
255
|
+
});
|
|
256
|
+
}
|
|
209
257
|
const result = await tx.signAndSubmit(aliceSigner);
|
|
210
258
|
if (!result.ok) throw new Error("dispatch failed");
|
|
211
|
-
|
|
259
|
+
if (opts.bulletinAuthorizeV2) {
|
|
260
|
+
console.log(` Authorized: ${TOPUP_TRANSACTIONS} txs / ${Number(TOPUP_BYTES) / 1e6}MB`);
|
|
261
|
+
} else {
|
|
262
|
+
const authExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
|
|
263
|
+
console.log(` Authorized: expires at block ${authExpiration}`);
|
|
264
|
+
}
|
|
212
265
|
} catch (e) {
|
|
213
266
|
console.log(` Authorization failed: ${e.message?.slice(0, 80)}`);
|
|
214
267
|
}
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
classifyErrorArea,
|
|
3
3
|
isInteractive,
|
|
4
4
|
promptYesNo
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VQBSWH77.js";
|
|
6
6
|
import {
|
|
7
7
|
VERSION,
|
|
8
8
|
getCurrentSentryTraceId
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KQ352MBU.js";
|
|
10
10
|
|
|
11
11
|
// src/bug-report.ts
|
|
12
12
|
import { execSync, execFileSync } from "child_process";
|
|
@@ -4,13 +4,8 @@ import {
|
|
|
4
4
|
|
|
5
5
|
// src/environments.ts
|
|
6
6
|
import * as fs from "fs/promises";
|
|
7
|
-
import * as path from "path";
|
|
8
|
-
import * as os from "os";
|
|
9
7
|
import { fileURLToPath } from "url";
|
|
10
|
-
var DEFAULT_ENVIRONMENTS_URL = "https://raw.githubusercontent.com/paritytech/triangle-deploy/main/assets/environments.json";
|
|
11
8
|
var DEFAULT_ENV_ID = "paseo-next";
|
|
12
|
-
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
13
|
-
var FETCH_TIMEOUT_MS = 5e3;
|
|
14
9
|
var HARDCODED_FALLBACK = {
|
|
15
10
|
environments: [
|
|
16
11
|
{
|
|
@@ -47,14 +42,6 @@ var HARDCODED_FALLBACK = {
|
|
|
47
42
|
}
|
|
48
43
|
]
|
|
49
44
|
};
|
|
50
|
-
function defaultCacheDir() {
|
|
51
|
-
const xdg = process.env.XDG_CACHE_HOME;
|
|
52
|
-
const base = xdg && xdg.length > 0 ? xdg : path.join(os.homedir(), ".cache");
|
|
53
|
-
return path.join(base, "bulletin-deploy");
|
|
54
|
-
}
|
|
55
|
-
function defaultCachePath() {
|
|
56
|
-
return path.join(defaultCacheDir(), "environments.json");
|
|
57
|
-
}
|
|
58
45
|
function defaultBundledPath() {
|
|
59
46
|
return fileURLToPath(new URL("../assets/environments.json", import.meta.url));
|
|
60
47
|
}
|
|
@@ -63,51 +50,6 @@ function isValidDoc(value) {
|
|
|
63
50
|
const v = value;
|
|
64
51
|
return Array.isArray(v.environments) && Array.isArray(v.chains);
|
|
65
52
|
}
|
|
66
|
-
async function readCache(cachePath) {
|
|
67
|
-
try {
|
|
68
|
-
const raw = await fs.readFile(cachePath, "utf8");
|
|
69
|
-
const parsed = JSON.parse(raw);
|
|
70
|
-
if (parsed && typeof parsed === "object" && typeof parsed.fetchedAt === "string" && isValidDoc(parsed.doc)) {
|
|
71
|
-
return parsed;
|
|
72
|
-
}
|
|
73
|
-
return null;
|
|
74
|
-
} catch {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
async function writeCache(cachePath, doc, now) {
|
|
79
|
-
try {
|
|
80
|
-
await fs.mkdir(path.dirname(cachePath), { recursive: true });
|
|
81
|
-
const payload = {
|
|
82
|
-
fetchedAt: new Date(now).toISOString(),
|
|
83
|
-
doc
|
|
84
|
-
};
|
|
85
|
-
await fs.writeFile(cachePath, JSON.stringify(payload, null, 2), "utf8");
|
|
86
|
-
} catch {
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
function isFresh(cache, now) {
|
|
90
|
-
const fetched = Date.parse(cache.fetchedAt);
|
|
91
|
-
if (Number.isNaN(fetched)) return false;
|
|
92
|
-
return now - fetched < CACHE_TTL_MS;
|
|
93
|
-
}
|
|
94
|
-
async function fetchLive(url, fetchImpl) {
|
|
95
|
-
const ctrl = new AbortController();
|
|
96
|
-
const timer = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);
|
|
97
|
-
try {
|
|
98
|
-
const res = await fetchImpl(url, { signal: ctrl.signal });
|
|
99
|
-
if (!res.ok) {
|
|
100
|
-
throw new Error(`fetch ${url} returned HTTP ${res.status}`);
|
|
101
|
-
}
|
|
102
|
-
const json = await res.json();
|
|
103
|
-
if (!isValidDoc(json)) {
|
|
104
|
-
throw new Error(`fetch ${url} returned malformed environments doc`);
|
|
105
|
-
}
|
|
106
|
-
return json;
|
|
107
|
-
} finally {
|
|
108
|
-
clearTimeout(timer);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
53
|
async function readBundled(bundledPath) {
|
|
112
54
|
try {
|
|
113
55
|
const raw = await fs.readFile(bundledPath, "utf8");
|
|
@@ -118,48 +60,14 @@ async function readBundled(bundledPath) {
|
|
|
118
60
|
}
|
|
119
61
|
}
|
|
120
62
|
async function loadEnvironments(opts = {}) {
|
|
121
|
-
const url = opts.url ?? process.env.BULLETIN_ENVIRONMENTS_URL ?? DEFAULT_ENVIRONMENTS_URL;
|
|
122
|
-
const cachePath = path.join(opts.cacheDir ?? defaultCacheDir(), "environments.json");
|
|
123
63
|
const bundledPath = opts.bundledPath ?? defaultBundledPath();
|
|
124
|
-
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
125
|
-
const nowFn = opts.now ?? Date.now;
|
|
126
64
|
const warn = opts.warn ?? ((msg) => console.error(msg));
|
|
127
65
|
const capture = opts.capture ?? (() => {
|
|
128
66
|
});
|
|
129
|
-
const
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return { doc, source: "live" };
|
|
134
|
-
}
|
|
135
|
-
const cache = await readCache(cachePath);
|
|
136
|
-
if (cache && isFresh(cache, now)) {
|
|
137
|
-
return { doc: cache.doc, source: "cache-fresh" };
|
|
138
|
-
}
|
|
139
|
-
try {
|
|
140
|
-
const doc = await fetchLive(url, fetchImpl);
|
|
141
|
-
await writeCache(cachePath, doc, now);
|
|
142
|
-
return { doc, source: "live" };
|
|
143
|
-
} catch (err) {
|
|
144
|
-
if (cache) {
|
|
145
|
-
warn(
|
|
146
|
-
`bulletin-deploy: live environments.json fetch failed; using cached copy from ${cache.fetchedAt} (${err.message ?? err})`
|
|
147
|
-
);
|
|
148
|
-
return { doc: cache.doc, source: "cache-stale" };
|
|
149
|
-
}
|
|
150
|
-
const bundled = await readBundled(bundledPath);
|
|
151
|
-
if (bundled) {
|
|
152
|
-
warn(
|
|
153
|
-
`bulletin-deploy: live environments.json fetch failed and no cache; using bundled snapshot (${err.message ?? err})`
|
|
154
|
-
);
|
|
155
|
-
return { doc: bundled, source: "bundled" };
|
|
156
|
-
}
|
|
157
|
-
capture(err);
|
|
158
|
-
warn(
|
|
159
|
-
`bulletin-deploy: live and bundled environments.json both unavailable; using hardcoded paseo-next fallback`
|
|
160
|
-
);
|
|
161
|
-
return { doc: HARDCODED_FALLBACK, source: "hardcoded-fallback" };
|
|
162
|
-
}
|
|
67
|
+
const bundled = await readBundled(bundledPath);
|
|
68
|
+
if (bundled) return { doc: bundled, source: "bundled" };
|
|
69
|
+
warn("bulletin-deploy: bundled environments.json unavailable; using hardcoded paseo-next fallback");
|
|
70
|
+
return { doc: HARDCODED_FALLBACK, source: "hardcoded-fallback" };
|
|
163
71
|
}
|
|
164
72
|
function normalizeWss(value) {
|
|
165
73
|
if (value === void 0) return [];
|
|
@@ -218,7 +126,17 @@ function resolveEndpoints(doc, envId) {
|
|
|
218
126
|
`Asset Hub endpoint missing for environment '${envId}'. Check https://github.com/paritytech/triangle-status/blob/main/environments.json.`
|
|
219
127
|
);
|
|
220
128
|
}
|
|
221
|
-
return {
|
|
129
|
+
return {
|
|
130
|
+
bulletin,
|
|
131
|
+
assetHub,
|
|
132
|
+
network: env.network,
|
|
133
|
+
envName: env.name,
|
|
134
|
+
autoAccountMapping: env.autoAccountMapping ?? false,
|
|
135
|
+
bulletinAuthorizeV2: env.bulletinAuthorizeV2 ?? false,
|
|
136
|
+
skipDotnsCli: env.skipDotnsCli ?? false,
|
|
137
|
+
contracts: env.contracts ?? {},
|
|
138
|
+
nativeToEthRatio: BigInt(env.nativeToEthRatio ?? 1e6)
|
|
139
|
+
};
|
|
222
140
|
}
|
|
223
141
|
function listEnvironments(doc) {
|
|
224
142
|
const bulletinChain = doc.chains.find((c) => c.id === "bulletin");
|
|
@@ -252,12 +170,7 @@ function formatEnvironmentTable(rows) {
|
|
|
252
170
|
}
|
|
253
171
|
|
|
254
172
|
export {
|
|
255
|
-
DEFAULT_ENVIRONMENTS_URL,
|
|
256
173
|
DEFAULT_ENV_ID,
|
|
257
|
-
CACHE_TTL_MS,
|
|
258
|
-
FETCH_TIMEOUT_MS,
|
|
259
|
-
defaultCacheDir,
|
|
260
|
-
defaultCachePath,
|
|
261
174
|
defaultBundledPath,
|
|
262
175
|
loadEnvironments,
|
|
263
176
|
resolveEndpoints,
|