@novasamatech/product-sdk 0.7.0-0 → 0.7.0-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.
package/README.md CHANGED
@@ -166,7 +166,7 @@ It can be used for various purposes like p2p communication, storing temp data, e
166
166
 
167
167
  ```ts
168
168
  import { createStatementStore } from '@novasamatech/product-sdk';
169
- import type { Topic, Statement, SignedStatement } from '@novasamatech/product-sdk';
169
+ import type { Topic, Statement, SignedStatement, StatementTopicFilter } from '@novasamatech/product-sdk';
170
170
 
171
171
  // Create statement store instance
172
172
  const statementStore = createStatementStore();
@@ -174,9 +174,11 @@ const statementStore = createStatementStore();
174
174
  // Define topics (32-byte identifiers) to categorize statements
175
175
  const topic: Topic = new Uint8Array(32);
176
176
 
177
- // Subscribe to statement updates for specific topics
178
- const subscription = statementStore.subscribe([topic], (statements) => {
179
- console.log('Received statement updates:', statements);
177
+ // Subscribe to statements matching ALL listed topics (AND semantics)
178
+ const filter: StatementTopicFilter = { matchAll: [topic] };
179
+ const subscription = statementStore.subscribe(filter, (page) => {
180
+ // page.isComplete is true once the initial historical dump is done
181
+ console.log('Received statements:', page.statements, 'synced:', page.isComplete);
180
182
  });
181
183
 
182
184
  // Create a proof for a new statement
@@ -215,6 +217,34 @@ import type { ProductAccount } from '@novasamatech/product-sdk';
215
217
  // Create accounts provider instance
216
218
  const accountsProvider = createAccountsProvider();
217
219
 
220
+ // Get the root (primary) account — prompts for permission on first call
221
+ const rootResult = await accountsProvider.getRootAccount();
222
+
223
+ if (rootResult.isOk()) {
224
+ const root = rootResult.value;
225
+ console.log('Root account public key:', root.publicKey);
226
+ console.log('Root DotNS name:', root.name);
227
+ } else {
228
+ const rootErr = rootResult.error;
229
+ if (rootErr.tag === 'Rejected') {
230
+ console.log('User denied access to root account');
231
+ } else if (rootErr.tag === 'NotFound') {
232
+ console.log('User has no DotNS account yet');
233
+ }
234
+ }
235
+
236
+ // Request login — triggers host sign-in UI; reason is shown to the user
237
+ const loginResult = await accountsProvider.requestLogin('Sign in to access your account');
238
+
239
+ if (loginResult.isOk()) {
240
+ const outcome = loginResult.value; // 'success' | 'alreadyConnected' | 'rejected'
241
+ if (outcome === 'rejected') {
242
+ console.log('User cancelled login');
243
+ }
244
+ } else {
245
+ console.error('Login error:', loginResult.error);
246
+ }
247
+
218
248
  // Get a product account by DotNS identifier and derivation index
219
249
  const accountResult = await accountsProvider.getProductAccount('product.dot', 0);
220
250
 
@@ -230,11 +260,11 @@ if (aliasResult.isOk()) {
230
260
  console.log('Alias:', aliasResult.value);
231
261
  }
232
262
 
233
- // Get non-product accounts (external wallets)
234
- const nonProductAccountsResult = await accountsProvider.getNonProductAccounts();
263
+ // Get legacy accounts (external wallets)
264
+ const legacyAccountsResult = await accountsProvider.getLegacyAccounts();
235
265
 
236
- if (nonProductAccountsResult.isOk()) {
237
- console.log('Non-product accounts:', nonProductAccountsResult.value);
266
+ if (legacyAccountsResult.isOk()) {
267
+ console.log('Legacy accounts:', legacyAccountsResult.value);
238
268
  }
239
269
 
240
270
  // Subscribe to account connection status changes
@@ -251,13 +281,13 @@ const account: ProductAccount = {
251
281
  };
252
282
  const signer = accountsProvider.getProductAccountSigner(account);
253
283
 
254
- // Create a signer for a non-product account
255
- const nonProductSigner = accountsProvider.getNonProductAccountSigner(account);
284
+ // Create a signer for a legacy account
285
+ const legacySigner = accountsProvider.getLegacyAccountSigner(account);
256
286
 
257
287
  // PAPI transaction signing example
258
288
 
259
289
  const productAccountSignedTx = await tx.signAndSubmit(signer);
260
- const nonProductAccountSignedTx = await tx.signAndSubmit(nonProductSigner);
290
+ const legacyAccountSignedTx = await tx.signAndSubmit(legacySigner);
261
291
  ```
262
292
 
263
293
  ### Local Storage
@@ -304,6 +334,35 @@ if (result.isOk()) {
304
334
  }
305
335
  ```
306
336
 
337
+ ### Permissions
338
+
339
+ Products can request device and remote permissions from the host. Decisions are prompted once and persisted permanently — subsequent calls for the same permission resolve immediately without prompting.
340
+
341
+ ```ts
342
+ import { requestDevicePermission, requestPermission } from '@novasamatech/product-sdk';
343
+
344
+ // Request a single device permission
345
+ const deviceResult = await requestDevicePermission('Camera');
346
+ if (deviceResult.isOk()) {
347
+ console.log('Camera granted:', deviceResult.value); // boolean
348
+ }
349
+
350
+ // Request remote permissions in a batch (single user prompt for all)
351
+ const remoteResult = await requestPermission([
352
+ { tag: 'Remote', value: ['api.coingecko.com', '*.example.com'] },
353
+ { tag: 'ChainSubmit', value: undefined },
354
+ ]);
355
+ if (remoteResult.isOk()) {
356
+ console.log('All remote permissions granted:', remoteResult.value); // boolean
357
+ }
358
+ ```
359
+
360
+ Available device permission values: `'Notifications'`, `'Camera'`, `'Microphone'`, `'Bluetooth'`, `'NFC'`, `'Location'`, `'Clipboard'`, `'OpenUrl'`, `'Biometrics'`.
361
+
362
+ Available remote permission tags: `'Remote'` (HTTP/WS domain patterns), `'WebRTC'`, `'ChainSubmit'`, `'PreimageSubmit'`, `'StatementSubmit'`.
363
+
364
+ > **Note:** `remote_chain_transaction_broadcast`, `remote_preimage_submit`, and `remote_statement_store_submit` implicitly trigger a permission prompt if the relevant permission has not yet been resolved. Call `requestPermission(...)` proactively before entering those flows for a controlled UX.
365
+
307
366
  ### Preimage Manager
308
367
 
309
368
  The Preimage Manager allows you to lookup and submit preimages to the host application.
@@ -8,6 +8,15 @@ export type ProductAccount = {
8
8
  };
9
9
  export type AccountConnectionStatus = CodecType<typeof AccountConnectionStatusCodec>;
10
10
  export declare const createAccountsProvider: (transport?: Transport) => {
11
+ getRootAccount(): import("neverthrow").ResultAsync<{
12
+ publicKey: Uint8Array<ArrayBufferLike>;
13
+ name: string | undefined;
14
+ }, import("packages/scale/src/err.js").CodecError<undefined, "RequestCredentialsErr::NotConnected"> | import("packages/scale/src/err.js").CodecError<undefined, "RequestCredentialsErr::Rejected"> | import("packages/scale/src/err.js").CodecError<undefined, "RequestCredentialsErr::DomainNotValid"> | import("packages/scale/src/err.js").CodecError<{
15
+ reason: string;
16
+ }, "RequestCredentialsErr::Unknown">>;
17
+ requestLogin(reason?: string): import("neverthrow").ResultAsync<"success" | "alreadyConnected" | "rejected", import("packages/scale/src/err.js").CodecError<{
18
+ reason: string;
19
+ }, "LoginErr::Unknown">>;
11
20
  getProductAccount(dotNsIdentifier: string, derivationIndex?: number): import("neverthrow").ResultAsync<{
12
21
  publicKey: Uint8Array<ArrayBufferLike>;
13
22
  name: string | undefined;
@@ -20,7 +29,7 @@ export declare const createAccountsProvider: (transport?: Transport) => {
20
29
  }, import("packages/scale/src/err.js").CodecError<undefined, "RequestCredentialsErr::NotConnected"> | import("packages/scale/src/err.js").CodecError<undefined, "RequestCredentialsErr::Rejected"> | import("packages/scale/src/err.js").CodecError<undefined, "RequestCredentialsErr::DomainNotValid"> | import("packages/scale/src/err.js").CodecError<{
21
30
  reason: string;
22
31
  }, "RequestCredentialsErr::Unknown">>;
23
- getNonProductAccounts(): import("neverthrow").ResultAsync<{
32
+ getLegacyAccounts(): import("neverthrow").ResultAsync<{
24
33
  publicKey: Uint8Array<ArrayBufferLike>;
25
34
  name: string | undefined;
26
35
  }[], import("packages/scale/src/err.js").CodecError<undefined, "RequestCredentialsErr::NotConnected"> | import("packages/scale/src/err.js").CodecError<undefined, "RequestCredentialsErr::Rejected"> | import("packages/scale/src/err.js").CodecError<undefined, "RequestCredentialsErr::DomainNotValid"> | import("packages/scale/src/err.js").CodecError<{
@@ -31,5 +40,5 @@ export declare const createAccountsProvider: (transport?: Transport) => {
31
40
  }, "CreateProofErr::Unknown"> | import("packages/scale/src/err.js").CodecError<undefined, "CreateProofErr::RingNotFound">>;
32
41
  getProductAccountSigner(account: ProductAccount): PolkadotSigner;
33
42
  subscribeAccountConnectionStatus(callback: (status: AccountConnectionStatus) => void): import("@novasamatech/host-api").Subscription;
34
- getNonProductAccountSigner(account: ProductAccount): PolkadotSigner;
43
+ getLegacyAccountSigner(account: ProductAccount): PolkadotSigner;
35
44
  };
package/dist/accounts.js CHANGED
@@ -1,11 +1,35 @@
1
- import { CreateProofErr, RequestCredentialsErr, RingLocation, SigningPayload, SigningPayloadWithoutAccount, SigningRawPayload, SigningRawPayloadWithoutAccount, assertEnumVariant, createHostApi, enumValue, fromHex, isEnumVariant, toHex, } from '@novasamatech/host-api';
2
- import { getPolkadotSignerFromPjs } from '@polkadot-api/pjs-signer';
1
+ import { CreateProofErr, LoginErr, RequestCredentialsErr, RingLocation, SigningPayload, SigningPayloadWithoutAccount, SigningRawPayload, SigningRawPayloadWithoutAccount, assertEnumVariant, createHostApi, enumValue, fromHex, isEnumVariant, toHex, } from '@novasamatech/host-api';
3
2
  import { err, ok } from 'neverthrow';
3
+ import { getPolkadotSignerFromPjs } from 'polkadot-api/pjs-signer';
4
4
  import { sandboxTransport } from './sandboxTransport.js';
5
5
  const UNSUPPORTED_VERSION_ERROR = 'Unsupported message version';
6
6
  export const createAccountsProvider = (transport = sandboxTransport) => {
7
7
  const hostApi = createHostApi(transport);
8
8
  return {
9
+ getRootAccount() {
10
+ return hostApi
11
+ .accountGetRoot(enumValue('v1', undefined))
12
+ .mapErr(e => e.value)
13
+ .andThen(response => {
14
+ if (isEnumVariant(response, 'v1')) {
15
+ return ok(response.value);
16
+ }
17
+ // @ts-expect-error response.tag is never here
18
+ return err(new RequestCredentialsErr.Unknown({ reason: `Unsupported response version ${response.tag}` }));
19
+ });
20
+ },
21
+ requestLogin(reason) {
22
+ return hostApi
23
+ .requestLogin(enumValue('v1', reason))
24
+ .mapErr(e => e.value)
25
+ .andThen(response => {
26
+ if (isEnumVariant(response, 'v1')) {
27
+ return ok(response.value);
28
+ }
29
+ // @ts-expect-error response.tag is never here
30
+ return err(new LoginErr.Unknown({ reason: `Unsupported response version ${response.tag}` }));
31
+ });
32
+ },
9
33
  getProductAccount(dotNsIdentifier, derivationIndex = 0) {
10
34
  return hostApi
11
35
  .accountGet(enumValue('v1', [dotNsIdentifier, derivationIndex]))
@@ -30,9 +54,9 @@ export const createAccountsProvider = (transport = sandboxTransport) => {
30
54
  return err(new RequestCredentialsErr.Unknown({ reason: `Unsupported response version ${response.tag}` }));
31
55
  });
32
56
  },
33
- getNonProductAccounts() {
57
+ getLegacyAccounts() {
34
58
  return hostApi
35
- .getNonProductAccounts(enumValue('v1', undefined))
59
+ .getLegacyAccounts(enumValue('v1', undefined))
36
60
  .mapErr(e => e.value)
37
61
  .andThen(response => {
38
62
  if (isEnumVariant(response, 'v1')) {
@@ -58,23 +82,7 @@ export const createAccountsProvider = (transport = sandboxTransport) => {
58
82
  return getPolkadotSignerFromPjs(toHex(account.publicKey), async (payload) => {
59
83
  const codecPayload = {
60
84
  account: [account.dotNsIdentifier, account.derivationIndex],
61
- payload: {
62
- blockHash: asHex(payload.blockHash),
63
- blockNumber: asHex(payload.blockNumber),
64
- era: asHex(payload.era),
65
- genesisHash: asHex(payload.genesisHash),
66
- nonce: asHex(payload.nonce),
67
- method: asHex(payload.method),
68
- specVersion: asHex(payload.specVersion),
69
- transactionVersion: asHex(payload.transactionVersion),
70
- metadataHash: payload.metadataHash ? asHex(payload.metadataHash) : undefined,
71
- tip: asHex(payload.tip),
72
- assetId: payload.assetId !== undefined ? payload.assetId : undefined,
73
- mode: payload.mode,
74
- withSignedTransaction: payload.withSignedTransaction,
75
- signedExtensions: payload.signedExtensions,
76
- version: payload.version,
77
- },
85
+ payload: buildSigningPayloadFields(payload),
78
86
  };
79
87
  const response = await hostApi.signPayload(enumValue('v1', codecPayload));
80
88
  return response.match(response => {
@@ -122,29 +130,13 @@ export const createAccountsProvider = (transport = sandboxTransport) => {
122
130
  }
123
131
  });
124
132
  },
125
- getNonProductAccountSigner(account) {
133
+ getLegacyAccountSigner(account) {
126
134
  return getPolkadotSignerFromPjs(toHex(account.publicKey), async (payload) => {
127
135
  const codecPayload = {
128
136
  signer: payload.address,
129
- payload: {
130
- blockHash: asHex(payload.blockHash),
131
- blockNumber: asHex(payload.blockNumber),
132
- era: asHex(payload.era),
133
- genesisHash: asHex(payload.genesisHash),
134
- nonce: asHex(payload.nonce),
135
- method: asHex(payload.method),
136
- specVersion: asHex(payload.specVersion),
137
- transactionVersion: asHex(payload.transactionVersion),
138
- metadataHash: payload.metadataHash ? asHex(payload.metadataHash) : undefined,
139
- tip: asHex(payload.tip),
140
- assetId: payload.assetId !== undefined ? payload.assetId : undefined,
141
- mode: payload.mode,
142
- withSignedTransaction: payload.withSignedTransaction,
143
- signedExtensions: payload.signedExtensions,
144
- version: payload.version,
145
- },
137
+ payload: buildSigningPayloadFields(payload),
146
138
  };
147
- const response = await hostApi.signPayloadWithNonProductAccount(enumValue('v1', codecPayload));
139
+ const response = await hostApi.signPayloadWithLegacyAccount(enumValue('v1', codecPayload));
148
140
  return response.match(response => {
149
141
  assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
150
142
  return {
@@ -161,7 +153,7 @@ export const createAccountsProvider = (transport = sandboxTransport) => {
161
153
  signer: raw.address,
162
154
  payload: { tag: 'Bytes', value: fromHex(asHex(raw.data)) },
163
155
  };
164
- const response = await hostApi.signRawWithNonProductAccount(enumValue('v1', payload));
156
+ const response = await hostApi.signRawWithLegacyAccount(enumValue('v1', payload));
165
157
  return response.match(response => {
166
158
  assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
167
159
  return {
@@ -182,3 +174,22 @@ function asHex(v) {
182
174
  return v;
183
175
  return `0x${v}`;
184
176
  }
177
+ function buildSigningPayloadFields(payload) {
178
+ return {
179
+ blockHash: asHex(payload.blockHash),
180
+ blockNumber: asHex(payload.blockNumber),
181
+ era: asHex(payload.era),
182
+ genesisHash: asHex(payload.genesisHash),
183
+ nonce: asHex(payload.nonce),
184
+ method: asHex(payload.method),
185
+ specVersion: asHex(payload.specVersion),
186
+ transactionVersion: asHex(payload.transactionVersion),
187
+ metadataHash: payload.metadataHash ? asHex(payload.metadataHash) : undefined,
188
+ tip: asHex(payload.tip),
189
+ assetId: payload.assetId !== undefined ? payload.assetId : undefined,
190
+ mode: payload.mode,
191
+ withSignedTransaction: payload.withSignedTransaction,
192
+ signedExtensions: payload.signedExtensions,
193
+ version: payload.version,
194
+ };
195
+ }
package/dist/index.d.ts CHANGED
@@ -2,11 +2,11 @@ export { SpektrExtensionName, WellKnownChain } from './constants.js';
2
2
  export { sandboxProvider, sandboxTransport } from './sandboxTransport.js';
3
3
  export { hostApi } from './hostApi.js';
4
4
  export { createMetaProvider, metaProvider } from './metaProvider.js';
5
- export { createNonProductExtensionEnableFactory, injectSpektrExtension } from './injectWeb3.js';
5
+ export { createLegacyExtensionEnableFactory, injectSpektrExtension } from './injectWeb3.js';
6
6
  export { createPapiProvider } from './papiProvider.js';
7
7
  export type { ChatBotRegistrationResult, ChatCustomMessageRenderer, ChatCustomMessageRendererParams, ChatMessageContent, ChatReceivedAction, ChatRoom, ChatRoomRegistrationResult, } from './chat.js';
8
8
  export { createProductChatManager, matchChatCustomRenderers } from './chat.js';
9
- export type { ProductAccountId, SignedStatement, Statement, Topic } from './statementStore.js';
9
+ export type { ProductAccountId, SignedStatement, Statement, StatementTopicFilter, StatementsPage, Topic, } from './statementStore.js';
10
10
  export { createStatementStore } from './statementStore.js';
11
11
  export type { AccountConnectionStatus, ProductAccount } from './accounts.js';
12
12
  export { createAccountsProvider } from './accounts.js';
@@ -17,3 +17,5 @@ export { createPreimageManager, preimageManager } from './preimage.js';
17
17
  export type { PaymentBalance, PaymentStatus, TopUpSource } from './payments.js';
18
18
  export { createPaymentManager, paymentManager } from './payments.js';
19
19
  export { deriveEntropy } from './deriveEntropy.js';
20
+ export type { DevicePermissionKind, RemotePermissionItem } from './permission.js';
21
+ export { requestDevicePermission, requestPermission } from './permission.js';
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ export { SpektrExtensionName, WellKnownChain } from './constants.js';
2
2
  export { sandboxProvider, sandboxTransport } from './sandboxTransport.js';
3
3
  export { hostApi } from './hostApi.js';
4
4
  export { createMetaProvider, metaProvider } from './metaProvider.js';
5
- export { createNonProductExtensionEnableFactory, injectSpektrExtension } from './injectWeb3.js';
5
+ export { createLegacyExtensionEnableFactory, injectSpektrExtension } from './injectWeb3.js';
6
6
  export { createPapiProvider } from './papiProvider.js';
7
7
  export { createProductChatManager, matchChatCustomRenderers } from './chat.js';
8
8
  export { createStatementStore } from './statementStore.js';
@@ -12,3 +12,4 @@ export { createLocalStorage, hostLocalStorage } from './localStorage.js';
12
12
  export { createPreimageManager, preimageManager } from './preimage.js';
13
13
  export { createPaymentManager, paymentManager } from './payments.js';
14
14
  export { deriveEntropy } from './deriveEntropy.js';
15
+ export { requestDevicePermission, requestPermission } from './permission.js';
@@ -19,6 +19,6 @@ interface Injected {
19
19
  accounts: InjectedAccounts;
20
20
  signer: Signer;
21
21
  }
22
- export declare function createNonProductExtensionEnableFactory(transport: Transport): Promise<(() => Promise<Injected>) | null>;
22
+ export declare function createLegacyExtensionEnableFactory(transport: Transport): Promise<(() => Promise<Injected>) | null>;
23
23
  export declare function injectSpektrExtension(transport?: Transport | null): Promise<boolean>;
24
24
  export {};
@@ -1,10 +1,10 @@
1
1
  import { assertEnumVariant, createHostApi, enumValue, fromHex, toHex } from '@novasamatech/host-api';
2
2
  import { injectExtension } from '@polkadot/extension-inject';
3
- import { AccountId } from '@polkadot-api/substrate-bindings';
3
+ import { AccountId } from 'polkadot-api';
4
4
  import { SpektrExtensionName, Version } from './constants.js';
5
5
  import { sandboxTransport } from './sandboxTransport.js';
6
6
  const UNSUPPORTED_VERSION_ERROR = 'Unsupported message version';
7
- export async function createNonProductExtensionEnableFactory(transport) {
7
+ export async function createLegacyExtensionEnableFactory(transport) {
8
8
  const ready = await transport.isReady();
9
9
  if (!ready)
10
10
  return null;
@@ -12,7 +12,7 @@ export async function createNonProductExtensionEnableFactory(transport) {
12
12
  const accountId = AccountId();
13
13
  async function enable() {
14
14
  async function getAccounts() {
15
- const response = await hostApi.getNonProductAccounts(enumValue('v1', undefined));
15
+ const response = await hostApi.getLegacyAccounts(enumValue('v1', undefined));
16
16
  return response.match(response => {
17
17
  assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
18
18
  return response.value.map(account => ({
@@ -51,7 +51,7 @@ export async function createNonProductExtensionEnableFactory(transport) {
51
51
  value: raw.data,
52
52
  },
53
53
  };
54
- const response = await hostApi.signRawWithNonProductAccount(enumValue('v1', payload));
54
+ const response = await hostApi.signRawWithLegacyAccount(enumValue('v1', payload));
55
55
  return response.match(response => {
56
56
  assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
57
57
  return {
@@ -85,7 +85,7 @@ export async function createNonProductExtensionEnableFactory(transport) {
85
85
  version: payload.version,
86
86
  },
87
87
  };
88
- const response = await hostApi.signPayloadWithNonProductAccount(enumValue('v1', codecPayload));
88
+ const response = await hostApi.signPayloadWithLegacyAccount(enumValue('v1', codecPayload));
89
89
  return response.match(response => {
90
90
  assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
91
91
  return {
@@ -99,7 +99,7 @@ export async function createNonProductExtensionEnableFactory(transport) {
99
99
  });
100
100
  },
101
101
  async createTransaction(payload) {
102
- const response = await hostApi.createTransactionWithNonProductAccount(enumValue('v1', payload));
102
+ const response = await hostApi.createTransactionWithLegacyAccount(enumValue('v1', payload));
103
103
  return response.match(response => {
104
104
  assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
105
105
  return toHex(response.value);
@@ -117,7 +117,7 @@ export async function injectSpektrExtension(transport = sandboxTransport) {
117
117
  if (!transport)
118
118
  return false;
119
119
  try {
120
- const enable = await createNonProductExtensionEnableFactory(transport);
120
+ const enable = await createLegacyExtensionEnableFactory(transport);
121
121
  if (enable) {
122
122
  injectExtension(enable, { name: SpektrExtensionName, version: Version });
123
123
  return true;
@@ -1,5 +1,5 @@
1
1
  import type { HexString, Transport } from '@novasamatech/host-api';
2
- import type { JsonRpcProvider } from '@polkadot-api/json-rpc-provider';
2
+ import type { JsonRpcProvider } from 'polkadot-api';
3
3
  type InternalParams = {
4
4
  transport?: Transport;
5
5
  };
@@ -18,17 +18,17 @@ __fallback, internal) {
18
18
  return `follow_${nextSubId++}`;
19
19
  }
20
20
  function sendJsonRpcResponse(id, result) {
21
- onMessage(JSON.stringify({ jsonrpc: '2.0', id, result }));
21
+ onMessage({ jsonrpc: '2.0', id, result });
22
22
  }
23
23
  function sendJsonRpcError(id, code, message) {
24
- onMessage(JSON.stringify({ jsonrpc: '2.0', id, error: { code, message } }));
24
+ onMessage({ jsonrpc: '2.0', id, error: { code, message } });
25
25
  }
26
26
  function sendFollowEvent(syntheticSubId, event) {
27
- onMessage(JSON.stringify({
27
+ onMessage({
28
28
  jsonrpc: '2.0',
29
29
  method: 'chainHead_v1_followEvent',
30
30
  params: { subscription: syntheticSubId, result: event },
31
- }));
31
+ });
32
32
  }
33
33
  function convertTypedEventToJsonRpc(event) {
34
34
  switch (event.tag) {
@@ -145,14 +145,9 @@ __fallback, internal) {
145
145
  return { result: 'limitReached' };
146
146
  }
147
147
  function handleMessage(message) {
148
- let parsed;
149
- try {
150
- parsed = JSON.parse(message);
151
- }
152
- catch {
153
- return;
154
- }
155
- const { id, method, params } = parsed;
148
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
149
+ const id = message.id;
150
+ const { method, params } = message;
156
151
  switch (method) {
157
152
  case 'chainHead_v1_follow': {
158
153
  const [withRuntime] = params;
@@ -319,20 +314,27 @@ __fallback, internal) {
319
314
  });
320
315
  });
321
316
  }
322
- return getSyncProvider(() => checkIfReady().then(ready => {
323
- if (ready)
324
- return typedProvider;
325
- if (__fallback)
326
- return __fallback;
317
+ return getSyncProvider(onResult => {
318
+ checkIfReady().then(ready => {
319
+ if (ready) {
320
+ onResult((onMessage, _onHalt) => typedProvider(onMessage));
321
+ }
322
+ else if (__fallback) {
323
+ onResult((onMessage, _onHalt) => __fallback(onMessage));
324
+ }
325
+ else {
326
+ onResult((_onMessage, _onHalt) => ({
327
+ send() {
328
+ transport.provider.logger.error(`Provider for chain ${genesisHash} was not started because Host doesn't support it`);
329
+ },
330
+ disconnect() {
331
+ /* empty */
332
+ },
333
+ }));
334
+ }
335
+ });
327
336
  return () => {
328
- return {
329
- send() {
330
- transport.provider.logger.error(`Provider for chain ${genesisHash} was not started because Host doesn't support it`);
331
- },
332
- disconnect() {
333
- /* empty */
334
- },
335
- };
337
+ /* empty */
336
338
  };
337
- }));
339
+ });
338
340
  }
@@ -3,8 +3,17 @@ export type Statement = CodecType<typeof StatementCodec>;
3
3
  export type SignedStatement = CodecType<typeof SignedStatementCodec>;
4
4
  export type Topic = CodecType<typeof TopicCodec>;
5
5
  export type ProductAccountId = CodecType<typeof ProductAccountIdCodec>;
6
+ export type StatementTopicFilter = {
7
+ matchAll: Topic[];
8
+ } | {
9
+ matchAny: Topic[];
10
+ };
11
+ export type StatementsPage = {
12
+ statements: SignedStatement[];
13
+ isComplete: boolean;
14
+ };
6
15
  export declare const createStatementStore: (transport?: Transport) => {
7
- subscribe(topics: Topic[], callback: (statements: SignedStatement[]) => void): import("@novasamatech/host-api").Subscription;
16
+ subscribe(filter: StatementTopicFilter, callback: (page: StatementsPage) => void): import("@novasamatech/host-api").Subscription;
8
17
  createProof(accountId: ProductAccountId, statement: Statement): Promise<{
9
18
  tag: "Sr25519";
10
19
  value: {
@@ -3,8 +3,9 @@ import { sandboxTransport } from './sandboxTransport.js';
3
3
  export const createStatementStore = (transport = sandboxTransport) => {
4
4
  const hostApi = createHostApi(transport);
5
5
  return {
6
- subscribe(topics, callback) {
7
- return hostApi.statementStoreSubscribe(enumValue('v1', topics), payload => {
6
+ subscribe(filter, callback) {
7
+ const scaleFilter = 'matchAll' in filter ? enumValue('MatchAll', filter.matchAll) : enumValue('MatchAny', filter.matchAny);
8
+ return hostApi.statementStoreSubscribe(enumValue('v1', scaleFilter), payload => {
8
9
  if (payload.tag === 'v1') {
9
10
  callback(payload.value);
10
11
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@novasamatech/product-sdk",
3
3
  "type": "module",
4
- "version": "0.7.0-0",
4
+ "version": "0.7.0-1",
5
5
  "description": "Polkadot product SDK: integrate and run your product inside Polkadot browser.",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -25,11 +25,11 @@
25
25
  "README.md"
26
26
  ],
27
27
  "dependencies": {
28
- "@polkadot/extension-inject": "^0.62.6",
29
- "@polkadot-api/substrate-bindings": "^0.17.0",
30
- "@polkadot-api/json-rpc-provider": "^0.0.4",
31
- "@polkadot-api/json-rpc-provider-proxy": "^0.2.7",
32
- "@novasamatech/host-api": "0.7.0-0"
28
+ "@polkadot/extension-inject": "^0.63.1",
29
+ "@polkadot-api/json-rpc-provider-proxy": "^0.4.0",
30
+ "@novasamatech/host-api": "0.7.0-1",
31
+ "polkadot-api": ">=2",
32
+ "neverthrow": "^8.2.0"
33
33
  },
34
34
  "publishConfig": {
35
35
  "access": "public"