@parity/product-deploy 0.10.0-rc.3 → 0.10.0
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/DEPLOYMENT.md +61 -83
- package/bin/bulletin-bootstrap +24 -9
- package/dist/auth/index.js +2 -1
- package/dist/auth/vendor/index.js +2 -1
- package/dist/auth-config.js +4 -3
- package/dist/bug-report.js +4 -4
- package/dist/{chunk-GKG2EQKM.js → chunk-32THWODT.js} +50 -21
- package/dist/{chunk-4PVJ2JBZ.js → chunk-4IUTMHVB.js} +73 -41
- package/dist/{chunk-5OKB3TEB.js → chunk-5FLTDWWP.js} +4 -1
- package/dist/{chunk-UBLIZRYW.js → chunk-7HQL3TPT.js} +1 -1
- package/dist/{chunk-FAB6BWDB.js → chunk-ARPBPQZQ.js} +2 -2
- package/dist/{chunk-7OOKA4BJ.js → chunk-F2SDBU57.js} +5 -2
- package/dist/{chunk-D2WW2CIA.js → chunk-OR7LUTET.js} +2 -2
- package/dist/{chunk-DFRIBV6O.js → chunk-ORIB2S5P.js} +1 -1
- package/dist/{chunk-EJ5QLQU4.js → chunk-QR6HCDY2.js} +5 -4
- package/dist/{chunk-IF6BNIKT.js → chunk-SNDIOANW.js} +1 -1
- package/dist/chunk-TSPERKUS.js +6 -0
- package/dist/{chunk-KY3CRS66.js → chunk-V4RTUMBT.js} +1 -1
- package/dist/{chunk-RI3ZLNPN.js → chunk-WIMRJK32.js} +1 -1
- package/dist/{chunk-ZG56UL3V.js → chunk-ZC43ORKF.js} +1 -1
- package/dist/chunk-probe.js +3 -3
- package/dist/commands/login.js +27 -18
- package/dist/commands/logout.js +6 -5
- package/dist/commands/transfer.js +8 -5
- package/dist/commands/whoami.js +7 -4
- package/dist/deploy-actors.js +6 -5
- package/dist/deploy.d.ts +19 -2
- package/dist/deploy.js +17 -10
- package/dist/dotns.js +4 -4
- package/dist/index.js +13 -12
- package/dist/manifest/byte-budget.d.ts +4 -5
- package/dist/manifest/byte-budget.js +1 -1
- package/dist/manifest/publish.js +13 -12
- package/dist/memory-report.js +2 -2
- package/dist/merkle.js +11 -10
- package/dist/personhood/bootstrap.js +4 -4
- package/dist/personhood/people-client.js +4 -4
- package/dist/pool.d.ts +7 -2
- package/dist/pool.js +3 -1
- package/dist/run-state.js +1 -1
- package/dist/sss-allowance-cache.js +5 -4
- package/dist/storage-signer.js +11 -10
- package/dist/telemetry.js +2 -2
- package/dist/version-check.js +3 -3
- package/docs/bootstrap.md +47 -13
- package/docs/e2e-bootstrap.md +5 -0
- package/package.json +1 -1
package/DEPLOYMENT.md
CHANGED
|
@@ -1,124 +1,102 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Setting up an environment
|
|
2
2
|
|
|
3
|
-
This guide
|
|
3
|
+
This guide is for the **operator / chain admin** standing up `bulletin-deploy` against a Polkadot environment. It covers what you configure and authorize so that deploys work against *your* chain.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
> This targets a **testnet** (`paseo-next-v2`) by default. It is reference/proof-of-concept tooling — see the security notice in the [README](README.md#security).
|
|
7
|
-
|
|
8
|
-
## Prerequisites
|
|
5
|
+
For **using** the tool once an environment is set up — building and shipping an app — see the [README](README.md). This document is the setup side.
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
node --version # must print v22 or higher
|
|
13
|
-
```
|
|
14
|
-
2. **The CLI**, installed globally:
|
|
15
|
-
```sh
|
|
16
|
-
npm install -g bulletin-deploy
|
|
17
|
-
```
|
|
18
|
-
3. **A built static site** — a directory of static files (HTML/CSS/JS), for example `./dist`. Build your app however you normally would (`npm run build`, etc.); `bulletin-deploy` uploads the resulting directory as-is.
|
|
19
|
-
4. **An identity to own the name** — choose one:
|
|
20
|
-
- **Mobile Polkadot wallet (recommended).** No mnemonic on disk; you sign in once by scanning a QR code. See [Sign in](#1-sign-in-recommended) below.
|
|
21
|
-
- **A testnet mnemonic.** Pass `--mnemonic "..."` (or set the `MNEMONIC` env var) instead of signing in.
|
|
7
|
+
> [!NOTE]
|
|
8
|
+
> `bulletin-deploy` is reference / proof-of-concept tooling — see the security notice in the [README](README.md#security). The defaults target Polkadot testnets.
|
|
22
9
|
|
|
23
|
-
|
|
10
|
+
**Documentation map — read in order:**
|
|
11
|
+
1. **[DEPLOYMENT.md](DEPLOYMENT.md)** (this doc) — set up `bulletin-deploy` for your environment.
|
|
12
|
+
2. **[docs/bootstrap.md](docs/bootstrap.md)** — the `bulletin-bootstrap` reference (Bulletin storage authorization).
|
|
13
|
+
3. **[docs/e2e-bootstrap.md](docs/e2e-bootstrap.md)** — a fully worked setup, end to end, for the E2E test environment.
|
|
24
14
|
|
|
25
|
-
|
|
15
|
+
(Using the tool to ship an app — not setting it up — is the [README](README.md).)
|
|
26
16
|
|
|
27
|
-
|
|
17
|
+
## What an "environment" is
|
|
28
18
|
|
|
29
|
-
|
|
19
|
+
A `bulletin-deploy` environment is three things, which it expects to already exist for your network:
|
|
30
20
|
|
|
31
|
-
|
|
21
|
+
- an **Asset Hub** (PolkaVM / `pallet-revive`) with the **DotNS** contracts deployed — names live here;
|
|
22
|
+
- a **Bulletin Chain** — content (your site, chunked + content-addressed) is stored here;
|
|
23
|
+
- an **IPFS gateway** — serves the stored content over HTTP.
|
|
32
24
|
|
|
33
|
-
-
|
|
34
|
-
- Pick something not already registered. The CLI tells you during a deploy whether the name is available or already owned by you.
|
|
25
|
+
Setup is: tell `bulletin-deploy` where those are, authorize the accounts that will write to the Bulletin Chain, and (if your DotNS gates registration) grant the registering account personhood. The steps below.
|
|
35
26
|
|
|
36
|
-
##
|
|
27
|
+
## 1. Define the environment
|
|
37
28
|
|
|
38
|
-
|
|
29
|
+
`bulletin-deploy` resolves environments from `environments.json`. The built-in presets ship in `assets/environments.json`:
|
|
39
30
|
|
|
40
31
|
```sh
|
|
41
|
-
bulletin-deploy
|
|
42
|
-
bulletin-deploy whoami # confirm the signed-in address
|
|
32
|
+
bulletin-deploy --list-environments # list the built-in environment IDs
|
|
43
33
|
```
|
|
44
34
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
### 2. Deploy your build directory
|
|
35
|
+
Add your network either by adding an entry to `assets/environments.json`, or by supplying one at runtime:
|
|
48
36
|
|
|
49
37
|
```sh
|
|
50
|
-
bulletin-deploy ./dist myapp.dot
|
|
51
|
-
|
|
52
|
-
bulletin-deploy ./dist myapp.dot --js-merkle
|
|
38
|
+
bulletin-deploy ./dist myapp.dot --environment-file ./my-env.json
|
|
39
|
+
bulletin-deploy ./dist myapp.dot --env <id> --contract DOTNS_REGISTRAR=0x... # override single fields
|
|
53
40
|
```
|
|
54
41
|
|
|
55
|
-
|
|
42
|
+
An environment entry provides:
|
|
56
43
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
44
|
+
- **Chain endpoints** — the `wss://` RPCs for at least the **bulletin** and **asset-hub** chains.
|
|
45
|
+
- **DotNS contract addresses** — the contract set deployed on your Asset Hub (`DOTNS_REGISTRAR`, `POP_RULES`, the resolvers, `STORE_FACTORY`, …).
|
|
46
|
+
- **`nativeToEthRatio`** — `10^(18 − native_decimals)`; e.g. a 10-decimal native token → `100000000`.
|
|
47
|
+
- **`registerStorageDeposit`** — the DotNS registration deposit on your chain.
|
|
48
|
+
- **`autoAccountMapping`** — whether the chain maps accounts to H160 automatically on first tx.
|
|
49
|
+
- **`ipfs`** — the gateway that serves deployed content.
|
|
61
50
|
|
|
62
|
-
|
|
51
|
+
Use the `paseo-next-v2` and `summit` entries in `assets/environments.json` as worked examples to copy.
|
|
63
52
|
|
|
64
|
-
|
|
65
|
-
============================================================
|
|
66
|
-
DEPLOYMENT COMPLETE!
|
|
67
|
-
============================================================
|
|
68
|
-
- Polkadot Desktop: myapp.dot
|
|
69
|
-
- Polkadot Browser: https://myapp.dot.li
|
|
70
|
-
```
|
|
53
|
+
## 2. Authorize Bulletin storage
|
|
71
54
|
|
|
72
|
-
|
|
55
|
+
Writing content to the Bulletin Chain requires each **storage account** to hold a `TransactionStorage` **authorization** — a quota of transactions and bytes. Storage is gated by this quota, **not by balance** (Bulletin has no fee model), so the storage accounts need no funds. `bulletin-deploy` never grants the authorization itself; the chain's **authorizer** must.
|
|
73
56
|
|
|
74
|
-
-
|
|
75
|
-
- Or open **`myapp.dot`** directly in a Polkadot-aware browser/extension.
|
|
57
|
+
The storage accounts are an upload **pool**, derived as `//deploy/0…N` from `BULLETIN_POOL_MNEMONIC` (default: the well-known `DEV_PHRASE`). The deploy path derives the **same** pool from that env var — so if you use a custom pool, set `BULLETIN_POOL_MNEMONIC` identically for both bootstrap and deploy, or they won't line up.
|
|
76
58
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
If your content uploads but the final ownership transfer fails, the name is registered by the worker and you can claim it separately:
|
|
59
|
+
`bulletin-bootstrap` reports each pool account's authorization status, and — given an authorizer key — grants authorization to the ones that lack it:
|
|
80
60
|
|
|
81
61
|
```sh
|
|
82
|
-
bulletin-
|
|
83
|
-
bulletin-
|
|
62
|
+
bulletin-bootstrap --env <id> # list pool accounts + their authorization status
|
|
63
|
+
bulletin-bootstrap --env <id> --authorizer "<seed>" # grant authorization with the authorizer key
|
|
64
|
+
bulletin-bootstrap --env <id> --pool-size 20 # inspect/authorize a larger pool
|
|
84
65
|
```
|
|
85
66
|
|
|
86
|
-
|
|
67
|
+
On a **testnet** the authorizer defaults to `//Alice` (it holds authorization authority there), so no `--authorizer` is needed. On a **production** chain, pass `--authorizer` with the key that actually holds authorization authority — if it can't grant, the tool reports that rather than pretending. See [`docs/bootstrap.md`](docs/bootstrap.md) for the full reference.
|
|
87
68
|
|
|
88
|
-
|
|
89
|
-
bulletin-deploy --list-environments # show available environment IDs
|
|
90
|
-
bulletin-deploy ./dist myapp.dot --env <id>
|
|
91
|
-
```
|
|
69
|
+
## 3. Personhood (if your DotNS gates registration)
|
|
92
70
|
|
|
93
|
-
|
|
71
|
+
If your `POP_RULES` contract requires Proof-of-Personhood to register a base name, the **registering account** needs a PoP status granted by the `POP_RULES` owner. (NoStatus-eligible label shapes skip this — see the rules in your DotNS deployment.)
|
|
94
72
|
|
|
95
|
-
|
|
73
|
+
- On Parity's testnets, request a grant by opening an issue on [paritytech/dotns](https://github.com/paritytech/dotns/issues).
|
|
74
|
+
- On your own chain, your `POP_RULES` owner grants it out of band — `bulletin-deploy` cannot upgrade a signer.
|
|
96
75
|
|
|
97
|
-
|
|
76
|
+
## 4. Fund the signing accounts
|
|
98
77
|
|
|
99
|
-
|
|
78
|
+
The accounts that register and transfer names need a balance on your Asset Hub for DotNS fees:
|
|
100
79
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
80
|
+
- **Public testnets** — use the faucet (e.g. [faucet.polkadot.io](https://faucet.polkadot.io/)).
|
|
81
|
+
- **Restricted networks** — fund the accounts out of band; there is no public faucet.
|
|
82
|
+
|
|
83
|
+
(These are the DotNS signing accounts on the Asset Hub — distinct from the Bulletin storage pool in step 2, which needs authorization, not funds.)
|
|
84
|
+
|
|
85
|
+
## 5. Content gateway
|
|
86
|
+
|
|
87
|
+
Deployed content is content-addressed (a CID) on the Bulletin Chain and served over HTTP by the IPFS gateway you set as `ipfs` in step 1. The `.dot` name resolves to that CID via DotNS. Parity's public testnets resolve a deployed name at `https://<name>.dot.li`; your environment uses whatever gateway / resolver you point it at.
|
|
88
|
+
|
|
89
|
+
## 6. Verify the setup
|
|
106
90
|
|
|
107
|
-
|
|
91
|
+
A **test deploy** is the real check — run one (see the [README](README.md)) and confirm it completes and resolves. Two failures map straight back to the steps above:
|
|
108
92
|
|
|
109
|
-
|
|
93
|
+
- `not authorized to upload` → the storage account lacks authorization (step 2).
|
|
94
|
+
- a personhood / registration gate → the registering account needs PoP (step 3).
|
|
110
95
|
|
|
111
|
-
|
|
112
|
-
- **`--no-transfer-to-signedin-user`:** sign every DotNS transaction with your mobile session instead.
|
|
113
|
-
- **`--mnemonic "..."` / `MNEMONIC`:** use a mnemonic instead of a session.
|
|
96
|
+
If you're working from a **clone of the repository** (not just the npm package), `tools/` has read-only diagnostics that take `--env <id>`: `check-bulletin-auth.mjs` (storage quotas), `check-balances.mjs` (balances + quota), `check-pop-status.mjs` (personhood), `probe-env-health.mjs` (RPC reachability). These ship with the repo, not the published package.
|
|
114
97
|
|
|
115
|
-
|
|
98
|
+
A concrete, fully worked instance of this setup — for the E2E test environment — lives in [`docs/e2e-bootstrap.md`](docs/e2e-bootstrap.md).
|
|
116
99
|
|
|
117
|
-
|
|
118
|
-
|---|---|
|
|
119
|
-
| `IPFS CLI not installed` | Install [Kubo](https://docs.ipfs.tech/install/), or add `--js-merkle`. |
|
|
120
|
-
| Name rejected as reserved / too short | Use a base label of **6+ characters**. |
|
|
121
|
-
| `Login session unavailable or expired` | Re-run `bulletin-deploy login`. |
|
|
122
|
-
| Not authorized to upload | The storage account lacks a Bulletin `TransactionStorage` authorization. On `paseo-next-v2` the shared pool is already authorized; on your own setup, see [Bootstrapping your own storage pool](#bootstrapping-your-own-storage-pool). On a production chain, request authorization from the network's authorizer. |
|
|
100
|
+
---
|
|
123
101
|
|
|
124
|
-
|
|
102
|
+
Once the environment is set up, day-to-day use is in the [README](README.md): build your site, `bulletin-deploy ./dist myapp.dot`, done.
|
package/bin/bulletin-bootstrap
CHANGED
|
@@ -13,6 +13,7 @@ const flags = {};
|
|
|
13
13
|
for (let i = 0; i < args.length; i++) {
|
|
14
14
|
if (args[i] === "--pool-size") { flags.poolSize = parseInt(args[++i], 10); }
|
|
15
15
|
else if (args[i] === "--mnemonic") { flags.mnemonic = args[++i]; }
|
|
16
|
+
else if (args[i] === "--authorizer") { flags.authorizer = args[++i]; }
|
|
16
17
|
else if (args[i] === "--rpc") { flags.rpc = args[++i]; }
|
|
17
18
|
else if (args[i] === "--env") { flags.env = args[++i]; }
|
|
18
19
|
else if (args[i] === "--version" || args[i] === "-V") { flags.version = true; }
|
|
@@ -32,17 +33,27 @@ if (flags.help) {
|
|
|
32
33
|
console.log(`bulletin-bootstrap v${VERSION}
|
|
33
34
|
|
|
34
35
|
Usage:
|
|
35
|
-
bulletin-bootstrap
|
|
36
|
+
bulletin-bootstrap [options]
|
|
37
|
+
|
|
38
|
+
Reports the authorization status of each pool account and, when an authorizer
|
|
39
|
+
key is available, grants authorization to any account that needs it.
|
|
40
|
+
|
|
41
|
+
The Bulletin chain has no fee model — storage access is gated by TransactionStorage
|
|
42
|
+
authorization quota, not account balance. This tool manages that quota.
|
|
36
43
|
|
|
37
44
|
Options:
|
|
38
|
-
--mnemonic "..."
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
--
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
--mnemonic "..." Pool root mnemonic used to derive pool accounts
|
|
46
|
+
(also readable from BULLETIN_POOL_MNEMONIC or MNEMONIC env var).
|
|
47
|
+
Default: the well-known dev phrase (same key the deploy path uses).
|
|
48
|
+
--authorizer "..." Seed/mnemonic of the key that holds authorization authority
|
|
49
|
+
on this chain (e.g. "//Alice", a full mnemonic, or a hex seed).
|
|
50
|
+
On testnets, defaults to //Alice if omitted.
|
|
51
|
+
On non-testnets, required to grant — omit to get status only.
|
|
52
|
+
--rpc wss://... Bulletin RPC endpoint (or set BULLETIN_RPC env var)
|
|
53
|
+
--env <id> Load environment by id from environments.json
|
|
54
|
+
--pool-size N Number of pool accounts to check/initialize (default: 10)
|
|
55
|
+
--version Show version
|
|
56
|
+
--help Show this help`);
|
|
46
57
|
process.exit(0);
|
|
47
58
|
}
|
|
48
59
|
|
|
@@ -52,6 +63,10 @@ const mnemonic = flags.mnemonic ?? process.env.BULLETIN_POOL_MNEMONIC ?? process
|
|
|
52
63
|
|
|
53
64
|
const bootstrapOpts = {};
|
|
54
65
|
|
|
66
|
+
if (flags.authorizer) {
|
|
67
|
+
bootstrapOpts.authorizerMnemonic = flags.authorizer;
|
|
68
|
+
}
|
|
69
|
+
|
|
55
70
|
if (flags.env) {
|
|
56
71
|
const envJsonPath = fileURLToPath(new URL("../assets/environments.json", import.meta.url));
|
|
57
72
|
let envDoc;
|
package/dist/auth/index.js
CHANGED
|
@@ -8,12 +8,13 @@ import {
|
|
|
8
8
|
requestResourceAllocation,
|
|
9
9
|
resolveSigner,
|
|
10
10
|
summarizeOutcomes
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-5FLTDWWP.js";
|
|
12
12
|
import {
|
|
13
13
|
renderLoginStatus,
|
|
14
14
|
renderLogoutStatus,
|
|
15
15
|
renderQrCode
|
|
16
16
|
} from "../chunk-RIRDBSBG.js";
|
|
17
|
+
import "../chunk-TSPERKUS.js";
|
|
17
18
|
import "../chunk-ZOC4GITL.js";
|
|
18
19
|
export {
|
|
19
20
|
BULLETIN_RESOURCE,
|
package/dist/auth-config.js
CHANGED
|
@@ -9,9 +9,10 @@ import {
|
|
|
9
9
|
getPeopleChainEndpoints,
|
|
10
10
|
hasPersistedSession,
|
|
11
11
|
resolveBulletinEndpoints
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-F2SDBU57.js";
|
|
13
|
+
import "./chunk-TSPERKUS.js";
|
|
14
|
+
import "./chunk-ORIB2S5P.js";
|
|
15
|
+
import "./chunk-V4RTUMBT.js";
|
|
15
16
|
import "./chunk-QRKI6MMK.js";
|
|
16
17
|
import "./chunk-ZOC4GITL.js";
|
|
17
18
|
export {
|
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-OR7LUTET.js";
|
|
13
|
+
import "./chunk-ZC43ORKF.js";
|
|
14
|
+
import "./chunk-ORIB2S5P.js";
|
|
15
|
+
import "./chunk-V4RTUMBT.js";
|
|
16
16
|
export {
|
|
17
17
|
buildCliFlagsSummary,
|
|
18
18
|
buildLabels,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
preflightSssAllowance
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SNDIOANW.js";
|
|
4
4
|
import {
|
|
5
5
|
statementSigningAccount
|
|
6
6
|
} from "./chunk-GRPLHUYC.js";
|
|
@@ -34,16 +34,19 @@ import {
|
|
|
34
34
|
STALE_SESSION_MESSAGE,
|
|
35
35
|
getPeopleChainEndpoints,
|
|
36
36
|
hasPersistedSession
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-F2SDBU57.js";
|
|
38
38
|
import {
|
|
39
39
|
setDeployContext
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-OR7LUTET.js";
|
|
41
41
|
import {
|
|
42
42
|
probeChunks
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-7HQL3TPT.js";
|
|
44
44
|
import {
|
|
45
45
|
packSection
|
|
46
46
|
} from "./chunk-C2TS5MER.js";
|
|
47
|
+
import {
|
|
48
|
+
CLI_NAME
|
|
49
|
+
} from "./chunk-TSPERKUS.js";
|
|
47
50
|
import {
|
|
48
51
|
DotNS,
|
|
49
52
|
PUBLISHER_ABI,
|
|
@@ -53,7 +56,7 @@ import {
|
|
|
53
56
|
parseDomainName,
|
|
54
57
|
popStatusName,
|
|
55
58
|
verifyNonceAdvanced
|
|
56
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-ARPBPQZQ.js";
|
|
57
60
|
import {
|
|
58
61
|
derivePoolAccounts,
|
|
59
62
|
detectTestnet,
|
|
@@ -61,7 +64,7 @@ import {
|
|
|
61
64
|
fetchPoolAuthorizations,
|
|
62
65
|
isAuthorizationSufficient,
|
|
63
66
|
selectAccount
|
|
64
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-4IUTMHVB.js";
|
|
65
68
|
import {
|
|
66
69
|
VERSION,
|
|
67
70
|
captureWarning,
|
|
@@ -75,7 +78,7 @@ import {
|
|
|
75
78
|
truncateAddress,
|
|
76
79
|
withDeploySpan,
|
|
77
80
|
withSpan
|
|
78
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-ORIB2S5P.js";
|
|
79
82
|
import {
|
|
80
83
|
DEFAULT_ENV_ID,
|
|
81
84
|
getPopSelfServeConfig,
|
|
@@ -417,7 +420,9 @@ function isBenignTeardownError(error) {
|
|
|
417
420
|
const s = error instanceof Error ? `${error.name ?? ""} ${error.message ?? ""}` : String(error);
|
|
418
421
|
return /DestroyedError|Client destroyed/.test(s);
|
|
419
422
|
}
|
|
420
|
-
var
|
|
423
|
+
var SHA256_MULTIHASH_CODE = 18;
|
|
424
|
+
var BLAKE2B_256_MULTIHASH_CODE = 45600;
|
|
425
|
+
var CID_CONFIG = { version: 1, codec: 85, hashCode: SHA256_MULTIHASH_CODE, hashLength: 32 };
|
|
421
426
|
function deriveRootSigner(mnemonic, path3 = "") {
|
|
422
427
|
const entropy = mnemonicToEntropy(mnemonic);
|
|
423
428
|
const miniSecret = entropyToMiniSecret(entropy);
|
|
@@ -593,6 +598,9 @@ function chooseSignerInput(opts) {
|
|
|
593
598
|
function isPhoneSignerActive(options) {
|
|
594
599
|
return !!(options.signer && options.signerAddress && !options.transferTo);
|
|
595
600
|
}
|
|
601
|
+
function shouldHandoverName(opts) {
|
|
602
|
+
return !!opts.transferTo && opts.registeredFresh;
|
|
603
|
+
}
|
|
596
604
|
function formatStorageSignerLine(slotAddress, failReason) {
|
|
597
605
|
if (slotAddress) return ` Storage signer: allowance slot ${slotAddress}`;
|
|
598
606
|
return ` Storage signer: pool fallback (${failReason ?? "no session"})`;
|
|
@@ -616,7 +624,7 @@ function selectStorageReconnect(options) {
|
|
|
616
624
|
console.warn(
|
|
617
625
|
`\u26A0 Bulletin allowance slot not usable: ${reason}
|
|
618
626
|
Falling back to the shared pool account for storage (fine on testnet).
|
|
619
|
-
To use your own allowance, run:
|
|
627
|
+
To use your own allowance, run: ${CLI_NAME} logout && ${CLI_NAME} login`
|
|
620
628
|
);
|
|
621
629
|
return getProvider();
|
|
622
630
|
}
|
|
@@ -690,9 +698,8 @@ function watchTransaction(tx, signer, txOpts, onSuccess, { label = "transaction"
|
|
|
690
698
|
});
|
|
691
699
|
}
|
|
692
700
|
async function storeChunk(unsafeApi, signer, chunkBytes, nonce, ss58, opts = {}) {
|
|
693
|
-
const
|
|
694
|
-
const
|
|
695
|
-
const tx = unsafeApi.tx.TransactionStorage.store_with_cid_config({ cid: { codec: BigInt(CID_CONFIG.codec), hashing: toHashingEnum(hashCode) }, data: chunkBytes });
|
|
701
|
+
const cid = createCID(chunkBytes, CID_CONFIG.codec, CID_CONFIG.hashCode);
|
|
702
|
+
const tx = unsafeApi.tx.TransactionStorage.store_with_cid_config({ cid: { codec: BigInt(CID_CONFIG.codec), hashing: toHashingEnum(CID_CONFIG.hashCode) }, data: chunkBytes });
|
|
696
703
|
const txOpts = { mortality: { mortal: true, period: CHUNK_MORTALITY_PERIOD }, nonce };
|
|
697
704
|
const { value, viaFallback, receipt } = await watchTransaction(tx, signer, txOpts, () => {
|
|
698
705
|
console.log(` CID: ${cid.toString()}`);
|
|
@@ -700,11 +707,15 @@ async function storeChunk(unsafeApi, signer, chunkBytes, nonce, ss58, opts = {})
|
|
|
700
707
|
}, { label: `chunk(nonce:${nonce})`, rpc: BULLETIN_ENDPOINTS, senderSS58: ss58, expectedNonce: nonce, timeoutMs: CHUNK_TIMEOUT_MS, fetchNonce: opts.fetchNonce });
|
|
701
708
|
return { ...value, viaFallback, receipt };
|
|
702
709
|
}
|
|
703
|
-
async function storeFile(contentBytes, {
|
|
710
|
+
async function storeFile(contentBytes, {
|
|
711
|
+
client: existingClient,
|
|
712
|
+
unsafeApi: existingApi,
|
|
713
|
+
signer: existingSigner,
|
|
714
|
+
hashCode = CID_CONFIG.hashCode
|
|
715
|
+
} = {}) {
|
|
704
716
|
console.log(`
|
|
705
717
|
Size: ${(contentBytes.length / 1024).toFixed(2)} KB`);
|
|
706
718
|
if (contentBytes.length > MAX_FILE_SIZE) throw new Error(`File exceeds 8MB limit. Use chunked deployment.`);
|
|
707
|
-
const hashCode = 18;
|
|
708
719
|
const cid = createCID(contentBytes, CID_CONFIG.codec, hashCode);
|
|
709
720
|
console.log(` CID: ${cid.toString()}`);
|
|
710
721
|
let client, unsafeApi, signer;
|
|
@@ -719,6 +730,13 @@ async function storeFile(contentBytes, { client: existingClient, unsafeApi: exis
|
|
|
719
730
|
signer = provider.signer;
|
|
720
731
|
}
|
|
721
732
|
try {
|
|
733
|
+
const [probe] = await probeChunks([cid.toString()], { client });
|
|
734
|
+
if (probe.present === true) {
|
|
735
|
+
console.log(` Already on chain (block ${probe.block}, index ${probe.index}) \u2014 skipping upload.
|
|
736
|
+
`);
|
|
737
|
+
if (!existingClient) client.destroy();
|
|
738
|
+
return cid.toString();
|
|
739
|
+
}
|
|
722
740
|
const tx = unsafeApi.tx.TransactionStorage.store_with_cid_config({ cid: { codec: BigInt(CID_CONFIG.codec), hashing: toHashingEnum(hashCode) }, data: contentBytes });
|
|
723
741
|
const txOpts = { mortality: { mortal: true, period: 256 } };
|
|
724
742
|
console.log(` Submitting...`);
|
|
@@ -1996,7 +2014,7 @@ async function deploy(content, domainName = null, options = {}) {
|
|
|
1996
2014
|
if (options.suri) throw e;
|
|
1997
2015
|
if (e?.name === "SignerNotAvailableError") {
|
|
1998
2016
|
if (hasSession) console.error(STALE_SESSION_MESSAGE);
|
|
1999
|
-
else console.log(
|
|
2017
|
+
else console.log(` Login session unavailable or expired \u2014 falling back to pool. Run \`${CLI_NAME} login\` to use your identity.`);
|
|
2000
2018
|
} else {
|
|
2001
2019
|
throw e;
|
|
2002
2020
|
}
|
|
@@ -2012,7 +2030,7 @@ async function deploy(content, domainName = null, options = {}) {
|
|
|
2012
2030
|
const allowed = await preflightSssAllowance(statementAccount, () => getPeopleChainEndpoints(envId));
|
|
2013
2031
|
if (allowed === false) {
|
|
2014
2032
|
throw new NonRetryableError(
|
|
2015
|
-
|
|
2033
|
+
`Session signing allowance has expired (~2-3 days after login). Run \`${CLI_NAME} logout\`, then \`${CLI_NAME} login\`, to renew (login alone won't refresh a stale session).`
|
|
2016
2034
|
);
|
|
2017
2035
|
}
|
|
2018
2036
|
} catch (e) {
|
|
@@ -2394,6 +2412,7 @@ Have your phone ready \u2014 1 signature needed (link content)`);
|
|
|
2394
2412
|
...phoneSignerActive ? { onPhoneSigningRequired: (label) => console.log(`
|
|
2395
2413
|
Check your phone \u2192 ${label}`) } : {}
|
|
2396
2414
|
});
|
|
2415
|
+
let registeredFresh = false;
|
|
2397
2416
|
if (parsed?.isSubdomain) {
|
|
2398
2417
|
const { owned, owner } = await dotns.checkSubdomainOwnership(parsed.sublabel, parsed.parentLabel);
|
|
2399
2418
|
if (owned) {
|
|
@@ -2405,6 +2424,7 @@ Have your phone ready \u2014 1 signature needed (link content)`);
|
|
|
2405
2424
|
if (!parentOwnership.owned) throw new Error(`You must own ${parsed.parentLabel}.dot to register subdomains under it`);
|
|
2406
2425
|
console.log(` Status: Registering subdomain...`);
|
|
2407
2426
|
await dotns.registerSubdomain(parsed.sublabel, parsed.parentLabel);
|
|
2427
|
+
registeredFresh = true;
|
|
2408
2428
|
}
|
|
2409
2429
|
} else {
|
|
2410
2430
|
const { owned } = await dotns.checkOwnership(name);
|
|
@@ -2413,6 +2433,7 @@ Have your phone ready \u2014 1 signature needed (link content)`);
|
|
|
2413
2433
|
} else {
|
|
2414
2434
|
console.log(` Status: Registering...`);
|
|
2415
2435
|
await dotns.register(name);
|
|
2436
|
+
registeredFresh = true;
|
|
2416
2437
|
}
|
|
2417
2438
|
}
|
|
2418
2439
|
const contenthashHex = `0x${encodeContenthash(cid)}`;
|
|
@@ -2422,7 +2443,12 @@ Have your phone ready \u2014 1 signature needed (link content)`);
|
|
|
2422
2443
|
await publish(dotns, parsed, options.failOnPublishError);
|
|
2423
2444
|
}
|
|
2424
2445
|
}
|
|
2425
|
-
if (options.transferTo) {
|
|
2446
|
+
if (options.transferTo && !registeredFresh) {
|
|
2447
|
+
console.log(` ${name}.dot already existed \u2014 updated content only; ownership unchanged (not transferred to ${options.transferTo}).`);
|
|
2448
|
+
console.log(` If you meant to claim it, run: ${CLI_NAME} transfer ${name} --env ${envId}${options.suri ? ` --mnemonic "<your worker key>"` : ""}`);
|
|
2449
|
+
setDeployAttribute("deploy.transfer.status", "skipped-existing");
|
|
2450
|
+
}
|
|
2451
|
+
if (shouldHandoverName({ transferTo: options.transferTo, registeredFresh })) {
|
|
2426
2452
|
const transferTo = options.transferTo;
|
|
2427
2453
|
await withSpan("deploy.transfer", `3. transfer ${name}.dot`, { "deploy.transfer.to": transferTo }, async () => {
|
|
2428
2454
|
setDeployAttribute("deploy.transfer.worker", truncateAddress(options.signerAddress ?? ""));
|
|
@@ -2434,7 +2460,7 @@ Have your phone ready \u2014 1 signature needed (link content)`);
|
|
|
2434
2460
|
console.log(` Handed ${name}.dot to ${transferTo} (${transferRes.status}${transferRes.txHash ? `, tx ${transferRes.txHash}` : ""}).`);
|
|
2435
2461
|
} catch (e) {
|
|
2436
2462
|
setDeployAttribute("deploy.transfer.status", "failed");
|
|
2437
|
-
const recover =
|
|
2463
|
+
const recover = `${CLI_NAME} transfer ${name} --env ${envId}` + (options.suri ? ` --mnemonic "<your worker key>"` : "");
|
|
2438
2464
|
try {
|
|
2439
2465
|
dotns.disconnect();
|
|
2440
2466
|
} catch {
|
|
@@ -2497,9 +2523,9 @@ Have your phone ready \u2014 1 signature needed (link content)`);
|
|
|
2497
2523
|
console.log("\n" + "=".repeat(60));
|
|
2498
2524
|
console.log("DEPLOYMENT COMPLETE!");
|
|
2499
2525
|
console.log("=".repeat(60));
|
|
2500
|
-
console.log("\
|
|
2501
|
-
console.log(`
|
|
2502
|
-
console.log(`
|
|
2526
|
+
console.log("\nCheck it out here:");
|
|
2527
|
+
console.log(` ${browserUrlFor(name, envId)}`);
|
|
2528
|
+
console.log(` ${name}.dot (in a Polkadot-aware browser)`);
|
|
2503
2529
|
console.log("\n" + "=".repeat(60) + "\n");
|
|
2504
2530
|
return { domainName: name, fullDomain: `${name}.dot`, cid, ipfsCid };
|
|
2505
2531
|
} finally {
|
|
@@ -2938,6 +2964,8 @@ export {
|
|
|
2938
2964
|
retryBudgetExhausted,
|
|
2939
2965
|
isConnectionError,
|
|
2940
2966
|
isBenignTeardownError,
|
|
2967
|
+
SHA256_MULTIHASH_CODE,
|
|
2968
|
+
BLAKE2B_256_MULTIHASH_CODE,
|
|
2941
2969
|
deriveRootSigner,
|
|
2942
2970
|
createCID,
|
|
2943
2971
|
encodeContenthash,
|
|
@@ -2951,6 +2979,7 @@ export {
|
|
|
2951
2979
|
__selectStorageProviderModeForTest,
|
|
2952
2980
|
chooseSignerInput,
|
|
2953
2981
|
isPhoneSignerActive,
|
|
2982
|
+
shouldHandoverName,
|
|
2954
2983
|
formatStorageSignerLine,
|
|
2955
2984
|
storeFile,
|
|
2956
2985
|
__assignDenseNoncesForTest,
|