@parity/product-sdk-terminal 0.0.0-dev.312.0 → 0.0.0-dev.454.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/README.md +75 -16
- package/dist/chunk-EORPX5XL.js +267 -0
- package/dist/chunk-EORPX5XL.js.map +1 -0
- package/dist/chunk-GHOFKVUG.js +8 -133
- package/dist/chunk-GHOFKVUG.js.map +1 -1
- package/dist/{host-C3KVvc1j.d.ts → host-_G9M0isV.d.ts} +36 -10
- package/dist/host.d.ts +1 -1
- package/dist/host.js +2 -14
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +162 -37
- package/dist/index.js +158 -872
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +24 -234
- package/dist/testing.js.map +1 -1
- package/package.json +9 -9
- package/dist/chunk-YS3GW2XW.js +0 -1508
- package/dist/chunk-YS3GW2XW.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,50 @@
|
|
|
1
|
-
import { T as TerminalAdapter } from './host-
|
|
2
|
-
export { A as AllocatableResource, a as ApAllocationOutcome, O as OnExistingAllowancePolicy, R as RequestResourceAllocationOptions, b as TerminalAdapterOptions, c as createTerminalAdapter, r as requestResourceAllocation, s as sendResourceAllocation } from './host-
|
|
1
|
+
import { T as TerminalAdapter } from './host-_G9M0isV.js';
|
|
2
|
+
export { A as AllocatableResource, a as ApAllocationOutcome, O as OnExistingAllowancePolicy, R as RequestResourceAllocationOptions, b as TerminalAdapterOptions, c as createTerminalAdapter, i as isBenignTeardownError, r as requestResourceAllocation, s as sendResourceAllocation } from './host-_G9M0isV.js';
|
|
3
3
|
import { UserSession } from '@novasamatech/host-papp';
|
|
4
|
-
export { AllowanceError, AllowanceErrorReason, AllowanceService, HostMetadata, PairingStatus, PappAdapter,
|
|
4
|
+
export { AllowanceError, AllowanceErrorReason, AllowanceService, HostMetadata, PairingStatus, PappAdapter, SS_STABLE_STAGE_ENDPOINTS, SigningPayloadRequest, SigningPayloadResponse, SigningRawRequest, StoredUserSession, UserSession } from '@novasamatech/host-papp';
|
|
5
5
|
import { PolkadotSigner } from 'polkadot-api';
|
|
6
6
|
export { AllowanceExpiredError, SignerError } from '@parity/product-sdk-signer/errors';
|
|
7
7
|
import { StatementProver } from '@novasamatech/statement-store';
|
|
8
8
|
import { StorageAdapter } from '@novasamatech/storage-adapter';
|
|
9
9
|
import 'neverthrow';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Statement store networks terminal can pair against, keyed as `BULLETIN_RPCS`
|
|
13
|
+
* in `@parity/product-sdk-host`, where `paseo` is Paseo Next v2.
|
|
14
|
+
*
|
|
15
|
+
* Both sides of a pairing must sit on the same people chain. The Polkadot app's
|
|
16
|
+
* nightly build uses `paseo`, which is why it is the default.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
declare const StatementStoreNetworks: {
|
|
20
|
+
paseo: string[];
|
|
21
|
+
previewnet: string[];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** Network keys with built-in endpoints in {@link StatementStoreNetworks}. */
|
|
25
|
+
type StatementStoreEnvironment = keyof typeof StatementStoreNetworks;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The product-subtree public key of `//product//{productId}` (RFC-0022).
|
|
29
|
+
*
|
|
30
|
+
* The request is consent-free and cacheable. The disk layer is what makes that
|
|
31
|
+
* worth having: without it every CLI command would need the phone reachable
|
|
32
|
+
* just to render a product address.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
interface ProductSubtreeOptions {
|
|
36
|
+
/** Names the cache file. Defaults to the productId. */
|
|
37
|
+
appId?: string;
|
|
38
|
+
storageDir?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Fetch the subtree public key for `productId`, reaching the wallet only on a
|
|
42
|
+
* cold cache.
|
|
43
|
+
*
|
|
44
|
+
* @throws Error when the wallet rejects the request or returns a malformed key.
|
|
45
|
+
*/
|
|
46
|
+
declare function getProductSubtreePublicKey(session: UserSession, productId: string, options?: ProductSubtreeOptions): Promise<Uint8Array>;
|
|
47
|
+
|
|
11
48
|
/**
|
|
12
49
|
* Create a PolkadotSigner from a QR-paired session.
|
|
13
50
|
*
|
|
@@ -37,10 +74,10 @@ import 'neverthrow';
|
|
|
37
74
|
* const [session] = adapter.sessions.sessions.read();
|
|
38
75
|
*
|
|
39
76
|
* // Default account — uses [adapter.appId, 0]:
|
|
40
|
-
* const signer = createSessionSigner(session, adapter);
|
|
77
|
+
* const signer = await createSessionSigner(session, adapter);
|
|
41
78
|
*
|
|
42
79
|
* // Non-default derivation index, or a different productId:
|
|
43
|
-
* const subSigner = createSessionSignerForAccount(session, {
|
|
80
|
+
* const subSigner = await createSessionSignerForAccount(session, {
|
|
44
81
|
* productId: "my-product",
|
|
45
82
|
* derivationIndex: 3,
|
|
46
83
|
* });
|
|
@@ -52,7 +89,7 @@ import 'neverthrow';
|
|
|
52
89
|
/**
|
|
53
90
|
* Identifies which sub-account of a paired session should sign.
|
|
54
91
|
*
|
|
55
|
-
* Mirrors the `host-papp` wire format `productAccountId: [productId,
|
|
92
|
+
* Mirrors the `host-papp` wire format `productAccountId: [productId, index]`:
|
|
56
93
|
* `productId` is the dotNS-style identifier for the requesting product (matches
|
|
57
94
|
* the adapter's `appId` in normal usage); `derivationIndex` is the BIP32-style
|
|
58
95
|
* child-key index, where `0` is the session's default account.
|
|
@@ -66,46 +103,41 @@ interface ProductAccountRef {
|
|
|
66
103
|
* The **product account's** sr25519 public key (32 bytes), as derived by the
|
|
67
104
|
* host for `[productId, derivationIndex]`.
|
|
68
105
|
*
|
|
69
|
-
* PAPI stamps this into the extrinsic's signer address and verifies
|
|
70
|
-
*
|
|
71
|
-
* wallet's selected/root account (`session.remoteAccount.accountId`). A
|
|
72
|
-
* mismatch produces an invalid signature.
|
|
106
|
+
* PAPI stamps this into the extrinsic's signer address and verifies against
|
|
107
|
+
* it, so a mismatch produces an invalid signature.
|
|
73
108
|
*
|
|
74
|
-
* When omitted, the signer
|
|
75
|
-
*
|
|
76
|
-
* for every product account. Supply it explicitly only to avoid the
|
|
77
|
-
* re-derivation or when you've already derived it elsewhere.
|
|
109
|
+
* When omitted, the signer fetches the subtree key and derives it. Supply it
|
|
110
|
+
* to skip that round trip.
|
|
78
111
|
*/
|
|
79
112
|
publicKey?: Uint8Array;
|
|
80
113
|
}
|
|
114
|
+
interface SessionSignerOptions extends ProductSubtreeOptions {
|
|
115
|
+
/**
|
|
116
|
+
* Extension version of the supplied signTx bytes. Does not change encoding.
|
|
117
|
+
*
|
|
118
|
+
* Defaults to the lowest pipeline version the chain metadata declares that
|
|
119
|
+
* holds every supplied extension, which is 0 on a chain with one pipeline.
|
|
120
|
+
*/
|
|
121
|
+
txExtVersion?: number;
|
|
122
|
+
}
|
|
81
123
|
declare const INCOMPLETE_SESSION_MESSAGE = "Stored login session is missing the root account public key. Run \"logout\" and then \"login\" to pair again.";
|
|
82
124
|
/**
|
|
83
|
-
* The
|
|
84
|
-
*
|
|
85
|
-
* parent key product accounts soft-derive from. host-papp's live `UserSession`
|
|
86
|
-
* doesn't surface it on the public type, so we read it structurally.
|
|
125
|
+
* The wallet's own root account key. Product accounts do **not** derive from it:
|
|
126
|
+
* RFC-0022 puts two hard junctions in between.
|
|
87
127
|
*
|
|
88
128
|
* @throws {@link INCOMPLETE_SESSION_MESSAGE} if the session predates the
|
|
89
|
-
* `rootAccountId` field
|
|
129
|
+
* `rootAccountId` field.
|
|
90
130
|
*/
|
|
91
131
|
declare function sessionRootPublicKey(session: UserSession): Uint8Array;
|
|
92
132
|
/**
|
|
93
|
-
*
|
|
94
|
-
* root account.
|
|
95
|
-
*
|
|
96
|
-
* This is the single source of truth for product-account math. The session
|
|
97
|
-
* signer uses it to stamp the correct signer address; consumers that need the
|
|
98
|
-
* product address *without* building a signer (e.g. a login-status display
|
|
99
|
-
* triple) call it directly so the displayed address can't desync from what the
|
|
100
|
-
* signer actually signs with.
|
|
133
|
+
* The product account's sr25519 public key for `ref`.
|
|
101
134
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* privately via `mnemonic + "/product/{productId}/{derivationIndex}"`.
|
|
135
|
+
* The one place product-account math happens, so a displayed address cannot
|
|
136
|
+
* desync from what the signer signs with.
|
|
105
137
|
*
|
|
106
|
-
* @throws
|
|
138
|
+
* @throws Error when the wallet is unreachable on a cold cache.
|
|
107
139
|
*/
|
|
108
|
-
declare function deriveProductPublicKey(session: UserSession, ref: ProductAccountRef): Uint8Array
|
|
140
|
+
declare function deriveProductPublicKey(session: UserSession, ref: ProductAccountRef, options?: ProductSubtreeOptions): Promise<Uint8Array>;
|
|
109
141
|
/**
|
|
110
142
|
* Create a `PolkadotSigner` backed by a QR-paired mobile wallet session,
|
|
111
143
|
* using the session's **default account** (`derivationIndex: 0`).
|
|
@@ -116,10 +148,10 @@ declare function deriveProductPublicKey(session: UserSession, ref: ProductAccoun
|
|
|
116
148
|
* @param adapter The {@link TerminalAdapter} that loaded the session. Its `appId`
|
|
117
149
|
* is used as the `productId` in the wire request.
|
|
118
150
|
* @param publicKey The product account's sr25519 public key for
|
|
119
|
-
* `[adapter.appId, 0]`. Optional — when omitted it's
|
|
120
|
-
*
|
|
151
|
+
* `[adapter.appId, 0]`. Optional — when omitted it's fetched and derived.
|
|
152
|
+
* See {@link ProductAccountRef.publicKey}.
|
|
121
153
|
*/
|
|
122
|
-
declare function createSessionSigner(session: UserSession, adapter: TerminalAdapter, publicKey?: Uint8Array): PolkadotSigner
|
|
154
|
+
declare function createSessionSigner(session: UserSession, adapter: TerminalAdapter, publicKey?: Uint8Array, options?: SessionSignerOptions): Promise<PolkadotSigner>;
|
|
123
155
|
/**
|
|
124
156
|
* Create a `PolkadotSigner` for a specific sub-account of a paired session.
|
|
125
157
|
*
|
|
@@ -130,7 +162,7 @@ declare function createSessionSigner(session: UserSession, adapter: TerminalAdap
|
|
|
130
162
|
* @param session The paired user session.
|
|
131
163
|
* @param ref The product account to sign as: `{ productId, derivationIndex }`.
|
|
132
164
|
*/
|
|
133
|
-
declare function createSessionSignerForAccount(session: UserSession, ref: ProductAccountRef): PolkadotSigner
|
|
165
|
+
declare function createSessionSignerForAccount(session: UserSession, ref: ProductAccountRef, options?: SessionSignerOptions): Promise<PolkadotSigner>;
|
|
134
166
|
|
|
135
167
|
/**
|
|
136
168
|
* Get a `PolkadotSigner` for a Bulletin allowance slot.
|
|
@@ -223,6 +255,99 @@ declare function hasStatementStoreAllowance(adapter: TerminalAdapter, productId:
|
|
|
223
255
|
*/
|
|
224
256
|
declare function waitForSessions(adapter: TerminalAdapter, timeoutMs?: number): Promise<UserSession[]>;
|
|
225
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Client-side RFC-0007 product-entropy derivation for terminal (QR/SSO) sessions.
|
|
260
|
+
*
|
|
261
|
+
* Specified normatively by host-spec §C.8 "RFC-0007 product entropy"
|
|
262
|
+
* ({@link https://github.com/paritytech/host-spec/blob/adb3989208ae1c2107dbf0159611353e6989422c/spec/C-account-derivation.md?plain=1#L129-L147 | spec/C-account-derivation.md}):
|
|
263
|
+
*
|
|
264
|
+
* layer1 = blake2b256_keyed(key = utf8("product-entropy-derivation"), msg = rootAccountSecret)
|
|
265
|
+
* layer2 = blake2b256_keyed(key = blake2b256(utf8(productId)), msg = layer1)
|
|
266
|
+
* result = blake2b256_keyed(key = callerKey, msg = layer2)
|
|
267
|
+
*
|
|
268
|
+
* The paired {@link UserSession} already carries layer 1 as `rootEntropySource`,
|
|
269
|
+
* so this module computes only layers 2 and 3 — no host round-trip. The output
|
|
270
|
+
* matches what an in-container app gets from `@parity/product-sdk-host`'s
|
|
271
|
+
* `deriveEntropy` for the same wallet + product + key, so entropy-derived keys
|
|
272
|
+
* interoperate across web (in-container) and terminal (QR/SSO) clients.
|
|
273
|
+
*
|
|
274
|
+
* Layer 1's input is the raw BIP-39 entropy of the root account — 16 or 32
|
|
275
|
+
* bytes, *not* the 64-byte PBKDF2 seed. Terminal never sees it: the host applies
|
|
276
|
+
* layer 1 during the SSO handshake and sends only the 32-byte result.
|
|
277
|
+
*
|
|
278
|
+
* The scheme has parallel implementations in five languages — host-container
|
|
279
|
+
* (TS), host-encoding (Rust, canonical), sdk-swift, sdk-android and
|
|
280
|
+
* brevity-flutter (Dart) — so the shared artifact is the spec rather than a
|
|
281
|
+
* package: Swift, Kotlin and Dart cannot import a TS one. The safety net is the
|
|
282
|
+
* cross-language conformance suite, which the tests below pin against verbatim.
|
|
283
|
+
* Cite the spec, not any one implementation: mirrors drift.
|
|
284
|
+
*
|
|
285
|
+
* A follow-up lifts the two halves into their canonical homes without changing
|
|
286
|
+
* behaviour: `blake2b256Keyed` into `@parity/product-sdk-crypto` (the missing
|
|
287
|
+
* sibling of the `blake2b256` already there) and the pure derivation into
|
|
288
|
+
* `@parity/product-sdk-keys`, beside `product-account.ts`. The session wrapper
|
|
289
|
+
* below stays exactly as it is.
|
|
290
|
+
*
|
|
291
|
+
* @module
|
|
292
|
+
*/
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Derive 32 bytes of deterministic entropy for a terminal session, scoped to the
|
|
296
|
+
* calling product and a caller key (RFC-0007 layers 2 + 3).
|
|
297
|
+
*
|
|
298
|
+
* Same wallet + product + key ⇒ same bytes; any difference ⇒ uncorrelated
|
|
299
|
+
* entropy. Because it derives from the wallet (not the device), the entropy is
|
|
300
|
+
* recreatable after device loss as long as the wallet is recoverable.
|
|
301
|
+
*
|
|
302
|
+
* @param session - A QR-paired {@link UserSession}. Must carry
|
|
303
|
+
* `rootEntropySource` (present since host-papp 0.8.6 / RFC-0007).
|
|
304
|
+
* @param productId - The calling product's identifier, used verbatim as the
|
|
305
|
+
* layer-2 scope. Per host-spec §C.7 that is `<label>.dot` for a dotNS product
|
|
306
|
+
* (e.g. `"my-app.dot"`), or `localhost:<port>` — no `.dot` suffix — for local
|
|
307
|
+
* dev. It is case-sensitive and is **not** normalized here: `"My-App.dot"`,
|
|
308
|
+
* `"my-app.dot "` and `"my-app.dot"` derive three uncorrelated entropies.
|
|
309
|
+
*
|
|
310
|
+
* This must be the identifier the *in-container* deployment is served under —
|
|
311
|
+
* the same value you pass as `productId` to `getBulletinSigner` and as
|
|
312
|
+
* `options.productId` to `requestResourceAllocation` — because that is the
|
|
313
|
+
* scope the host derives against. It is **not** `adapter.appId`: the adapter
|
|
314
|
+
* id is a local namespace (cache keys, storage dir) and the two are
|
|
315
|
+
* routinely different. The package's own example pairs
|
|
316
|
+
* `createTerminalAdapter({ appId: "my-cli" })` with
|
|
317
|
+
* `getBulletinSigner(adapter, "my-cli.dot")`. Note that
|
|
318
|
+
* `requestResourceAllocation` falls back to `adapter.appId` when
|
|
319
|
+
* `options.productId` is omitted, so a call relying on that default is *not*
|
|
320
|
+
* a reliable reference point for this argument.
|
|
321
|
+
*
|
|
322
|
+
* The host takes the scope from the iframe's deployment label rather than
|
|
323
|
+
* from the caller, so it differs per deployment: production, each PR preview
|
|
324
|
+
* and local dev all scope to different entropy. A CLI that hardcodes the
|
|
325
|
+
* production id derives valid-but-different bytes against a preview, with no
|
|
326
|
+
* error anywhere.
|
|
327
|
+
*
|
|
328
|
+
* Required and positional **by design** — do not give this a default. Unlike
|
|
329
|
+
* an allocation request, a wrong product scope here fails silently: it yields
|
|
330
|
+
* well-formed entropy that simply cannot decrypt anything.
|
|
331
|
+
* @param key - Caller key, 1..32 bytes (the layer-3 BLAKE2b key). Both
|
|
332
|
+
* bounds are normative: the spec requires zero-length and >32-byte keys to be
|
|
333
|
+
* rejected, because some BLAKE2b implementations silently degrade an empty MAC
|
|
334
|
+
* key to unkeyed mode.
|
|
335
|
+
* @returns 32 bytes of derived entropy.
|
|
336
|
+
* @throws if the session lacks `rootEntropySource` or carries one of the wrong
|
|
337
|
+
* width, if `productId` is not a non-empty string, or if `key` is not 1..32
|
|
338
|
+
* bytes.
|
|
339
|
+
*
|
|
340
|
+
* @remarks
|
|
341
|
+
* This reads nothing account-identifying, and a terminal may hold several paired
|
|
342
|
+
* sessions (see `waitForSessions`). Passing the wrong one yields valid entropy
|
|
343
|
+
* for a *different* wallet: the intended user cannot decrypt, and the other
|
|
344
|
+
* wallet's holder can. Pin the identity with `sessionRootPublicKey` before
|
|
345
|
+
* deriving long-lived keys.
|
|
346
|
+
*
|
|
347
|
+
* The return value is raw key material — do not log it or persist it unwrapped.
|
|
348
|
+
*/
|
|
349
|
+
declare function deriveEntropy(session: UserSession, productId: string, key: Uint8Array): Uint8Array;
|
|
350
|
+
|
|
226
351
|
/**
|
|
227
352
|
* Terminal QR code rendering using Unicode half-block characters.
|
|
228
353
|
*
|
|
@@ -259,4 +384,4 @@ declare function renderQrCode(data: string, options?: QrRenderOptions): Promise<
|
|
|
259
384
|
*/
|
|
260
385
|
declare function createNodeStorageAdapter(appId: string, storageDir?: string): StorageAdapter;
|
|
261
386
|
|
|
262
|
-
export { INCOMPLETE_SESSION_MESSAGE, type ProductAccountRef, type QrRenderOptions, TerminalAdapter, createNodeStorageAdapter, createSessionSigner, createSessionSignerForAccount, deriveProductPublicKey, getBulletinSigner, getStatementStoreProver, hasBulletinAllowance, hasStatementStoreAllowance, renderQrCode, sessionRootPublicKey, waitForSessions };
|
|
387
|
+
export { INCOMPLETE_SESSION_MESSAGE, type ProductAccountRef, type ProductSubtreeOptions, type QrRenderOptions, type SessionSignerOptions, type StatementStoreEnvironment, StatementStoreNetworks, TerminalAdapter, createNodeStorageAdapter, createSessionSigner, createSessionSignerForAccount, deriveEntropy, deriveProductPublicKey, getBulletinSigner, getProductSubtreePublicKey, getStatementStoreProver, hasBulletinAllowance, hasStatementStoreAllowance, renderQrCode, sessionRootPublicKey, waitForSessions };
|