@parity/product-sdk 0.1.0 → 0.2.1

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.
@@ -1,3 +1,3 @@
1
- // src/address/index.ts
2
- export * from "@parity/product-sdk-address";
1
+ export * from '@parity/product-sdk-address';
2
+ //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/address/index.ts"],"sourcesContent":["/**\n * @parity/product-sdk/address\n *\n * Re-exports from @parity/product-sdk-address.\n */\nexport * from \"@parity/product-sdk-address\";\n"],"mappings":";AAKA,cAAc;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -1,3 +1,3 @@
1
- // src/bulletin/index.ts
2
- export * from "@parity/product-sdk-bulletin";
1
+ export * from '@parity/product-sdk-bulletin';
2
+ //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bulletin/index.ts"],"sourcesContent":["/**\n * @parity/product-sdk/bulletin\n *\n * Re-exports from @parity/product-sdk-bulletin.\n */\nexport * from \"@parity/product-sdk-bulletin\";\n"],"mappings":";AAKA,cAAc;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -1,3 +1,3 @@
1
- // src/chain/index.ts
2
- export * from "@parity/product-sdk-chain-client";
1
+ export * from '@parity/product-sdk-chain-client';
2
+ //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/chain/index.ts"],"sourcesContent":["/**\n * @parity/product-sdk/chain\n *\n * Re-exports from @parity/product-sdk-chain-client.\n */\nexport * from \"@parity/product-sdk-chain-client\";\n"],"mappings":";AAKA,cAAc;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -1,14 +1,10 @@
1
+ import { createLogger, configure } from '@parity/product-sdk-logger';
2
+ import { createKvStore } from '@parity/product-sdk-storage';
3
+ import { SignerManager } from '@parity/product-sdk-signer';
4
+ import { BulletinClient, createLazySigner, calculateCid } from '@parity/product-sdk-bulletin';
5
+ import { destroyAll, isConnected, createChainClient, getClient } from '@parity/product-sdk-chain-client';
6
+
1
7
  // src/core/createApp.ts
2
- import { configure, createLogger } from "@parity/product-sdk-logger";
3
- import { createKvStore } from "@parity/product-sdk-storage";
4
- import { SignerManager } from "@parity/product-sdk-signer";
5
- import { BulletinClient, computeCid } from "@parity/product-sdk-bulletin";
6
- import {
7
- createChainClient,
8
- getClient,
9
- isConnected,
10
- destroyAll
11
- } from "@parity/product-sdk-chain-client";
12
8
  var log = createLogger("app");
13
9
  async function createApp(config) {
14
10
  if (config.logLevel) {
@@ -21,7 +17,10 @@ async function createApp(config) {
21
17
  });
22
18
  const bulletinEnabled = config.bulletin !== false;
23
19
  const bulletinEnvironment = typeof config.bulletin === "object" ? config.bulletin.environment : "paseo";
24
- const bulletinClient = bulletinEnabled ? await BulletinClient.create(bulletinEnvironment) : null;
20
+ const bulletinClient = bulletinEnabled ? await BulletinClient.create({
21
+ environment: bulletinEnvironment,
22
+ signer: createLazySigner(() => signerManager.getSigner())
23
+ }) : null;
25
24
  if (bulletinEnabled) {
26
25
  log.debug("Bulletin client initialized", { environment: bulletinEnvironment });
27
26
  } else {
@@ -66,13 +65,19 @@ async function createApp(config) {
66
65
  const bulletinApi = bulletinClient ? {
67
66
  upload: async (data) => {
68
67
  const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
69
- const result = await bulletinClient.upload(bytes);
70
- return result.cid;
68
+ const result = await bulletinClient.store(bytes).withManifest(true).send();
69
+ if (!result.cid) {
70
+ throw new Error(
71
+ "Bulletin upload returned no CID despite .withManifest(true). Upstream contract may have shifted \u2014 file an issue."
72
+ );
73
+ }
74
+ return result.cid.toString();
71
75
  },
72
76
  fetch: (cid) => bulletinClient.fetchBytes(cid),
73
- computeCid: (data) => {
77
+ computeCid: async (data) => {
74
78
  const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
75
- return computeCid(bytes);
79
+ const cid = await calculateCid(bytes);
80
+ return cid.toString();
76
81
  }
77
82
  } : null;
78
83
  log.info("Product SDK app created", {
@@ -171,7 +176,6 @@ function createWalletApi(signerManager) {
171
176
  };
172
177
  }
173
178
 
174
- export {
175
- createApp
176
- };
177
- //# sourceMappingURL=chunk-NVGSGXGH.js.map
179
+ export { createApp };
180
+ //# sourceMappingURL=chunk-6W3TCR3W.js.map
181
+ //# sourceMappingURL=chunk-6W3TCR3W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/createApp.ts"],"names":[],"mappings":"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","file":"chunk-6W3TCR3W.js","sourcesContent":["/**\n * createApp - Main entry point for the Product SDK\n *\n * Creates an App instance with wallet, storage, chain, and bulletin APIs.\n */\n\nimport type { ChainDefinition } from \"polkadot-api\";\nimport type {\n App,\n AppConfig,\n WalletApi,\n StorageApi,\n ChainApi,\n BulletinApi,\n Account,\n} from \"./types.js\";\nimport { configure, createLogger } from \"@parity/product-sdk-logger\";\nimport { createKvStore } from \"@parity/product-sdk-storage\";\nimport { SignerManager } from \"@parity/product-sdk-signer\";\nimport { BulletinClient, calculateCid, createLazySigner } from \"@parity/product-sdk-bulletin\";\nimport {\n createChainClient,\n getClient,\n isConnected,\n destroyAll,\n} from \"@parity/product-sdk-chain-client\";\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: bulletin enabled with paseo environment\n * const app = await createApp({\n * name: 'my-app',\n * logLevel: 'info',\n * });\n *\n * // Custom bulletin environment\n * const prodApp = await createApp({\n * name: 'my-app',\n * bulletin: { environment: 'polkadot' },\n * });\n *\n * // Disable bulletin entirely\n * const noBulletinApp = await createApp({\n * name: 'my-app',\n * bulletin: false,\n * });\n *\n * // Connect wallet\n * const { accounts } = await app.wallet.connect();\n *\n * // Use storage\n * await app.storage.set('key', 'value');\n *\n * // Use bulletin (check for null if it might be disabled)\n * if (app.bulletin) {\n * const cid = await app.bulletin.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 kvStore = await createKvStore({ prefix: config.name });\n\n // Initialize signer manager\n const signerManager = new SignerManager({\n dappName: config.name,\n });\n\n // Initialize bulletin client (configurable, defaults to paseo).\n //\n // The signer is wrapped lazily so the bulletin 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 and work regardless.\n const bulletinEnabled = config.bulletin !== false;\n const bulletinEnvironment =\n typeof config.bulletin === \"object\" ? config.bulletin.environment : \"paseo\";\n const bulletinClient = bulletinEnabled\n ? await BulletinClient.create({\n environment: bulletinEnvironment,\n signer: createLazySigner(() => signerManager.getSigner()),\n })\n : null;\n\n if (bulletinEnabled) {\n log.debug(\"Bulletin client initialized\", { environment: bulletinEnvironment });\n } else {\n log.debug(\"Bulletin client disabled\");\n }\n\n // Create storage API adapter\n const storageApi: StorageApi = {\n get: (key) => kvStore.get(key),\n set: (key, value) => kvStore.set(key, value),\n getJSON: <T>(key: string) => kvStore.getJSON<T>(key),\n setJSON: <T>(key: string, value: T) => kvStore.setJSON(key, value),\n remove: (key) => kvStore.remove(key),\n clear: async () => {\n // KvStore doesn't have clear - this is a no-op\n log.debug(\"clear() is not supported in container storage mode\");\n },\n };\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 // Build empty rpcs object (required by API but unused - host routes connections)\n const rpcs = Object.fromEntries(\n Object.keys(chains).map((k) => [k, [] as readonly string[]]),\n ) as { [K in keyof T]: readonly string[] };\n return createChainClient({ chains, rpcs });\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 bulletin API adapter (null if disabled)\n const bulletinApi: BulletinApi | null = bulletinClient\n ? {\n upload: async (data) => {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\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 BulletinApi.upload promises a string return, and\n // app consumers expect a CID they can hand to `fetch(cid)`. Keep\n // the defensive null-check below as belt-and-braces in case the\n // upstream contract shifts.\n const result = await bulletinClient.store(bytes).withManifest(true).send();\n if (!result.cid) {\n throw new Error(\n \"Bulletin upload returned no CID despite .withManifest(true). Upstream contract may have shifted — file an issue.\",\n );\n }\n return result.cid.toString();\n },\n fetch: (cid) => bulletinClient.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 bulletin: bulletinEnabled ? bulletinEnvironment : \"disabled\",\n });\n\n return {\n wallet: walletApi,\n storage: storageApi,\n chain: chainApi,\n bulletin: bulletinApi,\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 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"]}
@@ -1,8 +1,3 @@
1
- // src/core/logger.ts
2
- import { configure, createLogger } from "@parity/product-sdk-logger";
3
-
4
- export {
5
- configure,
6
- createLogger
7
- };
1
+ export { configure, createLogger } from '@parity/product-sdk-logger';
2
+ //# sourceMappingURL=chunk-XSKBA5SR.js.map
8
3
  //# sourceMappingURL=chunk-XSKBA5SR.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/logger.ts"],"sourcesContent":["/**\n * Logger module for @parity/product-sdk\n *\n * Re-exports from @parity/product-sdk-logger.\n */\nexport { configure, createLogger } from \"@parity/product-sdk-logger\";\nexport type {\n LogLevel,\n LogEntry,\n LogHandler,\n LoggerConfig,\n Logger,\n} from \"@parity/product-sdk-logger\";\n"],"mappings":";AAKA,SAAS,WAAW,oBAAoB;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-XSKBA5SR.js","sourcesContent":[]}
@@ -1,3 +1,3 @@
1
- // src/contracts/index.ts
2
- export * from "@parity/product-sdk-contracts";
1
+ export * from '@parity/product-sdk-contracts';
2
+ //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/contracts/index.ts"],"sourcesContent":["/**\n * @parity/product-sdk/contracts\n *\n * Re-exports from @parity/product-sdk-contracts.\n */\nexport * from \"@parity/product-sdk-contracts\";\n"],"mappings":";AAKA,cAAc;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -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, A as App, b as AppConfig, B as BulletinApi, c as BulletinConfig, C as ChainApi, S as StorageApi, W as WalletApi } from '../types-CZQDzQ53.js';
3
+ export { a as Account, A as App, b as AppConfig, B as BulletinApi, c as BulletinConfig, C as ChainApi, S as StorageApi, W as WalletApi } from '../types-CvHwLIWl.js';
4
4
  export { ChainClient } from '@parity/product-sdk-chain-client';
5
5
  export { ChainDefinition, PolkadotClient, TypedApi } from 'polkadot-api';
6
6
  import '@parity/product-sdk-host';
@@ -1,13 +1,4 @@
1
- import {
2
- configure,
3
- createLogger
4
- } from "../chunk-XSKBA5SR.js";
5
- import {
6
- createApp
7
- } from "../chunk-NVGSGXGH.js";
8
- export {
9
- configure,
10
- createApp,
11
- createLogger
12
- };
1
+ export { configure, createLogger } from '../chunk-XSKBA5SR.js';
2
+ export { createApp } from '../chunk-6W3TCR3W.js';
3
+ //# sourceMappingURL=index.js.map
13
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -1,3 +1,3 @@
1
- // src/crypto/index.ts
2
- export * from "@parity/product-sdk-crypto";
1
+ export * from '@parity/product-sdk-crypto';
2
+ //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/crypto/index.ts"],"sourcesContent":["/**\n * @parity/product-sdk/crypto\n *\n * Re-exports from @parity/product-sdk-crypto.\n */\nexport * from \"@parity/product-sdk-crypto\";\n"],"mappings":";AAKA,cAAc;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -1,3 +1,3 @@
1
- // src/host/index.ts
2
- export * from "@parity/product-sdk-host";
1
+ export * from '@parity/product-sdk-host';
2
+ //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/host/index.ts"],"sourcesContent":["/**\n * @parity/product-sdk/host\n *\n * Re-exports from @parity/product-sdk-host.\n */\nexport * from \"@parity/product-sdk-host\";\n"],"mappings":";AAKA,cAAc;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -1,5 +1,8 @@
1
+ import { createLogger } from '@parity/product-sdk-logger';
2
+ import { blake2b256 } from '@parity/product-sdk-crypto';
3
+ import { ss58Decode, ss58Encode, deriveH160 } from '@parity/product-sdk-address';
4
+
1
5
  // src/identity/dotns.ts
2
- import { createLogger } from "@parity/product-sdk-logger";
3
6
  var log = createLogger("identity");
4
7
  function isValidDotNsName(name) {
5
8
  if (!name.endsWith(".dot")) return false;
@@ -35,12 +38,7 @@ async function isDotNsAvailable(name) {
35
38
  const record = await resolveDotNs(name).catch(() => null);
36
39
  return record === null;
37
40
  }
38
-
39
- // src/identity/product-account.ts
40
- import { createLogger as createLogger2 } from "@parity/product-sdk-logger";
41
- import { blake2b256 } from "@parity/product-sdk-crypto";
42
- import { ss58Encode, ss58Decode, deriveH160 } from "@parity/product-sdk-address";
43
- var log2 = createLogger2("identity");
41
+ var log2 = createLogger("identity");
44
42
  function deriveProductAccount(parentAddress, productName, ss58Prefix = 42) {
45
43
  const { publicKey: parentPublicKey } = ss58Decode(parentAddress);
46
44
  const productNameBytes = new TextEncoder().encode(productName);
@@ -94,16 +92,7 @@ async function verifyRingProof(message, proof, alias) {
94
92
  "verifyRingProof() is not yet implemented. This requires container mode with Ring VRF support."
95
93
  );
96
94
  }
97
- export {
98
- createRingProof,
99
- deriveAnonymousAlias,
100
- deriveProductAccount,
101
- isDotNsAvailable,
102
- isValidDotNsName,
103
- normalizeDotNsName,
104
- resolveDotNs,
105
- reverseDotNs,
106
- verifyProductAccount,
107
- verifyRingProof
108
- };
95
+
96
+ export { createRingProof, deriveAnonymousAlias, deriveProductAccount, isDotNsAvailable, isValidDotNsName, normalizeDotNsName, resolveDotNs, reverseDotNs, verifyProductAccount, verifyRingProof };
97
+ //# sourceMappingURL=index.js.map
109
98
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/identity/dotns.ts","../../src/identity/product-account.ts"],"sourcesContent":["/**\n * DotNS (Polkadot Name Service) utilities\n *\n * Provides name resolution for .dot domains\n */\n\nimport { createLogger } from \"@parity/product-sdk-logger\";\nimport type { DotNsRecord } from \"./types.js\";\n\nconst log = createLogger(\"identity\");\n\n/**\n * Check if a string is a valid DotNS name\n *\n * @param name - Name to validate\n * @returns True if valid DotNS name\n */\nexport function isValidDotNsName(name: string): boolean {\n // Basic validation: alphanumeric, hyphens, ends with .dot\n if (!name.endsWith(\".dot\")) return false;\n const label = name.slice(0, -4);\n if (label.length < 3 || label.length > 63) return false;\n return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(label);\n}\n\n/**\n * Normalize a DotNS name (lowercase, trim whitespace)\n *\n * @param name - Name to normalize\n * @returns Normalized name\n */\nexport function normalizeDotNsName(name: string): string {\n let normalized = name.toLowerCase().trim();\n if (!normalized.endsWith(\".dot\")) {\n normalized += \".dot\";\n }\n return normalized;\n}\n\n/**\n * Resolve a DotNS name to an address\n *\n * @param name - DotNS name (e.g., \"alice.dot\")\n * @returns Resolved record or null if not found\n *\n * @example\n * ```ts\n * const record = await resolveDotNs('alice.dot');\n * if (record) {\n * console.log('Address:', record.address);\n * }\n * ```\n */\nexport async function resolveDotNs(name: string): Promise<DotNsRecord | null> {\n const normalized = normalizeDotNsName(name);\n\n if (!isValidDotNsName(normalized)) {\n log.warn(\"Invalid DotNS name\", { name });\n return null;\n }\n\n log.debug(\"Resolving DotNS name\", { name: normalized });\n\n // TODO: Implement via PAPI query to DotNS pallet\n throw new Error(\n \"resolveDotNs() is not yet implemented. \" +\n \"This is a skeleton for the Product SDK structure.\",\n );\n}\n\n/**\n * Reverse resolve an address to a DotNS name\n *\n * @param address - SS58 address\n * @returns Primary name or null if none set\n */\nexport async function reverseDotNs(address: string): Promise<string | null> {\n log.debug(\"Reverse resolving address\", { address });\n\n // TODO: Implement via PAPI query to DotNS pallet\n throw new Error(\n \"reverseDotNs() is not yet implemented. \" +\n \"This is a skeleton for the Product SDK structure.\",\n );\n}\n\n/**\n * Check if a DotNS name is available for registration\n *\n * @param name - Name to check\n * @returns True if available\n */\nexport async function isDotNsAvailable(name: string): Promise<boolean> {\n const record = await resolveDotNs(name).catch(() => null);\n return record === null;\n}\n","/**\n * Product account derivation\n *\n * Derives product-scoped accounts from a parent account\n */\n\nimport { createLogger } from \"@parity/product-sdk-logger\";\nimport { blake2b256 } from \"@parity/product-sdk-crypto\";\nimport { ss58Encode, ss58Decode, deriveH160 } from \"@parity/product-sdk-address\";\nimport type { ProductAccountInfo, AnonymousAliasInfo, RingLocation } from \"./types.js\";\n\nconst log = createLogger(\"identity\");\n\n/**\n * Derive a product-scoped account from a parent account\n *\n * The product account is deterministically derived using:\n * productPublicKey = hash(parentPublicKey || productName)\n *\n * @param parentAddress - Parent account SS58 address\n * @param productName - Product name for derivation\n * @param ss58Prefix - SS58 prefix (default: 42)\n * @returns Product account info\n *\n * @example\n * ```ts\n * const productAccount = deriveProductAccount(\n * '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',\n * 'my-app'\n * );\n * console.log('Product address:', productAccount.address);\n * ```\n */\nexport function deriveProductAccount(\n parentAddress: string,\n productName: string,\n ss58Prefix = 42,\n): ProductAccountInfo {\n const { publicKey: parentPublicKey } = ss58Decode(parentAddress);\n\n // Derive product public key: blake2b-256(parentPublicKey || productName)\n const productNameBytes = new TextEncoder().encode(productName);\n const combined = new Uint8Array(parentPublicKey.length + productNameBytes.length);\n combined.set(parentPublicKey, 0);\n combined.set(productNameBytes, parentPublicKey.length);\n\n const productPublicKey = blake2b256(combined);\n const address = ss58Encode(productPublicKey, ss58Prefix);\n const h160Address = deriveH160(productPublicKey);\n\n log.debug(\"Derived product account\", {\n parentAddress,\n productName,\n address,\n });\n\n return {\n address,\n h160Address,\n parentAddress,\n productName,\n };\n}\n\n/**\n * Verify that a product account was derived from a parent account\n *\n * @param productAddress - Product account address\n * @param parentAddress - Claimed parent address\n * @param productName - Product name\n * @returns True if derivation is valid\n */\nexport function verifyProductAccount(\n productAddress: string,\n parentAddress: string,\n productName: string,\n): boolean {\n try {\n const derived = deriveProductAccount(parentAddress, productName);\n const { publicKey: productKey } = ss58Decode(productAddress);\n const { publicKey: derivedKey } = ss58Decode(derived.address);\n\n // Compare public keys\n if (productKey.length !== derivedKey.length) return false;\n for (let i = 0; i < productKey.length; i++) {\n if (productKey[i] !== derivedKey[i]) return false;\n }\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Derive an anonymous alias using Ring VRF\n *\n * This creates a context-specific alias that cannot be linked\n * back to the original identity without the ring proof.\n *\n * @param context - Context for alias derivation (e.g., \"voting-round-1\")\n * @param ringLocation - Ring location for proof generation\n * @returns Anonymous alias info\n */\nexport function deriveAnonymousAlias(\n context: string,\n ringLocation: RingLocation,\n): AnonymousAliasInfo {\n log.debug(\"Deriving anonymous alias\", { context, ringLocation });\n\n // TODO: Implement Ring VRF alias derivation\n // This requires the Ring VRF implementation from TruAPI\n throw new Error(\n \"deriveAnonymousAlias() is not yet implemented. \" +\n \"This requires container mode with Ring VRF support.\",\n );\n}\n\n/**\n * Create a Ring VRF proof for a message\n *\n * @param message - Message to prove\n * @param ringLocation - Ring location\n * @returns Proof bytes\n */\nexport async function createRingProof(\n message: Uint8Array,\n ringLocation: RingLocation,\n): Promise<Uint8Array> {\n log.debug(\"Creating ring proof\", { ringLocation });\n\n // TODO: Implement Ring VRF proof creation via TruAPI\n throw new Error(\n \"createRingProof() is not yet implemented. \" +\n \"This requires container mode with Ring VRF support.\",\n );\n}\n\n/**\n * Verify a Ring VRF proof\n *\n * @param message - Original message\n * @param proof - Proof bytes\n * @param alias - Expected alias\n * @returns True if proof is valid\n */\nexport async function verifyRingProof(\n message: Uint8Array,\n proof: Uint8Array,\n alias: string,\n): Promise<boolean> {\n log.debug(\"Verifying ring proof\");\n\n // TODO: Implement Ring VRF proof verification\n throw new Error(\n \"verifyRingProof() is not yet implemented. \" +\n \"This requires container mode with Ring VRF support.\",\n );\n}\n"],"mappings":"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","names":["createLogger","log"]}
1
+ {"version":3,"sources":["../../src/identity/dotns.ts","../../src/identity/product-account.ts"],"names":["log","createLogger"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * DotNS (Polkadot Name Service) utilities\n *\n * Provides name resolution for .dot domains\n */\n\nimport { createLogger } from \"@parity/product-sdk-logger\";\nimport type { DotNsRecord } from \"./types.js\";\n\nconst log = createLogger(\"identity\");\n\n/**\n * Check if a string is a valid DotNS name\n *\n * @param name - Name to validate\n * @returns True if valid DotNS name\n */\nexport function isValidDotNsName(name: string): boolean {\n // Basic validation: alphanumeric, hyphens, ends with .dot\n if (!name.endsWith(\".dot\")) return false;\n const label = name.slice(0, -4);\n if (label.length < 3 || label.length > 63) return false;\n return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(label);\n}\n\n/**\n * Normalize a DotNS name (lowercase, trim whitespace)\n *\n * @param name - Name to normalize\n * @returns Normalized name\n */\nexport function normalizeDotNsName(name: string): string {\n let normalized = name.toLowerCase().trim();\n if (!normalized.endsWith(\".dot\")) {\n normalized += \".dot\";\n }\n return normalized;\n}\n\n/**\n * Resolve a DotNS name to an address\n *\n * @param name - DotNS name (e.g., \"alice.dot\")\n * @returns Resolved record or null if not found\n *\n * @example\n * ```ts\n * const record = await resolveDotNs('alice.dot');\n * if (record) {\n * console.log('Address:', record.address);\n * }\n * ```\n */\nexport async function resolveDotNs(name: string): Promise<DotNsRecord | null> {\n const normalized = normalizeDotNsName(name);\n\n if (!isValidDotNsName(normalized)) {\n log.warn(\"Invalid DotNS name\", { name });\n return null;\n }\n\n log.debug(\"Resolving DotNS name\", { name: normalized });\n\n // TODO: Implement via PAPI query to DotNS pallet\n throw new Error(\n \"resolveDotNs() is not yet implemented. \" +\n \"This is a skeleton for the Product SDK structure.\",\n );\n}\n\n/**\n * Reverse resolve an address to a DotNS name\n *\n * @param address - SS58 address\n * @returns Primary name or null if none set\n */\nexport async function reverseDotNs(address: string): Promise<string | null> {\n log.debug(\"Reverse resolving address\", { address });\n\n // TODO: Implement via PAPI query to DotNS pallet\n throw new Error(\n \"reverseDotNs() is not yet implemented. \" +\n \"This is a skeleton for the Product SDK structure.\",\n );\n}\n\n/**\n * Check if a DotNS name is available for registration\n *\n * @param name - Name to check\n * @returns True if available\n */\nexport async function isDotNsAvailable(name: string): Promise<boolean> {\n const record = await resolveDotNs(name).catch(() => null);\n return record === null;\n}\n","/**\n * Product account derivation\n *\n * Derives product-scoped accounts from a parent account\n */\n\nimport { createLogger } from \"@parity/product-sdk-logger\";\nimport { blake2b256 } from \"@parity/product-sdk-crypto\";\nimport { ss58Encode, ss58Decode, deriveH160 } from \"@parity/product-sdk-address\";\nimport type { ProductAccountInfo, AnonymousAliasInfo, RingLocation } from \"./types.js\";\n\nconst log = createLogger(\"identity\");\n\n/**\n * Derive a product-scoped account from a parent account\n *\n * The product account is deterministically derived using:\n * productPublicKey = hash(parentPublicKey || productName)\n *\n * @param parentAddress - Parent account SS58 address\n * @param productName - Product name for derivation\n * @param ss58Prefix - SS58 prefix (default: 42)\n * @returns Product account info\n *\n * @example\n * ```ts\n * const productAccount = deriveProductAccount(\n * '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',\n * 'my-app'\n * );\n * console.log('Product address:', productAccount.address);\n * ```\n */\nexport function deriveProductAccount(\n parentAddress: string,\n productName: string,\n ss58Prefix = 42,\n): ProductAccountInfo {\n const { publicKey: parentPublicKey } = ss58Decode(parentAddress);\n\n // Derive product public key: blake2b-256(parentPublicKey || productName)\n const productNameBytes = new TextEncoder().encode(productName);\n const combined = new Uint8Array(parentPublicKey.length + productNameBytes.length);\n combined.set(parentPublicKey, 0);\n combined.set(productNameBytes, parentPublicKey.length);\n\n const productPublicKey = blake2b256(combined);\n const address = ss58Encode(productPublicKey, ss58Prefix);\n const h160Address = deriveH160(productPublicKey);\n\n log.debug(\"Derived product account\", {\n parentAddress,\n productName,\n address,\n });\n\n return {\n address,\n h160Address,\n parentAddress,\n productName,\n };\n}\n\n/**\n * Verify that a product account was derived from a parent account\n *\n * @param productAddress - Product account address\n * @param parentAddress - Claimed parent address\n * @param productName - Product name\n * @returns True if derivation is valid\n */\nexport function verifyProductAccount(\n productAddress: string,\n parentAddress: string,\n productName: string,\n): boolean {\n try {\n const derived = deriveProductAccount(parentAddress, productName);\n const { publicKey: productKey } = ss58Decode(productAddress);\n const { publicKey: derivedKey } = ss58Decode(derived.address);\n\n // Compare public keys\n if (productKey.length !== derivedKey.length) return false;\n for (let i = 0; i < productKey.length; i++) {\n if (productKey[i] !== derivedKey[i]) return false;\n }\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Derive an anonymous alias using Ring VRF\n *\n * This creates a context-specific alias that cannot be linked\n * back to the original identity without the ring proof.\n *\n * @param context - Context for alias derivation (e.g., \"voting-round-1\")\n * @param ringLocation - Ring location for proof generation\n * @returns Anonymous alias info\n */\nexport function deriveAnonymousAlias(\n context: string,\n ringLocation: RingLocation,\n): AnonymousAliasInfo {\n log.debug(\"Deriving anonymous alias\", { context, ringLocation });\n\n // TODO: Implement Ring VRF alias derivation\n // This requires the Ring VRF implementation from TruAPI\n throw new Error(\n \"deriveAnonymousAlias() is not yet implemented. \" +\n \"This requires container mode with Ring VRF support.\",\n );\n}\n\n/**\n * Create a Ring VRF proof for a message\n *\n * @param message - Message to prove\n * @param ringLocation - Ring location\n * @returns Proof bytes\n */\nexport async function createRingProof(\n message: Uint8Array,\n ringLocation: RingLocation,\n): Promise<Uint8Array> {\n log.debug(\"Creating ring proof\", { ringLocation });\n\n // TODO: Implement Ring VRF proof creation via TruAPI\n throw new Error(\n \"createRingProof() is not yet implemented. \" +\n \"This requires container mode with Ring VRF support.\",\n );\n}\n\n/**\n * Verify a Ring VRF proof\n *\n * @param message - Original message\n * @param proof - Proof bytes\n * @param alias - Expected alias\n * @returns True if proof is valid\n */\nexport async function verifyRingProof(\n message: Uint8Array,\n proof: Uint8Array,\n alias: string,\n): Promise<boolean> {\n log.debug(\"Verifying ring proof\");\n\n // TODO: Implement Ring VRF proof verification\n throw new Error(\n \"verifyRingProof() is not yet implemented. \" +\n \"This requires container mode with Ring VRF support.\",\n );\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export { LogEntry, LogHandler, LogLevel, Logger, LoggerConfig, configure, createLogger } from '@parity/product-sdk-logger';
2
- import { b as AppConfig, A as App } from './types-CZQDzQ53.js';
3
- export { a as Account, B as BulletinApi, C as ChainApi, S as StorageApi, W as WalletApi } from './types-CZQDzQ53.js';
2
+ import { b as AppConfig, A as App } from './types-CvHwLIWl.js';
3
+ export { a as Account, B as BulletinApi, C as ChainApi, S as StorageApi, W as WalletApi } from './types-CvHwLIWl.js';
4
4
  export { isInsideContainer, isInsideContainerSync } from '@parity/product-sdk-host';
5
5
  export { ChainClient, createChainClient } from '@parity/product-sdk-chain-client';
6
6
  export { SignerManager } from '@parity/product-sdk-signer';
7
7
  export { createKvStore } from '@parity/product-sdk-storage';
8
- export { BulletinClient, computeCid } from '@parity/product-sdk-bulletin';
8
+ export { BulletinClient, calculateCid } from '@parity/product-sdk-bulletin';
9
9
  export { ChainDefinition, PolkadotClient, TypedApi } from 'polkadot-api';
10
10
 
11
11
  /**
package/dist/index.js CHANGED
@@ -1,27 +1,9 @@
1
- import {
2
- configure,
3
- createLogger
4
- } from "./chunk-XSKBA5SR.js";
5
- import {
6
- createApp
7
- } from "./chunk-NVGSGXGH.js";
8
-
9
- // src/index.ts
10
- import { isInsideContainer, isInsideContainerSync } from "@parity/product-sdk-host";
11
- import { createChainClient } from "@parity/product-sdk-chain-client";
12
- import { SignerManager } from "@parity/product-sdk-signer";
13
- import { createKvStore } from "@parity/product-sdk-storage";
14
- import { BulletinClient, computeCid } from "@parity/product-sdk-bulletin";
15
- export {
16
- BulletinClient,
17
- SignerManager,
18
- computeCid,
19
- configure,
20
- createApp,
21
- createChainClient,
22
- createKvStore,
23
- createLogger,
24
- isInsideContainer,
25
- isInsideContainerSync
26
- };
1
+ export { configure, createLogger } from './chunk-XSKBA5SR.js';
2
+ export { createApp } from './chunk-6W3TCR3W.js';
3
+ export { isInsideContainer, isInsideContainerSync } from '@parity/product-sdk-host';
4
+ export { createChainClient } from '@parity/product-sdk-chain-client';
5
+ export { SignerManager } from '@parity/product-sdk-signer';
6
+ export { createKvStore } from '@parity/product-sdk-storage';
7
+ export { BulletinClient, calculateCid } from '@parity/product-sdk-bulletin';
8
+ //# sourceMappingURL=index.js.map
27
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @parity/product-sdk\n *\n * Unified SDK for building products on the Polkadot ecosystem.\n *\n * @example\n * ```ts\n * import { createApp } from '@parity/product-sdk';\n *\n * const app = createApp({\n * name: 'my-app',\n * logLevel: 'info',\n * });\n *\n * // Connect wallet\n * const { accounts } = await app.wallet.connect();\n *\n * // Use storage\n * await app.storage.set('key', 'value');\n * ```\n *\n * @packageDocumentation\n */\n\n// Core exports\nexport { createApp } from \"./core/createApp.js\";\nexport { configure, createLogger } from \"./core/logger.js\";\nexport type {\n App,\n AppConfig,\n LogLevel,\n WalletApi,\n StorageApi,\n ChainApi,\n BulletinApi,\n Account,\n ChainClient,\n ChainDefinition,\n TypedApi,\n PolkadotClient,\n} from \"./core/types.js\";\nexport type { LogEntry, LogHandler, LoggerConfig, Logger } from \"./core/logger.js\";\n\n// Re-export common utilities from leaf packages\nexport { isInsideContainer, isInsideContainerSync } from \"@parity/product-sdk-host\";\nexport { createChainClient } from \"@parity/product-sdk-chain-client\";\nexport { SignerManager } from \"@parity/product-sdk-signer\";\nexport { createKvStore } from \"@parity/product-sdk-storage\";\nexport { BulletinClient, computeCid } from \"@parity/product-sdk-bulletin\";\n"],"mappings":";;;;;;;;;AA4CA,SAAS,mBAAmB,6BAA6B;AACzD,SAAS,yBAAyB;AAClC,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB,kBAAkB;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -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 { A as App, a as Account } from '../types-CZQDzQ53.js';
5
+ import { A as App, a as Account } from '../types-CvHwLIWl.js';
6
6
  import { ChainDefinition, TypedApi } from 'polkadot-api';
7
7
  import '@parity/product-sdk-bulletin';
8
8
  import '@parity/product-sdk-chain-client';
@@ -1,12 +1,7 @@
1
- import {
2
- createApp
3
- } from "../chunk-NVGSGXGH.js";
1
+ import { createApp } from '../chunk-6W3TCR3W.js';
2
+ import { createContext, useContext, useState, useEffect, useCallback, useMemo } from 'react';
3
+ import { jsx, Fragment } from 'react/jsx-runtime';
4
4
 
5
- // src/react/provider.tsx
6
- import { useEffect, useState } from "react";
7
-
8
- // src/react/context.ts
9
- import { createContext, useContext } from "react";
10
5
  var ProductSDKContext = createContext(null);
11
6
  function useProductSDK() {
12
7
  const app = useContext(ProductSDKContext);
@@ -17,9 +12,6 @@ function useProductSDK() {
17
12
  }
18
13
  return app;
19
14
  }
20
-
21
- // src/react/provider.tsx
22
- import { Fragment, jsx } from "react/jsx-runtime";
23
15
  function ProductSDKProvider({
24
16
  name,
25
17
  logLevel = "info",
@@ -51,12 +43,9 @@ function ProductSDKProvider({
51
43
  }
52
44
  return /* @__PURE__ */ jsx(ProductSDKContext.Provider, { value: app, children });
53
45
  }
54
-
55
- // src/react/useWallet.ts
56
- import { useState as useState2, useEffect as useEffect2, useCallback } from "react";
57
46
  function useWallet() {
58
47
  const app = useProductSDK();
59
- const [state, setState] = useState2({
48
+ const [state, setState] = useState({
60
49
  isConnected: false,
61
50
  isConnecting: false,
62
51
  accounts: [],
@@ -106,7 +95,7 @@ function useWallet() {
106
95
  },
107
96
  [app]
108
97
  );
109
- useEffect2(() => {
98
+ useEffect(() => {
110
99
  const unsubscribe = app.wallet.onAccountChange((account) => {
111
100
  setState((s) => ({ ...s, selectedAccount: account }));
112
101
  });
@@ -120,15 +109,12 @@ function useWallet() {
120
109
  signMessage
121
110
  };
122
111
  }
123
-
124
- // src/react/useStorage.ts
125
- import { useState as useState3, useEffect as useEffect3, useCallback as useCallback2 } from "react";
126
112
  function useStorage(key, defaultValue) {
127
113
  const app = useProductSDK();
128
- const [value, setValue] = useState3(null);
129
- const [loading, setLoading] = useState3(true);
130
- const [error, setError] = useState3(null);
131
- useEffect3(() => {
114
+ const [value, setValue] = useState(null);
115
+ const [loading, setLoading] = useState(true);
116
+ const [error, setError] = useState(null);
117
+ useEffect(() => {
132
118
  let mounted = true;
133
119
  const loadValue = async () => {
134
120
  try {
@@ -150,7 +136,7 @@ function useStorage(key, defaultValue) {
150
136
  mounted = false;
151
137
  };
152
138
  }, [app, key, defaultValue]);
153
- const setStoredValue = useCallback2(
139
+ const setStoredValue = useCallback(
154
140
  async (newValue) => {
155
141
  try {
156
142
  setError(null);
@@ -167,9 +153,9 @@ function useStorage(key, defaultValue) {
167
153
  }
168
154
  function useStorageString(key, defaultValue) {
169
155
  const app = useProductSDK();
170
- const [value, setValue] = useState3(null);
171
- const [loading, setLoading] = useState3(true);
172
- useEffect3(() => {
156
+ const [value, setValue] = useState(null);
157
+ const [loading, setLoading] = useState(true);
158
+ useEffect(() => {
173
159
  let mounted = true;
174
160
  const loadValue = async () => {
175
161
  const stored = await app.storage.get(key);
@@ -183,7 +169,7 @@ function useStorageString(key, defaultValue) {
183
169
  mounted = false;
184
170
  };
185
171
  }, [app, key, defaultValue]);
186
- const setStoredValue = useCallback2(
172
+ const setStoredValue = useCallback(
187
173
  async (newValue) => {
188
174
  await app.storage.set(key, newValue);
189
175
  setValue(newValue);
@@ -192,22 +178,13 @@ function useStorageString(key, defaultValue) {
192
178
  );
193
179
  return [value, setStoredValue, { loading }];
194
180
  }
195
-
196
- // src/react/useChain.ts
197
- import { useMemo } from "react";
198
181
  function useChain(chain) {
199
182
  const app = useProductSDK();
200
183
  return useMemo(() => {
201
184
  return app.chain.getClient(chain);
202
185
  }, [app, chain]);
203
186
  }
204
- export {
205
- ProductSDKContext,
206
- ProductSDKProvider,
207
- useChain,
208
- useProductSDK,
209
- useStorage,
210
- useStorageString,
211
- useWallet
212
- };
187
+
188
+ export { ProductSDKContext, ProductSDKProvider, useChain, useProductSDK, useStorage, useStorageString, useWallet };
189
+ //# sourceMappingURL=index.js.map
213
190
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/provider.tsx","../../src/react/context.ts","../../src/react/useWallet.ts","../../src/react/useStorage.ts","../../src/react/useChain.ts"],"sourcesContent":["/**\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","/**\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.storage, 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","/**\n * useWallet hook\n */\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useProductSDK } from \"./context.js\";\nimport type { Account } 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}\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 // 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 };\n}\n","/**\n * useStorage 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 }] = useStorage('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 useStorage<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.storage.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.storage.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 useStorageString(\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.storage.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.storage.set(key, newValue);\n setValue(newValue);\n },\n [app, key],\n );\n\n return [value, setStoredValue, { loading }];\n}\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"],"mappings":";;;;;AAIA,SAAgB,WAAW,gBAAgC;;;ACA3D,SAAS,eAAe,kBAAkB;AAInC,IAAM,oBAAoB,cAA0B,IAAI;AAexD,SAAS,gBAAqB;AACjC,QAAM,MAAM,WAAW,iBAAiB;AACxC,MAAI,CAAC,KAAK;AACN,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AACA,SAAO;AACX;;;ADuCe;AAlCR,SAAS,mBAAmB;AAAA,EAC/B;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA,WAAW;AACf,GAA4B;AACxB,QAAM,CAAC,KAAK,MAAM,IAAI,SAAqB,IAAI;AAC/C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AAErD,YAAU,MAAM;AACZ,QAAI,UAAU;AAEd,cAAU,EAAE,MAAM,SAAS,CAAC,EACvB,KAAK,CAAC,eAAe;AAClB,UAAI,SAAS;AACT,eAAO,UAAU;AAAA,MACrB;AAAA,IACJ,CAAC,EACA,MAAM,CAAC,MAAM;AACV,UAAI,SAAS;AACT,iBAAS,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC;AAAA,MAC1D;AAAA,IACJ,CAAC;AAEL,WAAO,MAAM;AACT,gBAAU;AAAA,IACd;AAAA,EACJ,GAAG,CAAC,MAAM,QAAQ,CAAC;AAEnB,MAAI,OAAO;AACP,UAAM;AAAA,EACV;AAEA,MAAI,CAAC,KAAK;AACN,WAAO,gCAAG,oBAAS;AAAA,EACvB;AAEA,SAAO,oBAAC,kBAAkB,UAAlB,EAA2B,OAAO,KAAM,UAAS;AAC7D;;;AEvEA,SAAS,YAAAA,WAAU,aAAAC,YAAW,mBAAmB;AA4D1C,SAAS,YAA6B;AACzC,QAAM,MAAM,cAAc;AAE1B,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAyB;AAAA,IAC/C,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU,CAAC;AAAA,IACX,iBAAiB;AAAA,IACjB,OAAO;AAAA,EACX,CAAC;AAED,QAAM,UAAU,YAAY,YAAY;AACpC,aAAS,CAAC,OAAO,EAAE,GAAG,GAAG,cAAc,MAAM,OAAO,KAAK,EAAE;AAC3D,QAAI;AACA,YAAM,SAAS,MAAM,IAAI,OAAO,QAAQ;AACxC,eAAS,CAAC,OAAO;AAAA,QACb,GAAG;AAAA,QACH,aAAa;AAAA,QACb,cAAc;AAAA,QACd,UAAU,OAAO;AAAA,QACjB,iBAAiB,OAAO,SAAS,CAAC,KAAK;AAAA,MAC3C,EAAE;AAAA,IACN,SAAS,GAAG;AACR,eAAS,CAAC,OAAO;AAAA,QACb,GAAG;AAAA,QACH,cAAc;AAAA,QACd,OAAO,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC;AAAA,MACvD,EAAE;AAAA,IACN;AAAA,EACJ,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,aAAa,YAAY,YAAY;AACvC,UAAM,IAAI,OAAO,WAAW;AAC5B,aAAS;AAAA,MACL,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU,CAAC;AAAA,MACX,iBAAiB;AAAA,MACjB,OAAO;AAAA,IACX,CAAC;AAAA,EACL,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,gBAAgB;AAAA,IAClB,CAAC,YAAoB;AACjB,UAAI,OAAO,cAAc,OAAO;AAChC,YAAM,UAAU,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO,KAAK;AACrE,eAAS,CAAC,OAAO,EAAE,GAAG,GAAG,iBAAiB,QAAQ,EAAE;AAAA,IACxD;AAAA,IACA,CAAC,KAAK,MAAM,QAAQ;AAAA,EACxB;AAEA,QAAM,cAAc;AAAA,IAChB,OAAO,YAAiC;AACpC,aAAO,IAAI,OAAO,YAAY,OAAO;AAAA,IACzC;AAAA,IACA,CAAC,GAAG;AAAA,EACR;AAGA,EAAAC,WAAU,MAAM;AACZ,UAAM,cAAc,IAAI,OAAO,gBAAgB,CAAC,YAAY;AACxD,eAAS,CAAC,OAAO,EAAE,GAAG,GAAG,iBAAiB,QAAQ,EAAE;AAAA,IACxD,CAAC;AACD,WAAO;AAAA,EACX,GAAG,CAAC,GAAG,CAAC;AAER,SAAO;AAAA,IACH,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AACJ;;;ACrIA,SAAS,YAAAC,WAAU,aAAAC,YAAW,eAAAC,oBAAmB;AAwB1C,SAAS,WACZ,KACA,cACkF;AAClF,QAAM,MAAM,cAAc;AAE1B,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAmB,IAAI;AACjD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AAGrD,EAAAC,WAAU,MAAM;AACZ,QAAI,UAAU;AAEd,UAAM,YAAY,YAAY;AAC1B,UAAI;AACA,mBAAW,IAAI;AACf,cAAM,SAAS,MAAM,IAAI,QAAQ,QAAW,GAAG;AAC/C,YAAI,SAAS;AACT,mBAAS,UAAU,gBAAgB,IAAI;AACvC,qBAAW,KAAK;AAAA,QACpB;AAAA,MACJ,SAAS,GAAG;AACR,YAAI,SAAS;AACT,mBAAS,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC;AACtD,qBAAW,KAAK;AAAA,QACpB;AAAA,MACJ;AAAA,IACJ;AAEA,cAAU;AAEV,WAAO,MAAM;AACT,gBAAU;AAAA,IACd;AAAA,EACJ,GAAG,CAAC,KAAK,KAAK,YAAY,CAAC;AAE3B,QAAM,iBAAiBC;AAAA,IACnB,OAAO,aAAgB;AACnB,UAAI;AACA,iBAAS,IAAI;AACb,cAAM,IAAI,QAAQ,QAAQ,KAAK,QAAQ;AACvC,iBAAS,QAAQ;AAAA,MACrB,SAAS,GAAG;AACR,iBAAS,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC;AACtD,cAAM;AAAA,MACV;AAAA,IACJ;AAAA,IACA,CAAC,KAAK,GAAG;AAAA,EACb;AAEA,SAAO,CAAC,OAAO,gBAAgB,EAAE,SAAS,MAAM,CAAC;AACrD;AAQO,SAAS,iBACZ,KACA,cACuE;AACvE,QAAM,MAAM,cAAc;AAE1B,QAAM,CAAC,OAAO,QAAQ,IAAIF,UAAwB,IAAI;AACtD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,IAAI;AAE3C,EAAAC,WAAU,MAAM;AACZ,QAAI,UAAU;AAEd,UAAM,YAAY,YAAY;AAC1B,YAAM,SAAS,MAAM,IAAI,QAAQ,IAAI,GAAG;AACxC,UAAI,SAAS;AACT,iBAAS,UAAU,gBAAgB,IAAI;AACvC,mBAAW,KAAK;AAAA,MACpB;AAAA,IACJ;AAEA,cAAU;AAEV,WAAO,MAAM;AACT,gBAAU;AAAA,IACd;AAAA,EACJ,GAAG,CAAC,KAAK,KAAK,YAAY,CAAC;AAE3B,QAAM,iBAAiBC;AAAA,IACnB,OAAO,aAAqB;AACxB,YAAM,IAAI,QAAQ,IAAI,KAAK,QAAQ;AACnC,eAAS,QAAQ;AAAA,IACrB;AAAA,IACA,CAAC,KAAK,GAAG;AAAA,EACb;AAEA,SAAO,CAAC,OAAO,gBAAgB,EAAE,QAAQ,CAAC;AAC9C;;;ACxHA,SAAS,eAAe;AAsBjB,SAAS,SAAoC,OAAuB;AACvE,QAAM,MAAM,cAAc;AAE1B,SAAO,QAAQ,MAAM;AACjB,WAAO,IAAI,MAAM,UAAU,KAAK;AAAA,EACpC,GAAG,CAAC,KAAK,KAAK,CAAC;AACnB;","names":["useState","useEffect","useState","useEffect","useState","useEffect","useCallback","useState","useEffect","useCallback"]}
1
+ {"version":3,"sources":["../../src/react/context.ts","../../src/react/provider.tsx","../../src/react/useWallet.ts","../../src/react/useStorage.ts","../../src/react/useChain.ts"],"names":["useState","useEffect","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\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.storage, 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","/**\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","/**\n * useWallet hook\n */\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useProductSDK } from \"./context.js\";\nimport type { Account } 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}\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 // 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 };\n}\n","/**\n * useStorage 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 }] = useStorage('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 useStorage<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.storage.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.storage.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 useStorageString(\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.storage.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.storage.set(key, newValue);\n setValue(newValue);\n },\n [app, key],\n );\n\n return [value, setStoredValue, { loading }];\n}\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,3 +1,3 @@
1
- // src/storage/index.ts
2
- export * from "@parity/product-sdk-storage";
1
+ export * from '@parity/product-sdk-storage';
2
+ //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/storage/index.ts"],"sourcesContent":["/**\n * @parity/product-sdk/storage\n *\n * Re-exports from @parity/product-sdk-storage.\n */\nexport * from \"@parity/product-sdk-storage\";\n"],"mappings":";AAKA,cAAc;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -1,5 +1,5 @@
1
1
  import { LogLevel } from '@parity/product-sdk-logger';
2
- import { Environment } from '@parity/product-sdk-bulletin';
2
+ import { BulletinEnvironment } from '@parity/product-sdk-bulletin';
3
3
  import { ChainClient } from '@parity/product-sdk-chain-client';
4
4
  import { ChainDefinition, TypedApi, PolkadotClient } from 'polkadot-api';
5
5
 
@@ -10,7 +10,7 @@ import { ChainDefinition, TypedApi, PolkadotClient } from 'polkadot-api';
10
10
  /** Bulletin configuration options */
11
11
  interface BulletinConfig {
12
12
  /** Bulletin environment to connect to */
13
- environment: Environment;
13
+ environment: BulletinEnvironment;
14
14
  }
15
15
  /** Configuration for createApp */
16
16
  interface AppConfig {
@@ -109,12 +109,21 @@ interface ChainApi {
109
109
  }
110
110
  /** Bulletin Chain API exposed by the SDK */
111
111
  interface BulletinApi {
112
- /** Upload data to Bulletin Chain */
112
+ /**
113
+ * Upload data to Bulletin Chain.
114
+ *
115
+ * Requires a wallet to be connected and an account selected. Throws
116
+ * "No signer available …" otherwise.
117
+ */
113
118
  upload(data: string | Uint8Array): Promise<string>;
114
- /** Fetch data by CID */
119
+ /** Fetch data by CID. */
115
120
  fetch(cid: string): Promise<Uint8Array>;
116
- /** Compute CID for data without uploading */
117
- computeCid(data: string | Uint8Array): string;
121
+ /**
122
+ * Compute the CID for data without uploading.
123
+ *
124
+ * Async because the underlying hash is computed via Web Crypto.
125
+ */
126
+ computeCid(data: string | Uint8Array): Promise<string>;
118
127
  }
119
128
  /** The main App instance returned by createApp */
120
129
  interface App {
@@ -135,7 +144,7 @@ interface Account {
135
144
  address: string;
136
145
  /** Account name/label (if available) */
137
146
  name?: string;
138
- /** Source of the account (extension name, host, etc.) */
147
+ /** Source of the account (host, dev signer, etc.) */
139
148
  source: string;
140
149
  }
141
150
 
@@ -1,3 +1,3 @@
1
- // src/wallet/index.ts
2
- export * from "@parity/product-sdk-signer";
1
+ export * from '@parity/product-sdk-signer';
2
+ //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/wallet/index.ts"],"sourcesContent":["/**\n * @parity/product-sdk/wallet\n *\n * Re-exports from @parity/product-sdk-signer.\n *\n * Note: The leaf package is named \"signer\" but exposed here as \"wallet\"\n * for backwards compatibility with the umbrella API.\n */\nexport * from \"@parity/product-sdk-signer\";\n"],"mappings":";AAQA,cAAc;","names":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parity/product-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Unified SDK for building products in the Polkadot ecosystem - umbrella package",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -62,18 +62,18 @@
62
62
  "src"
63
63
  ],
64
64
  "dependencies": {
65
- "polkadot-api": "^1.9.5",
66
- "@parity/product-sdk-address": "0.1.0",
67
- "@parity/product-sdk-bulletin": "0.1.0",
68
- "@parity/product-sdk-chain-client": "0.1.0",
69
- "@parity/product-sdk-contracts": "0.1.0",
70
- "@parity/product-sdk-crypto": "0.1.0",
71
- "@parity/product-sdk-host": "0.1.0",
72
- "@parity/product-sdk-keys": "0.1.0",
73
- "@parity/product-sdk-logger": "0.1.0",
74
- "@parity/product-sdk-storage": "0.1.0",
75
- "@parity/product-sdk-tx": "0.1.0",
76
- "@parity/product-sdk-signer": "0.1.0"
65
+ "polkadot-api": "^2.1.2",
66
+ "@parity/product-sdk-address": "0.1.1",
67
+ "@parity/product-sdk-bulletin": "0.2.1",
68
+ "@parity/product-sdk-chain-client": "0.2.1",
69
+ "@parity/product-sdk-contracts": "0.2.1",
70
+ "@parity/product-sdk-crypto": "0.1.1",
71
+ "@parity/product-sdk-host": "0.2.0",
72
+ "@parity/product-sdk-keys": "0.2.0",
73
+ "@parity/product-sdk-logger": "0.1.1",
74
+ "@parity/product-sdk-signer": "0.2.1",
75
+ "@parity/product-sdk-storage": "0.1.1",
76
+ "@parity/product-sdk-tx": "0.2.0"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "react": "^18.0.0 || ^19.0.0"
@@ -17,7 +17,7 @@ import type {
17
17
  import { configure, createLogger } from "@parity/product-sdk-logger";
18
18
  import { createKvStore } from "@parity/product-sdk-storage";
19
19
  import { SignerManager } from "@parity/product-sdk-signer";
20
- import { BulletinClient, computeCid } from "@parity/product-sdk-bulletin";
20
+ import { BulletinClient, calculateCid, createLazySigner } from "@parity/product-sdk-bulletin";
21
21
  import {
22
22
  createChainClient,
23
23
  getClient,
@@ -83,12 +83,20 @@ export async function createApp(config: AppConfig): Promise<App> {
83
83
  dappName: config.name,
84
84
  });
85
85
 
86
- // Initialize bulletin client (configurable, defaults to paseo)
86
+ // Initialize bulletin client (configurable, defaults to paseo).
87
+ //
88
+ // The signer is wrapped lazily so the bulletin client can be built before
89
+ // an account is selected. Uploads will throw a clear error if no signer
90
+ // is available at submission time. Reads (fetch / fetchJson) don't need
91
+ // a signer and work regardless.
87
92
  const bulletinEnabled = config.bulletin !== false;
88
93
  const bulletinEnvironment =
89
94
  typeof config.bulletin === "object" ? config.bulletin.environment : "paseo";
90
95
  const bulletinClient = bulletinEnabled
91
- ? await BulletinClient.create(bulletinEnvironment)
96
+ ? await BulletinClient.create({
97
+ environment: bulletinEnvironment,
98
+ signer: createLazySigner(() => signerManager.getSigner()),
99
+ })
92
100
  : null;
93
101
 
94
102
  if (bulletinEnabled) {
@@ -150,13 +158,26 @@ export async function createApp(config: AppConfig): Promise<App> {
150
158
  ? {
151
159
  upload: async (data) => {
152
160
  const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
153
- const result = await bulletinClient.upload(bytes);
154
- return result.cid;
161
+ // Explicitly request a DAG-PB manifest so chunked uploads always
162
+ // resolve to a single root CID. Without this, AsyncBulletinClient
163
+ // can return `result.cid: undefined` for chunked-without-manifest
164
+ // uploads — but BulletinApi.upload promises a string return, and
165
+ // app consumers expect a CID they can hand to `fetch(cid)`. Keep
166
+ // the defensive null-check below as belt-and-braces in case the
167
+ // upstream contract shifts.
168
+ const result = await bulletinClient.store(bytes).withManifest(true).send();
169
+ if (!result.cid) {
170
+ throw new Error(
171
+ "Bulletin upload returned no CID despite .withManifest(true). Upstream contract may have shifted — file an issue.",
172
+ );
173
+ }
174
+ return result.cid.toString();
155
175
  },
156
176
  fetch: (cid) => bulletinClient.fetchBytes(cid),
157
- computeCid: (data) => {
177
+ computeCid: async (data) => {
158
178
  const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
159
- return computeCid(bytes);
179
+ const cid = await calculateCid(bytes);
180
+ return cid.toString();
160
181
  },
161
182
  }
162
183
  : null;
package/src/core/types.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import type { LogLevel } from "@parity/product-sdk-logger";
6
- import type { Environment as BulletinEnvironment } from "@parity/product-sdk-bulletin";
6
+ import type { BulletinEnvironment } from "@parity/product-sdk-bulletin";
7
7
  import type { ChainClient } from "@parity/product-sdk-chain-client";
8
8
  import type { ChainDefinition, TypedApi, PolkadotClient } from "polkadot-api";
9
9
 
@@ -119,12 +119,21 @@ export interface ChainApi {
119
119
 
120
120
  /** Bulletin Chain API exposed by the SDK */
121
121
  export interface BulletinApi {
122
- /** Upload data to Bulletin Chain */
122
+ /**
123
+ * Upload data to Bulletin Chain.
124
+ *
125
+ * Requires a wallet to be connected and an account selected. Throws
126
+ * "No signer available …" otherwise.
127
+ */
123
128
  upload(data: string | Uint8Array): Promise<string>;
124
- /** Fetch data by CID */
129
+ /** Fetch data by CID. */
125
130
  fetch(cid: string): Promise<Uint8Array>;
126
- /** Compute CID for data without uploading */
127
- computeCid(data: string | Uint8Array): string;
131
+ /**
132
+ * Compute the CID for data without uploading.
133
+ *
134
+ * Async because the underlying hash is computed via Web Crypto.
135
+ */
136
+ computeCid(data: string | Uint8Array): Promise<string>;
128
137
  }
129
138
 
130
139
  /** The main App instance returned by createApp */
@@ -147,7 +156,7 @@ export interface Account {
147
156
  address: string;
148
157
  /** Account name/label (if available) */
149
158
  name?: string;
150
- /** Source of the account (extension name, host, etc.) */
159
+ /** Source of the account (host, dev signer, etc.) */
151
160
  source: string;
152
161
  }
153
162
 
package/src/index.ts CHANGED
@@ -46,4 +46,4 @@ export { isInsideContainer, isInsideContainerSync } from "@parity/product-sdk-ho
46
46
  export { createChainClient } from "@parity/product-sdk-chain-client";
47
47
  export { SignerManager } from "@parity/product-sdk-signer";
48
48
  export { createKvStore } from "@parity/product-sdk-storage";
49
- export { BulletinClient, computeCid } from "@parity/product-sdk-bulletin";
49
+ export { BulletinClient, calculateCid } from "@parity/product-sdk-bulletin";
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/createApp.ts"],"sourcesContent":["/**\n * createApp - Main entry point for the Product SDK\n *\n * Creates an App instance with wallet, storage, chain, and bulletin APIs.\n */\n\nimport type { ChainDefinition } from \"polkadot-api\";\nimport type {\n App,\n AppConfig,\n WalletApi,\n StorageApi,\n ChainApi,\n BulletinApi,\n Account,\n} from \"./types.js\";\nimport { configure, createLogger } from \"@parity/product-sdk-logger\";\nimport { createKvStore } from \"@parity/product-sdk-storage\";\nimport { SignerManager } from \"@parity/product-sdk-signer\";\nimport { BulletinClient, computeCid } from \"@parity/product-sdk-bulletin\";\nimport {\n createChainClient,\n getClient,\n isConnected,\n destroyAll,\n} from \"@parity/product-sdk-chain-client\";\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: bulletin enabled with paseo environment\n * const app = await createApp({\n * name: 'my-app',\n * logLevel: 'info',\n * });\n *\n * // Custom bulletin environment\n * const prodApp = await createApp({\n * name: 'my-app',\n * bulletin: { environment: 'polkadot' },\n * });\n *\n * // Disable bulletin entirely\n * const noBulletinApp = await createApp({\n * name: 'my-app',\n * bulletin: false,\n * });\n *\n * // Connect wallet\n * const { accounts } = await app.wallet.connect();\n *\n * // Use storage\n * await app.storage.set('key', 'value');\n *\n * // Use bulletin (check for null if it might be disabled)\n * if (app.bulletin) {\n * const cid = await app.bulletin.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 kvStore = await createKvStore({ prefix: config.name });\n\n // Initialize signer manager\n const signerManager = new SignerManager({\n dappName: config.name,\n });\n\n // Initialize bulletin client (configurable, defaults to paseo)\n const bulletinEnabled = config.bulletin !== false;\n const bulletinEnvironment =\n typeof config.bulletin === \"object\" ? config.bulletin.environment : \"paseo\";\n const bulletinClient = bulletinEnabled\n ? await BulletinClient.create(bulletinEnvironment)\n : null;\n\n if (bulletinEnabled) {\n log.debug(\"Bulletin client initialized\", { environment: bulletinEnvironment });\n } else {\n log.debug(\"Bulletin client disabled\");\n }\n\n // Create storage API adapter\n const storageApi: StorageApi = {\n get: (key) => kvStore.get(key),\n set: (key, value) => kvStore.set(key, value),\n getJSON: <T>(key: string) => kvStore.getJSON<T>(key),\n setJSON: <T>(key: string, value: T) => kvStore.setJSON(key, value),\n remove: (key) => kvStore.remove(key),\n clear: async () => {\n // KvStore doesn't have clear - this is a no-op\n log.debug(\"clear() is not supported in container storage mode\");\n },\n };\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 // Build empty rpcs object (required by API but unused - host routes connections)\n const rpcs = Object.fromEntries(\n Object.keys(chains).map((k) => [k, [] as readonly string[]]),\n ) as { [K in keyof T]: readonly string[] };\n return createChainClient({ chains, rpcs });\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 bulletin API adapter (null if disabled)\n const bulletinApi: BulletinApi | null = bulletinClient\n ? {\n upload: async (data) => {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n const result = await bulletinClient.upload(bytes);\n return result.cid;\n },\n fetch: (cid) => bulletinClient.fetchBytes(cid),\n computeCid: (data) => {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n return computeCid(bytes);\n },\n }\n : null;\n\n log.info(\"Product SDK app created\", {\n name: config.name,\n bulletin: bulletinEnabled ? bulletinEnvironment : \"disabled\",\n });\n\n return {\n wallet: walletApi,\n storage: storageApi,\n chain: chainApi,\n bulletin: bulletinApi,\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 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"],"mappings":"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","names":[]}