@parity/product-sdk-host 0.15.0 → 0.16.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/dist/chain-discovery-nLrPzb3d.d.ts +70 -0
- package/dist/index.d.ts +102 -13
- package/dist/index.js +148 -27
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +32 -8
- package/dist/testing.js +23 -5
- package/dist/testing.js.map +1 -1
- package/package.json +4 -4
- package/src/accounts.ts +451 -33
- package/src/chain-discovery.ts +287 -0
- package/src/index.ts +12 -1
- package/src/payments.ts +1 -1
- package/src/testing.ts +106 -11
- package/src/truapi.ts +3 -2
- package/dist/transport-B0cdhwrp.d.ts +0 -31
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { TrUApiClient, ChainIdentifier, HexString } from '@parity/truapi';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Access to the in-house TruAPI client (`@parity/truapi`) for the host package.
|
|
5
|
+
*
|
|
6
|
+
* Environment detection and the lazily-built, cached client come from
|
|
7
|
+
* `@parity/truapi/sandbox`; this module layers the product-sdk-specific glue on
|
|
8
|
+
* top — an async {@link getClient} accessor and {@link subscribeWithInterrupt},
|
|
9
|
+
* which adapts a truapi stream into the host's {@link HostSubscription} shape.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Test-only seam: force {@link getClient} / {@link getClientSync} to return
|
|
16
|
+
* `client`, and {@link isCorrectEnvironment} to report `true`. Pass `null` to
|
|
17
|
+
* restore normal detection. Exposed through `@parity/product-sdk-host/testing`,
|
|
18
|
+
* not the package's main entry.
|
|
19
|
+
*
|
|
20
|
+
* Calling this in a production build silently reroutes every host accessor to
|
|
21
|
+
* the injected client, so we warn — it almost always means a `/testing` import
|
|
22
|
+
* leaked into a production path.
|
|
23
|
+
*/
|
|
24
|
+
declare function setTruApiClient(client: TrUApiClient | null): void;
|
|
25
|
+
/**
|
|
26
|
+
* Host-container detection. `true` when a test client is injected, otherwise the
|
|
27
|
+
* sandbox heuristic (iframe / webview marker / injected message port).
|
|
28
|
+
*/
|
|
29
|
+
declare function isCorrectEnvironment(): boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Host chain discovery. Resolves chain roles to genesis hashes against the
|
|
33
|
+
* host's configured environment instead of hard-coding them.
|
|
34
|
+
*
|
|
35
|
+
* The wire method takes one identifier per call, so the facade fires one
|
|
36
|
+
* concurrent call per requested identifier and caches the combined result
|
|
37
|
+
* for the lifetime of the connection. Consumed internally by chain-client.
|
|
38
|
+
* Products normally never call this directly.
|
|
39
|
+
*
|
|
40
|
+
* @module
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Chain-role identifier. A closed protocol enum, not a free-form name. The
|
|
45
|
+
* host maps each role to the concrete chain of its configured environment.
|
|
46
|
+
*/
|
|
47
|
+
type HostChainIdentifier = ChainIdentifier;
|
|
48
|
+
/** The host's configured environment plus per-identifier resolved genesis hashes. */
|
|
49
|
+
interface HostChainDiscovery {
|
|
50
|
+
/** Ecosystem the host is configured for, e.g. `"polkadot"`, `"paseo"`. */
|
|
51
|
+
network: string;
|
|
52
|
+
/** Present for every requested identifier the host serves. */
|
|
53
|
+
chains: Partial<Record<HostChainIdentifier, HexString>>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve chain roles against the current host.
|
|
57
|
+
*
|
|
58
|
+
* Returns `null` when discovery is unavailable: outside a container, on a
|
|
59
|
+
* legacy host, or when the host serves none of the requested identifiers.
|
|
60
|
+
* Callers treat `null` as "fall back to configured constants".
|
|
61
|
+
*
|
|
62
|
+
* One concurrent `getChainInfo` call is made per identifier. Identifiers
|
|
63
|
+
* the host answers `NotSupported` for are absent from `chains`. Stable
|
|
64
|
+
* answers are cached per client and identifier set. Unexpected wire failures
|
|
65
|
+
* and probe timeouts are logged, return `null` and are not cached, so a later
|
|
66
|
+
* call re-probes.
|
|
67
|
+
*/
|
|
68
|
+
declare function getHostChainInfo(identifiers: readonly HostChainIdentifier[]): Promise<HostChainDiscovery | null>;
|
|
69
|
+
|
|
70
|
+
export { type HostChainDiscovery as H, type HostChainIdentifier as a, getHostChainInfo as g, isCorrectEnvironment as i, setTruApiClient as s };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { JsonRpcProvider, PolkadotSigner } from 'polkadot-api';
|
|
2
|
-
import { Topic, RemoteStatementStoreSubscribeItem, Statement, StatementProof, SignedStatement, HexString, scale, TrUApiClient, AllocatableResource, AllocationOutcome, VersionedHostGetUserIdError, HostRequestLoginResponse, VersionedHostRequestLoginError, ProductAccountId, ProductAccount as ProductAccount$1, VersionedHostAccountGetError,
|
|
3
|
-
export { AllocatableResource, AllocationOutcome, ChatMessageContent, ChatRoom, DerivationIndex, HexString, HostPaymentBalanceSubscribeItem, HostPaymentStatusSubscribeItem, NotificationId, PaymentTopUpSource, ProductAccountId, ProductProofContext, HostPushNotificationError as PushNotificationError, RemotePermission, RingLocation, SignedStatement, Statement, StatementProof, ThemeName, ThemeVariant, Topic } from '@parity/truapi';
|
|
2
|
+
import { Topic, RemoteStatementStoreSubscribeItem, Statement, StatementProof, SignedStatement, HexString, scale, TrUApiClient, AllocatableResource, AllocationOutcome, VersionedHostGetUserIdError, HostRequestLoginResponse, VersionedHostRequestLoginError, ProductAccountId, ProductAccount as ProductAccount$1, VersionedHostAccountGetError, RingLocation, VersionedHostAccountRegisterRingVrfKeyError, RingVrfKeyDisclosure, RegisteredRingVrfKey as RegisteredRingVrfKey$1, VersionedHostAccountListRingVrfKeysError, ProductProofContext, ContextualAlias as ContextualAlias$1, VersionedHostAccountGetAliasError, LegacyAccount, VersionedHostGetLegacyAccountsError, HostAccountCreateProofResponse, VersionedHostAccountCreateProofError, VersionedHostAccountRingVrfSignError, VrfTranscriptItem as VrfTranscriptItem$1, VrfSignature as VrfSignature$1, VersionedHostAccountSignVrfError, HostAccountConnectionStatusSubscribeItem, HostDevicePermissionRequest, RemotePermission, HostThemeSubscribeItem, ChatBotRegistrationStatus, HostChatCreateRoomRequest, ChatRoomRegistrationStatus, HostChatRegisterBotRequest, ChatMessageContent, ChatRoom, HostChatActionSubscribeItem, HostPaymentBalanceSubscribeItem, CoinPaymentPurseId, Balance, PaymentTopUpSource, HostPaymentStatusSubscribeItem, HostPushNotificationRequest, NotificationId } from '@parity/truapi';
|
|
3
|
+
export { AllocatableResource, AllocationOutcome, ChatMessageContent, ChatRoom, DerivationIndex, HexString, HostPaymentBalanceSubscribeItem, HostPaymentStatusSubscribeItem, NotificationId, PaymentTopUpSource, ProductAccountId, ProductProofContext, HostPushNotificationError as PushNotificationError, RemotePermission, RingLocation, RingVrfKeyDisclosure, SignedStatement, Statement, StatementProof, ThemeName, ThemeVariant, Topic } from '@parity/truapi';
|
|
4
4
|
import { SdkError } from '@parity/product-sdk-errors';
|
|
5
5
|
export { SdkError, isSdkError } from '@parity/product-sdk-errors';
|
|
6
6
|
import { Result } from '@parity/result';
|
|
7
7
|
export { Result, err, ok } from '@parity/result';
|
|
8
|
+
export { H as HostChainDiscovery, a as HostChainIdentifier, g as getHostChainInfo, i as isInsideContainerSync } from './chain-discovery-nLrPzb3d.js';
|
|
8
9
|
import { ResultAsync as ResultAsync$1 } from 'neverthrow';
|
|
9
|
-
export { i as isInsideContainerSync } from './transport-B0cdhwrp.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Public types for the host wrappers.
|
|
@@ -370,7 +370,8 @@ interface ResultAsync<T, E> {
|
|
|
370
370
|
* `getAccountsProvider()` returns the full accounts surface — user identity
|
|
371
371
|
* (`getUserId` / `requestLogin`), the user's existing wallet accounts
|
|
372
372
|
* (`getLegacyAccounts`), app-scoped product accounts (`getProductAccount` /
|
|
373
|
-
* `getProductAccountAlias`), Ring VRF proofs (`createRingVRFProof`),
|
|
373
|
+
* `getProductAccountAlias`), Ring VRF proofs (`createRingVRFProof`), sr25519 VRF
|
|
374
|
+
* signatures over a caller-supplied Merlin transcript (`signVrf`), connection
|
|
374
375
|
* status, and PAPI `PolkadotSigner` factories for both product and legacy
|
|
375
376
|
* accounts.
|
|
376
377
|
*
|
|
@@ -415,6 +416,41 @@ type ProductAccount = Omit<ProductAccountId, "derivationIndex"> & Omit<ProductAc
|
|
|
415
416
|
/** Raw public key bytes. */
|
|
416
417
|
publicKey: Uint8Array;
|
|
417
418
|
};
|
|
419
|
+
/**
|
|
420
|
+
* How callers address a product account: app identifier plus an optional index,
|
|
421
|
+
* defaulting to 0. A {@link ProductAccount} satisfies this, so an account from
|
|
422
|
+
* {@link AccountsProvider.getProductAccount} can be passed straight back in.
|
|
423
|
+
*/
|
|
424
|
+
type ProductAccountLookup = Omit<ProductAccountId, "derivationIndex"> & {
|
|
425
|
+
/** Plain account index within the product subtree. Defaults to 0. */
|
|
426
|
+
derivationIndex?: number;
|
|
427
|
+
};
|
|
428
|
+
declare const ringVrfKeyHandleBrand: unique symbol;
|
|
429
|
+
/**
|
|
430
|
+
* Opaque public name of a registered ring-VRF key.
|
|
431
|
+
*
|
|
432
|
+
* Handles come from {@link AccountsProvider.listRingVrfKeys}; product code
|
|
433
|
+
* cannot construct one from a derivation index.
|
|
434
|
+
*/
|
|
435
|
+
type RingVrfKeyHandle = {
|
|
436
|
+
readonly [ringVrfKeyHandleBrand]: "RingVrfKeyHandle";
|
|
437
|
+
};
|
|
438
|
+
/** Ring-VRF member public key, decoded from the wire's hex string. */
|
|
439
|
+
type RingVrfPublicKey = Uint8Array;
|
|
440
|
+
/** Registered key metadata returned by the host. */
|
|
441
|
+
type RegisteredRingVrfKey = Omit<RegisteredRingVrfKey$1, "handle" | "publicKey"> & {
|
|
442
|
+
/** Opaque handle to pass back for alias and proof requests. */
|
|
443
|
+
handle: RingVrfKeyHandle;
|
|
444
|
+
/** Present when public-key disclosure was granted. */
|
|
445
|
+
publicKey?: RingVrfPublicKey;
|
|
446
|
+
};
|
|
447
|
+
/**
|
|
448
|
+
* Select a registered key by its declared ring and return its opaque handle.
|
|
449
|
+
*
|
|
450
|
+
* Consumers must not hard-code another product's derivation index. Registry
|
|
451
|
+
* order breaks ties when an owner declares multiple keys for the same ring.
|
|
452
|
+
*/
|
|
453
|
+
declare function findRingVrfKeyHandle(keys: RegisteredRingVrfKey[], ring: RingLocation): RingVrfKeyHandle | undefined;
|
|
418
454
|
/**
|
|
419
455
|
* A contextual alias obtained from Ring VRF.
|
|
420
456
|
*
|
|
@@ -439,6 +475,23 @@ type RingVRFProof = Omit<HostAccountCreateProofResponse, "proof" | "contextualAl
|
|
|
439
475
|
/** Alias derived for the request's context. */
|
|
440
476
|
contextualAlias: ContextualAlias;
|
|
441
477
|
};
|
|
478
|
+
/**
|
|
479
|
+
* One `append_message(label, value)` call replayed against a VRF transcript.
|
|
480
|
+
* Merlin labels are ASCII by convention: use `utf8ToBytes("round")`.
|
|
481
|
+
*
|
|
482
|
+
* Derived from `@parity/truapi`'s `VrfTranscriptItem`, decoded to bytes.
|
|
483
|
+
*/
|
|
484
|
+
type VrfTranscriptItem = {
|
|
485
|
+
[K in keyof VrfTranscriptItem$1]: Uint8Array;
|
|
486
|
+
};
|
|
487
|
+
/**
|
|
488
|
+
* An sr25519 VRF signature: the pre-output and its DLEQ proof.
|
|
489
|
+
*
|
|
490
|
+
* Derived from `@parity/truapi`'s `VrfSignature`, decoded to bytes.
|
|
491
|
+
*/
|
|
492
|
+
type VrfSignature = {
|
|
493
|
+
[K in keyof VrfSignature$1]: Uint8Array;
|
|
494
|
+
};
|
|
442
495
|
/**
|
|
443
496
|
* Accounts provider handle, backed by `truApi.account.*` / `truApi.signing.*`.
|
|
444
497
|
* Surfaces the user's wallet accounts, app-scoped product accounts, Ring VRF,
|
|
@@ -456,17 +509,53 @@ interface AccountsProvider {
|
|
|
456
509
|
requestLogin(reason?: string): ResultAsync$1<HostRequestLoginResponse, scale.CallErrorValue<VersionedHostRequestLoginError>>;
|
|
457
510
|
getProductAccount(dotNsIdentifier: string, derivationIndex?: number): ResultAsync$1<ProductAccount, scale.CallErrorValue<VersionedHostAccountGetError>>;
|
|
458
511
|
/**
|
|
459
|
-
*
|
|
460
|
-
*
|
|
512
|
+
* Register a ring-VRF key owned by the calling product.
|
|
513
|
+
*
|
|
514
|
+
* `index` is the plain derivation index within the product's ring-VRF
|
|
515
|
+
* domain; the adapter wraps it into the wire's tagged selector.
|
|
516
|
+
*
|
|
517
|
+
* Registration returns the key's public key. Call {@link listRingVrfKeys}
|
|
518
|
+
* afterward to obtain the opaque handle required by alias and proof calls.
|
|
461
519
|
*/
|
|
462
|
-
|
|
520
|
+
registerRingVrfKey(index: number, ring: RingLocation): ResultAsync$1<RingVrfPublicKey, scale.CallErrorValue<VersionedHostAccountRegisterRingVrfKeyError>>;
|
|
521
|
+
/** List an owner's registered ring-VRF keys. */
|
|
522
|
+
listRingVrfKeys(owner: string, disclosure?: RingVrfKeyDisclosure): ResultAsync$1<RegisteredRingVrfKey[], scale.CallErrorValue<VersionedHostAccountListRingVrfKeysError>>;
|
|
523
|
+
/** Derive a contextual alias with an explicitly registered ring-VRF key. */
|
|
524
|
+
getProductAccountAlias(keyHandle: RingVrfKeyHandle, context: ProductProofContext, location: RingLocation): ResultAsync$1<ContextualAlias, scale.CallErrorValue<VersionedHostAccountGetAliasError>>;
|
|
463
525
|
getLegacyAccounts(): ResultAsync$1<HostAccount[], scale.CallErrorValue<VersionedHostGetLegacyAccountsError>>;
|
|
464
526
|
/**
|
|
465
|
-
* Generate a Ring VRF proof
|
|
466
|
-
* `
|
|
467
|
-
|
|
527
|
+
* Generate a Ring VRF proof with an explicitly registered key, binding
|
|
528
|
+
* `message` to the product-scoped `context`.
|
|
529
|
+
*/
|
|
530
|
+
createRingVRFProof(keyHandle: RingVrfKeyHandle, context: ProductProofContext, location: RingLocation, message: Uint8Array): ResultAsync$1<RingVRFProof, scale.CallErrorValue<VersionedHostAccountCreateProofError>>;
|
|
531
|
+
/**
|
|
532
|
+
* Sign `message` directly with an explicitly registered ring-VRF key.
|
|
533
|
+
*
|
|
534
|
+
* Unlike {@link createRingVRFProof} this proves nothing about ring
|
|
535
|
+
* membership; it is the plain signature under the member key, for
|
|
536
|
+
* protocols that carry their own proof.
|
|
537
|
+
*/
|
|
538
|
+
ringVrfSign(keyHandle: RingVrfKeyHandle, message: Uint8Array): ResultAsync$1<Uint8Array, scale.CallErrorValue<VersionedHostAccountRingVrfSignError>>;
|
|
539
|
+
/**
|
|
540
|
+
* Produce an sr25519 VRF signature from a product account (RFC-0023).
|
|
541
|
+
*
|
|
542
|
+
* The host builds a Merlin transcript from `transcriptLabel` and `items`,
|
|
543
|
+
* then signs it with the account's key. Unlike {@link createRingVRFProof},
|
|
544
|
+
* this names the signing account instead of proving ring membership.
|
|
545
|
+
*
|
|
546
|
+
* The caller owns four things the types cannot enforce:
|
|
547
|
+
*
|
|
548
|
+
* - Domain separation. A label borrowed from another protocol makes the
|
|
549
|
+
* output replayable across both.
|
|
550
|
+
* - Freshness. The VRF is deterministic, so per-round values belong in
|
|
551
|
+
* `items`.
|
|
552
|
+
* - Size. Hosts cap the transcript at 32 items and 8 KiB total.
|
|
553
|
+
* - Authorization. An `AutoSigning` allowance makes these calls silent. It
|
|
554
|
+
* is not VRF-scoped, so it covers other signing by that account too.
|
|
555
|
+
*
|
|
556
|
+
* Hosts predating the call reject it through the error channel.
|
|
468
557
|
*/
|
|
469
|
-
|
|
558
|
+
signVrf(account: ProductAccountLookup, transcriptLabel: Uint8Array, items: VrfTranscriptItem[]): ResultAsync$1<VrfSignature, scale.CallErrorValue<VersionedHostAccountSignVrfError>>;
|
|
470
559
|
/**
|
|
471
560
|
* Build a `PolkadotSigner` for a product account. Signing routes through the
|
|
472
561
|
* host's `createTransaction` path: the host decodes the metadata and forwards
|
|
@@ -725,7 +814,7 @@ interface PaymentManager {
|
|
|
725
814
|
* const payments = await getPaymentManager();
|
|
726
815
|
* if (payments) {
|
|
727
816
|
* const sub = payments.subscribeBalance((b) => { ... });
|
|
728
|
-
* await payments.topUp(1_000_000n, { tag: "ProductAccount", value: { derivationIndex: { tag: "
|
|
817
|
+
* await payments.topUp(1_000_000n, { tag: "ProductAccount", value: { derivationIndex: { tag: "Index", value: 0 } } });
|
|
729
818
|
* const { id } = await payments.requestPayment(500n, "0x…");
|
|
730
819
|
* sub.unsubscribe();
|
|
731
820
|
* }
|
|
@@ -1018,4 +1107,4 @@ declare function broadcastTransaction(genesisHash: HexString, transaction: HexSt
|
|
|
1018
1107
|
*/
|
|
1019
1108
|
declare function stopTransaction(genesisHash: HexString, operationId: string): Promise<Result<void, HostError>>;
|
|
1020
1109
|
|
|
1021
|
-
export { type AccountsProvider, BULLETIN_RPCS, ChainNotSupportedError, type ChainProperties, type ChainSpec, type ChatBotRegistrationResult, type ChatManager, type ChatReceivedAction, type ChatRoomRegistrationResult, type ContextualAlias, DEFAULT_BULLETIN_ENDPOINT, type DevicePermissionKind, type Feature, type HostAccount, HostCallFailedError, HostError, type HostErrorPayload, type HostLocalStorage, type HostStatementStore, type HostSubscription, HostUnavailableError, type NotificationManager, type PaymentManager, type PreimageManager, type ProductAccount, type PushNotificationInput, type RemotePermissionItem, type ResultAsync, type RingVRFProof, type StatementTopicFilter, type StatementsPage, type ThemeMode, type ThemeProvider, type TruApi, broadcastTransaction, createHostLocalStorage, createHostPreimageManager, createProofAuthorized, deriveEntropy, featureSupported, formatHostError, fromHex, getAccountsProvider, getChainSpec, getChatManager, getHostLocalStorage, getHostProvider, getNotificationManager, getPaymentManager, getPreimageManager, getStatementStore, getThemeProvider, getTruApi, isChainSupported, isHostError, isInsideContainer, navigateTo, requestDevicePermission, requestPermission, requestResourceAllocation, stopTransaction, toHex };
|
|
1110
|
+
export { type AccountsProvider, BULLETIN_RPCS, ChainNotSupportedError, type ChainProperties, type ChainSpec, type ChatBotRegistrationResult, type ChatManager, type ChatReceivedAction, type ChatRoomRegistrationResult, type ContextualAlias, DEFAULT_BULLETIN_ENDPOINT, type DevicePermissionKind, type Feature, type HostAccount, HostCallFailedError, HostError, type HostErrorPayload, type HostLocalStorage, type HostStatementStore, type HostSubscription, HostUnavailableError, type NotificationManager, type PaymentManager, type PreimageManager, type ProductAccount, type ProductAccountLookup, type PushNotificationInput, type RegisteredRingVrfKey, type RemotePermissionItem, type ResultAsync, type RingVRFProof, type RingVrfKeyHandle, type RingVrfPublicKey, type StatementTopicFilter, type StatementsPage, type ThemeMode, type ThemeProvider, type TruApi, type VrfSignature, type VrfTranscriptItem, broadcastTransaction, createHostLocalStorage, createHostPreimageManager, createProofAuthorized, deriveEntropy, featureSupported, findRingVrfKeyHandle, formatHostError, fromHex, getAccountsProvider, getChainSpec, getChatManager, getHostLocalStorage, getHostProvider, getNotificationManager, getPaymentManager, getPreimageManager, getStatementStore, getThemeProvider, getTruApi, isChainSupported, isHostError, isInsideContainer, navigateTo, requestDevicePermission, requestPermission, requestResourceAllocation, stopTransaction, toHex };
|
package/dist/index.js
CHANGED
|
@@ -580,6 +580,91 @@ var BULLETIN_RPCS = {
|
|
|
580
580
|
kusama: []
|
|
581
581
|
};
|
|
582
582
|
var DEFAULT_BULLETIN_ENDPOINT = BULLETIN_RPCS.paseo[0];
|
|
583
|
+
var log3 = createLogger("host");
|
|
584
|
+
var TRANSIENT_FAILURE = /* @__PURE__ */ Symbol("transient-failure");
|
|
585
|
+
var PROBE_TIMEOUT_MS = 3e3;
|
|
586
|
+
var discoveryCache = /* @__PURE__ */ new WeakMap();
|
|
587
|
+
async function getHostChainInfo(identifiers) {
|
|
588
|
+
const client = await getClient();
|
|
589
|
+
if (!client) return null;
|
|
590
|
+
let bySet = discoveryCache.get(client);
|
|
591
|
+
if (!bySet) {
|
|
592
|
+
bySet = /* @__PURE__ */ new Map();
|
|
593
|
+
discoveryCache.set(client, bySet);
|
|
594
|
+
}
|
|
595
|
+
const key = [...identifiers].sort().join(",");
|
|
596
|
+
let cached = bySet.get(key);
|
|
597
|
+
if (!cached) {
|
|
598
|
+
cached = fetchChainInfo(client, identifiers).then((result) => {
|
|
599
|
+
if (result === TRANSIENT_FAILURE) {
|
|
600
|
+
bySet.delete(key);
|
|
601
|
+
return null;
|
|
602
|
+
}
|
|
603
|
+
return result;
|
|
604
|
+
});
|
|
605
|
+
bySet.set(key, cached);
|
|
606
|
+
}
|
|
607
|
+
return cached;
|
|
608
|
+
}
|
|
609
|
+
async function fetchChainInfo(client, identifiers) {
|
|
610
|
+
try {
|
|
611
|
+
let timer;
|
|
612
|
+
const probe = Promise.all(
|
|
613
|
+
identifiers.map(
|
|
614
|
+
(id) => client.chain.getChainInfo({ chain: id }).match(
|
|
615
|
+
(value) => ({ id, ok: value }),
|
|
616
|
+
(error) => ({ id, err: error })
|
|
617
|
+
)
|
|
618
|
+
)
|
|
619
|
+
);
|
|
620
|
+
const outcomes = await Promise.race([
|
|
621
|
+
probe,
|
|
622
|
+
new Promise((resolve) => {
|
|
623
|
+
timer = setTimeout(() => resolve("timeout"), PROBE_TIMEOUT_MS);
|
|
624
|
+
})
|
|
625
|
+
]).finally(() => clearTimeout(timer));
|
|
626
|
+
if (outcomes === "timeout") {
|
|
627
|
+
log3.warn("getChainInfo probe timed out, treating the host as pre-discovery for now");
|
|
628
|
+
return TRANSIENT_FAILURE;
|
|
629
|
+
}
|
|
630
|
+
let network;
|
|
631
|
+
const chains = {};
|
|
632
|
+
for (const outcome of outcomes) {
|
|
633
|
+
if ("ok" in outcome) {
|
|
634
|
+
network = outcome.ok.network;
|
|
635
|
+
chains[outcome.id] = outcome.ok.genesisHash;
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
638
|
+
if (outcome.err.tag === "Unsupported") return null;
|
|
639
|
+
if (isNotSupported(outcome.err)) continue;
|
|
640
|
+
log3.warn(`getChainInfo failed: ${formatHostError(outcome.err)}`);
|
|
641
|
+
return TRANSIENT_FAILURE;
|
|
642
|
+
}
|
|
643
|
+
if (network === void 0) return null;
|
|
644
|
+
return { network, chains };
|
|
645
|
+
} catch (error) {
|
|
646
|
+
log3.warn(`getChainInfo failed: ${formatHostError(error)}`);
|
|
647
|
+
return TRANSIENT_FAILURE;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
function isNotSupported(error) {
|
|
651
|
+
return error.tag === "Domain" && error.value.value.tag === "NotSupported";
|
|
652
|
+
}
|
|
653
|
+
function sameRingLocation(a, b) {
|
|
654
|
+
if (a.chainId.toLowerCase() !== b.chainId.toLowerCase() || a.junctions.length !== b.junctions.length) {
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
return a.junctions.every((junction, index) => {
|
|
658
|
+
const candidate = b.junctions[index];
|
|
659
|
+
if (junction.tag === "PalletInstance") {
|
|
660
|
+
return candidate.tag === "PalletInstance" && junction.value === candidate.value;
|
|
661
|
+
}
|
|
662
|
+
return candidate.tag === "CollectionId" && junction.value.toLowerCase() === candidate.value.toLowerCase();
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
function findRingVrfKeyHandle(keys, ring) {
|
|
666
|
+
return keys.find((key) => key.rings.some((candidate) => sameRingLocation(candidate, ring)))?.handle;
|
|
667
|
+
}
|
|
583
668
|
function deriveTxExtVersion(metadata) {
|
|
584
669
|
const versions = unifyMetadata(decAnyMetadata(metadata)).extrinsic.version;
|
|
585
670
|
if (versions.length === 0) {
|
|
@@ -596,8 +681,11 @@ function toHostExtensions(signedExtensions) {
|
|
|
596
681
|
additionalSigned: toHex(ext.additionalSigned)
|
|
597
682
|
}));
|
|
598
683
|
}
|
|
599
|
-
function toWireProductAccountId(
|
|
600
|
-
|
|
684
|
+
function toWireProductAccountId({
|
|
685
|
+
dotNsIdentifier,
|
|
686
|
+
derivationIndex = 0
|
|
687
|
+
}) {
|
|
688
|
+
return { dotNsIdentifier, derivationIndex: { tag: "Index", value: derivationIndex } };
|
|
601
689
|
}
|
|
602
690
|
function adaptAccountsProvider(client) {
|
|
603
691
|
const account = client.account;
|
|
@@ -613,15 +701,31 @@ function adaptAccountsProvider(client) {
|
|
|
613
701
|
},
|
|
614
702
|
getProductAccount(dotNsIdentifier, derivationIndex = 0) {
|
|
615
703
|
return account.getAccount({
|
|
616
|
-
productAccountId: toWireProductAccountId(dotNsIdentifier, derivationIndex)
|
|
704
|
+
productAccountId: toWireProductAccountId({ dotNsIdentifier, derivationIndex })
|
|
617
705
|
}).map((response) => ({
|
|
618
706
|
publicKey: fromHex(response.account.publicKey),
|
|
619
707
|
dotNsIdentifier,
|
|
620
708
|
derivationIndex
|
|
621
709
|
}));
|
|
622
710
|
},
|
|
623
|
-
|
|
624
|
-
return account.
|
|
711
|
+
registerRingVrfKey(index, ring) {
|
|
712
|
+
return account.registerRingVrfKey({ index: { tag: "Index", value: index }, ring }).map(fromHex);
|
|
713
|
+
},
|
|
714
|
+
listRingVrfKeys(owner, disclosure = "Anonymized") {
|
|
715
|
+
return account.listRingVrfKeys({ owner, disclosure }).map(
|
|
716
|
+
(keys) => keys.map((key) => ({
|
|
717
|
+
...key,
|
|
718
|
+
handle: key.handle,
|
|
719
|
+
publicKey: key.publicKey === void 0 ? void 0 : fromHex(key.publicKey)
|
|
720
|
+
}))
|
|
721
|
+
);
|
|
722
|
+
},
|
|
723
|
+
getProductAccountAlias(keyHandle, context, location) {
|
|
724
|
+
return account.getAccountAlias({
|
|
725
|
+
keyHandle,
|
|
726
|
+
context,
|
|
727
|
+
ringLocation: location
|
|
728
|
+
}).map((response) => ({
|
|
625
729
|
context: fromHex(response.context),
|
|
626
730
|
alias: fromHex(response.alias)
|
|
627
731
|
}));
|
|
@@ -634,8 +738,9 @@ function adaptAccountsProvider(client) {
|
|
|
634
738
|
}))
|
|
635
739
|
);
|
|
636
740
|
},
|
|
637
|
-
createRingVRFProof(context, location, message) {
|
|
741
|
+
createRingVRFProof(keyHandle, context, location, message) {
|
|
638
742
|
return account.createAccountProof({
|
|
743
|
+
keyHandle,
|
|
639
744
|
context,
|
|
640
745
|
ringLocation: location,
|
|
641
746
|
message: toHex(message)
|
|
@@ -649,11 +754,27 @@ function adaptAccountsProvider(client) {
|
|
|
649
754
|
ringRevision: response.ringRevision
|
|
650
755
|
}));
|
|
651
756
|
},
|
|
757
|
+
ringVrfSign(keyHandle, message) {
|
|
758
|
+
return account.ringVrfSign({
|
|
759
|
+
keyHandle,
|
|
760
|
+
message: toHex(message)
|
|
761
|
+
}).map(fromHex);
|
|
762
|
+
},
|
|
763
|
+
signVrf(account_, transcriptLabel, items) {
|
|
764
|
+
return account.signVrf({
|
|
765
|
+
account: toWireProductAccountId(account_),
|
|
766
|
+
transcriptLabel: toHex(transcriptLabel),
|
|
767
|
+
items: items.map(({ label, value }) => ({
|
|
768
|
+
label: toHex(label),
|
|
769
|
+
value: toHex(value)
|
|
770
|
+
}))
|
|
771
|
+
}).map((response) => ({
|
|
772
|
+
preOutput: fromHex(response.preOutput),
|
|
773
|
+
proof: fromHex(response.proof)
|
|
774
|
+
}));
|
|
775
|
+
},
|
|
652
776
|
getProductAccountSigner(account_) {
|
|
653
|
-
const productAccountId = toWireProductAccountId(
|
|
654
|
-
account_.dotNsIdentifier,
|
|
655
|
-
account_.derivationIndex
|
|
656
|
-
);
|
|
777
|
+
const productAccountId = toWireProductAccountId(account_);
|
|
657
778
|
return {
|
|
658
779
|
publicKey: account_.publicKey,
|
|
659
780
|
async signTx(callData, signedExtensions, metadata) {
|
|
@@ -728,13 +849,13 @@ async function getAccountsProvider() {
|
|
|
728
849
|
const client = await getClient();
|
|
729
850
|
return client ? adaptAccountsProvider(client) : null;
|
|
730
851
|
}
|
|
731
|
-
var
|
|
852
|
+
var log4 = createLogger("host:permissions");
|
|
732
853
|
async function requestPermission(permission) {
|
|
733
854
|
const truApi = await getTruApi();
|
|
734
855
|
if (!truApi) {
|
|
735
856
|
return err(new HostUnavailableError("requestPermission: TruAPI unavailable"));
|
|
736
857
|
}
|
|
737
|
-
|
|
858
|
+
log4.debug("requestPermission", { tag: permission.tag });
|
|
738
859
|
return mapHostResult(
|
|
739
860
|
truApi.permissions.requestRemotePermission({ permission }),
|
|
740
861
|
(response) => response.granted,
|
|
@@ -746,7 +867,7 @@ async function requestDevicePermission(permission) {
|
|
|
746
867
|
if (!truApi) {
|
|
747
868
|
return err(new HostUnavailableError("requestDevicePermission: TruAPI unavailable"));
|
|
748
869
|
}
|
|
749
|
-
|
|
870
|
+
log4.debug("requestDevicePermission", { permission });
|
|
750
871
|
return mapHostResult(
|
|
751
872
|
truApi.permissions.requestDevicePermission(permission),
|
|
752
873
|
(response) => response.granted,
|
|
@@ -766,13 +887,13 @@ async function getThemeProvider() {
|
|
|
766
887
|
const client = await getClient();
|
|
767
888
|
return client ? adaptThemeProvider(client) : null;
|
|
768
889
|
}
|
|
769
|
-
var
|
|
890
|
+
var log5 = createLogger("host:entropy");
|
|
770
891
|
async function deriveEntropy(key) {
|
|
771
892
|
const truApi = await getTruApi();
|
|
772
893
|
if (!truApi) {
|
|
773
894
|
return err(new HostUnavailableError("deriveEntropy: TruAPI unavailable"));
|
|
774
895
|
}
|
|
775
|
-
|
|
896
|
+
log5.debug("deriveEntropy", { keyLen: key.length });
|
|
776
897
|
return mapHostResult(
|
|
777
898
|
truApi.entropy.derive({ context: toHex(key) }),
|
|
778
899
|
(response) => fromHex(response.entropy),
|
|
@@ -885,22 +1006,22 @@ async function getNotificationManager() {
|
|
|
885
1006
|
const client = await getClient();
|
|
886
1007
|
return client ? adaptNotificationManager(client) : null;
|
|
887
1008
|
}
|
|
888
|
-
var
|
|
1009
|
+
var log6 = createLogger("host:navigation");
|
|
889
1010
|
async function navigateTo(url) {
|
|
890
1011
|
const truApi = await getTruApi();
|
|
891
1012
|
if (!truApi) {
|
|
892
1013
|
return err(new HostUnavailableError("navigateTo: TruAPI unavailable"));
|
|
893
1014
|
}
|
|
894
|
-
|
|
1015
|
+
log6.debug("navigateTo", { url });
|
|
895
1016
|
return mapHostResult(truApi.system.navigateTo({ url }), () => void 0, "navigateTo failed");
|
|
896
1017
|
}
|
|
897
|
-
var
|
|
1018
|
+
var log7 = createLogger("host:features");
|
|
898
1019
|
async function featureSupported(feature) {
|
|
899
1020
|
const truApi = await getTruApi();
|
|
900
1021
|
if (!truApi) {
|
|
901
1022
|
return err(new HostUnavailableError("featureSupported: TruAPI unavailable"));
|
|
902
1023
|
}
|
|
903
|
-
|
|
1024
|
+
log7.debug("featureSupported", { tag: feature.tag });
|
|
904
1025
|
return mapHostResult(
|
|
905
1026
|
truApi.system.featureSupported({ tag: feature.tag, value: { genesisHash: feature.value } }),
|
|
906
1027
|
(response) => response.supported,
|
|
@@ -910,14 +1031,14 @@ async function featureSupported(feature) {
|
|
|
910
1031
|
async function isChainSupported(genesisHash) {
|
|
911
1032
|
return featureSupported({ tag: "Chain", value: genesisHash });
|
|
912
1033
|
}
|
|
913
|
-
var
|
|
1034
|
+
var log8 = createLogger("host:chain-spec");
|
|
914
1035
|
async function getChainSpec(genesisHash) {
|
|
915
1036
|
const truApi = await getTruApi();
|
|
916
1037
|
if (!truApi) {
|
|
917
|
-
|
|
1038
|
+
log8.debug("getChainSpec: TruAPI unavailable");
|
|
918
1039
|
return ok(null);
|
|
919
1040
|
}
|
|
920
|
-
|
|
1041
|
+
log8.debug("getChainSpec", { genesisHash });
|
|
921
1042
|
const [genesisHashResult, nameResult, propertiesResult] = await Promise.all([
|
|
922
1043
|
mapHostResult(
|
|
923
1044
|
truApi.chain.getSpecGenesisHash({ genesisHash }),
|
|
@@ -943,7 +1064,7 @@ async function getChainSpec(genesisHash) {
|
|
|
943
1064
|
try {
|
|
944
1065
|
properties = JSON.parse(propertiesRaw);
|
|
945
1066
|
} catch (parseError) {
|
|
946
|
-
|
|
1067
|
+
log8.debug("getChainSpec: properties JSON parse failed", parseError);
|
|
947
1068
|
properties = null;
|
|
948
1069
|
}
|
|
949
1070
|
return ok({
|
|
@@ -953,13 +1074,13 @@ async function getChainSpec(genesisHash) {
|
|
|
953
1074
|
propertiesRaw
|
|
954
1075
|
});
|
|
955
1076
|
}
|
|
956
|
-
var
|
|
1077
|
+
var log9 = createLogger("host:chain-transaction");
|
|
957
1078
|
async function broadcastTransaction(genesisHash, transaction) {
|
|
958
1079
|
const truApi = await getTruApi();
|
|
959
1080
|
if (!truApi) {
|
|
960
1081
|
return err(new HostUnavailableError("broadcastTransaction: TruAPI unavailable"));
|
|
961
1082
|
}
|
|
962
|
-
|
|
1083
|
+
log9.debug("broadcastTransaction", { genesisHash });
|
|
963
1084
|
return mapHostResult(
|
|
964
1085
|
truApi.chain.broadcastTransaction({ genesisHash, transaction }),
|
|
965
1086
|
(response) => response.operationId ?? null,
|
|
@@ -971,7 +1092,7 @@ async function stopTransaction(genesisHash, operationId) {
|
|
|
971
1092
|
if (!truApi) {
|
|
972
1093
|
return err(new HostUnavailableError("stopTransaction: TruAPI unavailable"));
|
|
973
1094
|
}
|
|
974
|
-
|
|
1095
|
+
log9.debug("stopTransaction", { genesisHash, operationId });
|
|
975
1096
|
return mapHostResult(
|
|
976
1097
|
truApi.chain.stopTransaction({ genesisHash, operationId }),
|
|
977
1098
|
() => void 0,
|
|
@@ -979,6 +1100,6 @@ async function stopTransaction(genesisHash, operationId) {
|
|
|
979
1100
|
);
|
|
980
1101
|
}
|
|
981
1102
|
|
|
982
|
-
export { BULLETIN_RPCS, ChainNotSupportedError, DEFAULT_BULLETIN_ENDPOINT, HostCallFailedError, HostError, HostUnavailableError, broadcastTransaction, createHostLocalStorage, createHostPreimageManager, createProofAuthorized, deriveEntropy, featureSupported, formatHostError, fromHex, getAccountsProvider, getChainSpec, getChatManager, getHostLocalStorage, getHostProvider, getNotificationManager, getPaymentManager, getPreimageManager, getStatementStore, getThemeProvider, getTruApi, isChainSupported, isHostError, isInsideContainer, navigateTo, requestDevicePermission, requestPermission, requestResourceAllocation, stopTransaction, toHex };
|
|
1103
|
+
export { BULLETIN_RPCS, ChainNotSupportedError, DEFAULT_BULLETIN_ENDPOINT, HostCallFailedError, HostError, HostUnavailableError, broadcastTransaction, createHostLocalStorage, createHostPreimageManager, createProofAuthorized, deriveEntropy, featureSupported, findRingVrfKeyHandle, formatHostError, fromHex, getAccountsProvider, getChainSpec, getChatManager, getHostChainInfo, getHostLocalStorage, getHostProvider, getNotificationManager, getPaymentManager, getPreimageManager, getStatementStore, getThemeProvider, getTruApi, isChainSupported, isHostError, isInsideContainer, navigateTo, requestDevicePermission, requestPermission, requestResourceAllocation, stopTransaction, toHex };
|
|
983
1104
|
//# sourceMappingURL=index.js.map
|
|
984
1105
|
//# sourceMappingURL=index.js.map
|