@parity/product-deploy 0.7.28-rc.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/LICENSE +201 -0
- package/README.md +233 -0
- package/assets/environments.json +313 -0
- package/bin/bulletin-bootstrap +84 -0
- package/bin/bulletin-deploy +429 -0
- package/dist/bug-report.d.ts +29 -0
- package/dist/bug-report.js +27 -0
- package/dist/chunk-2VAUMZB2.js +284 -0
- package/dist/chunk-43HLT335.js +232 -0
- package/dist/chunk-5VZQ2KSU.js +231 -0
- package/dist/chunk-ADNBLFDP.js +225 -0
- package/dist/chunk-BMAEWZYV.js +24 -0
- package/dist/chunk-C2TS5MER.js +64 -0
- package/dist/chunk-DNXH4QTI.js +2336 -0
- package/dist/chunk-FZWJV5AD.js +231 -0
- package/dist/chunk-GZD2UFLR.js +8 -0
- package/dist/chunk-HOTQDYHD.js +219 -0
- package/dist/chunk-IDYGYIMH.js +207 -0
- package/dist/chunk-KHVTYIIX.js +146 -0
- package/dist/chunk-KJH2T5TQ.js +172 -0
- package/dist/chunk-KOSF5FDO.js +49 -0
- package/dist/chunk-LZJMVPYW.js +156 -0
- package/dist/chunk-MFTODIIT.js +725 -0
- package/dist/chunk-MMAZFJDG.js +91 -0
- package/dist/chunk-NF2FL4ZO.js +164 -0
- package/dist/chunk-OITUIM2E.js +524 -0
- package/dist/chunk-P6CHOMN3.js +2368 -0
- package/dist/chunk-QMYW3D6E.js +316 -0
- package/dist/chunk-QTZNULSH.js +185 -0
- package/dist/chunk-RI3ZLNPN.js +71 -0
- package/dist/chunk-S7EM5VMW.js +108 -0
- package/dist/chunk-T7EEVWNU.js +32 -0
- package/dist/chunk-UPWEOGLQ.js +37 -0
- package/dist/chunk-ZOC4GITL.js +13 -0
- package/dist/chunk-ZYVGHDMU.js +117 -0
- package/dist/chunk-probe.d.ts +37 -0
- package/dist/chunk-probe.js +18 -0
- package/dist/chunker.d.ts +8 -0
- package/dist/chunker.js +10 -0
- package/dist/deploy.d.ts +299 -0
- package/dist/deploy.js +96 -0
- package/dist/dotns.d.ts +506 -0
- package/dist/dotns.js +101 -0
- package/dist/environments.d.ts +104 -0
- package/dist/environments.js +23 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +8 -0
- package/dist/gh-pages-mirror.d.ts +76 -0
- package/dist/gh-pages-mirror.js +30 -0
- package/dist/incremental-stats.d.ts +69 -0
- package/dist/incremental-stats.js +10 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +146 -0
- package/dist/manifest/byte-budget.d.ts +46 -0
- package/dist/manifest/byte-budget.js +14 -0
- package/dist/manifest/config-load.d.ts +36 -0
- package/dist/manifest/config-load.js +10 -0
- package/dist/manifest/publish.d.ts +54 -0
- package/dist/manifest/publish.js +23 -0
- package/dist/manifest/schema.d.ts +29 -0
- package/dist/manifest/schema.js +10 -0
- package/dist/manifest/types.d.ts +90 -0
- package/dist/manifest/types.js +6 -0
- package/dist/manifest-embed.d.ts +18 -0
- package/dist/manifest-embed.js +9 -0
- package/dist/manifest-fetch.d.ts +32 -0
- package/dist/manifest-fetch.js +21 -0
- package/dist/manifest-roundtrip.d.ts +15 -0
- package/dist/manifest-roundtrip.js +55 -0
- package/dist/manifest.d.ts +44 -0
- package/dist/manifest.js +20 -0
- package/dist/memory-report.d.ts +95 -0
- package/dist/memory-report.js +17 -0
- package/dist/merkle.d.ts +50 -0
- package/dist/merkle.js +33 -0
- package/dist/personhood/bind-paid-alias.d.ts +43 -0
- package/dist/personhood/bind-paid-alias.js +10 -0
- package/dist/personhood/bind-personal-id.d.ts +55 -0
- package/dist/personhood/bind-personal-id.js +12 -0
- package/dist/personhood/bootstrap.d.ts +85 -0
- package/dist/personhood/bootstrap.js +245 -0
- package/dist/personhood/claim-pgas.d.ts +61 -0
- package/dist/personhood/claim-pgas.js +12 -0
- package/dist/personhood/constants.d.ts +23 -0
- package/dist/personhood/constants.js +22 -0
- package/dist/personhood/encoding.d.ts +49 -0
- package/dist/personhood/encoding.js +24 -0
- package/dist/personhood/hashing.d.ts +4 -0
- package/dist/personhood/hashing.js +8 -0
- package/dist/personhood/member-key.d.ts +12 -0
- package/dist/personhood/member-key.js +10 -0
- package/dist/personhood/people-client.d.ts +14 -0
- package/dist/personhood/people-client.js +48 -0
- package/dist/personhood/reprove.d.ts +43 -0
- package/dist/personhood/reprove.js +225 -0
- package/dist/pool.d.ts +51 -0
- package/dist/pool.js +30 -0
- package/dist/run-state.d.ts +22 -0
- package/dist/run-state.js +20 -0
- package/dist/telemetry.d.ts +56 -0
- package/dist/telemetry.js +71 -0
- package/dist/version-check.d.ts +38 -0
- package/dist/version-check.js +30 -0
- package/docs/bootstrap.md +49 -0
- package/docs/e2e-bootstrap.md +154 -0
- package/docs/telemetry.md +62 -0
- package/docs/testing.md +44 -0
- package/package.json +82 -0
- package/tools/release-retry-wrapper.mjs +74 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// src/personhood/constants.ts
|
|
2
|
+
import { Binary } from "polkadot-api";
|
|
3
|
+
var DOTNS_CONTEXT_HEX = "0x646f746e73000000000000000000000000000000000000000000000000000000";
|
|
4
|
+
var DOTNS_CONTEXT_BYTES = Binary.fromHex(DOTNS_CONTEXT_HEX);
|
|
5
|
+
var PGAS_ASSET_ID = 2e9;
|
|
6
|
+
var PGAS_ASSET_LOCATION = {
|
|
7
|
+
parents: 0,
|
|
8
|
+
interior: {
|
|
9
|
+
type: "X2",
|
|
10
|
+
value: [
|
|
11
|
+
{ type: "PalletInstance", value: 50 },
|
|
12
|
+
{ type: "GeneralIndex", value: BigInt(PGAS_ASSET_ID) }
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var PROOF_BYTES = 788;
|
|
17
|
+
var BANDERSNATCH_SIGNATURE_BYTES = 96;
|
|
18
|
+
var PEOPLE_MEMBER_IDENTIFIER_HEX = "0x70656f706c652020202020202020202020202020202020202020202020202020";
|
|
19
|
+
var MEMBER_ENTROPY_KEY = new TextEncoder().encode("candidate");
|
|
20
|
+
var PAID_PROOF_TAG = new TextEncoder().encode("alias-accounts:paid");
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
DOTNS_CONTEXT_HEX,
|
|
24
|
+
DOTNS_CONTEXT_BYTES,
|
|
25
|
+
PGAS_ASSET_ID,
|
|
26
|
+
PGAS_ASSET_LOCATION,
|
|
27
|
+
PROOF_BYTES,
|
|
28
|
+
BANDERSNATCH_SIGNATURE_BYTES,
|
|
29
|
+
PEOPLE_MEMBER_IDENTIFIER_HEX,
|
|
30
|
+
MEMBER_ENTROPY_KEY,
|
|
31
|
+
PAID_PROOF_TAG
|
|
32
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// src/personhood/hashing.ts
|
|
2
|
+
import { blake2b } from "@noble/hashes/blake2b";
|
|
3
|
+
import { Binary } from "polkadot-api";
|
|
4
|
+
var hexToBytes = (hex) => {
|
|
5
|
+
const h = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
6
|
+
const out = new Uint8Array(h.length / 2);
|
|
7
|
+
for (let i = 0; i < out.length; i++) {
|
|
8
|
+
out[i] = Number.parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
9
|
+
}
|
|
10
|
+
return out;
|
|
11
|
+
};
|
|
12
|
+
function blake2b256(data) {
|
|
13
|
+
let payload;
|
|
14
|
+
if (typeof data === "string") {
|
|
15
|
+
if (data.startsWith("0x")) {
|
|
16
|
+
payload = hexToBytes(data);
|
|
17
|
+
} else {
|
|
18
|
+
payload = Binary.fromText(data);
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
if (data[0] === 48 && data[1] === 120) {
|
|
22
|
+
const hexString = new TextDecoder().decode(data);
|
|
23
|
+
payload = hexToBytes(hexString);
|
|
24
|
+
} else {
|
|
25
|
+
payload = data;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return blake2b(payload, { dkLen: 32 });
|
|
29
|
+
}
|
|
30
|
+
function blake2b256Keyed(data, key) {
|
|
31
|
+
return blake2b(data, { key, dkLen: 32 });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
blake2b256,
|
|
36
|
+
blake2b256Keyed
|
|
37
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// src/personhood/encoding.ts
|
|
2
|
+
import { blake2b } from "@noble/hashes/blake2b";
|
|
3
|
+
var concatBytes = (...arrays) => {
|
|
4
|
+
let total = 0;
|
|
5
|
+
for (const a of arrays) total += a.length;
|
|
6
|
+
const out = new Uint8Array(total);
|
|
7
|
+
let offset = 0;
|
|
8
|
+
for (const a of arrays) {
|
|
9
|
+
out.set(a, offset);
|
|
10
|
+
offset += a.length;
|
|
11
|
+
}
|
|
12
|
+
return out;
|
|
13
|
+
};
|
|
14
|
+
var compactEncode = (n) => {
|
|
15
|
+
if (n < 0) throw new Error("compactEncode: negative");
|
|
16
|
+
if (n < 64) return new Uint8Array([n << 2]);
|
|
17
|
+
if (n < 16384) {
|
|
18
|
+
const v = n << 2 | 1;
|
|
19
|
+
return new Uint8Array([v & 255, v >> 8 & 255]);
|
|
20
|
+
}
|
|
21
|
+
if (n < 1073741824) {
|
|
22
|
+
const v = n << 2 | 2;
|
|
23
|
+
return new Uint8Array([
|
|
24
|
+
v & 255,
|
|
25
|
+
v >> 8 & 255,
|
|
26
|
+
v >> 16 & 255,
|
|
27
|
+
v >>> 24 & 255
|
|
28
|
+
]);
|
|
29
|
+
}
|
|
30
|
+
throw new Error("compactEncode: value too large for inline path");
|
|
31
|
+
};
|
|
32
|
+
var blake2_256 = (data) => blake2b(data, { dkLen: 32 });
|
|
33
|
+
var buildImplicationMessage = (callBytes, extensions, excludeIdentifiers) => {
|
|
34
|
+
const exclude = typeof excludeIdentifiers === "string" ? /* @__PURE__ */ new Set([excludeIdentifiers]) : excludeIdentifiers;
|
|
35
|
+
const restExplicit = [];
|
|
36
|
+
const restImplicit = [];
|
|
37
|
+
for (const id of extensions.order) {
|
|
38
|
+
if (exclude.has(id)) continue;
|
|
39
|
+
const ext = extensions.byIdentifier[id];
|
|
40
|
+
if (!ext) throw new Error(`buildImplication: missing extension '${id}'`);
|
|
41
|
+
restExplicit.push(ext.value);
|
|
42
|
+
restImplicit.push(ext.additionalSigned);
|
|
43
|
+
}
|
|
44
|
+
const implication = concatBytes(
|
|
45
|
+
new Uint8Array([0]),
|
|
46
|
+
callBytes,
|
|
47
|
+
...restExplicit,
|
|
48
|
+
...restImplicit
|
|
49
|
+
);
|
|
50
|
+
return blake2_256(implication);
|
|
51
|
+
};
|
|
52
|
+
var buildV5GeneralExtrinsic = (callBytes, extensions) => {
|
|
53
|
+
const explicit = extensions.order.map((id) => {
|
|
54
|
+
const ext = extensions.byIdentifier[id];
|
|
55
|
+
if (!ext) throw new Error(`buildV5General: missing extension '${id}'`);
|
|
56
|
+
return ext.value;
|
|
57
|
+
});
|
|
58
|
+
const body = concatBytes(
|
|
59
|
+
new Uint8Array([69]),
|
|
60
|
+
new Uint8Array([0]),
|
|
61
|
+
...explicit,
|
|
62
|
+
callBytes
|
|
63
|
+
);
|
|
64
|
+
return concatBytes(compactEncode(body.length), body);
|
|
65
|
+
};
|
|
66
|
+
var toHex = (bytes) => {
|
|
67
|
+
let hex = "0x";
|
|
68
|
+
for (const b of bytes) {
|
|
69
|
+
hex += b.toString(16).padStart(2, "0");
|
|
70
|
+
}
|
|
71
|
+
return hex;
|
|
72
|
+
};
|
|
73
|
+
var hexToBytes = (hex) => {
|
|
74
|
+
const h = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
75
|
+
const out = new Uint8Array(h.length / 2);
|
|
76
|
+
for (let i = 0; i < out.length; i++) {
|
|
77
|
+
out[i] = Number.parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
};
|
|
81
|
+
var bytesToHex = (b) => "0x" + Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
82
|
+
var readExtensionOrder = async (metadata) => {
|
|
83
|
+
const { decAnyMetadata, unifyMetadata } = await import("@polkadot-api/substrate-bindings");
|
|
84
|
+
const meta = unifyMetadata(decAnyMetadata(metadata));
|
|
85
|
+
const raw = meta.extrinsic.signedExtensions;
|
|
86
|
+
let list = null;
|
|
87
|
+
if (Array.isArray(raw) && raw.length > 0 && Array.isArray(raw[0])) {
|
|
88
|
+
list = raw[0];
|
|
89
|
+
} else if (Array.isArray(raw)) {
|
|
90
|
+
list = raw;
|
|
91
|
+
} else if (typeof raw === "object" && raw !== null && Array.isArray(raw[0])) {
|
|
92
|
+
list = raw[0];
|
|
93
|
+
}
|
|
94
|
+
if (!list || list.length === 0) {
|
|
95
|
+
throw new Error("metadata has no signed extensions");
|
|
96
|
+
}
|
|
97
|
+
return list.map((entry) => entry.identifier);
|
|
98
|
+
};
|
|
99
|
+
var encodeMembers = (members) => {
|
|
100
|
+
for (const m of members) {
|
|
101
|
+
if (m.length !== 32) throw new Error("member key must be 32 bytes");
|
|
102
|
+
}
|
|
103
|
+
return concatBytes(compactEncode(members.length), ...members);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export {
|
|
107
|
+
concatBytes,
|
|
108
|
+
compactEncode,
|
|
109
|
+
blake2_256,
|
|
110
|
+
buildImplicationMessage,
|
|
111
|
+
buildV5GeneralExtrinsic,
|
|
112
|
+
toHex,
|
|
113
|
+
hexToBytes,
|
|
114
|
+
bytesToHex,
|
|
115
|
+
readExtensionOrder,
|
|
116
|
+
encodeMembers
|
|
117
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
type ChunkProbeFailureReason = "rpc_error" | "decode_error" | "metadata_error";
|
|
2
|
+
type ChunkProbeResult = {
|
|
3
|
+
cid: string;
|
|
4
|
+
present: false;
|
|
5
|
+
} | {
|
|
6
|
+
cid: string;
|
|
7
|
+
present: true;
|
|
8
|
+
block: number;
|
|
9
|
+
index: number;
|
|
10
|
+
} | {
|
|
11
|
+
cid: string;
|
|
12
|
+
present: null;
|
|
13
|
+
failureReason: ChunkProbeFailureReason;
|
|
14
|
+
};
|
|
15
|
+
interface ChainProbeOptions {
|
|
16
|
+
client: any;
|
|
17
|
+
batchSize?: number;
|
|
18
|
+
atFinalized?: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare class ChainProbeMetadataError extends Error {
|
|
21
|
+
constructor(msg: string);
|
|
22
|
+
}
|
|
23
|
+
declare class ChainProbeCrossValidationError extends Error {
|
|
24
|
+
constructor(msg: string);
|
|
25
|
+
}
|
|
26
|
+
/** Exported for unit testing. */
|
|
27
|
+
declare function _decodeStorageValue(hex: string | null | undefined): {
|
|
28
|
+
block: number;
|
|
29
|
+
index: number;
|
|
30
|
+
} | null;
|
|
31
|
+
declare function probeChunks(cids: string[], options: ChainProbeOptions): Promise<ChunkProbeResult[]>;
|
|
32
|
+
/** Reset session-level caches. Used in tests only. */
|
|
33
|
+
declare function _resetProbeSession(): void;
|
|
34
|
+
/** Pre-set metadataChecked so tests don't need a real metadata RPC mock. Used in tests only. */
|
|
35
|
+
declare function _bypassMetadataCheckForTest(): void;
|
|
36
|
+
|
|
37
|
+
export { ChainProbeCrossValidationError, ChainProbeMetadataError, type ChainProbeOptions, type ChunkProbeFailureReason, type ChunkProbeResult, _bypassMetadataCheckForTest, _decodeStorageValue, _resetProbeSession, probeChunks };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChainProbeCrossValidationError,
|
|
3
|
+
ChainProbeMetadataError,
|
|
4
|
+
_bypassMetadataCheckForTest,
|
|
5
|
+
_decodeStorageValue,
|
|
6
|
+
_resetProbeSession,
|
|
7
|
+
probeChunks
|
|
8
|
+
} from "./chunk-QTZNULSH.js";
|
|
9
|
+
import "./chunk-MFTODIIT.js";
|
|
10
|
+
import "./chunk-KJH2T5TQ.js";
|
|
11
|
+
export {
|
|
12
|
+
ChainProbeCrossValidationError,
|
|
13
|
+
ChainProbeMetadataError,
|
|
14
|
+
_bypassMetadataCheckForTest,
|
|
15
|
+
_decodeStorageValue,
|
|
16
|
+
_resetProbeSession,
|
|
17
|
+
probeChunks
|
|
18
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare const CHUNK_SIZE_TARGET: number;
|
|
2
|
+
declare const CHUNK_SIZE_MAX: number;
|
|
3
|
+
interface SectionFile {
|
|
4
|
+
blocks: Uint8Array[];
|
|
5
|
+
}
|
|
6
|
+
declare function packSection(files: SectionFile[]): Uint8Array[];
|
|
7
|
+
|
|
8
|
+
export { CHUNK_SIZE_MAX, CHUNK_SIZE_TARGET, type SectionFile, packSection };
|
package/dist/chunker.js
ADDED
package/dist/deploy.d.ts
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { CID } from 'multiformats/cid';
|
|
2
|
+
import { ManifestFileEntry } from './manifest.js';
|
|
3
|
+
import { PopSelfServeConfig } from './environments.js';
|
|
4
|
+
import { PolkadotSigner } from 'polkadot-api';
|
|
5
|
+
export { EXIT_CODE_NO_RETRY, NonRetryableError } from './errors.js';
|
|
6
|
+
|
|
7
|
+
interface DeployResult {
|
|
8
|
+
domainName: string;
|
|
9
|
+
fullDomain: string;
|
|
10
|
+
cid: string;
|
|
11
|
+
ipfsCid?: string;
|
|
12
|
+
}
|
|
13
|
+
type DeployContent = string | Uint8Array | Uint8Array[];
|
|
14
|
+
|
|
15
|
+
declare function friendlyChainError(msg: string): string;
|
|
16
|
+
interface ProviderResult {
|
|
17
|
+
client: any;
|
|
18
|
+
unsafeApi: any;
|
|
19
|
+
signer: PolkadotSigner;
|
|
20
|
+
ss58: string;
|
|
21
|
+
}
|
|
22
|
+
interface ExistingProvider {
|
|
23
|
+
client?: any;
|
|
24
|
+
unsafeApi?: any;
|
|
25
|
+
signer?: PolkadotSigner;
|
|
26
|
+
ss58?: string;
|
|
27
|
+
reconnect?: () => Promise<ProviderResult>;
|
|
28
|
+
fetchNonce?: (rpc: string | string[], ss58: string) => Promise<number>;
|
|
29
|
+
skipCids?: Set<string>;
|
|
30
|
+
probeFailedCids?: Set<string>;
|
|
31
|
+
gateway?: string;
|
|
32
|
+
bulletinAuthorizeV2?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* CIDs the caller vouches are already on-chain. Chunks matching these CIDs
|
|
35
|
+
* are skipped without any re-probe (unlike `skipCids` which re-probes before
|
|
36
|
+
* skipping). Invariant: only pass CIDs verified or uploaded within the same
|
|
37
|
+
* chain connection during the current deploy — they are trusted to still be
|
|
38
|
+
* present (eviction within a single deploy session is negligible).
|
|
39
|
+
*/
|
|
40
|
+
trustedCids?: Set<string>;
|
|
41
|
+
/**
|
|
42
|
+
* When true, skip the DAG-PB root build + setRoot tx at the end of
|
|
43
|
+
* storeChunkedContent. Phase A in the V2 path passes this because the
|
|
44
|
+
* caller (storeDirectoryV2) never uses the Phase A root CID — Phase B
|
|
45
|
+
* computes and stores the real root, which becomes the contenthash.
|
|
46
|
+
*/
|
|
47
|
+
skipRootStore?: boolean;
|
|
48
|
+
}
|
|
49
|
+
interface ChainReceipt {
|
|
50
|
+
txHash: string;
|
|
51
|
+
blockHash: string;
|
|
52
|
+
blockNumber: number;
|
|
53
|
+
}
|
|
54
|
+
interface StoredChunk {
|
|
55
|
+
cid: CID;
|
|
56
|
+
len: number;
|
|
57
|
+
viaFallback?: boolean;
|
|
58
|
+
receipt?: ChainReceipt;
|
|
59
|
+
}
|
|
60
|
+
declare const DEFAULT_BULLETIN_RPC = "wss://paseo-bulletin-rpc.polkadot.io";
|
|
61
|
+
declare const DEFAULT_POOL_SIZE = 10;
|
|
62
|
+
declare function setWsHaltCallback(cb: (() => void) | null): void;
|
|
63
|
+
declare const CHUNK_MORTALITY_PERIOD: number;
|
|
64
|
+
declare function retryBudgetExhausted(history: number[], maxEvents: number, windowMs: number, now?: number): boolean;
|
|
65
|
+
declare function isConnectionError(error: any): boolean;
|
|
66
|
+
declare function deriveRootSigner(mnemonic: string, path?: string): {
|
|
67
|
+
signer: PolkadotSigner;
|
|
68
|
+
ss58: string;
|
|
69
|
+
};
|
|
70
|
+
declare function createCID(data: Uint8Array, codec?: number, hashCode?: number): CID;
|
|
71
|
+
declare function encodeContenthash(cidString: string): string;
|
|
72
|
+
declare const ENCRYPT_MAGIC: Uint8Array<ArrayBuffer>;
|
|
73
|
+
declare const ENCRYPT_SALT_LEN = 16;
|
|
74
|
+
declare const ENCRYPT_NONCE_LEN = 12;
|
|
75
|
+
declare const ENCRYPT_TAG_LEN = 16;
|
|
76
|
+
declare const ENCRYPT_KEY_LEN = 32;
|
|
77
|
+
declare const ENCRYPT_PBKDF2_ITERATIONS = 100000;
|
|
78
|
+
declare function encryptContent(data: Uint8Array, password: string): Promise<Uint8Array>;
|
|
79
|
+
declare function storeFile(contentBytes: Uint8Array, { client: existingClient, unsafeApi: existingApi, signer: existingSigner }?: ExistingProvider): Promise<string>;
|
|
80
|
+
/**
|
|
81
|
+
* Pre-compute dense nonces for chunks that need submission.
|
|
82
|
+
* Chunks where stored[i] !== null are already on chain (skipped via skipCids or
|
|
83
|
+
* prior reconnect logic) and consume zero nonce slots.
|
|
84
|
+
* Exported under a test-only alias so unit tests can verify the dense property
|
|
85
|
+
* without touching the real chain.
|
|
86
|
+
*/
|
|
87
|
+
declare function assignDenseNonces(stored: (StoredChunk | null)[], startNonce: number): Map<number, number>;
|
|
88
|
+
declare const __assignDenseNoncesForTest: typeof assignDenseNonces;
|
|
89
|
+
declare function storeChunkedContent(chunks: Uint8Array[], { client: existingClient, unsafeApi: existingApi, signer: existingSigner, ss58: existingSS58, reconnect, fetchNonce: fetchNonceOverride, skipCids, probeFailedCids, gateway: providerGateway, bulletinAuthorizeV2, trustedCids, skipRootStore }?: ExistingProvider): Promise<{
|
|
90
|
+
storageCid: string;
|
|
91
|
+
tier2Verified: number;
|
|
92
|
+
tier2Inconclusive: number;
|
|
93
|
+
tier2Fallback: number;
|
|
94
|
+
liveProvider: ExistingProvider;
|
|
95
|
+
skipProbeResults: Map<string, true | false | null>;
|
|
96
|
+
rootSkipped: boolean;
|
|
97
|
+
}>;
|
|
98
|
+
declare function chunk(data: Uint8Array, size?: number): Uint8Array[];
|
|
99
|
+
declare function hasIPFS(): boolean;
|
|
100
|
+
declare function merkleize(directoryPath: string, outputCarPath: string): Promise<{
|
|
101
|
+
carPath: string;
|
|
102
|
+
cid: string;
|
|
103
|
+
}>;
|
|
104
|
+
declare function computeStorageCid(chunks: Uint8Array[]): string;
|
|
105
|
+
interface StoreDirectoryOptions {
|
|
106
|
+
provider?: ExistingProvider;
|
|
107
|
+
password?: string;
|
|
108
|
+
jsMerkle?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Fires exactly once, right after the CAR has been merkleized + encrypted
|
|
111
|
+
* and the final storage CID is known, but BEFORE the chunk upload to
|
|
112
|
+
* Bulletin starts. Use to kick off parallel side-effects (e.g. the
|
|
113
|
+
* gh-pages mirror) that can run concurrently with the slow upload. The
|
|
114
|
+
* returned promise is awaited at the end of the deploy; errors are passed
|
|
115
|
+
* through to the caller so they can decide fatal / non-fatal policy.
|
|
116
|
+
*/
|
|
117
|
+
onCarReady?: (carBytes: Uint8Array, storageCid: string) => Promise<void> | void;
|
|
118
|
+
/**
|
|
119
|
+
* v2 incremental upload: contenthash from the previous deploy of this
|
|
120
|
+
* domain (the IPFS CID, not the e3-prefixed bytes). The new flow fetches
|
|
121
|
+
* this CID's embedded manifest via the gateway, classifies files,
|
|
122
|
+
* probes chunks for presence, and skips re-uploading any chunk already
|
|
123
|
+
* stored on chain. Pass null (or omit) for first-deploy behaviour.
|
|
124
|
+
* Encrypted deploys (password set) bypass the incremental path because
|
|
125
|
+
* encryption breaks chunk-level dedup.
|
|
126
|
+
*/
|
|
127
|
+
previousContenthash?: string | null;
|
|
128
|
+
/** Override gateway URL for manifest fetch + chunk probes. */
|
|
129
|
+
gateway?: string;
|
|
130
|
+
/** Skip the 500 MiB abort guard and allow oversized deploys. */
|
|
131
|
+
allowLargeDeploy?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Pin the `deployedAt` timestamp for byte-identical rebuilds.
|
|
134
|
+
* Values: "commit" (git committer date), "epoch:<N>" (Unix epoch seconds),
|
|
135
|
+
* or any ISO 8601 string. Omit for a live wall-clock timestamp.
|
|
136
|
+
*/
|
|
137
|
+
reproducibleSource?: string;
|
|
138
|
+
/**
|
|
139
|
+
* DotNS domain label being deployed (without the `.dot` suffix, e.g. `"myapp"`).
|
|
140
|
+
* When provided, `fetchPreviousManifest` also tries the GitHub Pages mirror
|
|
141
|
+
* before falling through to the IPFS gateway.
|
|
142
|
+
*/
|
|
143
|
+
domain?: string;
|
|
144
|
+
/**
|
|
145
|
+
* Opt-in: write the pre-upload CAR file to disk after merkleization.
|
|
146
|
+
* - `true` → write to `<buildDir>.bulletin.car` (default path).
|
|
147
|
+
* - `string` → write to that explicit path.
|
|
148
|
+
* - omitted / `false` → no file written (default).
|
|
149
|
+
* Also honoured when `BULLETIN_DEPLOY_DUMP_CAR` env var is set (back-compat).
|
|
150
|
+
*/
|
|
151
|
+
dumpCar?: string | boolean;
|
|
152
|
+
}
|
|
153
|
+
declare function storeDirectory(directoryPath: string, providerOrOptions?: ExistingProvider | StoreDirectoryOptions, password?: string, jsMerkle?: boolean): Promise<{
|
|
154
|
+
storageCid: string;
|
|
155
|
+
ipfsCid: string;
|
|
156
|
+
carBytes: Uint8Array;
|
|
157
|
+
}>;
|
|
158
|
+
declare function buildFilesMap(buildDir: string, fileCids?: Map<string, string>): Record<string, ManifestFileEntry>;
|
|
159
|
+
declare function detectFramework(directoryPath: string): string | null;
|
|
160
|
+
type SizeDecision = {
|
|
161
|
+
kind: "ok";
|
|
162
|
+
} | {
|
|
163
|
+
kind: "warn";
|
|
164
|
+
message: string;
|
|
165
|
+
} | {
|
|
166
|
+
kind: "abort";
|
|
167
|
+
message: string;
|
|
168
|
+
};
|
|
169
|
+
declare function checkDeploySize(carBytes: number, opts: {
|
|
170
|
+
allowLargeDeploy?: boolean;
|
|
171
|
+
}): SizeDecision;
|
|
172
|
+
declare function resolveReproducibleTimestamp(source: string): string;
|
|
173
|
+
declare function applyManifestFetchAttributes(fetched: {
|
|
174
|
+
source: string;
|
|
175
|
+
attempts?: number;
|
|
176
|
+
bytesDownloaded?: number;
|
|
177
|
+
}): void;
|
|
178
|
+
declare function storeDirectoryV2(directoryPath: string, opts?: StoreDirectoryOptions): Promise<{
|
|
179
|
+
storageCid: string;
|
|
180
|
+
ipfsCid: string;
|
|
181
|
+
carBytes: Uint8Array;
|
|
182
|
+
}>;
|
|
183
|
+
interface DeployOptions {
|
|
184
|
+
mnemonic?: string;
|
|
185
|
+
/** Optional derivation path applied to the mnemonic (e.g. "//deploy/3"). Defaults to "" (root key). */
|
|
186
|
+
derivationPath?: string;
|
|
187
|
+
/** Pre-built signer — skips mnemonic derivation. Use for QR/mobile signing. */
|
|
188
|
+
signer?: PolkadotSigner;
|
|
189
|
+
/** SS58 address for the signer (required when signer is provided). */
|
|
190
|
+
signerAddress?: string;
|
|
191
|
+
rpc?: string;
|
|
192
|
+
poolSize?: number;
|
|
193
|
+
password?: string;
|
|
194
|
+
/** Use pure-JS merkleization instead of Kubo CLI. Required for WebContainer environments. */
|
|
195
|
+
jsMerkle?: boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Free-form label attached to the deploy span as `deploy.tag`. Used to separate
|
|
198
|
+
* test/benchmark/canary runs from real-user traffic in Sentry dashboards
|
|
199
|
+
* (e.g. "e2e-ci-pr", "load-test-a"). Falls back to DEPLOY_TAG env var.
|
|
200
|
+
*/
|
|
201
|
+
tag?: string;
|
|
202
|
+
/** Custom telemetry attributes, merged into the deploy span. Overrides auto-detected values. */
|
|
203
|
+
attributes?: Record<string, string>;
|
|
204
|
+
/**
|
|
205
|
+
* Opt-in: after a successful deploy, push the CAR to the current repo's
|
|
206
|
+
* `gh-pages` branch under `bulletin/<domain>.dot.car` so hosts can fetch it
|
|
207
|
+
* via `https://<owner>.github.io/<repo>/bulletin/<domain>.dot.car` as a
|
|
208
|
+
* fast-path cache. Non-fatal on failure. See docs/… for the discoverability
|
|
209
|
+
* caveat.
|
|
210
|
+
*/
|
|
211
|
+
ghPagesMirror?: boolean;
|
|
212
|
+
/** Skip the 500 MiB abort guard and allow oversized deploys. */
|
|
213
|
+
allowLargeDeploy?: boolean;
|
|
214
|
+
/**
|
|
215
|
+
* Filesystem path to a pre-built `.car` file. When set, skips directory
|
|
216
|
+
* scanning and merkleization; the CAR bytes are read from disk, the root
|
|
217
|
+
* CID is parsed from the CAR header, and the file is uploaded directly.
|
|
218
|
+
* The positional `<build-dir>` argument is not required when this is set.
|
|
219
|
+
*/
|
|
220
|
+
inputCar?: string;
|
|
221
|
+
/**
|
|
222
|
+
* Pin the `deployedAt` timestamp for byte-identical rebuilds.
|
|
223
|
+
* Values: "commit" (git committer date), "epoch:<N>" (Unix epoch seconds),
|
|
224
|
+
* or any ISO 8601 string. Omit for a live wall-clock timestamp.
|
|
225
|
+
*/
|
|
226
|
+
reproducibleSource?: string;
|
|
227
|
+
/**
|
|
228
|
+
* Environment id from environments.json (e.g. "paseo-next-v2", "paseo-review").
|
|
229
|
+
* Drives both the bulletin RPC and the asset-hub RPC. Defaults to
|
|
230
|
+
* DEFAULT_ENV_ID. `--rpc` / BULLETIN_RPC still override the bulletin endpoint
|
|
231
|
+
* within the chosen env.
|
|
232
|
+
*/
|
|
233
|
+
env?: string;
|
|
234
|
+
/**
|
|
235
|
+
* Pre-resolved bulletin endpoints (escape hatch for tests / library callers
|
|
236
|
+
* that want to skip environments.json loading). When provided, the loader
|
|
237
|
+
* is not called and `env` is ignored.
|
|
238
|
+
*/
|
|
239
|
+
bulletinEndpoints?: string[];
|
|
240
|
+
/** Pre-resolved asset-hub endpoints. Same escape-hatch semantics. */
|
|
241
|
+
assetHubEndpoints?: string[];
|
|
242
|
+
/**
|
|
243
|
+
* Opt-in: write the pre-upload CAR file to disk after merkleization.
|
|
244
|
+
* - `true` → write to `<buildDir>.bulletin.car` (default path).
|
|
245
|
+
* - `string` → write to that explicit path.
|
|
246
|
+
* - omitted / `false` → no file written (default).
|
|
247
|
+
* Also honoured when `BULLETIN_DEPLOY_DUMP_CAR` env var is set (back-compat).
|
|
248
|
+
* CLI: --dump-car[=<path>]
|
|
249
|
+
*/
|
|
250
|
+
dumpCar?: string | boolean;
|
|
251
|
+
/**
|
|
252
|
+
* After a successful deploy, list the label in the on-chain Publisher
|
|
253
|
+
* registry. Silently skipped on envs that do not have a Publisher contract.
|
|
254
|
+
*/
|
|
255
|
+
publish?: boolean;
|
|
256
|
+
/**
|
|
257
|
+
* When true, a publish failure after a successful deploy fails the run.
|
|
258
|
+
* Default (false): warning is logged, deploy still exits 0 — the bytes
|
|
259
|
+
* landed on Bulletin and the contenthash is on chain, the registry is a
|
|
260
|
+
* discovery courtesy.
|
|
261
|
+
*/
|
|
262
|
+
failOnPublishError?: boolean;
|
|
263
|
+
}
|
|
264
|
+
declare function resolveDotnsConnectOptions(options: Pick<DeployOptions, "mnemonic" | "derivationPath" | "signer" | "signerAddress">, assetHubEndpoints?: string[], autoAccountMapping?: boolean, contracts?: Record<string, string>, nativeToEthRatio?: bigint, environmentId?: string, popSelfServe?: PopSelfServeConfig | null, registerStorageDeposit?: bigint): {
|
|
265
|
+
signer?: PolkadotSigner;
|
|
266
|
+
signerAddress?: string;
|
|
267
|
+
mnemonic?: string;
|
|
268
|
+
derivationPath?: string;
|
|
269
|
+
assetHubEndpoints?: string[];
|
|
270
|
+
autoAccountMapping?: boolean;
|
|
271
|
+
contracts?: Record<string, string>;
|
|
272
|
+
nativeToEthRatio?: bigint;
|
|
273
|
+
environmentId?: string;
|
|
274
|
+
popSelfServe?: PopSelfServeConfig | null;
|
|
275
|
+
registerStorageDeposit?: bigint;
|
|
276
|
+
};
|
|
277
|
+
declare function estimateUploadBytes(content: DeployContent): Promise<number | null>;
|
|
278
|
+
/**
|
|
279
|
+
* Throws NonRetryableError if a subdomain is owned by a different address
|
|
280
|
+
* than the current signer. Called in the preflight branch before chunk upload.
|
|
281
|
+
* Issue #562: preflight was only checking `owned`, not comparing `owner`.
|
|
282
|
+
*/
|
|
283
|
+
declare function assertSubdomainOwnerMatchesSigner(result: {
|
|
284
|
+
owned: boolean;
|
|
285
|
+
owner: string | null | undefined;
|
|
286
|
+
}, signerEvmAddress: string | null | undefined, sublabel: string, parentLabel: string): void;
|
|
287
|
+
declare function unpublish(domainName: string, options?: {
|
|
288
|
+
mnemonic?: string;
|
|
289
|
+
derivationPath?: string;
|
|
290
|
+
rpc?: string;
|
|
291
|
+
env?: string;
|
|
292
|
+
}): Promise<{
|
|
293
|
+
domainName: string;
|
|
294
|
+
status: "unpublished" | "already-unpublished";
|
|
295
|
+
txHash?: string;
|
|
296
|
+
}>;
|
|
297
|
+
declare function deploy(content: DeployContent, domainName?: string | null, options?: DeployOptions): Promise<DeployResult>;
|
|
298
|
+
|
|
299
|
+
export { CHUNK_MORTALITY_PERIOD, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, type DeployContent, type DeployOptions, type DeployResult, ENCRYPT_KEY_LEN, ENCRYPT_MAGIC, ENCRYPT_NONCE_LEN, ENCRYPT_PBKDF2_ITERATIONS, ENCRYPT_SALT_LEN, ENCRYPT_TAG_LEN, type SizeDecision, type StoreDirectoryOptions, __assignDenseNoncesForTest, applyManifestFetchAttributes, assertSubdomainOwnerMatchesSigner, buildFilesMap, checkDeploySize, chunk, computeStorageCid, createCID, deploy, deriveRootSigner, detectFramework, encodeContenthash, encryptContent, estimateUploadBytes, friendlyChainError, hasIPFS, isConnectionError, merkleize, resolveDotnsConnectOptions, resolveReproducibleTimestamp, retryBudgetExhausted, setWsHaltCallback, storeChunkedContent, storeDirectory, storeDirectoryV2, storeFile, unpublish };
|
package/dist/deploy.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CHUNK_MORTALITY_PERIOD,
|
|
3
|
+
DEFAULT_BULLETIN_RPC,
|
|
4
|
+
DEFAULT_POOL_SIZE,
|
|
5
|
+
ENCRYPT_KEY_LEN,
|
|
6
|
+
ENCRYPT_MAGIC,
|
|
7
|
+
ENCRYPT_NONCE_LEN,
|
|
8
|
+
ENCRYPT_PBKDF2_ITERATIONS,
|
|
9
|
+
ENCRYPT_SALT_LEN,
|
|
10
|
+
ENCRYPT_TAG_LEN,
|
|
11
|
+
__assignDenseNoncesForTest,
|
|
12
|
+
applyManifestFetchAttributes,
|
|
13
|
+
assertSubdomainOwnerMatchesSigner,
|
|
14
|
+
buildFilesMap,
|
|
15
|
+
checkDeploySize,
|
|
16
|
+
chunk,
|
|
17
|
+
computeStorageCid,
|
|
18
|
+
createCID,
|
|
19
|
+
deploy,
|
|
20
|
+
deriveRootSigner,
|
|
21
|
+
detectFramework,
|
|
22
|
+
encodeContenthash,
|
|
23
|
+
encryptContent,
|
|
24
|
+
estimateUploadBytes,
|
|
25
|
+
friendlyChainError,
|
|
26
|
+
hasIPFS,
|
|
27
|
+
isConnectionError,
|
|
28
|
+
merkleize,
|
|
29
|
+
resolveDotnsConnectOptions,
|
|
30
|
+
resolveReproducibleTimestamp,
|
|
31
|
+
retryBudgetExhausted,
|
|
32
|
+
setWsHaltCallback,
|
|
33
|
+
storeChunkedContent,
|
|
34
|
+
storeDirectory,
|
|
35
|
+
storeDirectoryV2,
|
|
36
|
+
storeFile,
|
|
37
|
+
unpublish
|
|
38
|
+
} from "./chunk-P6CHOMN3.js";
|
|
39
|
+
import "./chunk-KHVTYIIX.js";
|
|
40
|
+
import "./chunk-KOSF5FDO.js";
|
|
41
|
+
import "./chunk-FZWJV5AD.js";
|
|
42
|
+
import "./chunk-S7EM5VMW.js";
|
|
43
|
+
import "./chunk-ADNBLFDP.js";
|
|
44
|
+
import "./chunk-43HLT335.js";
|
|
45
|
+
import "./chunk-QTZNULSH.js";
|
|
46
|
+
import "./chunk-C2TS5MER.js";
|
|
47
|
+
import "./chunk-DNXH4QTI.js";
|
|
48
|
+
import "./chunk-QMYW3D6E.js";
|
|
49
|
+
import "./chunk-MFTODIIT.js";
|
|
50
|
+
import "./chunk-KJH2T5TQ.js";
|
|
51
|
+
import "./chunk-OITUIM2E.js";
|
|
52
|
+
import {
|
|
53
|
+
EXIT_CODE_NO_RETRY,
|
|
54
|
+
NonRetryableError
|
|
55
|
+
} from "./chunk-ZOC4GITL.js";
|
|
56
|
+
import "./chunk-HOTQDYHD.js";
|
|
57
|
+
export {
|
|
58
|
+
CHUNK_MORTALITY_PERIOD,
|
|
59
|
+
DEFAULT_BULLETIN_RPC,
|
|
60
|
+
DEFAULT_POOL_SIZE,
|
|
61
|
+
ENCRYPT_KEY_LEN,
|
|
62
|
+
ENCRYPT_MAGIC,
|
|
63
|
+
ENCRYPT_NONCE_LEN,
|
|
64
|
+
ENCRYPT_PBKDF2_ITERATIONS,
|
|
65
|
+
ENCRYPT_SALT_LEN,
|
|
66
|
+
ENCRYPT_TAG_LEN,
|
|
67
|
+
EXIT_CODE_NO_RETRY,
|
|
68
|
+
NonRetryableError,
|
|
69
|
+
__assignDenseNoncesForTest,
|
|
70
|
+
applyManifestFetchAttributes,
|
|
71
|
+
assertSubdomainOwnerMatchesSigner,
|
|
72
|
+
buildFilesMap,
|
|
73
|
+
checkDeploySize,
|
|
74
|
+
chunk,
|
|
75
|
+
computeStorageCid,
|
|
76
|
+
createCID,
|
|
77
|
+
deploy,
|
|
78
|
+
deriveRootSigner,
|
|
79
|
+
detectFramework,
|
|
80
|
+
encodeContenthash,
|
|
81
|
+
encryptContent,
|
|
82
|
+
estimateUploadBytes,
|
|
83
|
+
friendlyChainError,
|
|
84
|
+
hasIPFS,
|
|
85
|
+
isConnectionError,
|
|
86
|
+
merkleize,
|
|
87
|
+
resolveDotnsConnectOptions,
|
|
88
|
+
resolveReproducibleTimestamp,
|
|
89
|
+
retryBudgetExhausted,
|
|
90
|
+
setWsHaltCallback,
|
|
91
|
+
storeChunkedContent,
|
|
92
|
+
storeDirectory,
|
|
93
|
+
storeDirectoryV2,
|
|
94
|
+
storeFile,
|
|
95
|
+
unpublish
|
|
96
|
+
};
|