@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,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WS_HEARTBEAT_TIMEOUT_MS
|
|
3
|
+
} from "../chunk-DNXH4QTI.js";
|
|
4
|
+
import "../chunk-QMYW3D6E.js";
|
|
5
|
+
import "../chunk-MFTODIIT.js";
|
|
6
|
+
import "../chunk-KJH2T5TQ.js";
|
|
7
|
+
import {
|
|
8
|
+
loadEnvironments
|
|
9
|
+
} from "../chunk-OITUIM2E.js";
|
|
10
|
+
import "../chunk-ZOC4GITL.js";
|
|
11
|
+
|
|
12
|
+
// src/personhood/people-client.ts
|
|
13
|
+
import { createClient } from "polkadot-api";
|
|
14
|
+
import { getWsProvider } from "polkadot-api/ws";
|
|
15
|
+
async function connectPeopleClient(environmentId) {
|
|
16
|
+
const { doc } = await loadEnvironments();
|
|
17
|
+
const peopleChain = doc.chains.find((c) => c.id === "people");
|
|
18
|
+
if (!peopleChain) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
`environments.json has no 'people' chain entry for env '${environmentId}'`
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
const entry = peopleChain.endpoints[environmentId];
|
|
24
|
+
if (!entry) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
`No People-chain endpoint for environment '${environmentId}'. Bootstrap is only available on paseo-next-v2.`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
const rawWss = entry.wss;
|
|
30
|
+
const wss = Array.isArray(rawWss) ? rawWss[0] : rawWss;
|
|
31
|
+
const client = createClient(
|
|
32
|
+
getWsProvider(wss, { heartbeatTimeout: WS_HEARTBEAT_TIMEOUT_MS })
|
|
33
|
+
);
|
|
34
|
+
const unsafeApi = client.getUnsafeApi();
|
|
35
|
+
return {
|
|
36
|
+
client,
|
|
37
|
+
unsafeApi,
|
|
38
|
+
disconnect: () => {
|
|
39
|
+
try {
|
|
40
|
+
client.destroy();
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
connectPeopleClient
|
|
48
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SS58String, PolkadotSigner } from 'polkadot-api';
|
|
2
|
+
|
|
3
|
+
type ReproveAliasErrorKind = "NoStoredAlias" | "NotPaid" | "RingRootNotFound" | "RevisionNotAdvanced" | "AliasMismatch" | "NotARecognizedPerson" | "BadProof" | "DispatchError" | "RpcError" | "ClientError" | "Unknown";
|
|
4
|
+
declare class ReproveAliasError extends Error {
|
|
5
|
+
readonly kind: ReproveAliasErrorKind;
|
|
6
|
+
readonly dispatchError?: unknown;
|
|
7
|
+
constructor(message: string, options?: ErrorOptions & {
|
|
8
|
+
kind?: ReproveAliasErrorKind;
|
|
9
|
+
dispatchError?: unknown;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
type RingExponent = 9 | 10 | 14;
|
|
13
|
+
interface BuildRingProofInput {
|
|
14
|
+
ringExponent: RingExponent;
|
|
15
|
+
members: Uint8Array;
|
|
16
|
+
context: Uint8Array;
|
|
17
|
+
msg: Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
type BuildRingProof = (input: BuildRingProofInput) => Promise<{
|
|
20
|
+
proof: Uint8Array;
|
|
21
|
+
alias: Uint8Array;
|
|
22
|
+
}>;
|
|
23
|
+
interface ReproveAliasProgress {
|
|
24
|
+
onBroadcasted?: () => void;
|
|
25
|
+
onBestBlock?: (blockHash: string) => void;
|
|
26
|
+
}
|
|
27
|
+
interface ReproveAliasParams {
|
|
28
|
+
peopleUnsafeApi: unknown;
|
|
29
|
+
ahUnsafeApi: unknown;
|
|
30
|
+
account: SS58String;
|
|
31
|
+
memberKey: Uint8Array;
|
|
32
|
+
signCall: PolkadotSigner;
|
|
33
|
+
buildRingProof: BuildRingProof;
|
|
34
|
+
progress?: ReproveAliasProgress;
|
|
35
|
+
}
|
|
36
|
+
interface ReproveAliasResult {
|
|
37
|
+
blockHash: string;
|
|
38
|
+
oldRevision: number;
|
|
39
|
+
newRevision: number;
|
|
40
|
+
}
|
|
41
|
+
declare const reproveAliasToAccount: ({ peopleUnsafeApi, ahUnsafeApi, account, memberKey, signCall, buildRingProof, progress, }: ReproveAliasParams) => Promise<ReproveAliasResult>;
|
|
42
|
+
|
|
43
|
+
export { type BuildRingProof, type BuildRingProofInput, ReproveAliasError, type ReproveAliasErrorKind, type ReproveAliasParams, type ReproveAliasProgress, type ReproveAliasResult, type RingExponent, reproveAliasToAccount };
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PAID_PROOF_TAG,
|
|
3
|
+
PEOPLE_MEMBER_IDENTIFIER_HEX,
|
|
4
|
+
PROOF_BYTES
|
|
5
|
+
} from "../chunk-T7EEVWNU.js";
|
|
6
|
+
import {
|
|
7
|
+
blake2_256,
|
|
8
|
+
bytesToHex,
|
|
9
|
+
concatBytes,
|
|
10
|
+
encodeMembers,
|
|
11
|
+
hexToBytes
|
|
12
|
+
} from "../chunk-ZYVGHDMU.js";
|
|
13
|
+
|
|
14
|
+
// src/personhood/reprove.ts
|
|
15
|
+
import { getSs58AddressInfo } from "polkadot-api";
|
|
16
|
+
var ReproveAliasError = class extends Error {
|
|
17
|
+
kind;
|
|
18
|
+
dispatchError;
|
|
19
|
+
constructor(message, options = {}) {
|
|
20
|
+
super(message, options);
|
|
21
|
+
this.name = "ReproveAliasError";
|
|
22
|
+
this.kind = options.kind ?? "Unknown";
|
|
23
|
+
this.dispatchError = options.dispatchError;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var reproveAliasToAccount = async ({
|
|
27
|
+
peopleUnsafeApi,
|
|
28
|
+
ahUnsafeApi,
|
|
29
|
+
account,
|
|
30
|
+
memberKey,
|
|
31
|
+
signCall,
|
|
32
|
+
buildRingProof,
|
|
33
|
+
progress
|
|
34
|
+
}) => {
|
|
35
|
+
const people = peopleUnsafeApi;
|
|
36
|
+
const ah = ahUnsafeApi;
|
|
37
|
+
if (memberKey.length !== 32) {
|
|
38
|
+
throw new ReproveAliasError("memberKey must be 32 bytes", {
|
|
39
|
+
kind: "ClientError"
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const stored = await ah.query.AliasAccounts.AccountToAlias.getValue(
|
|
43
|
+
account,
|
|
44
|
+
{ at: "best" }
|
|
45
|
+
);
|
|
46
|
+
if (!stored) {
|
|
47
|
+
throw new ReproveAliasError(
|
|
48
|
+
"no AccountToAlias row for this account \u2014 bind first",
|
|
49
|
+
{ kind: "NoStoredAlias" }
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (!stored.paid) {
|
|
53
|
+
throw new ReproveAliasError(
|
|
54
|
+
"AccountToAlias row is not paid \u2014 reprove_alias_account is only for paid aliases",
|
|
55
|
+
{ kind: "NotPaid" }
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
const contextBytes = hexToBytes(stored.ca.context);
|
|
59
|
+
const storedRevision = stored.revision;
|
|
60
|
+
const storedRing = stored.ring;
|
|
61
|
+
const storedAliasHex = stored.ca.alias.toLowerCase();
|
|
62
|
+
const position = await people.query.Members.Members.getValue(
|
|
63
|
+
PEOPLE_MEMBER_IDENTIFIER_HEX,
|
|
64
|
+
bytesToHex(memberKey),
|
|
65
|
+
{ at: "best" }
|
|
66
|
+
);
|
|
67
|
+
if (!position || position.type !== "Included") {
|
|
68
|
+
throw new ReproveAliasError(
|
|
69
|
+
`member position is '${position?.type ?? "absent"}', expected 'Included'`,
|
|
70
|
+
{ kind: "NotARecognizedPerson" }
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
const ringIndex = position.value.ring_index;
|
|
74
|
+
const allEntries = await people.query.Members.RingKeys.getEntries({
|
|
75
|
+
at: "best"
|
|
76
|
+
});
|
|
77
|
+
const pages = [];
|
|
78
|
+
const identHex = PEOPLE_MEMBER_IDENTIFIER_HEX.toLowerCase();
|
|
79
|
+
for (const entry of allEntries) {
|
|
80
|
+
if (entry.keyArgs[0].toLowerCase() !== identHex) continue;
|
|
81
|
+
if (Number(entry.keyArgs[1]) !== ringIndex) continue;
|
|
82
|
+
pages.push([Number(entry.keyArgs[2]), [...entry.value]]);
|
|
83
|
+
}
|
|
84
|
+
pages.sort((a, b) => a[0] - b[0]);
|
|
85
|
+
const ringKeys = pages.flatMap(([, ks]) => ks);
|
|
86
|
+
if (ringKeys.length === 0) {
|
|
87
|
+
throw new ReproveAliasError("ring has no members on People", {
|
|
88
|
+
kind: "ClientError"
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
const membersBytes = encodeMembers(ringKeys.map((k) => hexToBytes(k)));
|
|
92
|
+
const ringExp = await ah.constants.AliasAccounts.PeopleRingExponent();
|
|
93
|
+
const ringExponent = ringExp.type === "R2e9" ? 9 : ringExp.type === "R2e10" ? 10 : 14;
|
|
94
|
+
const ringRoots = await ah.query.MembersSubscriber.RingRoots.getValue(
|
|
95
|
+
stored.collection,
|
|
96
|
+
ringIndex,
|
|
97
|
+
{ at: "best" }
|
|
98
|
+
);
|
|
99
|
+
if (!ringRoots || ringRoots.length === 0) {
|
|
100
|
+
throw new ReproveAliasError(
|
|
101
|
+
"AH has no RingRoots for this (collection, ring_index)",
|
|
102
|
+
{ kind: "RingRootNotFound" }
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
const latest = ringRoots[ringRoots.length - 1];
|
|
106
|
+
const newRevision = latest.revision;
|
|
107
|
+
if (newRevision <= storedRevision && ringIndex === storedRing) {
|
|
108
|
+
throw new ReproveAliasError(
|
|
109
|
+
`latest revision ${newRevision} is not strictly greater than stored ${storedRevision} on the same ring`,
|
|
110
|
+
{ kind: "RevisionNotAdvanced" }
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const ss58Info = getSs58AddressInfo(account);
|
|
114
|
+
if (!ss58Info.isValid) {
|
|
115
|
+
throw new ReproveAliasError(`invalid SS58: ${account}`, {
|
|
116
|
+
kind: "ClientError"
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const paidMsg = blake2_256(concatBytes(PAID_PROOF_TAG, ss58Info.publicKey));
|
|
120
|
+
const { proof, alias } = await buildRingProof({
|
|
121
|
+
ringExponent,
|
|
122
|
+
members: membersBytes,
|
|
123
|
+
context: contextBytes,
|
|
124
|
+
msg: paidMsg
|
|
125
|
+
});
|
|
126
|
+
if (proof.length !== PROOF_BYTES) {
|
|
127
|
+
throw new ReproveAliasError(
|
|
128
|
+
`ring proof must be ${PROOF_BYTES} bytes, got ${proof.length}`,
|
|
129
|
+
{ kind: "ClientError" }
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
if (bytesToHex(alias).toLowerCase() !== storedAliasHex) {
|
|
133
|
+
throw new ReproveAliasError(
|
|
134
|
+
`regenerated alias ${bytesToHex(alias)} differs from stored ${storedAliasHex} \u2014 would fail ReproveMismatch`,
|
|
135
|
+
{ kind: "AliasMismatch" }
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
const tx = ah.tx.AliasAccounts.reprove_alias_account({
|
|
139
|
+
proof: bytesToHex(proof),
|
|
140
|
+
ring_index: ringIndex,
|
|
141
|
+
ring_revision: newRevision
|
|
142
|
+
});
|
|
143
|
+
const blockHash = await new Promise((resolve, reject) => {
|
|
144
|
+
let settled = false;
|
|
145
|
+
const fail = (err) => {
|
|
146
|
+
if (settled) return;
|
|
147
|
+
settled = true;
|
|
148
|
+
reject(err);
|
|
149
|
+
};
|
|
150
|
+
const succeed = (h) => {
|
|
151
|
+
if (settled) return;
|
|
152
|
+
settled = true;
|
|
153
|
+
resolve(h);
|
|
154
|
+
};
|
|
155
|
+
tx.signSubmitAndWatch(signCall).subscribe({
|
|
156
|
+
next: (event) => {
|
|
157
|
+
if (settled) return;
|
|
158
|
+
const ev = event;
|
|
159
|
+
if (ev.type === "broadcasted") {
|
|
160
|
+
progress?.onBroadcasted?.();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (ev.type === "txBestBlocksState" && ev.found) {
|
|
164
|
+
if (ev.ok === false) {
|
|
165
|
+
fail(
|
|
166
|
+
new ReproveAliasError(
|
|
167
|
+
"reprove_alias_account dispatched but failed in-block",
|
|
168
|
+
{
|
|
169
|
+
kind: narrowDispatchError(ev.dispatchError),
|
|
170
|
+
dispatchError: ev.dispatchError
|
|
171
|
+
}
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (ev.block) progress?.onBestBlock?.(ev.block.hash);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (ev.type === "finalized") {
|
|
180
|
+
if (ev.ok === false) {
|
|
181
|
+
fail(
|
|
182
|
+
new ReproveAliasError(
|
|
183
|
+
"reprove_alias_account failed at finalization",
|
|
184
|
+
{
|
|
185
|
+
kind: narrowDispatchError(ev.dispatchError),
|
|
186
|
+
dispatchError: ev.dispatchError
|
|
187
|
+
}
|
|
188
|
+
)
|
|
189
|
+
);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (ev.block) succeed(ev.block.hash);
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
error: (err) => {
|
|
196
|
+
fail(
|
|
197
|
+
err instanceof ReproveAliasError ? err : new ReproveAliasError(
|
|
198
|
+
err instanceof Error ? `RPC rejected extrinsic: ${err.message}` : "RPC error during submitAndWatch",
|
|
199
|
+
{ cause: err, kind: "RpcError" }
|
|
200
|
+
)
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
return { blockHash, oldRevision: storedRevision, newRevision };
|
|
206
|
+
};
|
|
207
|
+
var narrowDispatchError = (dispatchError) => {
|
|
208
|
+
if (typeof dispatchError === "object" && dispatchError !== null && "type" in dispatchError) {
|
|
209
|
+
const d = dispatchError;
|
|
210
|
+
if (d.type === "Module" && typeof d.value === "object" && d.value !== null) {
|
|
211
|
+
const v = d.value;
|
|
212
|
+
if (v.type === "AliasAccounts") {
|
|
213
|
+
if (v.value?.type === "BadProof") return "BadProof";
|
|
214
|
+
if (v.value?.type === "ReproveMismatch") return "AliasMismatch";
|
|
215
|
+
if (v.value?.type === "AliasAccountAlreadySet")
|
|
216
|
+
return "RevisionNotAdvanced";
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return "DispatchError";
|
|
221
|
+
};
|
|
222
|
+
export {
|
|
223
|
+
ReproveAliasError,
|
|
224
|
+
reproveAliasToAccount
|
|
225
|
+
};
|
package/dist/pool.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { PolkadotSigner } from 'polkadot-api';
|
|
2
|
+
|
|
3
|
+
declare function formatPasBalance(plancks: bigint): string;
|
|
4
|
+
interface PoolAccount {
|
|
5
|
+
index: number;
|
|
6
|
+
path: string;
|
|
7
|
+
publicKey: Uint8Array;
|
|
8
|
+
signer: PolkadotSigner;
|
|
9
|
+
address: string;
|
|
10
|
+
}
|
|
11
|
+
interface PoolAuthorization extends PoolAccount {
|
|
12
|
+
transactions: bigint;
|
|
13
|
+
bytes: bigint;
|
|
14
|
+
expiration: number;
|
|
15
|
+
}
|
|
16
|
+
declare function derivePoolAccounts(poolSize?: number, mnemonic?: string): PoolAccount[];
|
|
17
|
+
interface AuthorizationCheck {
|
|
18
|
+
needs?: AuthorizationNeeds;
|
|
19
|
+
bulletinAuthorizeV2?: boolean;
|
|
20
|
+
}
|
|
21
|
+
declare function isAuthorizationSufficient(auth: any, currentBlock: number, check?: AuthorizationCheck): boolean;
|
|
22
|
+
interface SelectionResult {
|
|
23
|
+
account: PoolAuthorization;
|
|
24
|
+
eligibleCount: number;
|
|
25
|
+
}
|
|
26
|
+
declare function selectAccount(authorizations: PoolAuthorization[], random?: () => number, currentBlock?: number): SelectionResult | null;
|
|
27
|
+
declare function fetchPoolAuthorizations(api: any, accounts: PoolAccount[]): Promise<PoolAuthorization[]>;
|
|
28
|
+
interface AuthorizationNeeds {
|
|
29
|
+
txs: bigint;
|
|
30
|
+
bytes: bigint;
|
|
31
|
+
}
|
|
32
|
+
declare function computeTopUpTarget(current: {
|
|
33
|
+
transactions: bigint;
|
|
34
|
+
bytes: bigint;
|
|
35
|
+
}, needs: AuthorizationNeeds): {
|
|
36
|
+
transactions: bigint;
|
|
37
|
+
bytes: bigint;
|
|
38
|
+
} | null;
|
|
39
|
+
type TxRetryDecision = "retry" | "abort";
|
|
40
|
+
declare function classifyAliceTxError(err: unknown): TxRetryDecision;
|
|
41
|
+
declare function isTestnetSpecName(specName: string | undefined | null): boolean;
|
|
42
|
+
declare function detectTestnet(api: any): Promise<boolean>;
|
|
43
|
+
declare function _resetTestnetCacheForTests(): void;
|
|
44
|
+
declare function ensureAuthorized(api: any, address: string, label?: string, bulletinAuthorizeV2?: boolean, needs?: AuthorizationNeeds): Promise<void>;
|
|
45
|
+
declare function topUpBy(api: any, address: string, needs: AuthorizationNeeds, label?: string, bulletinAuthorizeV2?: boolean): Promise<void>;
|
|
46
|
+
interface BootstrapOptions {
|
|
47
|
+
bulletinAuthorizeV2?: boolean;
|
|
48
|
+
}
|
|
49
|
+
declare function bootstrapPool(bulletinRpc: string, poolSize?: number, mnemonic?: string, opts?: BootstrapOptions): Promise<void>;
|
|
50
|
+
|
|
51
|
+
export { type AuthorizationCheck, type AuthorizationNeeds, type BootstrapOptions, type PoolAccount, type PoolAuthorization, type SelectionResult, type TxRetryDecision, _resetTestnetCacheForTests, bootstrapPool, classifyAliceTxError, computeTopUpTarget, derivePoolAccounts, detectTestnet, ensureAuthorized, fetchPoolAuthorizations, formatPasBalance, isAuthorizationSufficient, isTestnetSpecName, selectAccount, topUpBy };
|
package/dist/pool.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
_resetTestnetCacheForTests,
|
|
3
|
+
bootstrapPool,
|
|
4
|
+
classifyAliceTxError,
|
|
5
|
+
computeTopUpTarget,
|
|
6
|
+
derivePoolAccounts,
|
|
7
|
+
detectTestnet,
|
|
8
|
+
ensureAuthorized,
|
|
9
|
+
fetchPoolAuthorizations,
|
|
10
|
+
formatPasBalance,
|
|
11
|
+
isAuthorizationSufficient,
|
|
12
|
+
isTestnetSpecName,
|
|
13
|
+
selectAccount,
|
|
14
|
+
topUpBy
|
|
15
|
+
} from "./chunk-QMYW3D6E.js";
|
|
16
|
+
export {
|
|
17
|
+
_resetTestnetCacheForTests,
|
|
18
|
+
bootstrapPool,
|
|
19
|
+
classifyAliceTxError,
|
|
20
|
+
computeTopUpTarget,
|
|
21
|
+
derivePoolAccounts,
|
|
22
|
+
detectTestnet,
|
|
23
|
+
ensureAuthorized,
|
|
24
|
+
fetchPoolAuthorizations,
|
|
25
|
+
formatPasBalance,
|
|
26
|
+
isAuthorizationSufficient,
|
|
27
|
+
isTestnetSpecName,
|
|
28
|
+
selectAccount,
|
|
29
|
+
topUpBy
|
|
30
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
declare const VERSION: string;
|
|
2
|
+
type RunStatus = "running" | "succeeded" | "failed" | "crashed";
|
|
3
|
+
interface RunState {
|
|
4
|
+
status: RunStatus;
|
|
5
|
+
pid: number;
|
|
6
|
+
startedAt: number;
|
|
7
|
+
endedAt?: number;
|
|
8
|
+
toolVersion: string;
|
|
9
|
+
argv: string[];
|
|
10
|
+
lastPeakRssMb: number | null;
|
|
11
|
+
lastStage: string | null;
|
|
12
|
+
reason?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function resolveStateDir(): string;
|
|
15
|
+
declare function stateFilePath(): string;
|
|
16
|
+
declare function loadRunState(): RunState | null;
|
|
17
|
+
declare function writeRunState(patch: Partial<RunState>): void;
|
|
18
|
+
declare function shouldSkipStaleWarning(prev: RunState): boolean;
|
|
19
|
+
declare function probablyOomRssMb(override?: number): number;
|
|
20
|
+
declare function shouldShowOomHint(prev: RunState): boolean;
|
|
21
|
+
|
|
22
|
+
export { type RunState, type RunStatus, VERSION, loadRunState, probablyOomRssMb, resolveStateDir, shouldShowOomHint, shouldSkipStaleWarning, stateFilePath, writeRunState };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VERSION,
|
|
3
|
+
loadRunState,
|
|
4
|
+
probablyOomRssMb,
|
|
5
|
+
resolveStateDir,
|
|
6
|
+
shouldShowOomHint,
|
|
7
|
+
shouldSkipStaleWarning,
|
|
8
|
+
stateFilePath,
|
|
9
|
+
writeRunState
|
|
10
|
+
} from "./chunk-KJH2T5TQ.js";
|
|
11
|
+
export {
|
|
12
|
+
VERSION,
|
|
13
|
+
loadRunState,
|
|
14
|
+
probablyOomRssMb,
|
|
15
|
+
resolveStateDir,
|
|
16
|
+
shouldShowOomHint,
|
|
17
|
+
shouldSkipStaleWarning,
|
|
18
|
+
stateFilePath,
|
|
19
|
+
writeRunState
|
|
20
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as _sentry_node from '@sentry/node';
|
|
2
|
+
import { DeployContextForReport } from './memory-report.js';
|
|
3
|
+
import 'node:v8';
|
|
4
|
+
|
|
5
|
+
declare const VERSION: string;
|
|
6
|
+
type SentryModule = typeof _sentry_node | null;
|
|
7
|
+
interface InternalContextSignals {
|
|
8
|
+
githubRepository?: string;
|
|
9
|
+
runnerName?: string;
|
|
10
|
+
gitRemote?: string;
|
|
11
|
+
hostApp?: string;
|
|
12
|
+
}
|
|
13
|
+
declare function isInternalContextFromSignals(signals: InternalContextSignals): boolean;
|
|
14
|
+
declare function isInternalContext(): boolean;
|
|
15
|
+
declare function scrubPaths(msg: string): string;
|
|
16
|
+
declare function truncateAddress(ss58: string | undefined): string | undefined;
|
|
17
|
+
declare function sanitizeBranch(name: string | undefined): string | undefined;
|
|
18
|
+
declare function sanitizeRepo(slug: string | undefined): string | undefined;
|
|
19
|
+
declare function setRunStateActive(v: boolean): void;
|
|
20
|
+
declare function markRelaunchOomHintShown(): void;
|
|
21
|
+
declare function closeTelemetry(timeoutMs: number): Promise<void>;
|
|
22
|
+
declare function initTelemetry(): void;
|
|
23
|
+
declare function resolveRepo(domain: string): string;
|
|
24
|
+
declare function resolveRunner(): string;
|
|
25
|
+
declare function resolveRunnerType(): string;
|
|
26
|
+
declare function getDeployAttributes(domain: string): Record<string, string | number | boolean | undefined>;
|
|
27
|
+
declare function isExpectedError(msg: string): boolean;
|
|
28
|
+
type DeployErrorCategory = 'user' | 'environment' | 'internal' | 'unknown';
|
|
29
|
+
declare function classifyDeployError(msg: string): DeployErrorCategory;
|
|
30
|
+
declare function classifySadReason(message: string): string;
|
|
31
|
+
declare function computeDeployOutcome(errorCategory: DeployErrorCategory | null, isSad: boolean, sadReason: string): string;
|
|
32
|
+
type DeployErrorKind = 'contract-revert' | 'chain-timeout' | 'nonce-stale' | 'connection' | 'naming.pop_required' | 'naming.already_owned' | 'naming.subdomain_orphan' | 'verify.contenthash_mismatch' | 'verify.dagpb_not_finalised' | 'network.recovery_exhausted' | 'chain.api_timeout' | 'tool.invariant' | 'unknown';
|
|
33
|
+
declare function classifyErrorKind(msg: string): DeployErrorKind;
|
|
34
|
+
declare function sanitizeErrorMessage(msg: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Classify an error message's *shape* (length, presence of certain patterns)
|
|
37
|
+
* without excerpting content. The result is a comma-joined list of tags;
|
|
38
|
+
* future analysis of scrubbed events will use this to identify which content
|
|
39
|
+
* shape triggered Sentry's PII scrubber, so we can build a real sanitiser.
|
|
40
|
+
*/
|
|
41
|
+
declare function analyseErrorPattern(msg: string): string;
|
|
42
|
+
declare function withSpan<T>(op: string, description: string, attributes: Record<string, string | number | boolean | undefined>, fn: () => T | Promise<T>): Promise<T>;
|
|
43
|
+
declare function sampleMemory(stage: string): void;
|
|
44
|
+
declare function withDeploySpan<T>(domain: string, fn: () => T | Promise<T>): Promise<T>;
|
|
45
|
+
declare function setDeployReportContext(patch: Partial<DeployContextForReport> & {
|
|
46
|
+
outputDir?: string;
|
|
47
|
+
}): void;
|
|
48
|
+
declare function setDeployAttribute(key: string, value: string | number | boolean): void;
|
|
49
|
+
declare function __setDeployRootSpanForTest(span: any | null): void;
|
|
50
|
+
declare function __setSentryForTest(stub: any): SentryModule;
|
|
51
|
+
declare function getCurrentSentryTraceId(): string | undefined;
|
|
52
|
+
declare function setDeploySentryTag(key: string, value: string): void;
|
|
53
|
+
declare function captureWarning(message: string, context?: Record<string, unknown>): void;
|
|
54
|
+
declare function flush(): Promise<void>;
|
|
55
|
+
|
|
56
|
+
export { type DeployErrorCategory, type DeployErrorKind, type InternalContextSignals, VERSION, __setDeployRootSpanForTest, __setSentryForTest, analyseErrorPattern, captureWarning, classifyDeployError, classifyErrorKind, classifySadReason, closeTelemetry, computeDeployOutcome, flush, getCurrentSentryTraceId, getDeployAttributes, initTelemetry, isExpectedError, isInternalContext, isInternalContextFromSignals, markRelaunchOomHintShown, resolveRepo, resolveRunner, resolveRunnerType, sampleMemory, sanitizeBranch, sanitizeErrorMessage, sanitizeRepo, scrubPaths, setDeployAttribute, setDeployReportContext, setDeploySentryTag, setRunStateActive, truncateAddress, withDeploySpan, withSpan };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VERSION,
|
|
3
|
+
__setDeployRootSpanForTest,
|
|
4
|
+
__setSentryForTest,
|
|
5
|
+
analyseErrorPattern,
|
|
6
|
+
captureWarning,
|
|
7
|
+
classifyDeployError,
|
|
8
|
+
classifyErrorKind,
|
|
9
|
+
classifySadReason,
|
|
10
|
+
closeTelemetry,
|
|
11
|
+
computeDeployOutcome,
|
|
12
|
+
flush,
|
|
13
|
+
getCurrentSentryTraceId,
|
|
14
|
+
getDeployAttributes,
|
|
15
|
+
initTelemetry,
|
|
16
|
+
isExpectedError,
|
|
17
|
+
isInternalContext,
|
|
18
|
+
isInternalContextFromSignals,
|
|
19
|
+
markRelaunchOomHintShown,
|
|
20
|
+
resolveRepo,
|
|
21
|
+
resolveRunner,
|
|
22
|
+
resolveRunnerType,
|
|
23
|
+
sampleMemory,
|
|
24
|
+
sanitizeBranch,
|
|
25
|
+
sanitizeErrorMessage,
|
|
26
|
+
sanitizeRepo,
|
|
27
|
+
scrubPaths,
|
|
28
|
+
setDeployAttribute,
|
|
29
|
+
setDeployReportContext,
|
|
30
|
+
setDeploySentryTag,
|
|
31
|
+
setRunStateActive,
|
|
32
|
+
truncateAddress,
|
|
33
|
+
withDeploySpan,
|
|
34
|
+
withSpan
|
|
35
|
+
} from "./chunk-MFTODIIT.js";
|
|
36
|
+
import "./chunk-KJH2T5TQ.js";
|
|
37
|
+
export {
|
|
38
|
+
VERSION,
|
|
39
|
+
__setDeployRootSpanForTest,
|
|
40
|
+
__setSentryForTest,
|
|
41
|
+
analyseErrorPattern,
|
|
42
|
+
captureWarning,
|
|
43
|
+
classifyDeployError,
|
|
44
|
+
classifyErrorKind,
|
|
45
|
+
classifySadReason,
|
|
46
|
+
closeTelemetry,
|
|
47
|
+
computeDeployOutcome,
|
|
48
|
+
flush,
|
|
49
|
+
getCurrentSentryTraceId,
|
|
50
|
+
getDeployAttributes,
|
|
51
|
+
initTelemetry,
|
|
52
|
+
isExpectedError,
|
|
53
|
+
isInternalContext,
|
|
54
|
+
isInternalContextFromSignals,
|
|
55
|
+
markRelaunchOomHintShown,
|
|
56
|
+
resolveRepo,
|
|
57
|
+
resolveRunner,
|
|
58
|
+
resolveRunnerType,
|
|
59
|
+
sampleMemory,
|
|
60
|
+
sanitizeBranch,
|
|
61
|
+
sanitizeErrorMessage,
|
|
62
|
+
sanitizeRepo,
|
|
63
|
+
scrubPaths,
|
|
64
|
+
setDeployAttribute,
|
|
65
|
+
setDeployReportContext,
|
|
66
|
+
setDeploySentryTag,
|
|
67
|
+
setRunStateActive,
|
|
68
|
+
truncateAddress,
|
|
69
|
+
withDeploySpan,
|
|
70
|
+
withSpan
|
|
71
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
|
|
3
|
+
interface VersionInfo {
|
|
4
|
+
latest: string;
|
|
5
|
+
minimumFromRegistry: string | null;
|
|
6
|
+
minimumFromKillSwitch: string | null;
|
|
7
|
+
killSwitchMessage: string | null;
|
|
8
|
+
}
|
|
9
|
+
declare function checkNodeVersion(enginesNode: string, currentVersion: string): string | null;
|
|
10
|
+
declare function compareSemver(a: string, b: string): number;
|
|
11
|
+
declare function isPreReleaseVersion(version: string): boolean;
|
|
12
|
+
declare function preReleaseWarning(version: string): string | null;
|
|
13
|
+
declare function fetchVersionInfo(): Promise<VersionInfo | null>;
|
|
14
|
+
declare function handlePreflightVersionCheck(info: VersionInfo | null): "abort" | "nudge" | "ok";
|
|
15
|
+
declare function isInternalUser(cwd?: string): boolean;
|
|
16
|
+
declare function isInteractive(): boolean;
|
|
17
|
+
declare function promptYesNo(question: string, input?: Readable): Promise<boolean>;
|
|
18
|
+
declare function classifyErrorArea(msg: string): string | null;
|
|
19
|
+
type VersionVerdict = {
|
|
20
|
+
action: "forced_update";
|
|
21
|
+
currentVersion: string;
|
|
22
|
+
minimumVersion: string;
|
|
23
|
+
message: string | null;
|
|
24
|
+
} | {
|
|
25
|
+
action: "suggest_update";
|
|
26
|
+
currentVersion: string;
|
|
27
|
+
latestVersion: string;
|
|
28
|
+
internal: boolean;
|
|
29
|
+
} | {
|
|
30
|
+
action: "bug_report";
|
|
31
|
+
internal: boolean;
|
|
32
|
+
} | {
|
|
33
|
+
action: "none";
|
|
34
|
+
};
|
|
35
|
+
declare function assessVersion(currentVersion: string, info: VersionInfo, internal: boolean): VersionVerdict;
|
|
36
|
+
declare function handleFailedDeploy(error: Error): Promise<void>;
|
|
37
|
+
|
|
38
|
+
export { type VersionVerdict, assessVersion, checkNodeVersion, classifyErrorArea, compareSemver, fetchVersionInfo, handleFailedDeploy, handlePreflightVersionCheck, isInteractive, isInternalUser, isPreReleaseVersion, preReleaseWarning, promptYesNo };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assessVersion,
|
|
3
|
+
checkNodeVersion,
|
|
4
|
+
classifyErrorArea,
|
|
5
|
+
compareSemver,
|
|
6
|
+
fetchVersionInfo,
|
|
7
|
+
handleFailedDeploy,
|
|
8
|
+
handlePreflightVersionCheck,
|
|
9
|
+
isInteractive,
|
|
10
|
+
isInternalUser,
|
|
11
|
+
isPreReleaseVersion,
|
|
12
|
+
preReleaseWarning,
|
|
13
|
+
promptYesNo
|
|
14
|
+
} from "./chunk-43HLT335.js";
|
|
15
|
+
import "./chunk-MFTODIIT.js";
|
|
16
|
+
import "./chunk-KJH2T5TQ.js";
|
|
17
|
+
export {
|
|
18
|
+
assessVersion,
|
|
19
|
+
checkNodeVersion,
|
|
20
|
+
classifyErrorArea,
|
|
21
|
+
compareSemver,
|
|
22
|
+
fetchVersionInfo,
|
|
23
|
+
handleFailedDeploy,
|
|
24
|
+
handlePreflightVersionCheck,
|
|
25
|
+
isInteractive,
|
|
26
|
+
isInternalUser,
|
|
27
|
+
isPreReleaseVersion,
|
|
28
|
+
preReleaseWarning,
|
|
29
|
+
promptYesNo
|
|
30
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# bulletin-bootstrap
|
|
2
|
+
|
|
3
|
+
`bulletin-bootstrap` is the operator CLI for initializing Bulletin pool accounts. It is separate from `bulletin-deploy` on purpose: deploys are the normal user path, bootstrap is an admin/setup operation.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bulletin-bootstrap
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Options:
|
|
12
|
+
|
|
13
|
+
| Flag | What it does |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `--rpc wss://...` | Override the Bulletin RPC endpoint. Also readable from `BULLETIN_RPC`. |
|
|
16
|
+
| `--pool-size N` | Number of derived pool accounts to initialize. Default: `10`. |
|
|
17
|
+
| `--mnemonic "..."` | Root mnemonic used to derive the pool accounts. Also readable from `BULLETIN_POOL_MNEMONIC`, then `MNEMONIC`. |
|
|
18
|
+
| `--version` | Print the CLI version. |
|
|
19
|
+
| `--help` | Show help. |
|
|
20
|
+
|
|
21
|
+
## What it does
|
|
22
|
+
|
|
23
|
+
The command derives the pool account set and initializes the on-chain authorization state needed for Bulletin uploads.
|
|
24
|
+
|
|
25
|
+
Use it when:
|
|
26
|
+
|
|
27
|
+
- you are bringing up a fresh pool on a testnet
|
|
28
|
+
- the shared uploader pool has not been authorized yet
|
|
29
|
+
- you want to pre-initialize a non-default pool mnemonic
|
|
30
|
+
|
|
31
|
+
Do not use it as part of routine deploys. Normal deploys go through `bulletin-deploy`.
|
|
32
|
+
|
|
33
|
+
## Examples
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Default testnet pool against the default RPC
|
|
37
|
+
bulletin-bootstrap
|
|
38
|
+
|
|
39
|
+
# Different RPC and larger pool
|
|
40
|
+
bulletin-bootstrap --rpc wss://custom-bulletin.example.com --pool-size 20
|
|
41
|
+
|
|
42
|
+
# Explicit pool mnemonic
|
|
43
|
+
bulletin-bootstrap --mnemonic "..."
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Related Docs
|
|
47
|
+
|
|
48
|
+
- [Main README](../README.md)
|
|
49
|
+
- [E2E test setup](./e2e-bootstrap.md)
|