@parity/product-sdk 0.5.0 → 0.6.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.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Identity module types
3
3
  *
4
- * Types for DotNS name resolution and product account derivation
4
+ * Types for DotNS name resolution and context-alias derivation
5
5
  */
6
6
  /** DotNS name resolution result */
7
7
  interface DotNsRecord {
@@ -14,16 +14,16 @@ interface DotNsRecord {
14
14
  /** Expiration timestamp (if applicable) */
15
15
  expiresAt?: number;
16
16
  }
17
- /** Product account info */
18
- interface ProductAccountInfo {
19
- /** Product-scoped SS58 address */
17
+ /** Context alias info: a deterministic, context-bound alias derived from a parent account */
18
+ interface ContextAliasInfo {
19
+ /** Alias SS58 address */
20
20
  address: string;
21
21
  /** H160 EVM address */
22
22
  h160Address: `0x${string}`;
23
23
  /** Parent account address */
24
24
  parentAddress: string;
25
- /** Product name used for derivation */
26
- productName: string;
25
+ /** Context string used for derivation */
26
+ context: string;
27
27
  }
28
28
  /** Ring VRF alias info */
29
29
  interface AnonymousAliasInfo {
@@ -119,41 +119,45 @@ declare function reverseDotNs(address: string): Promise<string | null>;
119
119
  declare function isDotNsAvailable(name: string): Promise<boolean>;
120
120
 
121
121
  /**
122
- * Product account derivation
122
+ * Context alias derivation
123
+ *
124
+ * Derives a deterministic, context-bound alias from a parent account using blake2b-256.
123
125
  *
124
- * Derives product-scoped accounts from a parent account
126
+ * NOTE: this is NOT the canonical sr25519 product-account derivation used by
127
+ * mobile, desktop, and dotli hosts. For that, use
128
+ * `@parity/product-sdk-keys::deriveProductAccountPublicKey`.
125
129
  */
126
130
 
127
131
  /**
128
- * Derive a product-scoped account from a parent account
132
+ * Derive a context-bound alias from a parent account.
129
133
  *
130
- * The product account is deterministically derived using:
131
- * productPublicKey = hash(parentPublicKey || productName)
134
+ * The alias is deterministically derived using:
135
+ * aliasPublicKey = blake2b256(parentPublicKey || context)
132
136
  *
133
137
  * @param parentAddress - Parent account SS58 address
134
- * @param productName - Product name for derivation
138
+ * @param context - Context string for derivation (e.g. an app id or scope label)
135
139
  * @param ss58Prefix - SS58 prefix (default: 42)
136
- * @returns Product account info
140
+ * @returns Context alias info
137
141
  *
138
142
  * @example
139
143
  * ```ts
140
- * const productAccount = deriveProductAccount(
144
+ * const alias = deriveContextAlias(
141
145
  * '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
142
- * 'my-app'
146
+ * 'voting-round-1'
143
147
  * );
144
- * console.log('Product address:', productAccount.address);
148
+ * console.log('Alias address:', alias.address);
145
149
  * ```
146
150
  */
147
- declare function deriveProductAccount(parentAddress: string, productName: string, ss58Prefix?: number): ProductAccountInfo;
151
+ declare function deriveContextAlias(parentAddress: string, context: string, ss58Prefix?: number): ContextAliasInfo;
148
152
  /**
149
- * Verify that a product account was derived from a parent account
153
+ * Verify that a context alias was derived from a parent account.
150
154
  *
151
- * @param productAddress - Product account address
155
+ * @param aliasAddress - Context alias SS58 address
152
156
  * @param parentAddress - Claimed parent address
153
- * @param productName - Product name
157
+ * @param context - Context string used for derivation
154
158
  * @returns True if derivation is valid
155
159
  */
156
- declare function verifyProductAccount(productAddress: string, parentAddress: string, productName: string): boolean;
160
+ declare function verifyContextAlias(aliasAddress: string, parentAddress: string, context: string): boolean;
157
161
  /**
158
162
  * Derive an anonymous alias using Ring VRF
159
163
  *
@@ -183,4 +187,4 @@ declare function createRingProof(message: Uint8Array, ringLocation: RingLocation
183
187
  */
184
188
  declare function verifyRingProof(message: Uint8Array, proof: Uint8Array, alias: string): Promise<boolean>;
185
189
 
186
- export { type AnonymousAliasInfo, type DotNsRecord, type OnChainIdentity, type ProductAccountInfo, type RingLocation, type VerificationResult, createRingProof, deriveAnonymousAlias, deriveProductAccount, isDotNsAvailable, isValidDotNsName, normalizeDotNsName, resolveDotNs, reverseDotNs, verifyProductAccount, verifyRingProof };
190
+ export { type AnonymousAliasInfo, type ContextAliasInfo, type DotNsRecord, type OnChainIdentity, type RingLocation, type VerificationResult, createRingProof, deriveAnonymousAlias, deriveContextAlias, isDotNsAvailable, isValidDotNsName, normalizeDotNsName, resolveDotNs, reverseDotNs, verifyContextAlias, verifyRingProof };
@@ -39,35 +39,35 @@ async function isDotNsAvailable(name) {
39
39
  return record === null;
40
40
  }
41
41
  var log2 = createLogger("identity");
42
- function deriveProductAccount(parentAddress, productName, ss58Prefix = 42) {
42
+ function deriveContextAlias(parentAddress, context, ss58Prefix = 42) {
43
43
  const { publicKey: parentPublicKey } = ss58Decode(parentAddress);
44
- const productNameBytes = new TextEncoder().encode(productName);
45
- const combined = new Uint8Array(parentPublicKey.length + productNameBytes.length);
44
+ const contextBytes = new TextEncoder().encode(context);
45
+ const combined = new Uint8Array(parentPublicKey.length + contextBytes.length);
46
46
  combined.set(parentPublicKey, 0);
47
- combined.set(productNameBytes, parentPublicKey.length);
48
- const productPublicKey = blake2b256(combined);
49
- const address = ss58Encode(productPublicKey, ss58Prefix);
50
- const h160Address = deriveH160(productPublicKey);
51
- log2.debug("Derived product account", {
47
+ combined.set(contextBytes, parentPublicKey.length);
48
+ const aliasPublicKey = blake2b256(combined);
49
+ const address = ss58Encode(aliasPublicKey, ss58Prefix);
50
+ const h160Address = deriveH160(aliasPublicKey);
51
+ log2.debug("Derived context alias", {
52
52
  parentAddress,
53
- productName,
53
+ context,
54
54
  address
55
55
  });
56
56
  return {
57
57
  address,
58
58
  h160Address,
59
59
  parentAddress,
60
- productName
60
+ context
61
61
  };
62
62
  }
63
- function verifyProductAccount(productAddress, parentAddress, productName) {
63
+ function verifyContextAlias(aliasAddress, parentAddress, context) {
64
64
  try {
65
- const derived = deriveProductAccount(parentAddress, productName);
66
- const { publicKey: productKey } = ss58Decode(productAddress);
65
+ const derived = deriveContextAlias(parentAddress, context);
66
+ const { publicKey: aliasKey } = ss58Decode(aliasAddress);
67
67
  const { publicKey: derivedKey } = ss58Decode(derived.address);
68
- if (productKey.length !== derivedKey.length) return false;
69
- for (let i = 0; i < productKey.length; i++) {
70
- if (productKey[i] !== derivedKey[i]) return false;
68
+ if (aliasKey.length !== derivedKey.length) return false;
69
+ for (let i = 0; i < aliasKey.length; i++) {
70
+ if (aliasKey[i] !== derivedKey[i]) return false;
71
71
  }
72
72
  return true;
73
73
  } catch {
@@ -93,6 +93,6 @@ async function verifyRingProof(message, proof, alias) {
93
93
  );
94
94
  }
95
95
 
96
- export { createRingProof, deriveAnonymousAlias, deriveProductAccount, isDotNsAvailable, isValidDotNsName, normalizeDotNsName, resolveDotNs, reverseDotNs, verifyProductAccount, verifyRingProof };
96
+ export { createRingProof, deriveAnonymousAlias, deriveContextAlias, isDotNsAvailable, isValidDotNsName, normalizeDotNsName, resolveDotNs, reverseDotNs, verifyContextAlias, verifyRingProof };
97
97
  //# sourceMappingURL=index.js.map
98
98
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
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"]}
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 * Context alias derivation\n *\n * Derives a deterministic, context-bound alias from a parent account using blake2b-256.\n *\n * NOTE: this is NOT the canonical sr25519 product-account derivation used by\n * mobile, desktop, and dotli hosts. For that, use\n * `@parity/product-sdk-keys::deriveProductAccountPublicKey`.\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 { ContextAliasInfo, AnonymousAliasInfo, RingLocation } from \"./types.js\";\n\nconst log = createLogger(\"identity\");\n\n/**\n * Derive a context-bound alias from a parent account.\n *\n * The alias is deterministically derived using:\n * aliasPublicKey = blake2b256(parentPublicKey || context)\n *\n * @param parentAddress - Parent account SS58 address\n * @param context - Context string for derivation (e.g. an app id or scope label)\n * @param ss58Prefix - SS58 prefix (default: 42)\n * @returns Context alias info\n *\n * @example\n * ```ts\n * const alias = deriveContextAlias(\n * '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',\n * 'voting-round-1'\n * );\n * console.log('Alias address:', alias.address);\n * ```\n */\nexport function deriveContextAlias(\n parentAddress: string,\n context: string,\n ss58Prefix = 42,\n): ContextAliasInfo {\n const { publicKey: parentPublicKey } = ss58Decode(parentAddress);\n\n // Derive alias public key: blake2b-256(parentPublicKey || context)\n const contextBytes = new TextEncoder().encode(context);\n const combined = new Uint8Array(parentPublicKey.length + contextBytes.length);\n combined.set(parentPublicKey, 0);\n combined.set(contextBytes, parentPublicKey.length);\n\n const aliasPublicKey = blake2b256(combined);\n const address = ss58Encode(aliasPublicKey, ss58Prefix);\n const h160Address = deriveH160(aliasPublicKey);\n\n log.debug(\"Derived context alias\", {\n parentAddress,\n context,\n address,\n });\n\n return {\n address,\n h160Address,\n parentAddress,\n context,\n };\n}\n\n/**\n * Verify that a context alias was derived from a parent account.\n *\n * @param aliasAddress - Context alias SS58 address\n * @param parentAddress - Claimed parent address\n * @param context - Context string used for derivation\n * @returns True if derivation is valid\n */\nexport function verifyContextAlias(\n aliasAddress: string,\n parentAddress: string,\n context: string,\n): boolean {\n try {\n const derived = deriveContextAlias(parentAddress, context);\n const { publicKey: aliasKey } = ss58Decode(aliasAddress);\n const { publicKey: derivedKey } = ss58Decode(derived.address);\n\n // Compare public keys\n if (aliasKey.length !== derivedKey.length) return false;\n for (let i = 0; i < aliasKey.length; i++) {\n if (aliasKey[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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parity/product-sdk",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Unified SDK for building products in the Polkadot ecosystem - umbrella package",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -64,16 +64,16 @@
64
64
  "dependencies": {
65
65
  "polkadot-api": "^2.1.2",
66
66
  "@parity/product-sdk-address": "0.1.1",
67
- "@parity/product-sdk-bulletin": "0.4.1",
68
- "@parity/product-sdk-chain-client": "0.4.1",
69
- "@parity/product-sdk-contracts": "0.5.0",
67
+ "@parity/product-sdk-chain-client": "0.4.2",
68
+ "@parity/product-sdk-bulletin": "0.4.2",
70
69
  "@parity/product-sdk-crypto": "0.1.1",
71
- "@parity/product-sdk-host": "0.3.0",
70
+ "@parity/product-sdk-host": "0.4.0",
71
+ "@parity/product-sdk-contracts": "0.5.1",
72
+ "@parity/product-sdk-keys": "0.3.0",
72
73
  "@parity/product-sdk-logger": "0.1.1",
73
- "@parity/product-sdk-signer": "0.2.4",
74
- "@parity/product-sdk-keys": "0.2.3",
75
- "@parity/product-sdk-storage": "0.1.4",
76
- "@parity/product-sdk-tx": "0.2.3"
74
+ "@parity/product-sdk-signer": "0.3.0",
75
+ "@parity/product-sdk-storage": "0.1.5",
76
+ "@parity/product-sdk-tx": "0.2.4"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "react": "^18.0.0 || ^19.0.0"
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * @parity/product-sdk/identity
3
3
  *
4
- * Identity utilities including DotNS name resolution,
5
- * product account derivation, and Ring VRF anonymous aliases.
4
+ * Identity utilities: DotNS name resolution, context-alias derivation,
5
+ * and Ring VRF anonymous aliases.
6
6
  */
7
7
 
8
8
  // DotNS utilities
@@ -14,10 +14,10 @@ export {
14
14
  isDotNsAvailable,
15
15
  } from "./dotns.js";
16
16
 
17
- // Product account utilities
17
+ // Context alias utilities
18
18
  export {
19
- deriveProductAccount,
20
- verifyProductAccount,
19
+ deriveContextAlias,
20
+ verifyContextAlias,
21
21
  deriveAnonymousAlias,
22
22
  createRingProof,
23
23
  verifyRingProof,
@@ -26,7 +26,7 @@ export {
26
26
  // Types
27
27
  export type {
28
28
  DotNsRecord,
29
- ProductAccountInfo,
29
+ ContextAliasInfo,
30
30
  AnonymousAliasInfo,
31
31
  RingLocation,
32
32
  VerificationResult,
@@ -1,56 +1,60 @@
1
1
  /**
2
- * Product account derivation
2
+ * Context alias derivation
3
3
  *
4
- * Derives product-scoped accounts from a parent account
4
+ * Derives a deterministic, context-bound alias from a parent account using blake2b-256.
5
+ *
6
+ * NOTE: this is NOT the canonical sr25519 product-account derivation used by
7
+ * mobile, desktop, and dotli hosts. For that, use
8
+ * `@parity/product-sdk-keys::deriveProductAccountPublicKey`.
5
9
  */
6
10
 
7
11
  import { createLogger } from "@parity/product-sdk-logger";
8
12
  import { blake2b256 } from "@parity/product-sdk-crypto";
9
13
  import { ss58Encode, ss58Decode, deriveH160 } from "@parity/product-sdk-address";
10
- import type { ProductAccountInfo, AnonymousAliasInfo, RingLocation } from "./types.js";
14
+ import type { ContextAliasInfo, AnonymousAliasInfo, RingLocation } from "./types.js";
11
15
 
12
16
  const log = createLogger("identity");
13
17
 
14
18
  /**
15
- * Derive a product-scoped account from a parent account
19
+ * Derive a context-bound alias from a parent account.
16
20
  *
17
- * The product account is deterministically derived using:
18
- * productPublicKey = hash(parentPublicKey || productName)
21
+ * The alias is deterministically derived using:
22
+ * aliasPublicKey = blake2b256(parentPublicKey || context)
19
23
  *
20
24
  * @param parentAddress - Parent account SS58 address
21
- * @param productName - Product name for derivation
25
+ * @param context - Context string for derivation (e.g. an app id or scope label)
22
26
  * @param ss58Prefix - SS58 prefix (default: 42)
23
- * @returns Product account info
27
+ * @returns Context alias info
24
28
  *
25
29
  * @example
26
30
  * ```ts
27
- * const productAccount = deriveProductAccount(
31
+ * const alias = deriveContextAlias(
28
32
  * '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
29
- * 'my-app'
33
+ * 'voting-round-1'
30
34
  * );
31
- * console.log('Product address:', productAccount.address);
35
+ * console.log('Alias address:', alias.address);
32
36
  * ```
33
37
  */
34
- export function deriveProductAccount(
38
+ export function deriveContextAlias(
35
39
  parentAddress: string,
36
- productName: string,
40
+ context: string,
37
41
  ss58Prefix = 42,
38
- ): ProductAccountInfo {
42
+ ): ContextAliasInfo {
39
43
  const { publicKey: parentPublicKey } = ss58Decode(parentAddress);
40
44
 
41
- // Derive product public key: blake2b-256(parentPublicKey || productName)
42
- const productNameBytes = new TextEncoder().encode(productName);
43
- const combined = new Uint8Array(parentPublicKey.length + productNameBytes.length);
45
+ // Derive alias public key: blake2b-256(parentPublicKey || context)
46
+ const contextBytes = new TextEncoder().encode(context);
47
+ const combined = new Uint8Array(parentPublicKey.length + contextBytes.length);
44
48
  combined.set(parentPublicKey, 0);
45
- combined.set(productNameBytes, parentPublicKey.length);
49
+ combined.set(contextBytes, parentPublicKey.length);
46
50
 
47
- const productPublicKey = blake2b256(combined);
48
- const address = ss58Encode(productPublicKey, ss58Prefix);
49
- const h160Address = deriveH160(productPublicKey);
51
+ const aliasPublicKey = blake2b256(combined);
52
+ const address = ss58Encode(aliasPublicKey, ss58Prefix);
53
+ const h160Address = deriveH160(aliasPublicKey);
50
54
 
51
- log.debug("Derived product account", {
55
+ log.debug("Derived context alias", {
52
56
  parentAddress,
53
- productName,
57
+ context,
54
58
  address,
55
59
  });
56
60
 
@@ -58,32 +62,32 @@ export function deriveProductAccount(
58
62
  address,
59
63
  h160Address,
60
64
  parentAddress,
61
- productName,
65
+ context,
62
66
  };
63
67
  }
64
68
 
65
69
  /**
66
- * Verify that a product account was derived from a parent account
70
+ * Verify that a context alias was derived from a parent account.
67
71
  *
68
- * @param productAddress - Product account address
72
+ * @param aliasAddress - Context alias SS58 address
69
73
  * @param parentAddress - Claimed parent address
70
- * @param productName - Product name
74
+ * @param context - Context string used for derivation
71
75
  * @returns True if derivation is valid
72
76
  */
73
- export function verifyProductAccount(
74
- productAddress: string,
77
+ export function verifyContextAlias(
78
+ aliasAddress: string,
75
79
  parentAddress: string,
76
- productName: string,
80
+ context: string,
77
81
  ): boolean {
78
82
  try {
79
- const derived = deriveProductAccount(parentAddress, productName);
80
- const { publicKey: productKey } = ss58Decode(productAddress);
83
+ const derived = deriveContextAlias(parentAddress, context);
84
+ const { publicKey: aliasKey } = ss58Decode(aliasAddress);
81
85
  const { publicKey: derivedKey } = ss58Decode(derived.address);
82
86
 
83
87
  // Compare public keys
84
- if (productKey.length !== derivedKey.length) return false;
85
- for (let i = 0; i < productKey.length; i++) {
86
- if (productKey[i] !== derivedKey[i]) return false;
88
+ if (aliasKey.length !== derivedKey.length) return false;
89
+ for (let i = 0; i < aliasKey.length; i++) {
90
+ if (aliasKey[i] !== derivedKey[i]) return false;
87
91
  }
88
92
  return true;
89
93
  } catch {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Identity module types
3
3
  *
4
- * Types for DotNS name resolution and product account derivation
4
+ * Types for DotNS name resolution and context-alias derivation
5
5
  */
6
6
 
7
7
  /** DotNS name resolution result */
@@ -16,16 +16,16 @@ export interface DotNsRecord {
16
16
  expiresAt?: number;
17
17
  }
18
18
 
19
- /** Product account info */
20
- export interface ProductAccountInfo {
21
- /** Product-scoped SS58 address */
19
+ /** Context alias info: a deterministic, context-bound alias derived from a parent account */
20
+ export interface ContextAliasInfo {
21
+ /** Alias SS58 address */
22
22
  address: string;
23
23
  /** H160 EVM address */
24
24
  h160Address: `0x${string}`;
25
25
  /** Parent account address */
26
26
  parentAddress: string;
27
- /** Product name used for derivation */
28
- productName: string;
27
+ /** Context string used for derivation */
28
+ context: string;
29
29
  }
30
30
 
31
31
  /** Ring VRF alias info */