@parity/product-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/address/index.d.ts +8 -0
- package/dist/address/index.js +3 -0
- package/dist/address/index.js.map +1 -0
- package/dist/bulletin/index.d.ts +1 -0
- package/dist/bulletin/index.js +3 -0
- package/dist/bulletin/index.js.map +1 -0
- package/dist/chain/index.d.ts +1 -0
- package/dist/chain/index.js +3 -0
- package/dist/chain/index.js.map +1 -0
- package/dist/chunk-NVGSGXGH.js +177 -0
- package/dist/chunk-NVGSGXGH.js.map +1 -0
- package/dist/chunk-XSKBA5SR.js +8 -0
- package/dist/chunk-XSKBA5SR.js.map +1 -0
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.js +3 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/crypto/index.d.ts +1 -0
- package/dist/crypto/index.js +3 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/host/index.d.ts +1 -0
- package/dist/host/index.js +3 -0
- package/dist/host/index.js.map +1 -0
- package/dist/identity/index.d.ts +186 -0
- package/dist/identity/index.js +109 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.d.ts +177 -0
- package/dist/react/index.js +213 -0
- package/dist/react/index.js.map +1 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +3 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/types-CZQDzQ53.d.ts +142 -0
- package/dist/wallet/index.d.ts +1 -0
- package/dist/wallet/index.js +3 -0
- package/dist/wallet/index.js.map +1 -0
- package/package.json +105 -0
- package/src/address/index.ts +6 -0
- package/src/bulletin/index.ts +6 -0
- package/src/chain/index.ts +6 -0
- package/src/contracts/index.ts +6 -0
- package/src/core/createApp.ts +284 -0
- package/src/core/index.ts +10 -0
- package/src/core/logger.ts +13 -0
- package/src/core/types.ts +155 -0
- package/src/crypto/index.ts +6 -0
- package/src/host/index.ts +6 -0
- package/src/identity/dotns.ts +96 -0
- package/src/identity/index.ts +34 -0
- package/src/identity/product-account.ts +158 -0
- package/src/identity/types.ts +75 -0
- package/src/index.ts +49 -0
- package/src/react/context.ts +33 -0
- package/src/react/index.ts +41 -0
- package/src/react/provider.tsx +76 -0
- package/src/react/useChain.ts +33 -0
- package/src/react/useStorage.ts +125 -0
- package/src/react/useWallet.ts +138 -0
- package/src/storage/index.ts +6 -0
- package/src/wallet/index.ts +9 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createApp - Main entry point for the Product SDK
|
|
3
|
+
*
|
|
4
|
+
* Creates an App instance with wallet, storage, chain, and bulletin APIs.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ChainDefinition } from "polkadot-api";
|
|
8
|
+
import type {
|
|
9
|
+
App,
|
|
10
|
+
AppConfig,
|
|
11
|
+
WalletApi,
|
|
12
|
+
StorageApi,
|
|
13
|
+
ChainApi,
|
|
14
|
+
BulletinApi,
|
|
15
|
+
Account,
|
|
16
|
+
} from "./types.js";
|
|
17
|
+
import { configure, createLogger } from "@parity/product-sdk-logger";
|
|
18
|
+
import { createKvStore } from "@parity/product-sdk-storage";
|
|
19
|
+
import { SignerManager } from "@parity/product-sdk-signer";
|
|
20
|
+
import { BulletinClient, computeCid } from "@parity/product-sdk-bulletin";
|
|
21
|
+
import {
|
|
22
|
+
createChainClient,
|
|
23
|
+
getClient,
|
|
24
|
+
isConnected,
|
|
25
|
+
destroyAll,
|
|
26
|
+
} from "@parity/product-sdk-chain-client";
|
|
27
|
+
|
|
28
|
+
const log = createLogger("app");
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create a new Product SDK app instance
|
|
32
|
+
*
|
|
33
|
+
* @param config - Application configuration
|
|
34
|
+
* @returns App instance with all APIs
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { createApp } from '@parity/product-sdk';
|
|
39
|
+
*
|
|
40
|
+
* // Default: bulletin enabled with paseo environment
|
|
41
|
+
* const app = await createApp({
|
|
42
|
+
* name: 'my-app',
|
|
43
|
+
* logLevel: 'info',
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* // Custom bulletin environment
|
|
47
|
+
* const prodApp = await createApp({
|
|
48
|
+
* name: 'my-app',
|
|
49
|
+
* bulletin: { environment: 'polkadot' },
|
|
50
|
+
* });
|
|
51
|
+
*
|
|
52
|
+
* // Disable bulletin entirely
|
|
53
|
+
* const noBulletinApp = await createApp({
|
|
54
|
+
* name: 'my-app',
|
|
55
|
+
* bulletin: false,
|
|
56
|
+
* });
|
|
57
|
+
*
|
|
58
|
+
* // Connect wallet
|
|
59
|
+
* const { accounts } = await app.wallet.connect();
|
|
60
|
+
*
|
|
61
|
+
* // Use storage
|
|
62
|
+
* await app.storage.set('key', 'value');
|
|
63
|
+
*
|
|
64
|
+
* // Use bulletin (check for null if it might be disabled)
|
|
65
|
+
* if (app.bulletin) {
|
|
66
|
+
* const cid = await app.bulletin.upload('hello world');
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export async function createApp(config: AppConfig): Promise<App> {
|
|
71
|
+
// Set log level if specified
|
|
72
|
+
if (config.logLevel) {
|
|
73
|
+
configure({ level: config.logLevel });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
log.info("Creating Product SDK app", { name: config.name });
|
|
77
|
+
|
|
78
|
+
// Initialize storage (container-only - will throw if not in container)
|
|
79
|
+
const kvStore = await createKvStore({ prefix: config.name });
|
|
80
|
+
|
|
81
|
+
// Initialize signer manager
|
|
82
|
+
const signerManager = new SignerManager({
|
|
83
|
+
dappName: config.name,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Initialize bulletin client (configurable, defaults to paseo)
|
|
87
|
+
const bulletinEnabled = config.bulletin !== false;
|
|
88
|
+
const bulletinEnvironment =
|
|
89
|
+
typeof config.bulletin === "object" ? config.bulletin.environment : "paseo";
|
|
90
|
+
const bulletinClient = bulletinEnabled
|
|
91
|
+
? await BulletinClient.create(bulletinEnvironment)
|
|
92
|
+
: null;
|
|
93
|
+
|
|
94
|
+
if (bulletinEnabled) {
|
|
95
|
+
log.debug("Bulletin client initialized", { environment: bulletinEnvironment });
|
|
96
|
+
} else {
|
|
97
|
+
log.debug("Bulletin client disabled");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Create storage API adapter
|
|
101
|
+
const storageApi: StorageApi = {
|
|
102
|
+
get: (key) => kvStore.get(key),
|
|
103
|
+
set: (key, value) => kvStore.set(key, value),
|
|
104
|
+
getJSON: <T>(key: string) => kvStore.getJSON<T>(key),
|
|
105
|
+
setJSON: <T>(key: string, value: T) => kvStore.setJSON(key, value),
|
|
106
|
+
remove: (key) => kvStore.remove(key),
|
|
107
|
+
clear: async () => {
|
|
108
|
+
// KvStore doesn't have clear - this is a no-op
|
|
109
|
+
log.debug("clear() is not supported in container storage mode");
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// Create wallet API adapter
|
|
114
|
+
const walletApi = createWalletApi(signerManager);
|
|
115
|
+
|
|
116
|
+
// Create chain API
|
|
117
|
+
const chainApi: ChainApi = {
|
|
118
|
+
getClient(descriptor) {
|
|
119
|
+
log.debug("getClient called", { genesis: descriptor.genesis });
|
|
120
|
+
const client = getClient(descriptor);
|
|
121
|
+
return client.getTypedApi(descriptor);
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
getRawClient(descriptor) {
|
|
125
|
+
log.debug("getRawClient called", { genesis: descriptor.genesis });
|
|
126
|
+
return getClient(descriptor);
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
async connect<T extends Record<string, ChainDefinition>>(chains: T) {
|
|
130
|
+
log.debug("connect called", { chains: Object.keys(chains) });
|
|
131
|
+
// Build empty rpcs object (required by API but unused - host routes connections)
|
|
132
|
+
const rpcs = Object.fromEntries(
|
|
133
|
+
Object.keys(chains).map((k) => [k, [] as readonly string[]]),
|
|
134
|
+
) as { [K in keyof T]: readonly string[] };
|
|
135
|
+
return createChainClient({ chains, rpcs });
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
isConnected(descriptor) {
|
|
139
|
+
return isConnected(descriptor);
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
destroyAll() {
|
|
143
|
+
log.debug("destroyAll called");
|
|
144
|
+
destroyAll();
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// Create bulletin API adapter (null if disabled)
|
|
149
|
+
const bulletinApi: BulletinApi | null = bulletinClient
|
|
150
|
+
? {
|
|
151
|
+
upload: async (data) => {
|
|
152
|
+
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
153
|
+
const result = await bulletinClient.upload(bytes);
|
|
154
|
+
return result.cid;
|
|
155
|
+
},
|
|
156
|
+
fetch: (cid) => bulletinClient.fetchBytes(cid),
|
|
157
|
+
computeCid: (data) => {
|
|
158
|
+
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
159
|
+
return computeCid(bytes);
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
: null;
|
|
163
|
+
|
|
164
|
+
log.info("Product SDK app created", {
|
|
165
|
+
name: config.name,
|
|
166
|
+
bulletin: bulletinEnabled ? bulletinEnvironment : "disabled",
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
wallet: walletApi,
|
|
171
|
+
storage: storageApi,
|
|
172
|
+
chain: chainApi,
|
|
173
|
+
bulletin: bulletinApi,
|
|
174
|
+
getAppInfo: () => ({ ...config }),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Create wallet API adapter using SignerManager from leaf package
|
|
180
|
+
*/
|
|
181
|
+
function createWalletApi(signerManager: SignerManager): WalletApi {
|
|
182
|
+
// Track account change subscribers
|
|
183
|
+
const accountChangeSubscribers = new Set<(account: Account | null) => void>();
|
|
184
|
+
|
|
185
|
+
// Subscribe to signer manager state changes
|
|
186
|
+
signerManager.subscribe((state) => {
|
|
187
|
+
const account = state.selectedAccount
|
|
188
|
+
? {
|
|
189
|
+
address: state.selectedAccount.address,
|
|
190
|
+
name: state.selectedAccount.name ?? undefined,
|
|
191
|
+
source: state.selectedAccount.source,
|
|
192
|
+
}
|
|
193
|
+
: null;
|
|
194
|
+
for (const callback of accountChangeSubscribers) {
|
|
195
|
+
try {
|
|
196
|
+
callback(account);
|
|
197
|
+
} catch (e) {
|
|
198
|
+
log.warn("Account change callback threw", { error: e });
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
async connect(): Promise<{ accounts: Account[] }> {
|
|
205
|
+
const result = await signerManager.connect();
|
|
206
|
+
if (!result.ok) {
|
|
207
|
+
throw new Error(result.error.message);
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
accounts: result.value.map((a) => ({
|
|
211
|
+
address: a.address,
|
|
212
|
+
name: a.name ?? undefined,
|
|
213
|
+
source: a.source,
|
|
214
|
+
})),
|
|
215
|
+
};
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
async disconnect(): Promise<void> {
|
|
219
|
+
signerManager.disconnect();
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
getAccounts(): Account[] {
|
|
223
|
+
return signerManager.getState().accounts.map((a) => ({
|
|
224
|
+
address: a.address,
|
|
225
|
+
name: a.name ?? undefined,
|
|
226
|
+
source: a.source,
|
|
227
|
+
}));
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
getSelectedAccount(): Account | null {
|
|
231
|
+
const selected = signerManager.getState().selectedAccount;
|
|
232
|
+
if (!selected) return null;
|
|
233
|
+
return {
|
|
234
|
+
address: selected.address,
|
|
235
|
+
name: selected.name ?? undefined,
|
|
236
|
+
source: selected.source,
|
|
237
|
+
};
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
selectAccount(address: string): void {
|
|
241
|
+
signerManager.selectAccount(address);
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
async signMessage(message: string | Uint8Array): Promise<Uint8Array> {
|
|
245
|
+
const bytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
246
|
+
const result = await signerManager.signRaw(bytes);
|
|
247
|
+
if (!result.ok) {
|
|
248
|
+
throw new Error(result.error.message);
|
|
249
|
+
}
|
|
250
|
+
return result.value;
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
onAccountChange(callback: (account: Account | null) => void): () => void {
|
|
254
|
+
accountChangeSubscribers.add(callback);
|
|
255
|
+
return () => accountChangeSubscribers.delete(callback);
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
getProductAccount(): Account | null {
|
|
259
|
+
// Product accounts require async call - this sync API can't support it properly
|
|
260
|
+
// Users should use SignerManager.getProductAccount() directly
|
|
261
|
+
log.warn(
|
|
262
|
+
"getProductAccount() is deprecated - use SignerManager.getProductAccount() directly",
|
|
263
|
+
);
|
|
264
|
+
return null;
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
getAnonymousAlias(): string | null {
|
|
268
|
+
// Anonymous aliases require async call - this sync API can't support it properly
|
|
269
|
+
// Users should use SignerManager.getProductAccountAlias() directly
|
|
270
|
+
log.warn(
|
|
271
|
+
"getAnonymousAlias() is deprecated - use SignerManager.getProductAccountAlias() directly",
|
|
272
|
+
);
|
|
273
|
+
return null;
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
async createProof(_message: Uint8Array): Promise<Uint8Array> {
|
|
277
|
+
// Ring VRF proofs require SignerManager.createRingVRFProof() directly
|
|
278
|
+
throw new Error(
|
|
279
|
+
"createProof() is not implemented in the App API. " +
|
|
280
|
+
"Use SignerManager.createRingVRFProof() directly.",
|
|
281
|
+
);
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @parity/product-sdk core module
|
|
3
|
+
*
|
|
4
|
+
* Core functionality including createApp, logger, and type definitions.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { createApp } from "./createApp.js";
|
|
8
|
+
export { configure, createLogger } from "./logger.js";
|
|
9
|
+
export type { LogEntry, LogHandler, LoggerConfig, Logger } from "./logger.js";
|
|
10
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger module for @parity/product-sdk
|
|
3
|
+
*
|
|
4
|
+
* Re-exports from @parity/product-sdk-logger.
|
|
5
|
+
*/
|
|
6
|
+
export { configure, createLogger } from "@parity/product-sdk-logger";
|
|
7
|
+
export type {
|
|
8
|
+
LogLevel,
|
|
9
|
+
LogEntry,
|
|
10
|
+
LogHandler,
|
|
11
|
+
LoggerConfig,
|
|
12
|
+
Logger,
|
|
13
|
+
} from "@parity/product-sdk-logger";
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for @parity/product-sdk
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { LogLevel } from "@parity/product-sdk-logger";
|
|
6
|
+
import type { Environment as BulletinEnvironment } from "@parity/product-sdk-bulletin";
|
|
7
|
+
import type { ChainClient } from "@parity/product-sdk-chain-client";
|
|
8
|
+
import type { ChainDefinition, TypedApi, PolkadotClient } from "polkadot-api";
|
|
9
|
+
|
|
10
|
+
export type { LogLevel };
|
|
11
|
+
export type { ChainClient };
|
|
12
|
+
|
|
13
|
+
/** Bulletin configuration options */
|
|
14
|
+
export interface BulletinConfig {
|
|
15
|
+
/** Bulletin environment to connect to */
|
|
16
|
+
environment: BulletinEnvironment;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Configuration for createApp */
|
|
20
|
+
export interface AppConfig {
|
|
21
|
+
/** Application name - used to derive product accounts and namespace storage */
|
|
22
|
+
name: string;
|
|
23
|
+
/** Log level for SDK operations (default: 'info') */
|
|
24
|
+
logLevel?: LogLevel;
|
|
25
|
+
/**
|
|
26
|
+
* Bulletin Chain configuration.
|
|
27
|
+
* - Omit or pass config object to enable (default: { environment: "paseo" })
|
|
28
|
+
* - Pass `false` to disable bulletin initialization
|
|
29
|
+
*/
|
|
30
|
+
bulletin?: BulletinConfig | false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Wallet API exposed by the SDK */
|
|
34
|
+
export interface WalletApi {
|
|
35
|
+
/** Connect to available wallet providers */
|
|
36
|
+
connect(): Promise<{ accounts: Account[] }>;
|
|
37
|
+
/** Disconnect from wallet */
|
|
38
|
+
disconnect(): Promise<void>;
|
|
39
|
+
/** Get all available accounts */
|
|
40
|
+
getAccounts(): Account[];
|
|
41
|
+
/** Get currently selected account */
|
|
42
|
+
getSelectedAccount(): Account | null;
|
|
43
|
+
/** Select an account by address */
|
|
44
|
+
selectAccount(address: string): void;
|
|
45
|
+
/** Sign an arbitrary message */
|
|
46
|
+
signMessage(message: string | Uint8Array): Promise<Uint8Array>;
|
|
47
|
+
/** Subscribe to account changes */
|
|
48
|
+
onAccountChange(callback: (account: Account | null) => void): () => void;
|
|
49
|
+
/** Get product-scoped account (container mode only) */
|
|
50
|
+
getProductAccount(): Account | null;
|
|
51
|
+
/** Get anonymous alias via Ring VRF (container mode only) */
|
|
52
|
+
getAnonymousAlias(): string | null;
|
|
53
|
+
/** Create Ring VRF proof (container mode only) */
|
|
54
|
+
createProof(message: Uint8Array): Promise<Uint8Array>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Storage API exposed by the SDK */
|
|
58
|
+
export interface StorageApi {
|
|
59
|
+
/** Get a value by key */
|
|
60
|
+
get(key: string): Promise<string | null>;
|
|
61
|
+
/** Set a value by key */
|
|
62
|
+
set(key: string, value: string): Promise<void>;
|
|
63
|
+
/** Get a JSON value by key */
|
|
64
|
+
getJSON<T = unknown>(key: string): Promise<T | null>;
|
|
65
|
+
/** Set a JSON value by key */
|
|
66
|
+
setJSON<T = unknown>(key: string, value: T): Promise<void>;
|
|
67
|
+
/** Remove a value by key */
|
|
68
|
+
remove(key: string): Promise<void>;
|
|
69
|
+
/** Clear all values */
|
|
70
|
+
clear(): Promise<void>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Chain API exposed by the SDK */
|
|
74
|
+
export interface ChainApi {
|
|
75
|
+
/**
|
|
76
|
+
* Get a typed PAPI client for a chain.
|
|
77
|
+
*
|
|
78
|
+
* Connections are routed through the host provider. The chain must be
|
|
79
|
+
* connected first via {@link connect}.
|
|
80
|
+
*
|
|
81
|
+
* @param descriptor - PAPI chain descriptor (from @parity/product-sdk-descriptors or custom)
|
|
82
|
+
* @returns Typed API for the chain
|
|
83
|
+
* @throws If the chain is not connected
|
|
84
|
+
*/
|
|
85
|
+
getClient<T extends ChainDefinition>(descriptor: T): TypedApi<T>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get the raw PolkadotClient for a chain.
|
|
89
|
+
*
|
|
90
|
+
* Use this for advanced APIs like `createInkSdk` from `@polkadot-api/sdk-ink`.
|
|
91
|
+
*
|
|
92
|
+
* @param descriptor - PAPI chain descriptor
|
|
93
|
+
* @returns Raw PolkadotClient instance
|
|
94
|
+
* @throws If the chain is not connected
|
|
95
|
+
*/
|
|
96
|
+
getRawClient(descriptor: ChainDefinition): PolkadotClient;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Connect to one or more chains.
|
|
100
|
+
*
|
|
101
|
+
* Connections are routed through the host provider (container-only).
|
|
102
|
+
* Results are cached - calling with the same descriptors returns existing connections.
|
|
103
|
+
*
|
|
104
|
+
* @param chains - Record of named chain descriptors
|
|
105
|
+
* @returns Connected chain client with typed APIs
|
|
106
|
+
*/
|
|
107
|
+
connect<T extends Record<string, ChainDefinition>>(chains: T): Promise<ChainClient<T>>;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Check if a chain is currently connected.
|
|
111
|
+
*/
|
|
112
|
+
isConnected(descriptor: ChainDefinition): boolean;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Destroy all chain connections.
|
|
116
|
+
*/
|
|
117
|
+
destroyAll(): void;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Bulletin Chain API exposed by the SDK */
|
|
121
|
+
export interface BulletinApi {
|
|
122
|
+
/** Upload data to Bulletin Chain */
|
|
123
|
+
upload(data: string | Uint8Array): Promise<string>;
|
|
124
|
+
/** Fetch data by CID */
|
|
125
|
+
fetch(cid: string): Promise<Uint8Array>;
|
|
126
|
+
/** Compute CID for data without uploading */
|
|
127
|
+
computeCid(data: string | Uint8Array): string;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** The main App instance returned by createApp */
|
|
131
|
+
export interface App {
|
|
132
|
+
/** Wallet/signing operations */
|
|
133
|
+
wallet: WalletApi;
|
|
134
|
+
/** Key-value storage operations */
|
|
135
|
+
storage: StorageApi;
|
|
136
|
+
/** Chain interaction operations */
|
|
137
|
+
chain: ChainApi;
|
|
138
|
+
/** Bulletin Chain operations (null if disabled via config) */
|
|
139
|
+
bulletin: BulletinApi | null;
|
|
140
|
+
/** Get app configuration */
|
|
141
|
+
getAppInfo(): AppConfig;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Account information */
|
|
145
|
+
export interface Account {
|
|
146
|
+
/** Account address (SS58 format) */
|
|
147
|
+
address: string;
|
|
148
|
+
/** Account name/label (if available) */
|
|
149
|
+
name?: string;
|
|
150
|
+
/** Source of the account (extension name, host, etc.) */
|
|
151
|
+
source: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Re-export ChainDefinition from polkadot-api for convenience
|
|
155
|
+
export type { ChainDefinition, TypedApi, PolkadotClient } from "polkadot-api";
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DotNS (Polkadot Name Service) utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides name resolution for .dot domains
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createLogger } from "@parity/product-sdk-logger";
|
|
8
|
+
import type { DotNsRecord } from "./types.js";
|
|
9
|
+
|
|
10
|
+
const log = createLogger("identity");
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Check if a string is a valid DotNS name
|
|
14
|
+
*
|
|
15
|
+
* @param name - Name to validate
|
|
16
|
+
* @returns True if valid DotNS name
|
|
17
|
+
*/
|
|
18
|
+
export function isValidDotNsName(name: string): boolean {
|
|
19
|
+
// Basic validation: alphanumeric, hyphens, ends with .dot
|
|
20
|
+
if (!name.endsWith(".dot")) return false;
|
|
21
|
+
const label = name.slice(0, -4);
|
|
22
|
+
if (label.length < 3 || label.length > 63) return false;
|
|
23
|
+
return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(label);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Normalize a DotNS name (lowercase, trim whitespace)
|
|
28
|
+
*
|
|
29
|
+
* @param name - Name to normalize
|
|
30
|
+
* @returns Normalized name
|
|
31
|
+
*/
|
|
32
|
+
export function normalizeDotNsName(name: string): string {
|
|
33
|
+
let normalized = name.toLowerCase().trim();
|
|
34
|
+
if (!normalized.endsWith(".dot")) {
|
|
35
|
+
normalized += ".dot";
|
|
36
|
+
}
|
|
37
|
+
return normalized;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Resolve a DotNS name to an address
|
|
42
|
+
*
|
|
43
|
+
* @param name - DotNS name (e.g., "alice.dot")
|
|
44
|
+
* @returns Resolved record or null if not found
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const record = await resolveDotNs('alice.dot');
|
|
49
|
+
* if (record) {
|
|
50
|
+
* console.log('Address:', record.address);
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export async function resolveDotNs(name: string): Promise<DotNsRecord | null> {
|
|
55
|
+
const normalized = normalizeDotNsName(name);
|
|
56
|
+
|
|
57
|
+
if (!isValidDotNsName(normalized)) {
|
|
58
|
+
log.warn("Invalid DotNS name", { name });
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
log.debug("Resolving DotNS name", { name: normalized });
|
|
63
|
+
|
|
64
|
+
// TODO: Implement via PAPI query to DotNS pallet
|
|
65
|
+
throw new Error(
|
|
66
|
+
"resolveDotNs() is not yet implemented. " +
|
|
67
|
+
"This is a skeleton for the Product SDK structure.",
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Reverse resolve an address to a DotNS name
|
|
73
|
+
*
|
|
74
|
+
* @param address - SS58 address
|
|
75
|
+
* @returns Primary name or null if none set
|
|
76
|
+
*/
|
|
77
|
+
export async function reverseDotNs(address: string): Promise<string | null> {
|
|
78
|
+
log.debug("Reverse resolving address", { address });
|
|
79
|
+
|
|
80
|
+
// TODO: Implement via PAPI query to DotNS pallet
|
|
81
|
+
throw new Error(
|
|
82
|
+
"reverseDotNs() is not yet implemented. " +
|
|
83
|
+
"This is a skeleton for the Product SDK structure.",
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Check if a DotNS name is available for registration
|
|
89
|
+
*
|
|
90
|
+
* @param name - Name to check
|
|
91
|
+
* @returns True if available
|
|
92
|
+
*/
|
|
93
|
+
export async function isDotNsAvailable(name: string): Promise<boolean> {
|
|
94
|
+
const record = await resolveDotNs(name).catch(() => null);
|
|
95
|
+
return record === null;
|
|
96
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @parity/product-sdk/identity
|
|
3
|
+
*
|
|
4
|
+
* Identity utilities including DotNS name resolution,
|
|
5
|
+
* product account derivation, and Ring VRF anonymous aliases.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// DotNS utilities
|
|
9
|
+
export {
|
|
10
|
+
isValidDotNsName,
|
|
11
|
+
normalizeDotNsName,
|
|
12
|
+
resolveDotNs,
|
|
13
|
+
reverseDotNs,
|
|
14
|
+
isDotNsAvailable,
|
|
15
|
+
} from "./dotns.js";
|
|
16
|
+
|
|
17
|
+
// Product account utilities
|
|
18
|
+
export {
|
|
19
|
+
deriveProductAccount,
|
|
20
|
+
verifyProductAccount,
|
|
21
|
+
deriveAnonymousAlias,
|
|
22
|
+
createRingProof,
|
|
23
|
+
verifyRingProof,
|
|
24
|
+
} from "./product-account.js";
|
|
25
|
+
|
|
26
|
+
// Types
|
|
27
|
+
export type {
|
|
28
|
+
DotNsRecord,
|
|
29
|
+
ProductAccountInfo,
|
|
30
|
+
AnonymousAliasInfo,
|
|
31
|
+
RingLocation,
|
|
32
|
+
VerificationResult,
|
|
33
|
+
OnChainIdentity,
|
|
34
|
+
} from "./types.js";
|