@parity/product-deploy 0.10.0-rc.0 → 0.10.0-rc.2
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 +124 -0
- package/README.md +73 -6
- package/assets/environments.json +41 -0
- package/bin/bulletin-deploy +11 -16
- package/dist/allocations-CEPeZr6T.d.ts +111 -0
- package/dist/auth/index.d.ts +3 -2
- package/dist/auth/index.js +5 -1
- package/dist/auth/vendor/index.d.ts +3 -2
- package/dist/auth/vendor/index.js +5 -1
- package/dist/auth/vendor/ui/index.d.ts +2 -1
- package/dist/auth-CA_YKtM2.d.ts +128 -0
- package/dist/auth-config.d.ts +13 -8
- package/dist/auth-config.js +4 -4
- package/dist/bug-report.js +4 -4
- package/dist/{chunk-2BTYPNYW.js → chunk-4D6STP5G.js} +10 -2
- package/dist/{chunk-DHY2ZXVZ.js → chunk-5OKB3TEB.js} +8 -1
- package/dist/{chunk-DY7RVMM5.js → chunk-C74YSAWC.js} +64 -20
- package/dist/{chunk-MI5B3UCM.js → chunk-EHQPRWGC.js} +1 -1
- package/dist/{chunk-VR3LF62E.js → chunk-I7UEBFP5.js} +38 -12
- package/dist/{chunk-HUT626G6.js → chunk-LYWIW6WU.js} +1 -1
- package/dist/{chunk-GL3U7K2B.js → chunk-QRKI6MMK.js} +41 -0
- package/dist/{chunk-PKQOUCPD.js → chunk-SXWFDMFT.js} +5 -5
- package/dist/{chunk-GJTVPP7E.js → chunk-UJJQME5K.js} +1 -1
- package/dist/{chunk-G676QAN4.js → chunk-V5VD5CIC.js} +2 -2
- package/dist/{chunk-ZJCTG7HF.js → chunk-WM5R4O33.js} +4 -3
- package/dist/{chunk-Q3RIJ7PU.js → chunk-XX6LNB74.js} +3 -3
- package/dist/chunk-probe.js +3 -3
- package/dist/commands/login.d.ts +42 -6
- package/dist/commands/login.js +86 -34
- package/dist/commands/logout.d.ts +2 -1
- package/dist/commands/logout.js +6 -6
- package/dist/commands/transfer.js +5 -4
- package/dist/commands/whoami.d.ts +2 -1
- package/dist/commands/whoami.js +4 -4
- package/dist/deploy-actors.d.ts +3 -2
- package/dist/deploy-actors.js +6 -5
- package/dist/deploy.d.ts +13 -1
- package/dist/deploy.js +15 -10
- package/dist/dotns.d.ts +10 -4
- package/dist/dotns.js +5 -4
- package/dist/environments.js +1 -1
- package/dist/index.js +12 -11
- package/dist/manifest/publish.js +12 -11
- package/dist/memory-report.js +2 -2
- package/dist/merkle.js +11 -10
- package/dist/personhood/bootstrap.js +6 -6
- package/dist/personhood/people-client.js +5 -4
- package/dist/run-state.js +1 -1
- package/dist/{signer-vR6KKC7V.d.ts → signer-Duup0hgQ.d.ts} +1 -1
- package/dist/sss-allowance-cache.js +5 -5
- package/dist/storage-signer.js +11 -10
- package/dist/telemetry.d.ts +17 -1
- package/dist/telemetry.js +4 -2
- package/dist/version-check.js +3 -3
- package/docs/bootstrap.md +1 -1
- package/docs/e2e-bootstrap.md +34 -12
- package/docs/telemetry.md +10 -11
- package/docs/testing.md +2 -0
- package/package.json +4 -3
- package/dist/auth-C-Pel0AT.d.ts +0 -235
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { TerminalAdapter, UserSession } from '@parity/product-sdk-terminal';
|
|
2
|
+
import { PolkadotSigner } from 'polkadot-api';
|
|
3
|
+
import { A as AllocatableResource, O as OnExistingAllowancePolicy, a as AllocationOutcome } from './allocations-CEPeZr6T.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Per-product configuration injected into `createAuthClient`. Lifting the
|
|
7
|
+
* sign-in glue out of playground-cli (issue #411) means the env-specific
|
|
8
|
+
* constants playground hard-coded in its `config.ts` (DAPP_ID, product id,
|
|
9
|
+
* metadata URL, People-chain endpoints) become consumer-supplied so the same
|
|
10
|
+
* package serves `playground` and `dot` (and future products) unchanged.
|
|
11
|
+
*/
|
|
12
|
+
interface AuthConfig {
|
|
13
|
+
/** The dApp identity string. Scopes the on-disk session namespace
|
|
14
|
+
* (`~/.polkadot-apps/${dappId}_*`) and the SSO pairing — each product
|
|
15
|
+
* gets its own, independently-revocable session. */
|
|
16
|
+
dappId: string;
|
|
17
|
+
/** Product id used to derive the product account (`/product/{productId}/{index}`). */
|
|
18
|
+
productId: string;
|
|
19
|
+
/** Derivation index of the product account (0 = default). */
|
|
20
|
+
derivationIndex: number;
|
|
21
|
+
/** Wallet-facing app name shown on the Sign-In screen (sent inline at pairing). */
|
|
22
|
+
hostName: string;
|
|
23
|
+
/** Host app version sent inline at pairing. */
|
|
24
|
+
hostVersion: string;
|
|
25
|
+
/** People-parachain RPC endpoints the terminal adapter connects to. */
|
|
26
|
+
peopleEndpoints: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The three addresses we surface from a paired session.
|
|
31
|
+
*
|
|
32
|
+
* - `rootAddress` — SS58 of `session.rootAccountId`, the `rootUserAccountId`
|
|
33
|
+
* the mobile app sent over the SSO handshake (bare-mnemonic sr25519 root on
|
|
34
|
+
* current mobile builds). Keyed by `Resources.Consumers` on the People
|
|
35
|
+
* parachain, so it's the right input for `lookupUsername`.
|
|
36
|
+
* - `productAddress` — SS58 of the product account derived via
|
|
37
|
+
* `product/{productId}/{index}` from `rootAccountId`. This is what actually
|
|
38
|
+
* signs on-chain transactions from the CLI.
|
|
39
|
+
* - `productH160` — the same product pubkey as a 20-byte EVM address (Revive /
|
|
40
|
+
* contracts view). Derived from the SAME pubkey as `productAddress`.
|
|
41
|
+
*/
|
|
42
|
+
interface SessionAddresses {
|
|
43
|
+
rootAddress: string;
|
|
44
|
+
productAddress: string;
|
|
45
|
+
productH160: `0x${string}`;
|
|
46
|
+
}
|
|
47
|
+
type ConnectResult = {
|
|
48
|
+
kind: "existing";
|
|
49
|
+
address: string;
|
|
50
|
+
addresses: SessionAddresses;
|
|
51
|
+
} | {
|
|
52
|
+
kind: "qr";
|
|
53
|
+
qrCode: string;
|
|
54
|
+
login: LoginHandle;
|
|
55
|
+
};
|
|
56
|
+
type LoginStatus = {
|
|
57
|
+
step: "waiting";
|
|
58
|
+
} | {
|
|
59
|
+
step: "paired";
|
|
60
|
+
} | {
|
|
61
|
+
step: "pending";
|
|
62
|
+
stage: string;
|
|
63
|
+
} | {
|
|
64
|
+
step: "success";
|
|
65
|
+
address: string;
|
|
66
|
+
addresses: SessionAddresses;
|
|
67
|
+
} | {
|
|
68
|
+
step: "error";
|
|
69
|
+
message: string;
|
|
70
|
+
};
|
|
71
|
+
interface LoginHandle {
|
|
72
|
+
adapter: TerminalAdapter;
|
|
73
|
+
/** The authenticate() promise — already running since connect(). */
|
|
74
|
+
authPromise: ReturnType<TerminalAdapter["sso"]["authenticate"]>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A session signer bundle — the signer plus an explicit `destroy()` that tears
|
|
78
|
+
* down the long-lived adapter the signer depends on. Callers MUST invoke
|
|
79
|
+
* `destroy()` once done — the WebSocket keeps the event loop alive.
|
|
80
|
+
*
|
|
81
|
+
* `adapter` is exposed so callers that need to send a host request (e.g.
|
|
82
|
+
* `requestResourceAllocation`) can pass it without creating a second WebSocket.
|
|
83
|
+
*/
|
|
84
|
+
interface SessionHandle {
|
|
85
|
+
address: string;
|
|
86
|
+
addresses: SessionAddresses;
|
|
87
|
+
signer: PolkadotSigner;
|
|
88
|
+
userSession: UserSession;
|
|
89
|
+
adapter: TerminalAdapter;
|
|
90
|
+
destroy(): void;
|
|
91
|
+
}
|
|
92
|
+
type LogoutStatus = {
|
|
93
|
+
step: "disconnecting";
|
|
94
|
+
address: string;
|
|
95
|
+
} | {
|
|
96
|
+
step: "success";
|
|
97
|
+
address: string;
|
|
98
|
+
} | {
|
|
99
|
+
step: "partial";
|
|
100
|
+
address: string;
|
|
101
|
+
reason: string;
|
|
102
|
+
} | {
|
|
103
|
+
step: "error";
|
|
104
|
+
message: string;
|
|
105
|
+
};
|
|
106
|
+
interface LogoutHandle {
|
|
107
|
+
adapter: TerminalAdapter;
|
|
108
|
+
address: string;
|
|
109
|
+
session: UserSession;
|
|
110
|
+
}
|
|
111
|
+
/** The product-bound auth surface returned by `createAuthClient`. */
|
|
112
|
+
interface AuthClient {
|
|
113
|
+
connect(): Promise<ConnectResult>;
|
|
114
|
+
waitForLogin(handle: LoginHandle, onStatus: (status: LoginStatus) => void): Promise<SessionHandle | null>;
|
|
115
|
+
getSessionSigner(): Promise<SessionHandle | null>;
|
|
116
|
+
findSession(): Promise<LogoutHandle | null>;
|
|
117
|
+
waitForLogout(handle: LogoutHandle, onStatus: (status: LogoutStatus) => void): Promise<void>;
|
|
118
|
+
requestAllocation(session: UserSession, adapter: TerminalAdapter, resources?: AllocatableResource[], onExisting?: OnExistingAllowancePolicy): Promise<AllocationOutcome[]>;
|
|
119
|
+
clearLocalAppStorage(dir?: string): Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Build an auth client bound to a product's `AuthConfig`. All adapter creation,
|
|
123
|
+
* address derivation, and session-storage scoping read from `config`, so the
|
|
124
|
+
* same code serves any product.
|
|
125
|
+
*/
|
|
126
|
+
declare function createAuthClient(config: AuthConfig): AuthClient;
|
|
127
|
+
|
|
128
|
+
export { type AuthClient as A, type ConnectResult as C, type LoginHandle as L, type SessionAddresses as S, type AuthConfig as a, type LoginStatus as b, type LogoutHandle as c, type LogoutStatus as d, type SessionHandle as e, createAuthClient as f };
|
package/dist/auth-config.d.ts
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as AuthConfig, A as AuthClient } from './auth-CA_YKtM2.js';
|
|
2
2
|
import { EnvironmentsDoc } from './environments.js';
|
|
3
3
|
import '@parity/product-sdk-terminal';
|
|
4
4
|
import 'polkadot-api';
|
|
5
|
+
import './allocations-CEPeZr6T.js';
|
|
5
6
|
|
|
6
|
-
/** dApp identity
|
|
7
|
-
*
|
|
8
|
-
declare const DOT_DAPP_ID = "
|
|
7
|
+
/** dApp identity: scopes the SSO session namespace + terminal allowance cache on disk
|
|
8
|
+
* and the wallet pairing product. Aligned to the app's dedicated id "polkadot-app-deploy". */
|
|
9
|
+
declare const DOT_DAPP_ID = "polkadot-app-deploy";
|
|
9
10
|
/** Product id used for product-account derivation (`/product/{productId}/{index}`).
|
|
10
|
-
*
|
|
11
|
-
|
|
11
|
+
* UNIFIED with DOT_DAPP_ID (#885): the wallet funds PGAS to product/{appId}/{index},
|
|
12
|
+
* so deriving the signer/owner under the same id lands the account where PGAS sits —
|
|
13
|
+
* one account is owner + AH signer + PGAS-funded. Requires a fresh re-pairing so the
|
|
14
|
+
* Bulletin/statement allowance is also claimed under this id (verify the wallet serves
|
|
15
|
+
* "polkadot-app-deploy"; that's the open mobile-side question). */
|
|
16
|
+
declare const DOT_PRODUCT_ID = "polkadot-app-deploy";
|
|
12
17
|
/** Derivation index (0 = default product account). */
|
|
13
18
|
declare const DOT_DERIVATION_INDEX = 0;
|
|
14
|
-
/** Wallet-facing app name shown on the Sign-In screen
|
|
15
|
-
declare const DOT_HOST_NAME = "
|
|
19
|
+
/** Wallet-facing app name shown on the Sign-In screen. Aligned to the unified identity. */
|
|
20
|
+
declare const DOT_HOST_NAME = "polkadot-app-deploy";
|
|
16
21
|
/**
|
|
17
22
|
* Shown when a persisted session file exists but the V2 codec cannot decode it —
|
|
18
23
|
* typically a v0.7 SCALE blob that is structurally incompatible with the V2 wire format.
|
package/dist/auth-config.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
getPeopleChainEndpoints,
|
|
10
10
|
hasPersistedSession,
|
|
11
11
|
resolveBulletinEndpoints
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-SXWFDMFT.js";
|
|
13
|
+
import "./chunk-4D6STP5G.js";
|
|
14
|
+
import "./chunk-WM5R4O33.js";
|
|
15
|
+
import "./chunk-QRKI6MMK.js";
|
|
16
16
|
import "./chunk-ZOC4GITL.js";
|
|
17
17
|
export {
|
|
18
18
|
DOT_DAPP_ID,
|
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-V5VD5CIC.js";
|
|
13
|
+
import "./chunk-EHQPRWGC.js";
|
|
14
|
+
import "./chunk-4D6STP5G.js";
|
|
15
|
+
import "./chunk-WM5R4O33.js";
|
|
16
16
|
export {
|
|
17
17
|
buildCliFlagsSummary,
|
|
18
18
|
buildLabels,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
package_default,
|
|
3
3
|
writeRunState
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WM5R4O33.js";
|
|
5
5
|
|
|
6
6
|
// src/memory-report.ts
|
|
7
7
|
import * as fs2 from "fs";
|
|
@@ -46,7 +46,14 @@ function isInternalContext() {
|
|
|
46
46
|
}
|
|
47
47
|
var OPT_OUT = process.env.BULLETIN_DEPLOY_TELEMETRY === "0" || process.env.BULLETIN_DEPLOY_TELEMETRY === "off";
|
|
48
48
|
var OPT_IN = process.env.BULLETIN_DEPLOY_TELEMETRY === "1";
|
|
49
|
-
var
|
|
49
|
+
var DO_NOT_TRACK = !!process.env.DO_NOT_TRACK && process.env.DO_NOT_TRACK !== "0" && process.env.DO_NOT_TRACK !== "";
|
|
50
|
+
function isTelemetryDisabled(s) {
|
|
51
|
+
if (s.optOut) return true;
|
|
52
|
+
if (s.optIn) return false;
|
|
53
|
+
if (s.doNotTrack) return true;
|
|
54
|
+
return !s.internalContext;
|
|
55
|
+
}
|
|
56
|
+
var DISABLED = isTelemetryDisabled({ optIn: OPT_IN, optOut: OPT_OUT, doNotTrack: DO_NOT_TRACK, internalContext: isInternalContext() });
|
|
50
57
|
var CONVENTIONAL_BRANCH_PREFIXES = /* @__PURE__ */ new Set([
|
|
51
58
|
"fix",
|
|
52
59
|
"feat",
|
|
@@ -719,6 +726,7 @@ export {
|
|
|
719
726
|
VERSION,
|
|
720
727
|
isInternalContextFromSignals,
|
|
721
728
|
isInternalContext,
|
|
729
|
+
isTelemetryDisabled,
|
|
722
730
|
scrubPaths,
|
|
723
731
|
truncateAddress,
|
|
724
732
|
sanitizeBranch,
|
|
@@ -96,7 +96,8 @@ function createSessionSigner(session, ref) {
|
|
|
96
96
|
|
|
97
97
|
// src/auth/vendor/allocations.ts
|
|
98
98
|
import {
|
|
99
|
-
requestResourceAllocation as terminalRequestResourceAllocation
|
|
99
|
+
requestResourceAllocation as terminalRequestResourceAllocation,
|
|
100
|
+
createSlotAccountSigner as terminalCreateSlotAccountSigner
|
|
100
101
|
} from "@parity/product-sdk-terminal/host";
|
|
101
102
|
var DEFAULT_RESOURCES = [
|
|
102
103
|
{ tag: "BulletInAllowance", value: void 0 },
|
|
@@ -104,6 +105,7 @@ var DEFAULT_RESOURCES = [
|
|
|
104
105
|
// derivation index 0 = the default product account.
|
|
105
106
|
{ tag: "SmartContractAllowance", value: 0 }
|
|
106
107
|
];
|
|
108
|
+
var BULLETIN_RESOURCE = { tag: "BulletInAllowance", value: void 0 };
|
|
107
109
|
async function requestResourceAllocation(session, adapter, resources = DEFAULT_RESOURCES, onExisting = "Ignore") {
|
|
108
110
|
const outcomes = await terminalRequestResourceAllocation(session, adapter, resources, { onExisting });
|
|
109
111
|
return outcomes;
|
|
@@ -121,6 +123,9 @@ function summarizeOutcomes(outcomes, resources) {
|
|
|
121
123
|
});
|
|
122
124
|
return { granted, rejected, unavailable };
|
|
123
125
|
}
|
|
126
|
+
async function createSlotAccountSigner(adapter, resource) {
|
|
127
|
+
return terminalCreateSlotAccountSigner(adapter, resource);
|
|
128
|
+
}
|
|
124
129
|
|
|
125
130
|
// src/auth/vendor/auth.ts
|
|
126
131
|
var QR_TIMEOUT_MS = 6e4;
|
|
@@ -409,8 +414,10 @@ export {
|
|
|
409
414
|
deriveProductPublicKey,
|
|
410
415
|
createSessionSigner,
|
|
411
416
|
DEFAULT_RESOURCES,
|
|
417
|
+
BULLETIN_RESOURCE,
|
|
412
418
|
requestResourceAllocation,
|
|
413
419
|
summarizeOutcomes,
|
|
420
|
+
createSlotAccountSigner,
|
|
414
421
|
createAuthClient,
|
|
415
422
|
SignerNotAvailableError,
|
|
416
423
|
parseDevAccountName,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
preflightSssAllowance
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UJJQME5K.js";
|
|
4
4
|
import {
|
|
5
5
|
statementSigningAccount
|
|
6
6
|
} from "./chunk-GRPLHUYC.js";
|
|
@@ -34,13 +34,13 @@ import {
|
|
|
34
34
|
STALE_SESSION_MESSAGE,
|
|
35
35
|
getPeopleChainEndpoints,
|
|
36
36
|
hasPersistedSession
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-SXWFDMFT.js";
|
|
38
38
|
import {
|
|
39
39
|
setDeployContext
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-V5VD5CIC.js";
|
|
41
41
|
import {
|
|
42
42
|
probeChunks
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-LYWIW6WU.js";
|
|
44
44
|
import {
|
|
45
45
|
packSection
|
|
46
46
|
} from "./chunk-C2TS5MER.js";
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
parseDomainName,
|
|
54
54
|
popStatusName,
|
|
55
55
|
verifyNonceAdvanced
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-I7UEBFP5.js";
|
|
57
57
|
import {
|
|
58
58
|
derivePoolAccounts,
|
|
59
59
|
detectTestnet,
|
|
@@ -75,13 +75,13 @@ import {
|
|
|
75
75
|
truncateAddress,
|
|
76
76
|
withDeploySpan,
|
|
77
77
|
withSpan
|
|
78
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-4D6STP5G.js";
|
|
79
79
|
import {
|
|
80
80
|
DEFAULT_ENV_ID,
|
|
81
81
|
getPopSelfServeConfig,
|
|
82
82
|
loadEnvironments,
|
|
83
83
|
resolveEndpoints
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-QRKI6MMK.js";
|
|
85
85
|
import {
|
|
86
86
|
NonRetryableError
|
|
87
87
|
} from "./chunk-ZOC4GITL.js";
|
|
@@ -412,6 +412,11 @@ function isConnectionError(error) {
|
|
|
412
412
|
const msg = error?.message || String(error);
|
|
413
413
|
return /heartbeat timeout|WS halt|Unable to connect|ChainHead disjointed/i.test(msg);
|
|
414
414
|
}
|
|
415
|
+
function isBenignTeardownError(error) {
|
|
416
|
+
if (isConnectionError(error)) return true;
|
|
417
|
+
const s = error instanceof Error ? `${error.name ?? ""} ${error.message ?? ""}` : String(error);
|
|
418
|
+
return /DestroyedError|Client destroyed/.test(s);
|
|
419
|
+
}
|
|
415
420
|
var CID_CONFIG = { version: 1, codec: 85, hashCode: 18, hashLength: 32 };
|
|
416
421
|
function deriveRootSigner(mnemonic, path3 = "") {
|
|
417
422
|
const entropy = mnemonicToEntropy(mnemonic);
|
|
@@ -585,6 +590,9 @@ function chooseSignerInput(opts) {
|
|
|
585
590
|
if (opts.hasSession) return "resolve";
|
|
586
591
|
return "pool";
|
|
587
592
|
}
|
|
593
|
+
function isPhoneSignerActive(options) {
|
|
594
|
+
return !!(options.signer && options.signerAddress && !options.transferTo);
|
|
595
|
+
}
|
|
588
596
|
function formatStorageSignerLine(slotAddress, failReason) {
|
|
589
597
|
if (slotAddress) return ` Storage signer: allowance slot ${slotAddress}`;
|
|
590
598
|
return ` Storage signer: pool fallback (${failReason ?? "no session"})`;
|
|
@@ -1948,6 +1956,7 @@ async function deploy(content, domainName = null, options = {}) {
|
|
|
1948
1956
|
BULLETIN_ENDPOINTS = userRpc ? [userRpc, ...envBulletin.filter((e) => e !== userRpc)] : envBulletin;
|
|
1949
1957
|
_deployRpcFailedOver = false;
|
|
1950
1958
|
POOL_SIZE = options.poolSize ?? parseInt(process.env.BULLETIN_POOL_SIZE ?? String(DEFAULT_POOL_SIZE), 10);
|
|
1959
|
+
const parsed = domainName ? parseDomainName(domainName) : null;
|
|
1951
1960
|
let sessionCleanup;
|
|
1952
1961
|
const hasSession = hasPersistedSession();
|
|
1953
1962
|
const signerChoice = chooseSignerInput({
|
|
@@ -2037,8 +2046,8 @@ async function deploy(content, domainName = null, options = {}) {
|
|
|
2037
2046
|
}
|
|
2038
2047
|
initTelemetry();
|
|
2039
2048
|
const randomSuffix = Math.floor(Math.random() * 100).toString().padStart(2, "0");
|
|
2040
|
-
const parsed = domainName ? parseDomainName(domainName) : null;
|
|
2041
2049
|
const name = parsed ? parsed.label : `test-domain-${Date.now().toString(36)}${randomSuffix}`;
|
|
2050
|
+
const phoneSignerActive = isPhoneSignerActive(options);
|
|
2042
2051
|
try {
|
|
2043
2052
|
return await withDeploySpan(name, async () => {
|
|
2044
2053
|
const deployTag = options.tag ?? process.env.DEPLOY_TAG;
|
|
@@ -2130,13 +2139,13 @@ async function deploy(content, domainName = null, options = {}) {
|
|
|
2130
2139
|
setDeployAttribute("deploy.dotns.preflight.action", dotnsPreflight.plannedAction);
|
|
2131
2140
|
setDeployAttribute("deploy.dotns.preflight.classification", popStatusName(dotnsPreflight.classification.status));
|
|
2132
2141
|
}
|
|
2133
|
-
const alreadyOwned = dotnsPreflight.plannedAction === "already-owned-by-us";
|
|
2142
|
+
const alreadyOwned = dotnsPreflight.plannedAction === "already-owned-by-us" || dotnsPreflight.plannedAction === "already-owned-by-recipient";
|
|
2134
2143
|
const reqSuffix = alreadyOwned ? " (already owned, requirement not enforced)" : "";
|
|
2135
2144
|
console.log(` DotNS: ${name}.dot requires ${popStatusName(dotnsPreflight.classification.status)}${reqSuffix}`);
|
|
2136
2145
|
if (dotnsPreflight.canProceed) {
|
|
2137
2146
|
const fromName = popStatusName(dotnsPreflight.userStatus);
|
|
2138
2147
|
console.log(` Your PoP: ${fromName}`);
|
|
2139
|
-
console.log(` Domain: ${
|
|
2148
|
+
console.log(` Domain: ${alreadyOwned ? "owned by you" : "available"}`);
|
|
2140
2149
|
}
|
|
2141
2150
|
if (!dotnsPreflight.canProceed) {
|
|
2142
2151
|
throw new NonRetryableError(
|
|
@@ -2144,17 +2153,17 @@ async function deploy(content, domainName = null, options = {}) {
|
|
|
2144
2153
|
);
|
|
2145
2154
|
}
|
|
2146
2155
|
}
|
|
2147
|
-
if (
|
|
2156
|
+
if (phoneSignerActive) {
|
|
2148
2157
|
const steps = computePhoneSigningSteps(dotnsPreflight, preflightPublishNeeded);
|
|
2149
2158
|
if (steps.length === 1) {
|
|
2150
2159
|
console.log(`
|
|
2151
|
-
|
|
2160
|
+
Have your phone ready \u2014 1 signature needed (${steps[0].toLowerCase()})`);
|
|
2152
2161
|
} else if (steps.length > 1) {
|
|
2153
2162
|
const display = steps.flatMap(
|
|
2154
2163
|
(s, i) => s === "Register" && steps[i - 1] === "Commitment" ? ["(wait)", s] : [s]
|
|
2155
2164
|
);
|
|
2156
2165
|
console.log(`
|
|
2157
|
-
|
|
2166
|
+
Have your phone ready \u2014 ${steps.length} signatures needed`);
|
|
2158
2167
|
console.log(` ${display.map((s) => s.toLowerCase()).join(" \xB7 ")}`);
|
|
2159
2168
|
}
|
|
2160
2169
|
}
|
|
@@ -2341,15 +2350,48 @@ async function deploy(content, domainName = null, options = {}) {
|
|
|
2341
2350
|
console.log("DotNS");
|
|
2342
2351
|
console.log("=".repeat(60));
|
|
2343
2352
|
await withSpan("deploy.dotns", "2. dotns", { "deploy.domain": name, "deploy.subdomain": String(parsed?.isSubdomain ?? false) }, async () => {
|
|
2353
|
+
if (dotnsPreflight?.plannedAction === "already-owned-by-recipient") {
|
|
2354
|
+
console.log(` You already own ${name}.dot \u2014 updating its content needs your signature.`);
|
|
2355
|
+
const { getAuthClient } = await import("./auth-config.js");
|
|
2356
|
+
const { resolveSigner } = await import("./auth/index.js");
|
|
2357
|
+
const authClient = await getAuthClient(envId);
|
|
2358
|
+
const owner = await resolveSigner(authClient, {});
|
|
2359
|
+
const ownerDotns = new DotNS();
|
|
2360
|
+
const prevSessionCleanup = sessionCleanup;
|
|
2361
|
+
sessionCleanup = () => {
|
|
2362
|
+
try {
|
|
2363
|
+
prevSessionCleanup?.();
|
|
2364
|
+
} catch {
|
|
2365
|
+
}
|
|
2366
|
+
try {
|
|
2367
|
+
ownerDotns.disconnect();
|
|
2368
|
+
} catch {
|
|
2369
|
+
}
|
|
2370
|
+
try {
|
|
2371
|
+
owner.destroy();
|
|
2372
|
+
} catch {
|
|
2373
|
+
}
|
|
2374
|
+
};
|
|
2375
|
+
await ownerDotns.connect({
|
|
2376
|
+
...resolveDotnsConnectOptions({ ...options, signer: owner.signer, signerAddress: owner.address }, envAssetHub, envAutoAccountMapping, envContracts, envNativeToEthRatio, envId, envPopSelfServe, envRegisterStorageDeposit),
|
|
2377
|
+
onPhoneSigningRequired: (label) => console.log(`
|
|
2378
|
+
Check your phone \u2192 ${label}`)
|
|
2379
|
+
});
|
|
2380
|
+
const willPublish = !!(options.publish && parsed && preflightPublishNeeded !== false);
|
|
2381
|
+
console.log(willPublish ? `
|
|
2382
|
+
Have your phone ready \u2014 2 signatures needed (link content \xB7 publish)` : `
|
|
2383
|
+
Have your phone ready \u2014 1 signature needed (link content)`);
|
|
2384
|
+
const contenthashHex2 = `0x${encodeContenthash(cid)}`;
|
|
2385
|
+
await ownerDotns.setContenthash(name, contenthashHex2, { feeAsset: "pgas" });
|
|
2386
|
+
if (willPublish) await publish(ownerDotns, parsed, options.failOnPublishError);
|
|
2387
|
+
return;
|
|
2388
|
+
}
|
|
2344
2389
|
const dotns = new DotNS();
|
|
2345
2390
|
await dotns.connect({
|
|
2346
2391
|
...resolveDotnsConnectOptions(options, envAssetHub, envAutoAccountMapping, envContracts, envNativeToEthRatio, envId, envPopSelfServe, envRegisterStorageDeposit),
|
|
2347
|
-
//
|
|
2348
|
-
//
|
|
2349
|
-
|
|
2350
|
-
// suppress the reminder there or it falsely tells the user to check
|
|
2351
|
-
// their phone for a tx signed locally.
|
|
2352
|
-
...options.signer && options.signerAddress && !options.transferTo ? { onPhoneSigningRequired: (label) => console.log(`
|
|
2392
|
+
// Per-step "check your phone" reminder — only for a phone-backed signer
|
|
2393
|
+
// (see phoneSignerActive); a transfer-mode local worker signs locally.
|
|
2394
|
+
...phoneSignerActive ? { onPhoneSigningRequired: (label) => console.log(`
|
|
2353
2395
|
Check your phone \u2192 ${label}`) } : {}
|
|
2354
2396
|
});
|
|
2355
2397
|
if (parsed?.isSubdomain) {
|
|
@@ -2455,7 +2497,7 @@ async function deploy(content, domainName = null, options = {}) {
|
|
|
2455
2497
|
console.log("\n" + "=".repeat(60));
|
|
2456
2498
|
console.log("DEPLOYMENT COMPLETE!");
|
|
2457
2499
|
console.log("=".repeat(60));
|
|
2458
|
-
console.log("\
|
|
2500
|
+
console.log("\nPolkadot Triangle");
|
|
2459
2501
|
console.log(` - Polkadot Desktop: ${name}.dot`);
|
|
2460
2502
|
console.log(` - Polkadot Browser: ${browserUrlFor(name, envId)}`);
|
|
2461
2503
|
console.log("\n" + "=".repeat(60) + "\n");
|
|
@@ -2895,6 +2937,7 @@ export {
|
|
|
2895
2937
|
WS_HEARTBEAT_TIMEOUT_MS,
|
|
2896
2938
|
retryBudgetExhausted,
|
|
2897
2939
|
isConnectionError,
|
|
2940
|
+
isBenignTeardownError,
|
|
2898
2941
|
deriveRootSigner,
|
|
2899
2942
|
createCID,
|
|
2900
2943
|
encodeContenthash,
|
|
@@ -2907,6 +2950,7 @@ export {
|
|
|
2907
2950
|
encryptContent,
|
|
2908
2951
|
__selectStorageProviderModeForTest,
|
|
2909
2952
|
chooseSignerInput,
|
|
2953
|
+
isPhoneSignerActive,
|
|
2910
2954
|
formatStorageSignerLine,
|
|
2911
2955
|
storeFile,
|
|
2912
2956
|
__assignDenseNoncesForTest,
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PGAS_ASSET_LOCATION
|
|
3
|
+
} from "./chunk-SI2ZUOYD.js";
|
|
1
4
|
import {
|
|
2
5
|
isTestnetSpecName
|
|
3
6
|
} from "./chunk-4PVJ2JBZ.js";
|
|
@@ -8,10 +11,10 @@ import {
|
|
|
8
11
|
setDeploySentryTag,
|
|
9
12
|
truncateAddress,
|
|
10
13
|
withSpan
|
|
11
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-4D6STP5G.js";
|
|
12
15
|
import {
|
|
13
16
|
validateContractAddresses
|
|
14
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-QRKI6MMK.js";
|
|
15
18
|
import {
|
|
16
19
|
NonRetryableError
|
|
17
20
|
} from "./chunk-ZOC4GITL.js";
|
|
@@ -85,12 +88,15 @@ function resolveNativeTokenSymbol(envId) {
|
|
|
85
88
|
if (envId.includes("rococo")) return "ROC";
|
|
86
89
|
return "PAS";
|
|
87
90
|
}
|
|
91
|
+
function isOwnedAction(plannedAction) {
|
|
92
|
+
return plannedAction === "already-owned-by-us" || plannedAction === "already-owned-by-recipient";
|
|
93
|
+
}
|
|
88
94
|
function feeFloorFor(plannedAction, storageDeposit = MINIMUM_REGISTER_STORAGE_DEPOSIT, rentPriceNative = 0n, transferFeeNative = 0n) {
|
|
89
|
-
if (plannedAction
|
|
95
|
+
if (isOwnedAction(plannedAction)) return FEE_FLOOR_OWNED + transferFeeNative;
|
|
90
96
|
return FEE_FLOOR_REGISTER + storageDeposit + rentPriceNative + transferFeeNative;
|
|
91
97
|
}
|
|
92
98
|
function topUpTargetFor(plannedAction, storageDeposit = MINIMUM_REGISTER_STORAGE_DEPOSIT, rentPriceNative = 0n, transferFeeNative = 0n) {
|
|
93
|
-
if (plannedAction
|
|
99
|
+
if (isOwnedAction(plannedAction)) return TOP_UP_TARGET + transferFeeNative;
|
|
94
100
|
return TOP_UP_TARGET + storageDeposit + rentPriceNative + transferFeeNative;
|
|
95
101
|
}
|
|
96
102
|
var RPC_ENDPOINTS = [
|
|
@@ -359,6 +365,9 @@ function formatWeight(weight) {
|
|
|
359
365
|
return `ref_time=${weight.referenceTime.toString()} proof_size=${weight.proofSize.toString()}`;
|
|
360
366
|
}
|
|
361
367
|
var BARE_REVERT_DIAGNOSTIC_FUNCTIONS = /* @__PURE__ */ new Set(["register", "commit", "setContenthash", "setSubnodeOwner", "setResolver"]);
|
|
368
|
+
var PGAS_FEE_OPTIONS = {
|
|
369
|
+
customSignedExtensions: { ChargeAssetTxPayment: { value: { tip: 0n, asset_id: PGAS_ASSET_LOCATION } } }
|
|
370
|
+
};
|
|
362
371
|
function formatContractDryRunFailure(gasEstimate, context) {
|
|
363
372
|
const functionName = context.functionName ?? "unknown";
|
|
364
373
|
const contractName = dotnsContractName(context.contractAddress, context.contracts);
|
|
@@ -714,7 +723,7 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
|
|
|
714
723
|
};
|
|
715
724
|
deadlinePoller = setTimeout(poll, 6e3);
|
|
716
725
|
try {
|
|
717
|
-
sub = extrinsic.signSubmitAndWatch(signer, { mortality: { mortal: true, period: 256 } }).subscribe({
|
|
726
|
+
sub = extrinsic.signSubmitAndWatch(signer, { mortality: { mortal: true, period: 256 }, ...opts.feeAsset === "pgas" ? PGAS_FEE_OPTIONS : {} }).subscribe({
|
|
718
727
|
next: (event) => {
|
|
719
728
|
lastEventAt = Date.now();
|
|
720
729
|
lastEventType = event.type;
|
|
@@ -815,7 +824,7 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
|
|
|
815
824
|
storage_deposit_limit: storageDepositLimit
|
|
816
825
|
};
|
|
817
826
|
}
|
|
818
|
-
async submitTransaction(contractAddress, value, encodedData, signerSubstrateAddress, signer, statusCallback, { rpcs, useNoncePolling, functionName, args, contracts, verifyEffect }) {
|
|
827
|
+
async submitTransaction(contractAddress, value, encodedData, signerSubstrateAddress, signer, statusCallback, { rpcs, useNoncePolling, functionName, args, contracts, verifyEffect, feeAsset }) {
|
|
819
828
|
await this.ensureAccountMapped(signerSubstrateAddress, signer);
|
|
820
829
|
if (functionName === "register") {
|
|
821
830
|
try {
|
|
@@ -847,7 +856,7 @@ var ReviveClientWrapper = class _ReviveClientWrapper {
|
|
|
847
856
|
"chain.tx.submit",
|
|
848
857
|
`sign+submit ${functionName ?? "Revive.call"}`,
|
|
849
858
|
{ "chain.function_name": functionName ?? "Revive.call", "chain.use_nonce_polling": Boolean(useNoncePolling) },
|
|
850
|
-
() => this.signAndSubmitWithRetry(buildExtrinsic, signer, statusCallback, "Revive.call", { nonceFallback, verifyEffect })
|
|
859
|
+
() => this.signAndSubmitWithRetry(buildExtrinsic, signer, statusCallback, "Revive.call", { nonceFallback, verifyEffect, feeAsset })
|
|
851
860
|
);
|
|
852
861
|
}
|
|
853
862
|
// Dry-runs each call individually, then wraps them in a single
|
|
@@ -1449,13 +1458,13 @@ var DotNS = class {
|
|
|
1449
1458
|
return decodeFunctionResult({ abi: contractAbi, functionName, data: rawData });
|
|
1450
1459
|
}
|
|
1451
1460
|
async contractTransaction(contractAddress, value, contractAbi, functionName, args = [], statusCallback = () => {
|
|
1452
|
-
}, { useNoncePolling, verifyEffect } = {}) {
|
|
1461
|
+
}, { useNoncePolling, verifyEffect, feeAsset } = {}) {
|
|
1453
1462
|
this.ensureConnected();
|
|
1454
1463
|
if (!this.clientWrapper) throw new Error("contractTransaction: polkadot-api client not available");
|
|
1455
1464
|
const encodedCallData = encodeFunctionData({ abi: contractAbi, functionName, args });
|
|
1456
1465
|
const rpcs = this.rpc ? [this.rpc, ...this.assetHubEndpoints.filter((ep) => ep !== this.rpc)] : this.assetHubEndpoints;
|
|
1457
1466
|
return await withTimeout(
|
|
1458
|
-
this.clientWrapper.submitTransaction(contractAddress, value, encodedCallData, this.substrateAddress, this.signer, statusCallback, { rpcs, useNoncePolling, functionName, args, contracts: this._contracts, verifyEffect }),
|
|
1467
|
+
this.clientWrapper.submitTransaction(contractAddress, value, encodedCallData, this.substrateAddress, this.signer, statusCallback, { rpcs, useNoncePolling, functionName, args, contracts: this._contracts, verifyEffect, feeAsset }),
|
|
1459
1468
|
OPERATION_TIMEOUT_MS,
|
|
1460
1469
|
functionName
|
|
1461
1470
|
);
|
|
@@ -1673,7 +1682,7 @@ var DotNS = class {
|
|
|
1673
1682
|
label
|
|
1674
1683
|
);
|
|
1675
1684
|
}
|
|
1676
|
-
async setContenthash(domainName, contenthashHex) {
|
|
1685
|
+
async setContenthash(domainName, contenthashHex, opts = {}) {
|
|
1677
1686
|
return withSpan("deploy.dotns.set-contenthash", "2b. set-contenthash", {}, async () => {
|
|
1678
1687
|
this.ensureConnected();
|
|
1679
1688
|
const node = namehash(`${domainName}.dot`);
|
|
@@ -1727,7 +1736,7 @@ var DotNS = class {
|
|
|
1727
1736
|
console.log(`
|
|
1728
1737
|
Linking content...`);
|
|
1729
1738
|
this._onPhoneSigningRequired?.("Link content");
|
|
1730
|
-
const txRes = await this.contractTransaction(this._contracts.DOTNS_CONTENT_RESOLVER, 0n, DOTNS_CONTENT_RESOLVER_ABI, "setContenthash", [node, contenthashHex], (s) => console.log(` ${s}`), { useNoncePolling: true, verifyEffect });
|
|
1739
|
+
const txRes = await this.contractTransaction(this._contracts.DOTNS_CONTENT_RESOLVER, 0n, DOTNS_CONTENT_RESOLVER_ABI, "setContenthash", [node, contenthashHex], (s) => console.log(` ${s}`), { useNoncePolling: true, verifyEffect, feeAsset: opts.feeAsset });
|
|
1731
1740
|
const finalOnChain = (await this.getContenthash(domainName) || "0x").toLowerCase();
|
|
1732
1741
|
if (finalOnChain !== expected) {
|
|
1733
1742
|
throw new Error(
|
|
@@ -2175,7 +2184,6 @@ var DotNS = class {
|
|
|
2175
2184
|
);
|
|
2176
2185
|
}
|
|
2177
2186
|
const priceWei = typeof priceRaw === "bigint" ? priceRaw : BigInt(priceRaw);
|
|
2178
|
-
console.log(` Required status: ${popStatusName(requiredStatus)}`);
|
|
2179
2187
|
console.log(` User status: ${popStatusName(userStatus)}`);
|
|
2180
2188
|
console.log(` Price: ${formatEther(priceWei)} PAS`);
|
|
2181
2189
|
return { priceWei, requiredStatus, userStatus, message };
|
|
@@ -2267,6 +2275,24 @@ var DotNS = class {
|
|
|
2267
2275
|
const ownerRaw = ownership.owner?.toLowerCase() ?? null;
|
|
2268
2276
|
const existingOwner = ownerRaw && ownerRaw !== zeroAddress ? ownerRaw : null;
|
|
2269
2277
|
const selfAddress = this.evmAddress.toLowerCase();
|
|
2278
|
+
if (transferRecipientH160 && existingOwner !== null && existingOwner === transferRecipientH160.toLowerCase()) {
|
|
2279
|
+
return {
|
|
2280
|
+
label: validated,
|
|
2281
|
+
classification,
|
|
2282
|
+
userStatus,
|
|
2283
|
+
trailingDigits,
|
|
2284
|
+
baselength,
|
|
2285
|
+
isAvailable: false,
|
|
2286
|
+
existingOwner,
|
|
2287
|
+
isBaseNameReserved: isReserved,
|
|
2288
|
+
reservationOwner,
|
|
2289
|
+
isTestnet,
|
|
2290
|
+
canProceed: true,
|
|
2291
|
+
plannedAction: "already-owned-by-recipient",
|
|
2292
|
+
needsPopUpgrade: false,
|
|
2293
|
+
signerFreeBalance
|
|
2294
|
+
};
|
|
2295
|
+
}
|
|
2270
2296
|
if (existingOwner !== null && existingOwner !== selfAddress) {
|
|
2271
2297
|
return {
|
|
2272
2298
|
label: validated,
|