bulletin-deploy 0.7.17 → 0.7.19-rc.1

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/README.md CHANGED
@@ -79,6 +79,7 @@ bulletin-deploy ./dist my-app00.dot --rpc wss://custom-bulletin.example.com
79
79
  | Env id | Network | Bulletin available? |
80
80
  |---|---|---|
81
81
  | `paseo-next` (default) | testnet | yes |
82
+ | `paseo-next-v2` | testnet | yes |
82
83
  | `paseo-review` | testnet | yes |
83
84
  | `preview` | testnet | yes |
84
85
  | `polkadot` | mainnet | not yet |
@@ -103,6 +104,8 @@ The runtime uses a 24-hour cache at `${XDG_CACHE_HOME:-~/.cache}/bulletin-deploy
103
104
  | `--js-merkle` | Use pure-JS merkleization instead of the Kubo binary. |
104
105
  | `--tag "..."` | Attach a free-form telemetry label. Also readable from `DEPLOY_TAG`. |
105
106
  | `--gh-pages-mirror` | After a successful deploy, push the generated CAR to the current repo's `gh-pages` branch as an HTTP mirror. |
107
+ | `--skip-automated-deployment-to-paseo-next-v2` | Suppress the automatic mirror deploy to `paseo-next-v2` that runs after a successful `paseo-next` deploy. |
108
+ | `--fail-on-mirror-error` | Exit non-zero if the automated mirror deploy to `paseo-next-v2` fails (default: warn only). |
106
109
  | `--input-car <path>` | Deploy from a pre-built CAR file instead of a build directory. Skips merkleization; reads the root CID from the CAR header. Usage: `bulletin-deploy --input-car site.car my-app.dot` |
107
110
  | `--version` | Print the CLI version. |
108
111
  | `--help` | Show help. |
@@ -175,6 +178,25 @@ to the current repo's `gh-pages` branch and prints the Pages URL.
175
178
 
176
179
  Use it when you want to validate or consume the mirror feature. The source of truth remains Bulletin plus DotNS.
177
180
 
181
+ ## Automatic Mirror to paseo-next-v2
182
+
183
+ When you deploy to `paseo-next` (the default), `bulletin-deploy` automatically runs a second deploy to `paseo-next-v2` using the same build artefact. This keeps both environments in sync without any extra steps during the period when `paseo-next-v2` is being validated alongside the existing testnet.
184
+
185
+ ```bash
186
+ # Standard deploy — mirrors to paseo-next-v2 automatically
187
+ bulletin-deploy ./dist my-app00.dot
188
+
189
+ # Opt out of the mirror
190
+ bulletin-deploy ./dist my-app00.dot --skip-automated-deployment-to-paseo-next-v2
191
+
192
+ # Treat a mirror failure as a hard error instead of a warning
193
+ bulletin-deploy ./dist my-app00.dot --fail-on-mirror-error
194
+ ```
195
+
196
+ The mirror runs after the primary deploy succeeds. By default, a mirror failure prints a warning and exits zero so it does not block your pipeline. Pass `--fail-on-mirror-error` if you want the process to exit non-zero on mirror failure.
197
+
198
+ This behaviour is temporary and will be removed once `paseo-next-v2` fully replaces `paseo-next`.
199
+
178
200
  ## Programmatic API
179
201
 
180
202
  ```js
@@ -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
+ }
@@ -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
- const rpc = flags.rpc ?? process.env.BULLETIN_RPC ?? DEFAULT_BULLETIN_RPC;
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
- await bootstrapPool(rpc, poolSize, mnemonic);
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);
@@ -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, DEFAULT_ENVIRONMENTS_URL } from "../dist/environments.js";
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
- // --refresh-environments alone (no positional args): refresh and exit. With
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;
@@ -9,10 +9,10 @@ import {
9
9
  offerBugReport,
10
10
  scrubSecrets,
11
11
  setDeployContext
12
- } from "./chunk-AJ3IT7P5.js";
13
- import "./chunk-WSHGL6SP.js";
14
- import "./chunk-ME32MC6X.js";
15
- import "./chunk-BS7SZNE3.js";
12
+ } from "./chunk-D4ZXOJLO.js";
13
+ import "./chunk-376G4CVG.js";
14
+ import "./chunk-NRWRL75I.js";
15
+ import "./chunk-KSWXBDHQ.js";
16
16
  import "./chunk-QGM4M3NI.js";
17
17
  export {
18
18
  buildCliFlagsSummary,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-ME32MC6X.js";
3
+ } from "./chunk-NRWRL75I.js";
4
4
 
5
5
  // src/version-check.ts
6
6
  import { execSync, execFileSync } from "child_process";
@@ -3,8 +3,7 @@ import { sr25519CreateDerive } from "@polkadot-labs/hdkd";
3
3
  import { DEV_PHRASE, entropyToMiniSecret, mnemonicToEntropy } from "@polkadot-labs/hdkd-helpers";
4
4
  import { createClient, Enum } from "polkadot-api";
5
5
  import { getPolkadotSigner } from "polkadot-api/signer";
6
- import { getWsProvider } from "polkadot-api/ws-provider";
7
- import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat";
6
+ import { getWsProvider } from "polkadot-api/ws";
8
7
  import { Keyring } from "@polkadot/keyring";
9
8
  import { cryptoWaitReady } from "@polkadot/util-crypto";
10
9
  var PAS_DECIMALS_DIVISOR = 1e10;
@@ -134,7 +133,13 @@ function aliceKeyring() {
134
133
  const signer = getPolkadotSigner(alice.publicKey, "Sr25519", (data) => alice.sign(data));
135
134
  return { alice, signer };
136
135
  }
137
- async function ensureAuthorized(api, address, label) {
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) {
138
143
  const [auth, currentBlock] = await Promise.all([
139
144
  api.query.TransactionStorage.Authorizations.getValue(Enum("Account", address)),
140
145
  api.query.System.Number.getValue()
@@ -142,18 +147,31 @@ async function ensureAuthorized(api, address, label) {
142
147
  if (isAuthorizationActive(auth, currentBlock)) return;
143
148
  console.log(` Auto-authorizing ${label ?? "account"} (${address.slice(0, 8)}...)...`);
144
149
  const { signer } = aliceKeyring();
145
- const newExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
146
- await submitAliceTxWithRetry(
147
- () => api.tx.TransactionStorage.authorize_account({
148
- who: address,
149
- expiration: newExpiration
150
- }),
151
- signer,
152
- `authorize_account(${label ?? "account"})`
153
- );
154
- console.log(` Authorized: expires at block ${newExpiration} (current: ${currentBlock})`);
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
+ }
155
173
  }
156
- async function topUpBy(api, address, needs, label) {
174
+ async function topUpBy(api, address, needs, label, bulletinAuthorizeV2) {
157
175
  const [currentAuth, currentBlock] = await Promise.all([
158
176
  api.query.TransactionStorage.Authorizations.getValue(Enum("Account", address)),
159
177
  api.query.System.Number.getValue()
@@ -166,28 +184,42 @@ async function topUpBy(api, address, needs, label) {
166
184
  console.log(` Pre-auth skipped for ${label ?? "account"} (${address.slice(0, 8)}...): authorized until block ${expiration}, ${txsRemaining} txs / ${fmtMB(bytesRemaining)}MB remaining.`);
167
185
  return;
168
186
  }
169
- const newExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
170
187
  const { signer } = aliceKeyring();
171
- console.log(` Pre-authorizing ${label ?? "account"} (${address.slice(0, 8)}...): extending authorization to block ${newExpiration}...`);
172
- await submitAliceTxWithRetry(
173
- () => api.tx.TransactionStorage.authorize_account({
174
- who: address,
175
- expiration: newExpiration
176
- }),
177
- signer,
178
- `topUpBy(${label ?? "account"})`
179
- );
180
- console.log(` Pre-authorized: expires at block ${newExpiration}`);
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
+ }
181
213
  }
182
- async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic) {
214
+ async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic, opts = {}) {
183
215
  console.log(`Bootstrapping ${poolSize} pool accounts on ${bulletinRpc}...
184
216
  `);
185
217
  await cryptoWaitReady();
186
218
  const accounts = derivePoolAccounts(poolSize, mnemonic);
187
- const client = createClient(withPolkadotSdkCompat(getWsProvider(
219
+ const client = createClient(getWsProvider(
188
220
  bulletinRpc,
189
221
  { heartbeatTimeout: WS_HEARTBEAT_TIMEOUT_MS }
190
- )));
222
+ ));
191
223
  const api = client.getUnsafeApi();
192
224
  const keyring = new Keyring({ type: "sr25519" });
193
225
  const alice = keyring.addFromUri("//Alice");
@@ -197,19 +229,39 @@ async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic) {
197
229
  console.log(`Alice balance: ${formatPasBalance(aliceBalance)} PAS
198
230
  `);
199
231
  const currentBlock = await api.query.System.Number.getValue();
200
- const authExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
201
- console.log(`Authorizing accounts until block ${authExpiration} (current: ${currentBlock})
232
+ if (opts.bulletinAuthorizeV2) {
233
+ console.log(`Authorizing accounts with V2 (${TOPUP_TRANSACTIONS} txs / ${Number(TOPUP_BYTES) / 1e6}MB)
202
234
  `);
235
+ } else {
236
+ const authExpiration = currentBlock + AUTHORIZATION_EXTENSION_BLOCKS;
237
+ console.log(`Authorizing accounts until block ${authExpiration} (current: ${currentBlock})
238
+ `);
239
+ }
203
240
  for (const account of accounts) {
204
241
  console.log(`Account ${account.index}: ${account.address}`);
205
242
  try {
206
- const tx = api.tx.TransactionStorage.authorize_account({
207
- who: account.address,
208
- expiration: authExpiration
209
- });
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
+ }
210
257
  const result = await tx.signAndSubmit(aliceSigner);
211
258
  if (!result.ok) throw new Error("dispatch failed");
212
- console.log(` Authorized: expires at block ${authExpiration}`);
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
+ }
213
265
  } catch (e) {
214
266
  console.log(` Authorization failed: ${e.message?.slice(0, 80)}`);
215
267
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  captureWarning
3
- } from "./chunk-ME32MC6X.js";
3
+ } from "./chunk-NRWRL75I.js";
4
4
 
5
5
  // src/chunk-probe.ts
6
6
  import { Twox128, Blake2128Concat, decAnyMetadata, unifyMetadata } from "@polkadot-api/substrate-bindings";
@@ -2,11 +2,11 @@ import {
2
2
  classifyErrorArea,
3
3
  isInteractive,
4
4
  promptYesNo
5
- } from "./chunk-WSHGL6SP.js";
5
+ } from "./chunk-376G4CVG.js";
6
6
  import {
7
7
  VERSION,
8
8
  getCurrentSentryTraceId
9
- } from "./chunk-ME32MC6X.js";
9
+ } from "./chunk-NRWRL75I.js";
10
10
 
11
11
  // src/bug-report.ts
12
12
  import { execSync, execFileSync } from "child_process";