@parity/product-sdk 0.29.0 → 0.30.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/address/index.d.ts +1 -0
- package/dist/{chunk-KXJT2BNL.js → chunk-VWD6HK2C.js} +26 -9
- package/dist/chunk-VWD6HK2C.js.map +1 -0
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.js +1 -1
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +2 -2
- package/dist/react/index.js.map +1 -1
- package/dist/renderer/index.d.ts +1 -0
- package/dist/renderer/index.js +3 -0
- package/dist/renderer/index.js.map +1 -0
- package/dist/testing/index.d.ts +1 -1
- package/dist/{types-C676_6Fp.d.ts → types-BpWw-OJl.d.ts} +10 -5
- package/package.json +17 -11
- package/src/core/createApp.test.ts +194 -0
- package/src/core/createApp.ts +32 -10
- package/src/core/types.ts +10 -4
- package/src/index.ts +3 -2
- package/src/react/context.ts +1 -1
- package/src/react/index.ts +1 -1
- package/src/react/provider.tsx +3 -3
- package/src/renderer/index.ts +10 -0
- package/dist/chunk-KXJT2BNL.js.map +0 -1
package/dist/address/index.d.ts
CHANGED
|
@@ -7,17 +7,34 @@ import { CloudStorageClient, createLazySigner, calculateCid, ProductCloudStorage
|
|
|
7
7
|
import { err, ok } from '@parity/result';
|
|
8
8
|
import { isConnected, getClient, createChainClient, destroyAll } from '@parity/product-sdk-chain-client';
|
|
9
9
|
import { accountIdBytes } from '@parity/product-sdk-address';
|
|
10
|
-
import { getAccountsProvider } from '@parity/product-sdk-host';
|
|
10
|
+
import { getTruApi, HostUnavailableError, HostCallFailedError, getAccountsProvider } from '@parity/product-sdk-host';
|
|
11
11
|
|
|
12
12
|
var log = createLogger("app");
|
|
13
|
-
async function createApp(config) {
|
|
13
|
+
async function createApp(config = {}) {
|
|
14
14
|
if (config.logLevel) {
|
|
15
15
|
configure({ level: config.logLevel });
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
if (config.name !== void 0) {
|
|
18
|
+
log.warn(
|
|
19
|
+
"createApp: name is deprecated and ignored. Remove the name option. The SDK resolves the app name from system.getProductContext(), dropping the product ID's final domain suffix (my-app.dot -> my-app). Local development IDs stay unchanged."
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
const truApi = await getTruApi();
|
|
23
|
+
if (!truApi) {
|
|
24
|
+
throw new HostUnavailableError("createApp requires a host product context");
|
|
25
|
+
}
|
|
26
|
+
const { productId } = await truApi.system.getProductContext().match(
|
|
27
|
+
(context) => context,
|
|
28
|
+
(error) => {
|
|
29
|
+
throw new HostCallFailedError("system.getProductContext", error);
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
const isLocalHost = /^(?:localhost|127\.0\.0\.1|[^:]+\.localhost)(?::\d+)?$/i.test(productId);
|
|
33
|
+
const name = isLocalHost ? productId : productId.replace(/\.[^.]+$/, "");
|
|
34
|
+
log.info("Creating Product SDK app", { name });
|
|
35
|
+
const localKvStore = await createLocalKvStore({ prefix: name });
|
|
19
36
|
const signerManager = new SignerManager({
|
|
20
|
-
dappName:
|
|
37
|
+
dappName: productId
|
|
21
38
|
});
|
|
22
39
|
const cloudStorageEnabled = config.cloudStorage !== false;
|
|
23
40
|
const cloudStorageEnvironment = typeof config.cloudStorage === "object" ? config.cloudStorage.environment : "paseo";
|
|
@@ -82,7 +99,7 @@ async function createApp(config) {
|
|
|
82
99
|
}
|
|
83
100
|
} : null;
|
|
84
101
|
log.info("Product SDK app created", {
|
|
85
|
-
name
|
|
102
|
+
name,
|
|
86
103
|
cloudStorage: cloudStorageEnabled ? cloudStorageEnvironment : "disabled"
|
|
87
104
|
});
|
|
88
105
|
return {
|
|
@@ -90,7 +107,7 @@ async function createApp(config) {
|
|
|
90
107
|
localStorage: localStorageApi,
|
|
91
108
|
chain: chainApi,
|
|
92
109
|
cloudStorage: cloudStorageApi,
|
|
93
|
-
getAppInfo: () => ({ ...config })
|
|
110
|
+
getAppInfo: () => ({ ...config, name })
|
|
94
111
|
};
|
|
95
112
|
}
|
|
96
113
|
function createWalletApi(signerManager) {
|
|
@@ -228,5 +245,5 @@ async function getPrimaryUsername(accountsProvider) {
|
|
|
228
245
|
}
|
|
229
246
|
|
|
230
247
|
export { createApp };
|
|
231
|
-
//# sourceMappingURL=chunk-
|
|
232
|
-
//# sourceMappingURL=chunk-
|
|
248
|
+
//# sourceMappingURL=chunk-VWD6HK2C.js.map
|
|
249
|
+
//# sourceMappingURL=chunk-VWD6HK2C.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/createApp.ts"],"names":["err"],"mappings":"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","file":"chunk-VWD6HK2C.js","sourcesContent":["// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * createApp - Main entry point for the Product SDK\n *\n * Creates an App instance with wallet, storage, chain, and cloud storage APIs.\n */\n\nimport type { ChainDefinition } from \"polkadot-api\";\nimport type {\n App,\n AppConfig,\n WalletApi,\n ChainApi,\n Account,\n CloudStorageApi,\n LocalStorageApi,\n} from \"./types.js\";\nimport { createLocalStorageApi } from \"./local-storage-api.js\";\nimport { configure, createLogger } from \"@parity/product-sdk-logger\";\nimport { createLocalKvStore } from \"@parity/product-sdk-local-storage\";\nimport { SignerManager } from \"@parity/product-sdk-signer\";\nimport {\n CloudStorageClient,\n ProductCloudStorageError,\n calculateCid,\n createLazySigner,\n} from \"@parity/product-sdk-cloud-storage\";\nimport { err, ok } from \"@parity/result\";\nimport {\n createChainClient,\n getClient,\n isConnected,\n destroyAll,\n} from \"@parity/product-sdk-chain-client\";\nimport { accountIdBytes } from \"@parity/product-sdk-address\";\nimport {\n getAccountsProvider,\n getTruApi,\n HostCallFailedError,\n HostUnavailableError,\n} from \"@parity/product-sdk-host\";\nimport {\n accountIdBytesToHex,\n type PeopleUsernameQueryApi,\n resolvePeopleUsernameOwner,\n} from \"../identity/dotns.js\";\n\nconst log = createLogger(\"app\");\n\n/**\n * Create a new Product SDK app instance\n *\n * @param config - Application configuration\n * @returns App instance with all APIs\n *\n * @example\n * ```ts\n * import { createApp } from '@parity/product-sdk';\n *\n * // Default: cloud storage enabled with paseo environment\n * const app = await createApp({\n * logLevel: 'info',\n * });\n *\n * // Custom cloud storage environment\n * const prodApp = await createApp({\n * cloudStorage: { environment: 'polkadot' },\n * });\n *\n * // Disable cloud storage entirely\n * const noCloudStorageApp = await createApp({\n * cloudStorage: false,\n * });\n *\n * // Connect wallet\n * const { accounts } = await app.wallet.connect();\n *\n * // Use storage\n * await app.localStorage.set('key', 'value');\n *\n * // Use cloud storage (check for null if it might be disabled)\n * if (app.cloudStorage) {\n * const cid = await app.cloudStorage.upload('hello world');\n * }\n * ```\n */\nexport async function createApp(config: AppConfig = {}): Promise<App> {\n // Set log level if specified\n if (config.logLevel) {\n configure({ level: config.logLevel });\n }\n\n if (config.name !== undefined) {\n log.warn(\n \"createApp: name is deprecated and ignored. Remove the name option. The SDK resolves the app name from system.getProductContext(), dropping the product ID's final domain suffix (my-app.dot -> my-app). Local development IDs stay unchanged.\",\n );\n }\n\n const truApi = await getTruApi();\n if (!truApi) {\n throw new HostUnavailableError(\"createApp requires a host product context\");\n }\n const { productId } = await truApi.system.getProductContext().match(\n (context) => context,\n (error) => {\n throw new HostCallFailedError(\"system.getProductContext\", error);\n },\n );\n\n const isLocalHost = /^(?:localhost|127\\.0\\.0\\.1|[^:]+\\.localhost)(?::\\d+)?$/i.test(productId);\n const name = isLocalHost ? productId : productId.replace(/\\.[^.]+$/, \"\");\n\n log.info(\"Creating Product SDK app\", { name });\n\n // Initialize storage (container-only - will throw if not in container)\n const localKvStore = await createLocalKvStore({ prefix: name });\n\n // Initialize signer manager\n const signerManager = new SignerManager({\n dappName: productId,\n });\n\n // Initialize cloud storage client (configurable, defaults to paseo).\n //\n // The signer is wrapped lazily so the cloud storage client can be built before\n // an account is selected. Uploads will throw a clear error if no signer\n // is available at submission time. Reads (fetch / fetchJson) don't need\n // a signer, so they work regardless of whether an account is selected --\n // but they are container-only and throw CloudStorageHostUnavailableError\n // outside a host container (no IPFS-gateway fallback).\n const cloudStorageEnabled = config.cloudStorage !== false;\n const cloudStorageEnvironment =\n typeof config.cloudStorage === \"object\" ? config.cloudStorage.environment : \"paseo\";\n const cloudStorageClient = cloudStorageEnabled\n ? await CloudStorageClient.create({\n environment: cloudStorageEnvironment,\n signer: createLazySigner(() => signerManager.getSigner()),\n })\n : null;\n\n if (cloudStorageEnabled) {\n log.debug(\"Cloud Storage client (Bulletin) initialized\", {\n environment: cloudStorageEnvironment,\n });\n } else {\n log.debug(\"Cloud Storage client disabled\");\n }\n\n // Storage API adapter — shared with `createFakeApp` so the two cannot drift.\n const localStorageApi: LocalStorageApi = createLocalStorageApi(localKvStore);\n\n // Create wallet API adapter\n const walletApi = createWalletApi(signerManager);\n\n // Create chain API\n const chainApi: ChainApi = {\n getClient(descriptor) {\n log.debug(\"getClient called\", { genesis: descriptor.genesis });\n const client = getClient(descriptor);\n return client.getTypedApi(descriptor);\n },\n\n getRawClient(descriptor) {\n log.debug(\"getRawClient called\", { genesis: descriptor.genesis });\n return getClient(descriptor);\n },\n\n async connect<T extends Record<string, ChainDefinition>>(chains: T) {\n log.debug(\"connect called\", { chains: Object.keys(chains) });\n return createChainClient({ chains });\n },\n\n isConnected(descriptor) {\n return isConnected(descriptor);\n },\n\n destroyAll() {\n log.debug(\"destroyAll called\");\n destroyAll();\n },\n };\n\n // Create Cloud Storage API adapter (null if disabled)\n const cloudStorageApi: CloudStorageApi | null = cloudStorageClient\n ? {\n upload: async (data) => {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n try {\n // Explicitly request a DAG-PB manifest so chunked uploads always\n // resolve to a single root CID. Without this, AsyncBulletinClient\n // can return `result.cid: undefined` for chunked-without-manifest\n // uploads — but app consumers expect a CID they can hand to\n // `fetch(cid)`, so treat a missing CID as an error.\n const uploaded = await cloudStorageClient\n .store(bytes)\n .withManifest(true)\n .send();\n if (!uploaded.cid) {\n return err(\n new ProductCloudStorageError(\n \"Cloud storage upload returned no CID despite .withManifest(true). Upstream contract may have shifted — file an issue.\",\n ),\n );\n }\n return ok(uploaded.cid.toString());\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n return err(new ProductCloudStorageError(message, { cause }));\n }\n },\n fetch: (cid) => cloudStorageClient.fetchBytes(cid),\n computeCid: async (data) => {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n const cid = await calculateCid(bytes);\n return cid.toString();\n },\n }\n : null;\n\n log.info(\"Product SDK app created\", {\n name,\n cloudStorage: cloudStorageEnabled ? cloudStorageEnvironment : \"disabled\",\n });\n\n return {\n wallet: walletApi,\n localStorage: localStorageApi,\n chain: chainApi,\n cloudStorage: cloudStorageApi,\n getAppInfo: () => ({ ...config, name }),\n };\n}\n\n/**\n * Create wallet API adapter using SignerManager from leaf package\n */\nfunction createWalletApi(signerManager: SignerManager): WalletApi {\n // Track account change subscribers\n const accountChangeSubscribers = new Set<(account: Account | null) => void>();\n\n // Subscribe to signer manager state changes\n signerManager.subscribe((state) => {\n const account = state.selectedAccount\n ? {\n address: state.selectedAccount.address,\n name: state.selectedAccount.name ?? undefined,\n source: state.selectedAccount.source,\n }\n : null;\n for (const callback of accountChangeSubscribers) {\n try {\n callback(account);\n } catch (e) {\n log.warn(\"Account change callback threw\", { error: e });\n }\n }\n });\n\n return {\n async connect(): Promise<{ accounts: Account[] }> {\n const result = await signerManager.connect();\n if (!result.ok) {\n throw new Error(result.error.message);\n }\n return {\n accounts: result.value.map((a) => ({\n address: a.address,\n name: a.name ?? undefined,\n source: a.source,\n })),\n };\n },\n\n async disconnect(): Promise<void> {\n signerManager.disconnect();\n },\n\n getAccounts(): Account[] {\n return signerManager.getState().accounts.map((a) => ({\n address: a.address,\n name: a.name ?? undefined,\n source: a.source,\n }));\n },\n\n getSelectedAccount(): Account | null {\n const selected = signerManager.getState().selectedAccount;\n if (!selected) return null;\n return {\n address: selected.address,\n name: selected.name ?? undefined,\n source: selected.source,\n };\n },\n\n selectAccount(address: string): void {\n signerManager.selectAccount(address);\n },\n\n async signMessage(message: string | Uint8Array): Promise<Uint8Array> {\n const bytes = typeof message === \"string\" ? new TextEncoder().encode(message) : message;\n const result = await signerManager.signRaw(bytes);\n if (!result.ok) {\n throw new Error(result.error.message);\n }\n return result.value;\n },\n\n async signMessageWithDotNsIdentity(args) {\n const message =\n typeof args.message === \"string\"\n ? new TextEncoder().encode(args.message)\n : args.message;\n const accountsProvider = await getHostAccountsProvider();\n const username = args.username ?? (await getPrimaryUsername(accountsProvider));\n\n // Reuse an already-connected People chain when the caller has\n // wired one up via `app.chain.connect({ ..., <name>: peopleChain })`.\n // Fall back to opening a transient connection so first-time users\n // don't have to think about chain lifecycles. The chain-client\n // module caches by genesis fingerprint, so subsequent\n // signMessageWithDotNsIdentity calls share whichever connection\n // got established first.\n const peopleClient = isConnected(args.peopleChain)\n ? getClient(args.peopleChain)\n : await createChainClient({ chains: { people: args.peopleChain } }).then(\n (c) => c.raw.people,\n );\n // PAPI's `TypedApi.query.X.Y.getValue` is variadic\n // (`...args: [...WithCallOptions<Args>]`) so it's not assignable\n // to our deliberately-narrow `(key) => Promise<...>` shape. The\n // resolver only ever passes the storage key; the cast adapts the\n // wider PAPI surface to the minimum we depend on.\n const peopleApi = peopleClient.getTypedApi(\n args.peopleChain,\n ) as unknown as PeopleUsernameQueryApi;\n const owner = await resolvePeopleUsernameOwner(username, peopleApi);\n if (!owner) {\n throw new Error(`No account owns DotNS username \"${username}\"`);\n }\n\n const publicKey = accountIdBytes(owner);\n // This field is hex, not the SS58 the resolver now returns. Converted\n // here and not in the try, so an address failure is not reported as a\n // signing failure.\n const accountId = accountIdBytesToHex(publicKey);\n const signer = accountsProvider.getLegacyAccountSigner({ publicKey, name: username });\n\n try {\n return {\n username,\n accountId,\n signature: await signer.signBytes(message),\n };\n } catch (cause) {\n throw new Error(\n `Failed to sign with DotNS username \"${username}\": ${\n cause instanceof Error ? cause.message : String(cause)\n }`,\n { cause },\n );\n }\n },\n\n onAccountChange(callback: (account: Account | null) => void): () => void {\n accountChangeSubscribers.add(callback);\n return () => accountChangeSubscribers.delete(callback);\n },\n\n getProductAccount(): Account | null {\n // Product accounts require async call - this sync API can't support it properly\n // Users should use SignerManager.getProductAccount() directly\n log.warn(\n \"getProductAccount() is deprecated - use SignerManager.getProductAccount() directly\",\n );\n return null;\n },\n\n getAnonymousAlias(): string | null {\n // Anonymous aliases require async call - this sync API can't support it properly\n // Users should use SignerManager.getProductAccountAlias() directly\n log.warn(\n \"getAnonymousAlias() is deprecated - use SignerManager.getProductAccountAlias() directly\",\n );\n return null;\n },\n\n async createProof(_message: Uint8Array): Promise<Uint8Array> {\n // Ring VRF proofs require SignerManager.createRingVRFProof() directly\n throw new Error(\n \"createProof() is not implemented in the App API. \" +\n \"Use SignerManager.createRingVRFProof() directly.\",\n );\n },\n };\n}\n\ntype HostAccountsProvider = NonNullable<Awaited<ReturnType<typeof getAccountsProvider>>>;\n\nasync function getHostAccountsProvider(): Promise<HostAccountsProvider> {\n const provider = await getAccountsProvider();\n if (!provider) {\n throw new Error(\"Host accounts provider is not available\");\n }\n return provider;\n}\n\nasync function getPrimaryUsername(accountsProvider: HostAccountsProvider): Promise<string> {\n const result = await accountsProvider.getUserId().match(\n (value) => value,\n (err) => {\n throw err;\n },\n );\n const username = result.primaryUsername.trim();\n if (!username) {\n throw new Error(\"Host identity did not provide a primary DotNS username\");\n }\n return username;\n}\n"]}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createApp } from '../index.js';
|
|
2
2
|
export { LogEntry, LogHandler, LogLevel, Logger, LoggerConfig, configure, createLogger } from '@parity/product-sdk-logger';
|
|
3
|
-
export { A as Account, b as App, c as AppConfig, C as ChainApi, a as CloudStorageApi,
|
|
3
|
+
export { A as Account, b as App, c as AppConfig, d as AppInfo, C as ChainApi, a as CloudStorageApi, e as CloudStorageConfig, D as DotNsIdentitySignature, L as LocalStorageApi, S as SignMessageWithDotNsIdentityArgs, W as WalletApi } from '../types-BpWw-OJl.js';
|
|
4
4
|
export { ChainClient } from '@parity/product-sdk-chain-client';
|
|
5
5
|
export { ChainDefinition, PolkadotClient, TypedApi } from 'polkadot-api';
|
|
6
6
|
import '@parity/result';
|
package/dist/core/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { LogEntry, LogHandler, LogLevel, Logger, LoggerConfig, configure, createLogger } from '@parity/product-sdk-logger';
|
|
2
|
-
import { c as AppConfig, b as App } from './types-
|
|
3
|
-
export { A as Account, C as ChainApi, a as CloudStorageApi, D as DotNsIdentitySignature, L as LocalStorageApi, S as SignMessageWithDotNsIdentityArgs, W as WalletApi } from './types-
|
|
2
|
+
import { c as AppConfig, b as App } from './types-BpWw-OJl.js';
|
|
3
|
+
export { A as Account, d as AppInfo, C as ChainApi, a as CloudStorageApi, D as DotNsIdentitySignature, L as LocalStorageApi, S as SignMessageWithDotNsIdentityArgs, W as WalletApi } from './types-BpWw-OJl.js';
|
|
4
4
|
export { Result, err, isErrorOf, ok } from '@parity/result';
|
|
5
5
|
export { SdkError, isSdkError } from '@parity/product-sdk-errors';
|
|
6
6
|
export { isInsideContainer, isInsideContainerSync } from '@parity/product-sdk-host';
|
|
@@ -29,19 +29,16 @@ import './dotns-CtmOwVQW.js';
|
|
|
29
29
|
*
|
|
30
30
|
* // Default: cloud storage enabled with paseo environment
|
|
31
31
|
* const app = await createApp({
|
|
32
|
-
* name: 'my-app',
|
|
33
32
|
* logLevel: 'info',
|
|
34
33
|
* });
|
|
35
34
|
*
|
|
36
35
|
* // Custom cloud storage environment
|
|
37
36
|
* const prodApp = await createApp({
|
|
38
|
-
* name: 'my-app',
|
|
39
37
|
* cloudStorage: { environment: 'polkadot' },
|
|
40
38
|
* });
|
|
41
39
|
*
|
|
42
40
|
* // Disable cloud storage entirely
|
|
43
41
|
* const noCloudStorageApp = await createApp({
|
|
44
|
-
* name: 'my-app',
|
|
45
42
|
* cloudStorage: false,
|
|
46
43
|
* });
|
|
47
44
|
*
|
|
@@ -57,6 +54,6 @@ import './dotns-CtmOwVQW.js';
|
|
|
57
54
|
* }
|
|
58
55
|
* ```
|
|
59
56
|
*/
|
|
60
|
-
declare function createApp(config
|
|
57
|
+
declare function createApp(config?: AppConfig): Promise<App>;
|
|
61
58
|
|
|
62
59
|
export { App, AppConfig, createApp };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { configure, createLogger } from './chunk-JVJ552RU.js';
|
|
2
|
-
export { createApp } from './chunk-
|
|
2
|
+
export { createApp } from './chunk-VWD6HK2C.js';
|
|
3
3
|
import './chunk-7GM3HUZF.js';
|
|
4
4
|
import './chunk-TUXU2VPS.js';
|
|
5
5
|
export { err, isErrorOf, ok } from '@parity/result';
|
package/dist/react/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
4
|
import { LogLevel } from '@parity/product-sdk-logger';
|
|
5
|
-
import { b as App, S as SignMessageWithDotNsIdentityArgs, D as DotNsIdentitySignature, A as Account } from '../types-
|
|
5
|
+
import { b as App, S as SignMessageWithDotNsIdentityArgs, D as DotNsIdentitySignature, A as Account } from '../types-BpWw-OJl.js';
|
|
6
6
|
import { ChainDefinition, TypedApi } from 'polkadot-api';
|
|
7
7
|
import '@parity/product-sdk-cloud-storage';
|
|
8
8
|
import '@parity/result';
|
|
@@ -11,8 +11,8 @@ import '../dotns-CtmOwVQW.js';
|
|
|
11
11
|
|
|
12
12
|
/** Props for ProductSDKProvider */
|
|
13
13
|
interface ProductSDKProviderProps {
|
|
14
|
-
/**
|
|
15
|
-
name
|
|
14
|
+
/** @deprecated Ignored with a warning. The host product ID supplies the app name. */
|
|
15
|
+
name?: string;
|
|
16
16
|
/** Log level (default: 'info') */
|
|
17
17
|
logLevel?: LogLevel;
|
|
18
18
|
/** Child components */
|
|
@@ -29,7 +29,7 @@ interface ProductSDKProviderProps {
|
|
|
29
29
|
*
|
|
30
30
|
* function App() {
|
|
31
31
|
* return (
|
|
32
|
-
* <ProductSDKProvider
|
|
32
|
+
* <ProductSDKProvider fallback={<Loading />}>
|
|
33
33
|
* <MyApp />
|
|
34
34
|
* </ProductSDKProvider>
|
|
35
35
|
* );
|
package/dist/react/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createApp } from '../chunk-
|
|
1
|
+
import { createApp } from '../chunk-VWD6HK2C.js';
|
|
2
2
|
import '../chunk-7GM3HUZF.js';
|
|
3
3
|
import '../chunk-TUXU2VPS.js';
|
|
4
4
|
import { createContext, useContext, useState, useEffect, useCallback, useMemo } from 'react';
|
|
@@ -9,7 +9,7 @@ function useProductSDK() {
|
|
|
9
9
|
const app = useContext(ProductSDKContext);
|
|
10
10
|
if (!app) {
|
|
11
11
|
throw new Error(
|
|
12
|
-
|
|
12
|
+
"useProductSDK must be used within a ProductSDKProvider. Wrap your app with <ProductSDKProvider>."
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
return app;
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/context.ts","../../src/react/provider.tsx","../../src/react/useWallet.ts","../../src/react/useLocalStorage.ts","../../src/react/useChain.ts"],"names":["useState","useEffect","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * React context for Product SDK\n */\n\nimport { createContext, useContext } from \"react\";\nimport type { App } from \"../core/types.js\";\n\n/** Context for the Product SDK app instance */\nexport const ProductSDKContext = createContext<App | null>(null);\n\n/**\n * Hook to access the Product SDK app instance\n *\n * @throws If used outside of ProductSDKProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const app = useProductSDK();\n * // Use app.wallet, app.localStorage, etc.\n * }\n * ```\n */\nexport function useProductSDK(): App {\n const app = useContext(ProductSDKContext);\n if (!app) {\n throw new Error(\n \"useProductSDK must be used within a ProductSDKProvider. \" +\n 'Wrap your app with <ProductSDKProvider name=\"your-app\">.',\n );\n }\n return app;\n}\n","// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * ProductSDKProvider component\n */\n\nimport React, { useEffect, useState, type ReactNode } from \"react\";\nimport { ProductSDKContext } from \"./context.js\";\nimport { createApp } from \"../core/createApp.js\";\nimport type { App, LogLevel } from \"../core/types.js\";\n\n/** Props for ProductSDKProvider */\nexport interface ProductSDKProviderProps {\n /** Application name - used for storage namespacing and product account derivation */\n name: string;\n /** Log level (default: 'info') */\n logLevel?: LogLevel;\n /** Child components */\n children: ReactNode;\n /** Fallback to show while loading */\n fallback?: ReactNode;\n}\n\n/**\n * Provider component that initializes the Product SDK\n *\n * @example\n * ```tsx\n * import { ProductSDKProvider } from '@parity/product-sdk/react';\n *\n * function App() {\n * return (\n * <ProductSDKProvider name=\"my-app\" fallback={<Loading />}>\n * <MyApp />\n * </ProductSDKProvider>\n * );\n * }\n * ```\n */\nexport function ProductSDKProvider({\n name,\n logLevel = \"info\",\n children,\n fallback = null,\n}: ProductSDKProviderProps) {\n const [app, setApp] = useState<App | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n let mounted = true;\n\n createApp({ name, logLevel })\n .then((createdApp) => {\n if (mounted) {\n setApp(createdApp);\n }\n })\n .catch((e) => {\n if (mounted) {\n setError(e instanceof Error ? e : new Error(String(e)));\n }\n });\n\n return () => {\n mounted = false;\n };\n }, [name, logLevel]);\n\n if (error) {\n throw error;\n }\n\n if (!app) {\n return <>{fallback}</>;\n }\n\n return <ProductSDKContext.Provider value={app}>{children}</ProductSDKContext.Provider>;\n}\n","// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * useWallet hook\n */\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useProductSDK } from \"./context.js\";\nimport type {\n Account,\n DotNsIdentitySignature,\n SignMessageWithDotNsIdentityArgs,\n} from \"../core/types.js\";\n\n/** Wallet hook state */\nexport interface UseWalletState {\n /** Whether wallet is connected */\n isConnected: boolean;\n /** Whether connection is in progress */\n isConnecting: boolean;\n /** Available accounts */\n accounts: Account[];\n /** Currently selected account */\n selectedAccount: Account | null;\n /** Last error */\n error: Error | null;\n}\n\n/** Wallet hook actions */\nexport interface UseWalletActions {\n /** Connect to wallet */\n connect: () => Promise<void>;\n /** Disconnect from wallet */\n disconnect: () => Promise<void>;\n /** Select an account */\n selectAccount: (address: string) => void;\n /** Sign a message */\n signMessage: (message: string | Uint8Array) => Promise<Uint8Array>;\n /** Sign a message with the account that owns a DotNS / People username identity. */\n signMessageWithDotNsIdentity: (\n args: SignMessageWithDotNsIdentityArgs,\n ) => Promise<DotNsIdentitySignature>;\n}\n\n/** Return type of useWallet */\nexport type UseWalletReturn = UseWalletState & UseWalletActions;\n\n/**\n * Hook for wallet connection and signing\n *\n * @example\n * ```tsx\n * function WalletButton() {\n * const { isConnected, accounts, connect, disconnect, selectAccount } = useWallet();\n *\n * if (!isConnected) {\n * return <button onClick={connect}>Connect Wallet</button>;\n * }\n *\n * return (\n * <div>\n * <select onChange={(e) => selectAccount(e.target.value)}>\n * {accounts.map((a) => (\n * <option key={a.address} value={a.address}>\n * {a.name || a.address}\n * </option>\n * ))}\n * </select>\n * <button onClick={disconnect}>Disconnect</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useWallet(): UseWalletReturn {\n const app = useProductSDK();\n\n const [state, setState] = useState<UseWalletState>({\n isConnected: false,\n isConnecting: false,\n accounts: [],\n selectedAccount: null,\n error: null,\n });\n\n const connect = useCallback(async () => {\n setState((s) => ({ ...s, isConnecting: true, error: null }));\n try {\n const result = await app.wallet.connect();\n setState((s) => ({\n ...s,\n isConnected: true,\n isConnecting: false,\n accounts: result.accounts,\n selectedAccount: result.accounts[0] || null,\n }));\n } catch (e) {\n setState((s) => ({\n ...s,\n isConnecting: false,\n error: e instanceof Error ? e : new Error(String(e)),\n }));\n }\n }, [app]);\n\n const disconnect = useCallback(async () => {\n await app.wallet.disconnect();\n setState({\n isConnected: false,\n isConnecting: false,\n accounts: [],\n selectedAccount: null,\n error: null,\n });\n }, [app]);\n\n const selectAccount = useCallback(\n (address: string) => {\n app.wallet.selectAccount(address);\n const account = state.accounts.find((a) => a.address === address) || null;\n setState((s) => ({ ...s, selectedAccount: account }));\n },\n [app, state.accounts],\n );\n\n const signMessage = useCallback(\n async (message: string | Uint8Array) => {\n return app.wallet.signMessage(message);\n },\n [app],\n );\n\n const signMessageWithDotNsIdentity = useCallback(\n async (args: SignMessageWithDotNsIdentityArgs) => {\n return app.wallet.signMessageWithDotNsIdentity(args);\n },\n [app],\n );\n\n // Subscribe to account changes\n useEffect(() => {\n const unsubscribe = app.wallet.onAccountChange((account) => {\n setState((s) => ({ ...s, selectedAccount: account }));\n });\n return unsubscribe;\n }, [app]);\n\n return {\n ...state,\n connect,\n disconnect,\n selectAccount,\n signMessage,\n signMessageWithDotNsIdentity,\n };\n}\n","// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * useLocalStorage hook\n */\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useProductSDK } from \"./context.js\";\n\n/**\n * Hook for key-value storage operations\n *\n * @param key - Storage key\n * @param defaultValue - Default value if key doesn't exist\n *\n * @example\n * ```tsx\n * function ThemeToggle() {\n * const [theme, setTheme, { loading }] = useLocalStorage('theme', 'light');\n *\n * if (loading) return <div>Loading...</div>;\n *\n * return (\n * <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>\n * Current: {theme}\n * </button>\n * );\n * }\n * ```\n */\nexport function useLocalStorage<T = string>(\n key: string,\n defaultValue?: T,\n): [T | null, (value: T) => Promise<void>, { loading: boolean; error: Error | null }] {\n const app = useProductSDK();\n\n const [value, setValue] = useState<T | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n // Load initial value\n useEffect(() => {\n let mounted = true;\n\n const loadValue = async () => {\n try {\n setLoading(true);\n const stored = await app.localStorage.getJSON<T>(key);\n if (mounted) {\n setValue(stored ?? defaultValue ?? null);\n setLoading(false);\n }\n } catch (e) {\n if (mounted) {\n setError(e instanceof Error ? e : new Error(String(e)));\n setLoading(false);\n }\n }\n };\n\n loadValue();\n\n return () => {\n mounted = false;\n };\n }, [app, key, defaultValue]);\n\n const setStoredValue = useCallback(\n async (newValue: T) => {\n try {\n setError(null);\n await app.localStorage.setJSON(key, newValue);\n setValue(newValue);\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n throw e;\n }\n },\n [app, key],\n );\n\n return [value, setStoredValue, { loading, error }];\n}\n\n/**\n * Hook for string storage (simpler API)\n *\n * @param key - Storage key\n * @param defaultValue - Default value\n */\nexport function useLocalStorageString(\n key: string,\n defaultValue?: string,\n): [string | null, (value: string) => Promise<void>, { loading: boolean }] {\n const app = useProductSDK();\n\n const [value, setValue] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let mounted = true;\n\n const loadValue = async () => {\n const stored = await app.localStorage.get(key);\n if (mounted) {\n setValue(stored ?? defaultValue ?? null);\n setLoading(false);\n }\n };\n\n loadValue();\n\n return () => {\n mounted = false;\n };\n }, [app, key, defaultValue]);\n\n const setStoredValue = useCallback(\n async (newValue: string) => {\n await app.localStorage.set(key, newValue);\n setValue(newValue);\n },\n [app, key],\n );\n\n return [value, setStoredValue, { loading }];\n}\n","// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * useChain hook\n */\n\nimport { useMemo } from \"react\";\nimport { useProductSDK } from \"./context.js\";\nimport type { ChainDefinition, TypedApi } from \"../core/types.js\";\n\n/**\n * Hook to get a typed chain client\n *\n * @param chain - Chain descriptor (PAPI ChainDefinition)\n *\n * @example\n * ```tsx\n * import { paseo_asset_hub } from '@parity/product-sdk-descriptors/paseo-asset-hub';\n * import { useChain } from '@parity/product-sdk/react';\n *\n * function AssetHubBalance() {\n * const assetHub = useChain(paseo_asset_hub);\n *\n * // assetHub is typed for Asset Hub queries\n * const balance = await assetHub.query.System.Account.getValue(address);\n * }\n * ```\n */\nexport function useChain<T extends ChainDefinition>(chain: T): TypedApi<T> {\n const app = useProductSDK();\n\n return useMemo(() => {\n return app.chain.getClient(chain);\n }, [app, chain]);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/context.ts","../../src/react/provider.tsx","../../src/react/useWallet.ts","../../src/react/useLocalStorage.ts","../../src/react/useChain.ts"],"names":["useState","useEffect","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * React context for Product SDK\n */\n\nimport { createContext, useContext } from \"react\";\nimport type { App } from \"../core/types.js\";\n\n/** Context for the Product SDK app instance */\nexport const ProductSDKContext = createContext<App | null>(null);\n\n/**\n * Hook to access the Product SDK app instance\n *\n * @throws If used outside of ProductSDKProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const app = useProductSDK();\n * // Use app.wallet, app.localStorage, etc.\n * }\n * ```\n */\nexport function useProductSDK(): App {\n const app = useContext(ProductSDKContext);\n if (!app) {\n throw new Error(\n \"useProductSDK must be used within a ProductSDKProvider. \" +\n \"Wrap your app with <ProductSDKProvider>.\",\n );\n }\n return app;\n}\n","// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * ProductSDKProvider component\n */\n\nimport React, { useEffect, useState, type ReactNode } from \"react\";\nimport { ProductSDKContext } from \"./context.js\";\nimport { createApp } from \"../core/createApp.js\";\nimport type { App, LogLevel } from \"../core/types.js\";\n\n/** Props for ProductSDKProvider */\nexport interface ProductSDKProviderProps {\n /** @deprecated Ignored with a warning. The host product ID supplies the app name. */\n name?: string;\n /** Log level (default: 'info') */\n logLevel?: LogLevel;\n /** Child components */\n children: ReactNode;\n /** Fallback to show while loading */\n fallback?: ReactNode;\n}\n\n/**\n * Provider component that initializes the Product SDK\n *\n * @example\n * ```tsx\n * import { ProductSDKProvider } from '@parity/product-sdk/react';\n *\n * function App() {\n * return (\n * <ProductSDKProvider fallback={<Loading />}>\n * <MyApp />\n * </ProductSDKProvider>\n * );\n * }\n * ```\n */\nexport function ProductSDKProvider({\n name,\n logLevel = \"info\",\n children,\n fallback = null,\n}: ProductSDKProviderProps) {\n const [app, setApp] = useState<App | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n let mounted = true;\n\n createApp({ name, logLevel })\n .then((createdApp) => {\n if (mounted) {\n setApp(createdApp);\n }\n })\n .catch((e) => {\n if (mounted) {\n setError(e instanceof Error ? e : new Error(String(e)));\n }\n });\n\n return () => {\n mounted = false;\n };\n }, [name, logLevel]);\n\n if (error) {\n throw error;\n }\n\n if (!app) {\n return <>{fallback}</>;\n }\n\n return <ProductSDKContext.Provider value={app}>{children}</ProductSDKContext.Provider>;\n}\n","// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * useWallet hook\n */\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useProductSDK } from \"./context.js\";\nimport type {\n Account,\n DotNsIdentitySignature,\n SignMessageWithDotNsIdentityArgs,\n} from \"../core/types.js\";\n\n/** Wallet hook state */\nexport interface UseWalletState {\n /** Whether wallet is connected */\n isConnected: boolean;\n /** Whether connection is in progress */\n isConnecting: boolean;\n /** Available accounts */\n accounts: Account[];\n /** Currently selected account */\n selectedAccount: Account | null;\n /** Last error */\n error: Error | null;\n}\n\n/** Wallet hook actions */\nexport interface UseWalletActions {\n /** Connect to wallet */\n connect: () => Promise<void>;\n /** Disconnect from wallet */\n disconnect: () => Promise<void>;\n /** Select an account */\n selectAccount: (address: string) => void;\n /** Sign a message */\n signMessage: (message: string | Uint8Array) => Promise<Uint8Array>;\n /** Sign a message with the account that owns a DotNS / People username identity. */\n signMessageWithDotNsIdentity: (\n args: SignMessageWithDotNsIdentityArgs,\n ) => Promise<DotNsIdentitySignature>;\n}\n\n/** Return type of useWallet */\nexport type UseWalletReturn = UseWalletState & UseWalletActions;\n\n/**\n * Hook for wallet connection and signing\n *\n * @example\n * ```tsx\n * function WalletButton() {\n * const { isConnected, accounts, connect, disconnect, selectAccount } = useWallet();\n *\n * if (!isConnected) {\n * return <button onClick={connect}>Connect Wallet</button>;\n * }\n *\n * return (\n * <div>\n * <select onChange={(e) => selectAccount(e.target.value)}>\n * {accounts.map((a) => (\n * <option key={a.address} value={a.address}>\n * {a.name || a.address}\n * </option>\n * ))}\n * </select>\n * <button onClick={disconnect}>Disconnect</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useWallet(): UseWalletReturn {\n const app = useProductSDK();\n\n const [state, setState] = useState<UseWalletState>({\n isConnected: false,\n isConnecting: false,\n accounts: [],\n selectedAccount: null,\n error: null,\n });\n\n const connect = useCallback(async () => {\n setState((s) => ({ ...s, isConnecting: true, error: null }));\n try {\n const result = await app.wallet.connect();\n setState((s) => ({\n ...s,\n isConnected: true,\n isConnecting: false,\n accounts: result.accounts,\n selectedAccount: result.accounts[0] || null,\n }));\n } catch (e) {\n setState((s) => ({\n ...s,\n isConnecting: false,\n error: e instanceof Error ? e : new Error(String(e)),\n }));\n }\n }, [app]);\n\n const disconnect = useCallback(async () => {\n await app.wallet.disconnect();\n setState({\n isConnected: false,\n isConnecting: false,\n accounts: [],\n selectedAccount: null,\n error: null,\n });\n }, [app]);\n\n const selectAccount = useCallback(\n (address: string) => {\n app.wallet.selectAccount(address);\n const account = state.accounts.find((a) => a.address === address) || null;\n setState((s) => ({ ...s, selectedAccount: account }));\n },\n [app, state.accounts],\n );\n\n const signMessage = useCallback(\n async (message: string | Uint8Array) => {\n return app.wallet.signMessage(message);\n },\n [app],\n );\n\n const signMessageWithDotNsIdentity = useCallback(\n async (args: SignMessageWithDotNsIdentityArgs) => {\n return app.wallet.signMessageWithDotNsIdentity(args);\n },\n [app],\n );\n\n // Subscribe to account changes\n useEffect(() => {\n const unsubscribe = app.wallet.onAccountChange((account) => {\n setState((s) => ({ ...s, selectedAccount: account }));\n });\n return unsubscribe;\n }, [app]);\n\n return {\n ...state,\n connect,\n disconnect,\n selectAccount,\n signMessage,\n signMessageWithDotNsIdentity,\n };\n}\n","// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * useLocalStorage hook\n */\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useProductSDK } from \"./context.js\";\n\n/**\n * Hook for key-value storage operations\n *\n * @param key - Storage key\n * @param defaultValue - Default value if key doesn't exist\n *\n * @example\n * ```tsx\n * function ThemeToggle() {\n * const [theme, setTheme, { loading }] = useLocalStorage('theme', 'light');\n *\n * if (loading) return <div>Loading...</div>;\n *\n * return (\n * <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>\n * Current: {theme}\n * </button>\n * );\n * }\n * ```\n */\nexport function useLocalStorage<T = string>(\n key: string,\n defaultValue?: T,\n): [T | null, (value: T) => Promise<void>, { loading: boolean; error: Error | null }] {\n const app = useProductSDK();\n\n const [value, setValue] = useState<T | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n // Load initial value\n useEffect(() => {\n let mounted = true;\n\n const loadValue = async () => {\n try {\n setLoading(true);\n const stored = await app.localStorage.getJSON<T>(key);\n if (mounted) {\n setValue(stored ?? defaultValue ?? null);\n setLoading(false);\n }\n } catch (e) {\n if (mounted) {\n setError(e instanceof Error ? e : new Error(String(e)));\n setLoading(false);\n }\n }\n };\n\n loadValue();\n\n return () => {\n mounted = false;\n };\n }, [app, key, defaultValue]);\n\n const setStoredValue = useCallback(\n async (newValue: T) => {\n try {\n setError(null);\n await app.localStorage.setJSON(key, newValue);\n setValue(newValue);\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n throw e;\n }\n },\n [app, key],\n );\n\n return [value, setStoredValue, { loading, error }];\n}\n\n/**\n * Hook for string storage (simpler API)\n *\n * @param key - Storage key\n * @param defaultValue - Default value\n */\nexport function useLocalStorageString(\n key: string,\n defaultValue?: string,\n): [string | null, (value: string) => Promise<void>, { loading: boolean }] {\n const app = useProductSDK();\n\n const [value, setValue] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let mounted = true;\n\n const loadValue = async () => {\n const stored = await app.localStorage.get(key);\n if (mounted) {\n setValue(stored ?? defaultValue ?? null);\n setLoading(false);\n }\n };\n\n loadValue();\n\n return () => {\n mounted = false;\n };\n }, [app, key, defaultValue]);\n\n const setStoredValue = useCallback(\n async (newValue: string) => {\n await app.localStorage.set(key, newValue);\n setValue(newValue);\n },\n [app, key],\n );\n\n return [value, setStoredValue, { loading }];\n}\n","// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * useChain hook\n */\n\nimport { useMemo } from \"react\";\nimport { useProductSDK } from \"./context.js\";\nimport type { ChainDefinition, TypedApi } from \"../core/types.js\";\n\n/**\n * Hook to get a typed chain client\n *\n * @param chain - Chain descriptor (PAPI ChainDefinition)\n *\n * @example\n * ```tsx\n * import { paseo_asset_hub } from '@parity/product-sdk-descriptors/paseo-asset-hub';\n * import { useChain } from '@parity/product-sdk/react';\n *\n * function AssetHubBalance() {\n * const assetHub = useChain(paseo_asset_hub);\n *\n * // assetHub is typed for Asset Hub queries\n * const balance = await assetHub.query.System.Account.getValue(address);\n * }\n * ```\n */\nexport function useChain<T extends ChainDefinition>(chain: T): TypedApi<T> {\n const app = useProductSDK();\n\n return useMemo(() => {\n return app.chain.getClient(chain);\n }, [app, chain]);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@parity/product-sdk-renderer';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as Account, L as LocalStorageApi, C as ChainApi, a as CloudStorageApi, b as App } from '../types-
|
|
1
|
+
import { A as Account, L as LocalStorageApi, C as ChainApi, a as CloudStorageApi, b as App } from '../types-BpWw-OJl.js';
|
|
2
2
|
export * from '@parity/product-sdk-local-storage/testing';
|
|
3
3
|
export * from '@parity/product-sdk-signer/testing';
|
|
4
4
|
export * from '@parity/product-sdk-contracts/testing';
|
|
@@ -16,8 +16,8 @@ interface CloudStorageConfig {
|
|
|
16
16
|
}
|
|
17
17
|
/** Configuration for createApp */
|
|
18
18
|
interface AppConfig {
|
|
19
|
-
/**
|
|
20
|
-
name
|
|
19
|
+
/** @deprecated Ignored with a warning. The host product ID supplies the app name. */
|
|
20
|
+
name?: string;
|
|
21
21
|
/** Log level for SDK operations (default: 'info') */
|
|
22
22
|
logLevel?: LogLevel;
|
|
23
23
|
/**
|
|
@@ -27,6 +27,11 @@ interface AppConfig {
|
|
|
27
27
|
*/
|
|
28
28
|
cloudStorage?: CloudStorageConfig | false;
|
|
29
29
|
}
|
|
30
|
+
/** App configuration with the identity resolved from the host. */
|
|
31
|
+
interface AppInfo extends Omit<AppConfig, "name"> {
|
|
32
|
+
/** App name and storage prefix, omitting the host ID's final domain suffix. Local host IDs stay unchanged. */
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
30
35
|
/** Wallet API exposed by the SDK */
|
|
31
36
|
interface WalletApi {
|
|
32
37
|
/** Connect to available wallet providers */
|
|
@@ -158,8 +163,8 @@ interface App {
|
|
|
158
163
|
chain: ChainApi;
|
|
159
164
|
/** Cloud Storage operations (null if disabled via config) */
|
|
160
165
|
cloudStorage: CloudStorageApi | null;
|
|
161
|
-
/** Get app configuration */
|
|
162
|
-
getAppInfo():
|
|
166
|
+
/** Get app configuration with the host-derived name. */
|
|
167
|
+
getAppInfo(): AppInfo;
|
|
163
168
|
}
|
|
164
169
|
/** Account information */
|
|
165
170
|
interface Account {
|
|
@@ -213,4 +218,4 @@ interface DotNsIdentitySignature {
|
|
|
213
218
|
signature: Uint8Array;
|
|
214
219
|
}
|
|
215
220
|
|
|
216
|
-
export type { Account as A, ChainApi as C, DotNsIdentitySignature as D, LocalStorageApi as L, SignMessageWithDotNsIdentityArgs as S, WalletApi as W, CloudStorageApi as a, App as b, AppConfig as c,
|
|
221
|
+
export type { Account as A, ChainApi as C, DotNsIdentitySignature as D, LocalStorageApi as L, SignMessageWithDotNsIdentityArgs as S, WalletApi as W, CloudStorageApi as a, App as b, AppConfig as c, AppInfo as d, CloudStorageConfig as e };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parity/product-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "Unified SDK for building products in the Polkadot ecosystem - umbrella package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -56,6 +56,10 @@
|
|
|
56
56
|
"import": "./dist/local-storage/index.js",
|
|
57
57
|
"types": "./dist/local-storage/index.d.ts"
|
|
58
58
|
},
|
|
59
|
+
"./renderer": {
|
|
60
|
+
"import": "./dist/renderer/index.js",
|
|
61
|
+
"types": "./dist/renderer/index.d.ts"
|
|
62
|
+
},
|
|
59
63
|
"./wallet": {
|
|
60
64
|
"import": "./dist/wallet/index.js",
|
|
61
65
|
"types": "./dist/wallet/index.d.ts"
|
|
@@ -71,20 +75,21 @@
|
|
|
71
75
|
],
|
|
72
76
|
"dependencies": {
|
|
73
77
|
"polkadot-api": "^2.1.6",
|
|
74
|
-
"@parity/product-sdk-
|
|
75
|
-
"@parity/product-sdk-
|
|
76
|
-
"@parity/product-sdk-chain-client": "0.12.5",
|
|
77
|
-
"@parity/product-sdk-contracts": "0.10.9",
|
|
78
|
-
"@parity/product-sdk-host": "0.21.0",
|
|
78
|
+
"@parity/product-sdk-cloud-storage": "0.12.2",
|
|
79
|
+
"@parity/product-sdk-chain-client": "0.12.6",
|
|
79
80
|
"@parity/product-sdk-crypto": "0.1.1",
|
|
80
|
-
"@parity/product-sdk-
|
|
81
|
+
"@parity/product-sdk-contracts": "0.10.10",
|
|
82
|
+
"@parity/product-sdk-individuality": "0.6.0",
|
|
83
|
+
"@parity/product-sdk-host": "0.22.0",
|
|
84
|
+
"@parity/product-sdk-address": "0.2.0",
|
|
85
|
+
"@parity/product-sdk-keys": "0.4.0",
|
|
81
86
|
"@parity/product-sdk-logger": "0.1.1",
|
|
82
87
|
"@parity/product-sdk-errors": "0.2.0",
|
|
83
|
-
"@parity/product-sdk-individuality": "0.5.0",
|
|
84
88
|
"@parity/result": "0.2.0",
|
|
85
|
-
"@parity/product-sdk-signer": "0.
|
|
86
|
-
"@parity/product-sdk-local-storage": "0.3.
|
|
87
|
-
"@parity/product-sdk-tx": "0.4.
|
|
89
|
+
"@parity/product-sdk-signer": "0.15.0",
|
|
90
|
+
"@parity/product-sdk-local-storage": "0.3.12",
|
|
91
|
+
"@parity/product-sdk-tx": "0.4.10",
|
|
92
|
+
"@parity/product-sdk-renderer": "0.2.0"
|
|
88
93
|
},
|
|
89
94
|
"peerDependencies": {
|
|
90
95
|
"react": "^18.0.0 || ^19.0.0"
|
|
@@ -97,6 +102,7 @@
|
|
|
97
102
|
"devDependencies": {
|
|
98
103
|
"@types/node": "^22.0.0",
|
|
99
104
|
"@types/react": "^18.0.0",
|
|
105
|
+
"neverthrow": "^8.2.0",
|
|
100
106
|
"react": "^18.0.0",
|
|
101
107
|
"typescript": "^5.7.0",
|
|
102
108
|
"vitest": "^3.0.0"
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// Copyright 2026 Parity Technologies (UK) Ltd.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import {
|
|
4
|
+
afterEach,
|
|
5
|
+
beforeEach,
|
|
6
|
+
describe,
|
|
7
|
+
expect,
|
|
8
|
+
expectTypeOf,
|
|
9
|
+
it,
|
|
10
|
+
vi,
|
|
11
|
+
type MockInstance,
|
|
12
|
+
} from "vitest";
|
|
13
|
+
import { errAsync, okAsync } from "neverthrow";
|
|
14
|
+
import { HostUnavailableError, type TruApi } from "@parity/product-sdk-host";
|
|
15
|
+
import {
|
|
16
|
+
createFakeHost,
|
|
17
|
+
createFakeTruApiClient,
|
|
18
|
+
setTruApiClient,
|
|
19
|
+
} from "@parity/product-sdk-host/testing";
|
|
20
|
+
import { configure, type LogEntry } from "@parity/product-sdk-logger";
|
|
21
|
+
import { createApp } from "./createApp.js";
|
|
22
|
+
import type { App } from "./types.js";
|
|
23
|
+
import type { ProductSDKProviderProps } from "../react/provider.js";
|
|
24
|
+
|
|
25
|
+
describe("host-derived app identity", () => {
|
|
26
|
+
let client: TruApi;
|
|
27
|
+
let entries: LogEntry[];
|
|
28
|
+
const apps: App[] = [];
|
|
29
|
+
let getProductContext: MockInstance<TruApi["system"]["getProductContext"]>;
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
client = createFakeTruApiClient();
|
|
33
|
+
getProductContext = vi.spyOn(client.system, "getProductContext");
|
|
34
|
+
getProductContext.mockReturnValue(okAsync({ productId: "session.paseo" }));
|
|
35
|
+
setTruApiClient(client);
|
|
36
|
+
entries = [];
|
|
37
|
+
configure({ level: "warn", namespaces: [], handler: (entry) => entries.push(entry) });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterEach(async () => {
|
|
41
|
+
for (const app of apps.splice(0)) await app.wallet.disconnect();
|
|
42
|
+
setTruApiClient(null);
|
|
43
|
+
vi.restoreAllMocks();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("works with the public fake host without overriding protocol methods", async () => {
|
|
47
|
+
using host = createFakeHost();
|
|
48
|
+
const app = await createApp({ cloudStorage: false });
|
|
49
|
+
apps.push(app);
|
|
50
|
+
const { accounts } = await app.wallet.connect();
|
|
51
|
+
await app.localStorage.set("key", "value");
|
|
52
|
+
expect({
|
|
53
|
+
info: app.getAppInfo(),
|
|
54
|
+
accountCount: accounts.length,
|
|
55
|
+
stored: (await host.client.localStorage.read({ key: "fake-app:key" }))._unsafeUnwrap(),
|
|
56
|
+
}).toEqual({
|
|
57
|
+
info: { name: "fake-app", cloudStorage: false },
|
|
58
|
+
accountCount: 1,
|
|
59
|
+
stored: { value: "0x76616c7565" },
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it.each([
|
|
64
|
+
["my-app.dot", "my-app"],
|
|
65
|
+
["session.paseo", "session"],
|
|
66
|
+
["nested.app.dot", "nested.app"],
|
|
67
|
+
["localhost", "localhost"],
|
|
68
|
+
["localhost:3000", "localhost:3000"],
|
|
69
|
+
["127.0.0.1", "127.0.0.1"],
|
|
70
|
+
["127.0.0.1:3000", "127.0.0.1:3000"],
|
|
71
|
+
["app.localhost", "app.localhost"],
|
|
72
|
+
["app.localhost:3000", "app.localhost:3000"],
|
|
73
|
+
])(
|
|
74
|
+
"keeps wallet identity %s while using %s for app info and storage",
|
|
75
|
+
async (productId, appName) => {
|
|
76
|
+
getProductContext.mockReturnValue(okAsync({ productId }));
|
|
77
|
+
const getAccount = vi.spyOn(client.account, "getAccount");
|
|
78
|
+
const write = vi.spyOn(client.localStorage, "write");
|
|
79
|
+
const app = await createApp({ cloudStorage: false });
|
|
80
|
+
apps.push(app);
|
|
81
|
+
const { accounts } = await app.wallet.connect();
|
|
82
|
+
await app.localStorage.set("key", "value");
|
|
83
|
+
const name: string = app.getAppInfo().name;
|
|
84
|
+
|
|
85
|
+
expect({
|
|
86
|
+
name,
|
|
87
|
+
accountCount: accounts.length,
|
|
88
|
+
accountRequests: getAccount.mock.calls,
|
|
89
|
+
storageWrite: write.mock.calls.at(-1),
|
|
90
|
+
stored: await app.localStorage.get("key"),
|
|
91
|
+
}).toEqual({
|
|
92
|
+
name: appName,
|
|
93
|
+
accountCount: 1,
|
|
94
|
+
accountRequests: [
|
|
95
|
+
[
|
|
96
|
+
{
|
|
97
|
+
productAccountId: {
|
|
98
|
+
dotNsIdentifier: productId,
|
|
99
|
+
derivationIndex: { tag: "Index", value: 0 },
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
],
|
|
104
|
+
storageWrite: [{ key: `${appName}:key`, value: "0x76616c7565" }],
|
|
105
|
+
stored: "value",
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
it("keeps existing bare-name storage readable and writes to the same prefix", async () => {
|
|
111
|
+
getProductContext.mockReturnValue(okAsync({ productId: "my-app.dot" }));
|
|
112
|
+
await client.localStorage.write({ key: "my-app:theme", value: "0x6461726b" });
|
|
113
|
+
const app = await createApp({ cloudStorage: false });
|
|
114
|
+
apps.push(app);
|
|
115
|
+
const previous = await app.localStorage.get("theme");
|
|
116
|
+
await app.localStorage.set("theme", "light");
|
|
117
|
+
|
|
118
|
+
expect({
|
|
119
|
+
previous,
|
|
120
|
+
current: (await client.localStorage.read({ key: "my-app:theme" }))._unsafeUnwrap(),
|
|
121
|
+
fullIdPrefix: (
|
|
122
|
+
await client.localStorage.read({ key: "my-app.dot:theme" })
|
|
123
|
+
)._unsafeUnwrap(),
|
|
124
|
+
}).toEqual({
|
|
125
|
+
previous: "dark",
|
|
126
|
+
current: { value: "0x6c69676874" },
|
|
127
|
+
fullIdPrefix: { value: undefined },
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("requests the host identity without configuration or a deprecation warning", async () => {
|
|
132
|
+
expectTypeOf({ children: null }).toMatchTypeOf<ProductSDKProviderProps>();
|
|
133
|
+
const error = { tag: "Unsupported" } as const;
|
|
134
|
+
getProductContext.mockReturnValue(errAsync(error));
|
|
135
|
+
await expect(createApp()).rejects.toMatchObject({
|
|
136
|
+
name: "HostCallFailedError",
|
|
137
|
+
cause: error,
|
|
138
|
+
});
|
|
139
|
+
expect(entries.filter((entry) => entry.namespace === "app")).toEqual([]);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it.each(["wrong-app", ""])("ignores and warns about the deprecated name %j", async (name) => {
|
|
143
|
+
const app = await createApp({ name, cloudStorage: false });
|
|
144
|
+
apps.push(app);
|
|
145
|
+
await app.localStorage.set("key", "retained");
|
|
146
|
+
const unnamed = await createApp({ cloudStorage: false });
|
|
147
|
+
apps.push(unnamed);
|
|
148
|
+
expect({
|
|
149
|
+
info: app.getAppInfo(),
|
|
150
|
+
storedWithoutName: await unnamed.localStorage.get("key"),
|
|
151
|
+
warnings: entries
|
|
152
|
+
.filter((entry) => entry.namespace === "app")
|
|
153
|
+
.map(({ level, message }) => ({ level, message })),
|
|
154
|
+
}).toEqual({
|
|
155
|
+
info: { name: "session", cloudStorage: false },
|
|
156
|
+
storedWithoutName: "retained",
|
|
157
|
+
warnings: [
|
|
158
|
+
{
|
|
159
|
+
level: "warn",
|
|
160
|
+
message:
|
|
161
|
+
"createApp: name is deprecated and ignored. Remove the name option. The SDK resolves the app name from system.getProductContext(), dropping the product ID's final domain suffix (my-app.dot -> my-app). Local development IDs stay unchanged.",
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("rejects unavailable hosts even when a deprecated name is supplied", async () => {
|
|
168
|
+
setTruApiClient(null);
|
|
169
|
+
await expect(createApp({ name: "fallback", cloudStorage: false })).rejects.toBeInstanceOf(
|
|
170
|
+
HostUnavailableError,
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("preserves a refused context instead of using the deprecated name", async () => {
|
|
175
|
+
const error = { tag: "Unsupported" } as const;
|
|
176
|
+
getProductContext.mockReturnValue(errAsync(error));
|
|
177
|
+
await expect(createApp({ name: "fallback", cloudStorage: false })).rejects.toMatchObject({
|
|
178
|
+
name: "HostCallFailedError",
|
|
179
|
+
message: "system.getProductContext: Unsupported",
|
|
180
|
+
payload: error,
|
|
181
|
+
cause: error,
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("preserves a context transport rejection", async () => {
|
|
186
|
+
const error = new Error("host connection closed");
|
|
187
|
+
getProductContext.mockImplementation(() =>
|
|
188
|
+
okAsync(undefined).map(() => {
|
|
189
|
+
throw error;
|
|
190
|
+
}),
|
|
191
|
+
);
|
|
192
|
+
await expect(createApp({ cloudStorage: false })).rejects.toBe(error);
|
|
193
|
+
});
|
|
194
|
+
});
|
package/src/core/createApp.ts
CHANGED
|
@@ -34,7 +34,12 @@ import {
|
|
|
34
34
|
destroyAll,
|
|
35
35
|
} from "@parity/product-sdk-chain-client";
|
|
36
36
|
import { accountIdBytes } from "@parity/product-sdk-address";
|
|
37
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
getAccountsProvider,
|
|
39
|
+
getTruApi,
|
|
40
|
+
HostCallFailedError,
|
|
41
|
+
HostUnavailableError,
|
|
42
|
+
} from "@parity/product-sdk-host";
|
|
38
43
|
import {
|
|
39
44
|
accountIdBytesToHex,
|
|
40
45
|
type PeopleUsernameQueryApi,
|
|
@@ -55,19 +60,16 @@ const log = createLogger("app");
|
|
|
55
60
|
*
|
|
56
61
|
* // Default: cloud storage enabled with paseo environment
|
|
57
62
|
* const app = await createApp({
|
|
58
|
-
* name: 'my-app',
|
|
59
63
|
* logLevel: 'info',
|
|
60
64
|
* });
|
|
61
65
|
*
|
|
62
66
|
* // Custom cloud storage environment
|
|
63
67
|
* const prodApp = await createApp({
|
|
64
|
-
* name: 'my-app',
|
|
65
68
|
* cloudStorage: { environment: 'polkadot' },
|
|
66
69
|
* });
|
|
67
70
|
*
|
|
68
71
|
* // Disable cloud storage entirely
|
|
69
72
|
* const noCloudStorageApp = await createApp({
|
|
70
|
-
* name: 'my-app',
|
|
71
73
|
* cloudStorage: false,
|
|
72
74
|
* });
|
|
73
75
|
*
|
|
@@ -83,20 +85,40 @@ const log = createLogger("app");
|
|
|
83
85
|
* }
|
|
84
86
|
* ```
|
|
85
87
|
*/
|
|
86
|
-
export async function createApp(config: AppConfig): Promise<App> {
|
|
88
|
+
export async function createApp(config: AppConfig = {}): Promise<App> {
|
|
87
89
|
// Set log level if specified
|
|
88
90
|
if (config.logLevel) {
|
|
89
91
|
configure({ level: config.logLevel });
|
|
90
92
|
}
|
|
91
93
|
|
|
92
|
-
|
|
94
|
+
if (config.name !== undefined) {
|
|
95
|
+
log.warn(
|
|
96
|
+
"createApp: name is deprecated and ignored. Remove the name option. The SDK resolves the app name from system.getProductContext(), dropping the product ID's final domain suffix (my-app.dot -> my-app). Local development IDs stay unchanged.",
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const truApi = await getTruApi();
|
|
101
|
+
if (!truApi) {
|
|
102
|
+
throw new HostUnavailableError("createApp requires a host product context");
|
|
103
|
+
}
|
|
104
|
+
const { productId } = await truApi.system.getProductContext().match(
|
|
105
|
+
(context) => context,
|
|
106
|
+
(error) => {
|
|
107
|
+
throw new HostCallFailedError("system.getProductContext", error);
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const isLocalHost = /^(?:localhost|127\.0\.0\.1|[^:]+\.localhost)(?::\d+)?$/i.test(productId);
|
|
112
|
+
const name = isLocalHost ? productId : productId.replace(/\.[^.]+$/, "");
|
|
113
|
+
|
|
114
|
+
log.info("Creating Product SDK app", { name });
|
|
93
115
|
|
|
94
116
|
// Initialize storage (container-only - will throw if not in container)
|
|
95
|
-
const localKvStore = await createLocalKvStore({ prefix:
|
|
117
|
+
const localKvStore = await createLocalKvStore({ prefix: name });
|
|
96
118
|
|
|
97
119
|
// Initialize signer manager
|
|
98
120
|
const signerManager = new SignerManager({
|
|
99
|
-
dappName:
|
|
121
|
+
dappName: productId,
|
|
100
122
|
});
|
|
101
123
|
|
|
102
124
|
// Initialize cloud storage client (configurable, defaults to paseo).
|
|
@@ -197,7 +219,7 @@ export async function createApp(config: AppConfig): Promise<App> {
|
|
|
197
219
|
: null;
|
|
198
220
|
|
|
199
221
|
log.info("Product SDK app created", {
|
|
200
|
-
name
|
|
222
|
+
name,
|
|
201
223
|
cloudStorage: cloudStorageEnabled ? cloudStorageEnvironment : "disabled",
|
|
202
224
|
});
|
|
203
225
|
|
|
@@ -206,7 +228,7 @@ export async function createApp(config: AppConfig): Promise<App> {
|
|
|
206
228
|
localStorage: localStorageApi,
|
|
207
229
|
chain: chainApi,
|
|
208
230
|
cloudStorage: cloudStorageApi,
|
|
209
|
-
getAppInfo: () => ({ ...config }),
|
|
231
|
+
getAppInfo: () => ({ ...config, name }),
|
|
210
232
|
};
|
|
211
233
|
}
|
|
212
234
|
|
package/src/core/types.ts
CHANGED
|
@@ -25,8 +25,8 @@ export interface CloudStorageConfig {
|
|
|
25
25
|
|
|
26
26
|
/** Configuration for createApp */
|
|
27
27
|
export interface AppConfig {
|
|
28
|
-
/**
|
|
29
|
-
name
|
|
28
|
+
/** @deprecated Ignored with a warning. The host product ID supplies the app name. */
|
|
29
|
+
name?: string;
|
|
30
30
|
/** Log level for SDK operations (default: 'info') */
|
|
31
31
|
logLevel?: LogLevel;
|
|
32
32
|
/**
|
|
@@ -37,6 +37,12 @@ export interface AppConfig {
|
|
|
37
37
|
cloudStorage?: CloudStorageConfig | false;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/** App configuration with the identity resolved from the host. */
|
|
41
|
+
export interface AppInfo extends Omit<AppConfig, "name"> {
|
|
42
|
+
/** App name and storage prefix, omitting the host ID's final domain suffix. Local host IDs stay unchanged. */
|
|
43
|
+
name: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
/** Wallet API exposed by the SDK */
|
|
41
47
|
export interface WalletApi {
|
|
42
48
|
/** Connect to available wallet providers */
|
|
@@ -176,8 +182,8 @@ export interface App {
|
|
|
176
182
|
chain: ChainApi;
|
|
177
183
|
/** Cloud Storage operations (null if disabled via config) */
|
|
178
184
|
cloudStorage: CloudStorageApi | null;
|
|
179
|
-
/** Get app configuration */
|
|
180
|
-
getAppInfo():
|
|
185
|
+
/** Get app configuration with the host-derived name. */
|
|
186
|
+
getAppInfo(): AppInfo;
|
|
181
187
|
}
|
|
182
188
|
|
|
183
189
|
/** Account information */
|
package/src/index.ts
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* @parity/product-sdk
|
|
5
5
|
*
|
|
6
6
|
* Unified SDK for building products on the Polkadot ecosystem.
|
|
7
|
+
* App identity comes from the host and scopes wallet accounts and local storage.
|
|
7
8
|
*
|
|
8
9
|
* @example
|
|
9
10
|
* ```ts
|
|
10
11
|
* import { createApp } from '@parity/product-sdk';
|
|
11
12
|
*
|
|
12
|
-
* const app = createApp({
|
|
13
|
-
* name: 'my-app',
|
|
13
|
+
* const app = await createApp({
|
|
14
14
|
* logLevel: 'info',
|
|
15
15
|
* });
|
|
16
16
|
*
|
|
@@ -30,6 +30,7 @@ export { configure, createLogger } from "./core/logger.js";
|
|
|
30
30
|
export type {
|
|
31
31
|
App,
|
|
32
32
|
AppConfig,
|
|
33
|
+
AppInfo,
|
|
33
34
|
LogLevel,
|
|
34
35
|
WalletApi,
|
|
35
36
|
LocalStorageApi,
|
package/src/react/context.ts
CHANGED
|
@@ -28,7 +28,7 @@ export function useProductSDK(): App {
|
|
|
28
28
|
if (!app) {
|
|
29
29
|
throw new Error(
|
|
30
30
|
"useProductSDK must be used within a ProductSDKProvider. " +
|
|
31
|
-
|
|
31
|
+
"Wrap your app with <ProductSDKProvider>.",
|
|
32
32
|
);
|
|
33
33
|
}
|
|
34
34
|
return app;
|
package/src/react/index.ts
CHANGED
package/src/react/provider.tsx
CHANGED
|
@@ -11,8 +11,8 @@ import type { App, LogLevel } from "../core/types.js";
|
|
|
11
11
|
|
|
12
12
|
/** Props for ProductSDKProvider */
|
|
13
13
|
export interface ProductSDKProviderProps {
|
|
14
|
-
/**
|
|
15
|
-
name
|
|
14
|
+
/** @deprecated Ignored with a warning. The host product ID supplies the app name. */
|
|
15
|
+
name?: string;
|
|
16
16
|
/** Log level (default: 'info') */
|
|
17
17
|
logLevel?: LogLevel;
|
|
18
18
|
/** Child components */
|
|
@@ -30,7 +30,7 @@ export interface ProductSDKProviderProps {
|
|
|
30
30
|
*
|
|
31
31
|
* function App() {
|
|
32
32
|
* return (
|
|
33
|
-
* <ProductSDKProvider
|
|
33
|
+
* <ProductSDKProvider fallback={<Loading />}>
|
|
34
34
|
* <MyApp />
|
|
35
35
|
* </ProductSDKProvider>
|
|
36
36
|
* );
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright 2026 Parity Technologies (UK) Ltd.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Renderer trees — Pocket card faces and rendered chat bodies.
|
|
5
|
+
*
|
|
6
|
+
* Re-exports `@parity/product-sdk-renderer`.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
export * from "@parity/product-sdk-renderer";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/createApp.ts"],"names":["err"],"mappings":"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","file":"chunk-KXJT2BNL.js","sourcesContent":["// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * createApp - Main entry point for the Product SDK\n *\n * Creates an App instance with wallet, storage, chain, and cloud storage APIs.\n */\n\nimport type { ChainDefinition } from \"polkadot-api\";\nimport type {\n App,\n AppConfig,\n WalletApi,\n ChainApi,\n Account,\n CloudStorageApi,\n LocalStorageApi,\n} from \"./types.js\";\nimport { createLocalStorageApi } from \"./local-storage-api.js\";\nimport { configure, createLogger } from \"@parity/product-sdk-logger\";\nimport { createLocalKvStore } from \"@parity/product-sdk-local-storage\";\nimport { SignerManager } from \"@parity/product-sdk-signer\";\nimport {\n CloudStorageClient,\n ProductCloudStorageError,\n calculateCid,\n createLazySigner,\n} from \"@parity/product-sdk-cloud-storage\";\nimport { err, ok } from \"@parity/result\";\nimport {\n createChainClient,\n getClient,\n isConnected,\n destroyAll,\n} from \"@parity/product-sdk-chain-client\";\nimport { accountIdBytes } from \"@parity/product-sdk-address\";\nimport { getAccountsProvider } from \"@parity/product-sdk-host\";\nimport {\n accountIdBytesToHex,\n type PeopleUsernameQueryApi,\n resolvePeopleUsernameOwner,\n} from \"../identity/dotns.js\";\n\nconst log = createLogger(\"app\");\n\n/**\n * Create a new Product SDK app instance\n *\n * @param config - Application configuration\n * @returns App instance with all APIs\n *\n * @example\n * ```ts\n * import { createApp } from '@parity/product-sdk';\n *\n * // Default: cloud storage enabled with paseo environment\n * const app = await createApp({\n * name: 'my-app',\n * logLevel: 'info',\n * });\n *\n * // Custom cloud storage environment\n * const prodApp = await createApp({\n * name: 'my-app',\n * cloudStorage: { environment: 'polkadot' },\n * });\n *\n * // Disable cloud storage entirely\n * const noCloudStorageApp = await createApp({\n * name: 'my-app',\n * cloudStorage: false,\n * });\n *\n * // Connect wallet\n * const { accounts } = await app.wallet.connect();\n *\n * // Use storage\n * await app.localStorage.set('key', 'value');\n *\n * // Use cloud storage (check for null if it might be disabled)\n * if (app.cloudStorage) {\n * const cid = await app.cloudStorage.upload('hello world');\n * }\n * ```\n */\nexport async function createApp(config: AppConfig): Promise<App> {\n // Set log level if specified\n if (config.logLevel) {\n configure({ level: config.logLevel });\n }\n\n log.info(\"Creating Product SDK app\", { name: config.name });\n\n // Initialize storage (container-only - will throw if not in container)\n const localKvStore = await createLocalKvStore({ prefix: config.name });\n\n // Initialize signer manager\n const signerManager = new SignerManager({\n dappName: config.name,\n });\n\n // Initialize cloud storage client (configurable, defaults to paseo).\n //\n // The signer is wrapped lazily so the cloud storage client can be built before\n // an account is selected. Uploads will throw a clear error if no signer\n // is available at submission time. Reads (fetch / fetchJson) don't need\n // a signer, so they work regardless of whether an account is selected --\n // but they are container-only and throw CloudStorageHostUnavailableError\n // outside a host container (no IPFS-gateway fallback).\n const cloudStorageEnabled = config.cloudStorage !== false;\n const cloudStorageEnvironment =\n typeof config.cloudStorage === \"object\" ? config.cloudStorage.environment : \"paseo\";\n const cloudStorageClient = cloudStorageEnabled\n ? await CloudStorageClient.create({\n environment: cloudStorageEnvironment,\n signer: createLazySigner(() => signerManager.getSigner()),\n })\n : null;\n\n if (cloudStorageEnabled) {\n log.debug(\"Cloud Storage client (Bulletin) initialized\", {\n environment: cloudStorageEnvironment,\n });\n } else {\n log.debug(\"Cloud Storage client disabled\");\n }\n\n // Storage API adapter — shared with `createFakeApp` so the two cannot drift.\n const localStorageApi: LocalStorageApi = createLocalStorageApi(localKvStore);\n\n // Create wallet API adapter\n const walletApi = createWalletApi(signerManager);\n\n // Create chain API\n const chainApi: ChainApi = {\n getClient(descriptor) {\n log.debug(\"getClient called\", { genesis: descriptor.genesis });\n const client = getClient(descriptor);\n return client.getTypedApi(descriptor);\n },\n\n getRawClient(descriptor) {\n log.debug(\"getRawClient called\", { genesis: descriptor.genesis });\n return getClient(descriptor);\n },\n\n async connect<T extends Record<string, ChainDefinition>>(chains: T) {\n log.debug(\"connect called\", { chains: Object.keys(chains) });\n return createChainClient({ chains });\n },\n\n isConnected(descriptor) {\n return isConnected(descriptor);\n },\n\n destroyAll() {\n log.debug(\"destroyAll called\");\n destroyAll();\n },\n };\n\n // Create Cloud Storage API adapter (null if disabled)\n const cloudStorageApi: CloudStorageApi | null = cloudStorageClient\n ? {\n upload: async (data) => {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n try {\n // Explicitly request a DAG-PB manifest so chunked uploads always\n // resolve to a single root CID. Without this, AsyncBulletinClient\n // can return `result.cid: undefined` for chunked-without-manifest\n // uploads — but app consumers expect a CID they can hand to\n // `fetch(cid)`, so treat a missing CID as an error.\n const uploaded = await cloudStorageClient\n .store(bytes)\n .withManifest(true)\n .send();\n if (!uploaded.cid) {\n return err(\n new ProductCloudStorageError(\n \"Cloud storage upload returned no CID despite .withManifest(true). Upstream contract may have shifted — file an issue.\",\n ),\n );\n }\n return ok(uploaded.cid.toString());\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n return err(new ProductCloudStorageError(message, { cause }));\n }\n },\n fetch: (cid) => cloudStorageClient.fetchBytes(cid),\n computeCid: async (data) => {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n const cid = await calculateCid(bytes);\n return cid.toString();\n },\n }\n : null;\n\n log.info(\"Product SDK app created\", {\n name: config.name,\n cloudStorage: cloudStorageEnabled ? cloudStorageEnvironment : \"disabled\",\n });\n\n return {\n wallet: walletApi,\n localStorage: localStorageApi,\n chain: chainApi,\n cloudStorage: cloudStorageApi,\n getAppInfo: () => ({ ...config }),\n };\n}\n\n/**\n * Create wallet API adapter using SignerManager from leaf package\n */\nfunction createWalletApi(signerManager: SignerManager): WalletApi {\n // Track account change subscribers\n const accountChangeSubscribers = new Set<(account: Account | null) => void>();\n\n // Subscribe to signer manager state changes\n signerManager.subscribe((state) => {\n const account = state.selectedAccount\n ? {\n address: state.selectedAccount.address,\n name: state.selectedAccount.name ?? undefined,\n source: state.selectedAccount.source,\n }\n : null;\n for (const callback of accountChangeSubscribers) {\n try {\n callback(account);\n } catch (e) {\n log.warn(\"Account change callback threw\", { error: e });\n }\n }\n });\n\n return {\n async connect(): Promise<{ accounts: Account[] }> {\n const result = await signerManager.connect();\n if (!result.ok) {\n throw new Error(result.error.message);\n }\n return {\n accounts: result.value.map((a) => ({\n address: a.address,\n name: a.name ?? undefined,\n source: a.source,\n })),\n };\n },\n\n async disconnect(): Promise<void> {\n signerManager.disconnect();\n },\n\n getAccounts(): Account[] {\n return signerManager.getState().accounts.map((a) => ({\n address: a.address,\n name: a.name ?? undefined,\n source: a.source,\n }));\n },\n\n getSelectedAccount(): Account | null {\n const selected = signerManager.getState().selectedAccount;\n if (!selected) return null;\n return {\n address: selected.address,\n name: selected.name ?? undefined,\n source: selected.source,\n };\n },\n\n selectAccount(address: string): void {\n signerManager.selectAccount(address);\n },\n\n async signMessage(message: string | Uint8Array): Promise<Uint8Array> {\n const bytes = typeof message === \"string\" ? new TextEncoder().encode(message) : message;\n const result = await signerManager.signRaw(bytes);\n if (!result.ok) {\n throw new Error(result.error.message);\n }\n return result.value;\n },\n\n async signMessageWithDotNsIdentity(args) {\n const message =\n typeof args.message === \"string\"\n ? new TextEncoder().encode(args.message)\n : args.message;\n const accountsProvider = await getHostAccountsProvider();\n const username = args.username ?? (await getPrimaryUsername(accountsProvider));\n\n // Reuse an already-connected People chain when the caller has\n // wired one up via `app.chain.connect({ ..., <name>: peopleChain })`.\n // Fall back to opening a transient connection so first-time users\n // don't have to think about chain lifecycles. The chain-client\n // module caches by genesis fingerprint, so subsequent\n // signMessageWithDotNsIdentity calls share whichever connection\n // got established first.\n const peopleClient = isConnected(args.peopleChain)\n ? getClient(args.peopleChain)\n : await createChainClient({ chains: { people: args.peopleChain } }).then(\n (c) => c.raw.people,\n );\n // PAPI's `TypedApi.query.X.Y.getValue` is variadic\n // (`...args: [...WithCallOptions<Args>]`) so it's not assignable\n // to our deliberately-narrow `(key) => Promise<...>` shape. The\n // resolver only ever passes the storage key; the cast adapts the\n // wider PAPI surface to the minimum we depend on.\n const peopleApi = peopleClient.getTypedApi(\n args.peopleChain,\n ) as unknown as PeopleUsernameQueryApi;\n const owner = await resolvePeopleUsernameOwner(username, peopleApi);\n if (!owner) {\n throw new Error(`No account owns DotNS username \"${username}\"`);\n }\n\n const publicKey = accountIdBytes(owner);\n // This field is hex, not the SS58 the resolver now returns. Converted\n // here and not in the try, so an address failure is not reported as a\n // signing failure.\n const accountId = accountIdBytesToHex(publicKey);\n const signer = accountsProvider.getLegacyAccountSigner({ publicKey, name: username });\n\n try {\n return {\n username,\n accountId,\n signature: await signer.signBytes(message),\n };\n } catch (cause) {\n throw new Error(\n `Failed to sign with DotNS username \"${username}\": ${\n cause instanceof Error ? cause.message : String(cause)\n }`,\n { cause },\n );\n }\n },\n\n onAccountChange(callback: (account: Account | null) => void): () => void {\n accountChangeSubscribers.add(callback);\n return () => accountChangeSubscribers.delete(callback);\n },\n\n getProductAccount(): Account | null {\n // Product accounts require async call - this sync API can't support it properly\n // Users should use SignerManager.getProductAccount() directly\n log.warn(\n \"getProductAccount() is deprecated - use SignerManager.getProductAccount() directly\",\n );\n return null;\n },\n\n getAnonymousAlias(): string | null {\n // Anonymous aliases require async call - this sync API can't support it properly\n // Users should use SignerManager.getProductAccountAlias() directly\n log.warn(\n \"getAnonymousAlias() is deprecated - use SignerManager.getProductAccountAlias() directly\",\n );\n return null;\n },\n\n async createProof(_message: Uint8Array): Promise<Uint8Array> {\n // Ring VRF proofs require SignerManager.createRingVRFProof() directly\n throw new Error(\n \"createProof() is not implemented in the App API. \" +\n \"Use SignerManager.createRingVRFProof() directly.\",\n );\n },\n };\n}\n\ntype HostAccountsProvider = NonNullable<Awaited<ReturnType<typeof getAccountsProvider>>>;\n\nasync function getHostAccountsProvider(): Promise<HostAccountsProvider> {\n const provider = await getAccountsProvider();\n if (!provider) {\n throw new Error(\"Host accounts provider is not available\");\n }\n return provider;\n}\n\nasync function getPrimaryUsername(accountsProvider: HostAccountsProvider): Promise<string> {\n const result = await accountsProvider.getUserId().match(\n (value) => value,\n (err) => {\n throw err;\n },\n );\n const username = result.primaryUsername.trim();\n if (!username) {\n throw new Error(\"Host identity did not provide a primary DotNS username\");\n }\n return username;\n}\n"]}
|