@novasamatech/host-container 0.5.3-0 → 0.5.4-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.
@@ -0,0 +1 @@
1
+ export declare const WEBVIEW_HOST_PORT_NAME = "__HOST_API_PORT__";
@@ -0,0 +1 @@
1
+ export const WEBVIEW_HOST_PORT_NAME = '__HOST_API_PORT__';
@@ -1,4 +1,4 @@
1
- import { ChatContactRegistrationErr, ChatMessagePostingErr, CreateProofErr, CreateTransactionErr, GenericError, PermissionErr, RequestCredentialsErr, SigningErr, StatementProofErr, StorageErr, assertEnumVariant, createTransport, enumValue, isEnumVariant, resultErr, resultOk, } from '@novasamatech/host-api';
1
+ import { ChatMessagePostingErr, ChatRoomRegistrationErr, CreateProofErr, CreateTransactionErr, GenericError, RequestCredentialsErr, SigningErr, StatementProofErr, StorageErr, assertEnumVariant, createTransport, enumValue, isEnumVariant, resultErr, resultOk, } from '@novasamatech/host-api';
2
2
  import { err, errAsync, ok, okAsync } from 'neverthrow';
3
3
  const UNSUPPORTED_MESSAGE_FORMAT_ERROR = 'Unsupported message format';
4
4
  function guardVersion(value, tag, error) {
@@ -18,6 +18,7 @@ export function createContainer(provider) {
18
18
  }
19
19
  return {
20
20
  handleFeature(handler) {
21
+ init();
21
22
  return transport.handleRequest('feature', async (message) => {
22
23
  const version = 'v1';
23
24
  const error = new GenericError({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -28,19 +29,9 @@ export function createContainer(provider) {
28
29
  .unwrapOr(enumValue(version, resultErr(error)));
29
30
  });
30
31
  },
31
- handlePermissionRequest(handler) {
32
- return transport.handleRequest('permission_request', async (message) => {
33
- const version = 'v1';
34
- const error = new PermissionErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
35
- return guardVersion(message, version, error)
36
- .asyncMap(async (params) => handler(params, { ok: (okAsync), err: (errAsync) }))
37
- .andThen(r => r.map(r => enumValue(version, resultOk(r))))
38
- .orElse(r => ok(enumValue(version, resultErr(r))))
39
- .unwrapOr(enumValue(version, resultErr(error)));
40
- });
41
- },
42
- handleStorageRead(handler) {
43
- return transport.handleRequest('storage_read', async (message) => {
32
+ handleLocalStorageRead(handler) {
33
+ init();
34
+ return transport.handleRequest('local_storage_read', async (message) => {
44
35
  const version = 'v1';
45
36
  const error = new StorageErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
46
37
  return guardVersion(message, version, error)
@@ -50,8 +41,9 @@ export function createContainer(provider) {
50
41
  .unwrapOr(enumValue(version, resultErr(error)));
51
42
  });
52
43
  },
53
- handleStorageWrite(handler) {
54
- return transport.handleRequest('storage_write', async (message) => {
44
+ handleLocalStorageWrite(handler) {
45
+ init();
46
+ return transport.handleRequest('local_storage_write', async (message) => {
55
47
  const version = 'v1';
56
48
  const error = new StorageErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
57
49
  return guardVersion(message, version, error)
@@ -61,8 +53,9 @@ export function createContainer(provider) {
61
53
  .unwrapOr(enumValue(version, resultErr(error)));
62
54
  });
63
55
  },
64
- handleStorageClear(handler) {
65
- return transport.handleRequest('storage_clear', async (params) => {
56
+ handleLocalStorageClear(handler) {
57
+ init();
58
+ return transport.handleRequest('local_storage_clear', async (params) => {
66
59
  const version = 'v1';
67
60
  const error = new StorageErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
68
61
  return guardVersion(params, version, error)
@@ -73,6 +66,7 @@ export function createContainer(provider) {
73
66
  });
74
67
  },
75
68
  handleAccountGet(handler) {
69
+ init();
76
70
  return transport.handleRequest('account_get', async (params) => {
77
71
  const version = 'v1';
78
72
  const error = new RequestCredentialsErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -84,6 +78,7 @@ export function createContainer(provider) {
84
78
  });
85
79
  },
86
80
  handleAccountGetAlias(handler) {
81
+ init();
87
82
  return transport.handleRequest('account_get_alias', async (params) => {
88
83
  const version = 'v1';
89
84
  const error = new RequestCredentialsErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -95,6 +90,7 @@ export function createContainer(provider) {
95
90
  });
96
91
  },
97
92
  handleAccountCreateProof(handler) {
93
+ init();
98
94
  return transport.handleRequest('account_create_proof', async (params) => {
99
95
  const version = 'v1';
100
96
  const error = new CreateProofErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -106,6 +102,7 @@ export function createContainer(provider) {
106
102
  });
107
103
  },
108
104
  handleGetNonProductAccounts(handler) {
105
+ init();
109
106
  return transport.handleRequest('get_non_product_accounts', async (params) => {
110
107
  const version = 'v1';
111
108
  const error = new RequestCredentialsErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -117,6 +114,7 @@ export function createContainer(provider) {
117
114
  });
118
115
  },
119
116
  handleCreateTransaction(handler) {
117
+ init();
120
118
  return transport.handleRequest('create_transaction', async (params) => {
121
119
  const version = 'v1';
122
120
  const error = new CreateTransactionErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -128,6 +126,7 @@ export function createContainer(provider) {
128
126
  });
129
127
  },
130
128
  handleCreateTransactionWithNonProductAccount(handler) {
129
+ init();
131
130
  return transport.handleRequest('create_transaction_with_non_product_account', async (params) => {
132
131
  const version = 'v1';
133
132
  const error = new CreateTransactionErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -139,6 +138,7 @@ export function createContainer(provider) {
139
138
  });
140
139
  },
141
140
  handleSignRaw(handler) {
141
+ init();
142
142
  return transport.handleRequest('sign_raw', async (params) => {
143
143
  const version = 'v1';
144
144
  const error = new SigningErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -150,6 +150,7 @@ export function createContainer(provider) {
150
150
  });
151
151
  },
152
152
  handleSignPayload(handler) {
153
+ init();
153
154
  return transport.handleRequest('sign_payload', async (params) => {
154
155
  const version = 'v1';
155
156
  const error = new SigningErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -160,10 +161,11 @@ export function createContainer(provider) {
160
161
  .unwrapOr(enumValue(version, resultErr(error)));
161
162
  });
162
163
  },
163
- handleChatCreateContact(handler) {
164
- return transport.handleRequest('chat_create_contact', async (params) => {
164
+ handleChatCreateRoom(handler) {
165
+ init();
166
+ return transport.handleRequest('chat_create_room', async (params) => {
165
167
  const version = 'v1';
166
- const error = new ChatContactRegistrationErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
168
+ const error = new ChatRoomRegistrationErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
167
169
  return guardVersion(params, version, error)
168
170
  .asyncMap(async (params) => handler(params, { ok: (okAsync), err: (errAsync) }))
169
171
  .andThen(r => r.map(r => enumValue(version, resultOk(r))))
@@ -171,7 +173,20 @@ export function createContainer(provider) {
171
173
  .unwrapOr(enumValue(version, resultErr(error)));
172
174
  });
173
175
  },
176
+ handleChatListSubscribe(handler) {
177
+ init();
178
+ return transport.handleSubscription('chat_list_subscribe', (params, send, interrupt) => {
179
+ const version = 'v1';
180
+ return guardVersion(params, version, null)
181
+ .map(params => handler(params, payload => send(enumValue(version, payload)), interrupt))
182
+ .orTee(interrupt)
183
+ .unwrapOr(() => {
184
+ /* empty */
185
+ });
186
+ });
187
+ },
174
188
  handleChatPostMessage(handler) {
189
+ init();
175
190
  return transport.handleRequest('chat_post_message', async (params) => {
176
191
  const version = 'v1';
177
192
  const error = new ChatMessagePostingErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -183,6 +198,7 @@ export function createContainer(provider) {
183
198
  });
184
199
  },
185
200
  handleChatActionSubscribe(handler) {
201
+ init();
186
202
  return transport.handleSubscription('chat_action_subscribe', (params, send, interrupt) => {
187
203
  const version = 'v1';
188
204
  return guardVersion(params, version, null)
@@ -193,7 +209,32 @@ export function createContainer(provider) {
193
209
  });
194
210
  });
195
211
  },
212
+ handleStatementStoreQuery(handler) {
213
+ init();
214
+ return transport.handleRequest('statement_store_query', async (params) => {
215
+ const version = 'v1';
216
+ const error = new GenericError({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
217
+ return guardVersion(params, version, error)
218
+ .asyncMap(async (params) => handler(params, { ok: (okAsync), err: (errAsync) }))
219
+ .andThen(r => r.map(r => enumValue(version, resultOk(r))))
220
+ .orElse(r => ok(enumValue(version, resultErr(r))))
221
+ .unwrapOr(enumValue(version, resultErr(error)));
222
+ });
223
+ },
224
+ handleStatementStoreSubscribe(handler) {
225
+ init();
226
+ return transport.handleSubscription('statement_store_subscribe', (params, send, interrupt) => {
227
+ const version = 'v1';
228
+ return guardVersion(params, version, null)
229
+ .map(params => handler(params, payload => send(enumValue(version, payload)), interrupt))
230
+ .orTee(interrupt)
231
+ .unwrapOr(() => {
232
+ /* empty */
233
+ });
234
+ });
235
+ },
196
236
  handleStatementStoreCreateProof(handler) {
237
+ init();
197
238
  return transport.handleRequest('statement_store_create_proof', async (params) => {
198
239
  const version = 'v1';
199
240
  const error = new StatementProofErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
@@ -204,6 +245,18 @@ export function createContainer(provider) {
204
245
  .unwrapOr(enumValue(version, resultErr(error)));
205
246
  });
206
247
  },
248
+ handleStatementStoreSubmit(handler) {
249
+ init();
250
+ return transport.handleRequest('statement_store_submit', async (params) => {
251
+ const version = 'v1';
252
+ const error = new GenericError({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR });
253
+ return guardVersion(params, version, error)
254
+ .asyncMap(async (params) => handler(params, { ok: (okAsync), err: (errAsync) }))
255
+ .andThen(r => r.map(r => enumValue(version, resultOk(r))))
256
+ .orElse(r => ok(enumValue(version, resultErr(r))))
257
+ .unwrapOr(enumValue(version, resultErr(error)));
258
+ });
259
+ },
207
260
  handleJsonRpcMessageSubscribe(genesisHash, provider) {
208
261
  init();
209
262
  return transport.handleSubscription('jsonrpc_message_subscribe', (params, send) => {
@@ -0,0 +1,8 @@
1
+ import type { Logger, Provider } from '@novasamatech/host-api';
2
+ import type { WebviewTag } from 'electron';
3
+ type Params = {
4
+ webview: WebviewTag;
5
+ logger?: Logger;
6
+ };
7
+ export declare function createWebviewProvider({ webview, logger }: Params): Provider;
8
+ export {};
@@ -0,0 +1,99 @@
1
+ import { createDefaultLogger } from '@novasamatech/host-api';
2
+ import { nanoid } from 'nanoid';
3
+ import { WEBVIEW_HOST_PORT_NAME } from './constants.js';
4
+ function hasWindow() {
5
+ try {
6
+ return typeof window !== 'undefined';
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ }
12
+ function isValidMessage(event, sourceEnv, currentEnv) {
13
+ return (event.source !== currentEnv &&
14
+ event.source === sourceEnv &&
15
+ event.data &&
16
+ event.data.constructor.name === 'Uint8Array');
17
+ }
18
+ export function createWebviewProvider({ webview, logger }) {
19
+ let disposed = false;
20
+ let subscribed = false;
21
+ let port = null;
22
+ const subscribers = new Set();
23
+ const webviewPromise = new Promise((resolve, reject) => {
24
+ webview.addEventListener('did-fail-load', e => {
25
+ reject(new Error(e.errorDescription));
26
+ });
27
+ webview.addEventListener('dom-ready', async () => {
28
+ const { port1, port2 } = new MessageChannel();
29
+ const portInitMessage = `PORT_INIT_${nanoid(12)}`;
30
+ port = port1;
31
+ await webview
32
+ .executeJavaScript(`
33
+ window.addEventListener('message', e => {
34
+ if (e.data === '${portInitMessage}') {
35
+ const port = e.ports[0];
36
+ if (port) {
37
+ window['${WEBVIEW_HOST_PORT_NAME}'] = port;
38
+ }
39
+ }
40
+ });
41
+ `)
42
+ .catch(reject);
43
+ // @ts-expect-error contentWindow is undefined somehow
44
+ webview.contentWindow.postMessage(portInitMessage, '*', [port2]);
45
+ resolve(port);
46
+ });
47
+ });
48
+ function waitForWebview(callback) {
49
+ if (port) {
50
+ return callback(port);
51
+ }
52
+ webviewPromise.then(callback);
53
+ }
54
+ const messageHandler = (event) => {
55
+ if (disposed)
56
+ return;
57
+ waitForWebview(port => {
58
+ if (disposed)
59
+ return;
60
+ if (!isValidMessage(event, port, window))
61
+ return;
62
+ for (const subscriber of subscribers) {
63
+ subscriber(event.data);
64
+ }
65
+ });
66
+ };
67
+ return {
68
+ logger: logger ?? createDefaultLogger(),
69
+ isCorrectEnvironment() {
70
+ return hasWindow();
71
+ },
72
+ postMessage(message) {
73
+ if (disposed)
74
+ return;
75
+ waitForWebview(port => {
76
+ if (disposed)
77
+ return;
78
+ port.postMessage(message, [message.buffer]);
79
+ });
80
+ },
81
+ subscribe(callback) {
82
+ if (!subscribed && port) {
83
+ subscribed = true;
84
+ port.addEventListener('message', messageHandler);
85
+ }
86
+ subscribers.add(callback);
87
+ return () => {
88
+ subscribers.delete(callback);
89
+ };
90
+ },
91
+ dispose() {
92
+ disposed = true;
93
+ subscribers.clear();
94
+ if (port) {
95
+ port.removeEventListener('message', messageHandler);
96
+ }
97
+ },
98
+ };
99
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export { createWebviewProvider } from './createWebviewProvider.js';
1
2
  export { createIframeProvider } from './createIframeProvider.js';
2
3
  export { createContainer } from './createContainer.js';
3
4
  export type { Container } from './types.js';
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
+ export { createWebviewProvider } from './createWebviewProvider.js';
1
2
  export { createIframeProvider } from './createIframeProvider.js';
2
3
  export { createContainer } from './createContainer.js';
package/dist/types.d.ts CHANGED
@@ -51,10 +51,9 @@ type InferSubscribeHandler<V extends string, T extends VersionedProtocolSubscrip
51
51
  type InferHandler<V extends string, T extends VersionedProtocolRequest | VersionedProtocolSubscription> = T extends VersionedProtocolRequest ? InferRequestHandler<V, T> : T extends VersionedProtocolSubscription ? InferSubscribeHandler<V, T> : never;
52
52
  export type Container = {
53
53
  handleFeature: InferHandler<'v1', HostApiProtocol['feature']>;
54
- handlePermissionRequest: InferHandler<'v1', HostApiProtocol['permission_request']>;
55
- handleStorageRead: InferHandler<'v1', HostApiProtocol['storage_read']>;
56
- handleStorageWrite: InferHandler<'v1', HostApiProtocol['storage_write']>;
57
- handleStorageClear: InferHandler<'v1', HostApiProtocol['storage_clear']>;
54
+ handleLocalStorageRead: InferHandler<'v1', HostApiProtocol['local_storage_read']>;
55
+ handleLocalStorageWrite: InferHandler<'v1', HostApiProtocol['local_storage_write']>;
56
+ handleLocalStorageClear: InferHandler<'v1', HostApiProtocol['local_storage_clear']>;
58
57
  handleAccountGet: InferHandler<'v1', HostApiProtocol['account_get']>;
59
58
  handleAccountGetAlias: InferHandler<'v1', HostApiProtocol['account_get_alias']>;
60
59
  handleAccountCreateProof: InferHandler<'v1', HostApiProtocol['account_create_proof']>;
@@ -63,10 +62,14 @@ export type Container = {
63
62
  handleCreateTransactionWithNonProductAccount: InferHandler<'v1', HostApiProtocol['create_transaction_with_non_product_account']>;
64
63
  handleSignRaw: InferHandler<'v1', HostApiProtocol['sign_raw']>;
65
64
  handleSignPayload: InferHandler<'v1', HostApiProtocol['sign_payload']>;
66
- handleChatCreateContact: InferHandler<'v1', HostApiProtocol['chat_create_contact']>;
65
+ handleChatCreateRoom: InferHandler<'v1', HostApiProtocol['chat_create_room']>;
66
+ handleChatListSubscribe: InferHandler<'v1', HostApiProtocol['chat_list_subscribe']>;
67
67
  handleChatPostMessage: InferHandler<'v1', HostApiProtocol['chat_post_message']>;
68
68
  handleChatActionSubscribe: InferHandler<'v1', HostApiProtocol['chat_action_subscribe']>;
69
+ handleStatementStoreQuery: InferHandler<'v1', HostApiProtocol['statement_store_query']>;
70
+ handleStatementStoreSubscribe: InferHandler<'v1', HostApiProtocol['statement_store_subscribe']>;
69
71
  handleStatementStoreCreateProof: InferHandler<'v1', HostApiProtocol['statement_store_create_proof']>;
72
+ handleStatementStoreSubmit: InferHandler<'v1', HostApiProtocol['statement_store_submit']>;
70
73
  handleJsonRpcMessageSubscribe: (params: WithVersion<'v1', Value<HostApiProtocol['jsonrpc_message_subscribe']['start']>>, provider: JsonRpcProvider) => VoidFunction;
71
74
  isReady(): Promise<boolean>;
72
75
  dispose(): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@novasamatech/host-container",
3
3
  "type": "module",
4
- "version": "0.5.3-0",
4
+ "version": "0.5.4-0",
5
5
  "description": "Host container for hosting and managing products within the Polkadot ecosystem.",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -28,7 +28,11 @@
28
28
  "dependencies": {
29
29
  "@polkadot-api/utils": "^0.2.0",
30
30
  "@polkadot-api/json-rpc-provider": "^0.0.4",
31
- "@novasamatech/host-api": "0.5.3-0"
31
+ "@novasamatech/host-api": "0.5.4-0",
32
+ "nanoid": "5.1.6"
33
+ },
34
+ "devDependencies": {
35
+ "electron": "^40.1.0"
32
36
  },
33
37
  "publishConfig": {
34
38
  "access": "public"