@parity/product-sdk-host 0.10.3 → 0.12.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/dist/index.d.ts +681 -462
- package/dist/index.js +890 -219
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/src/accounts.ts +544 -0
- package/src/chain-spec.ts +272 -0
- package/src/chain-transaction.ts +241 -0
- package/src/chat.ts +81 -85
- package/src/container.ts +211 -246
- package/src/entropy.ts +63 -25
- package/src/errors.ts +198 -0
- package/src/features.ts +172 -0
- package/src/index.ts +47 -22
- package/src/navigation.ts +128 -0
- package/src/notifications.ts +59 -69
- package/src/papi-provider.ts +673 -0
- package/src/payments.ts +77 -61
- package/src/permissions.ts +107 -105
- package/src/result.ts +56 -0
- package/src/theme.ts +35 -63
- package/src/transport.ts +71 -0
- package/src/truapi.ts +166 -409
- package/src/types.ts +69 -61
package/dist/index.js
CHANGED
|
@@ -1,9 +1,482 @@
|
|
|
1
1
|
import { createLogger } from '@parity/product-sdk-logger';
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
2
|
+
import { isCorrectEnvironment, getClientSync } from '@parity/truapi/sandbox';
|
|
3
|
+
export { isCorrectEnvironment as isInsideContainerSync } from '@parity/truapi/sandbox';
|
|
4
|
+
import { scale } from '@parity/truapi';
|
|
5
|
+
import { unifyMetadata, decAnyMetadata } from '@polkadot-api/substrate-bindings';
|
|
6
|
+
import { AccountId } from 'polkadot-api';
|
|
7
|
+
|
|
8
|
+
// src/errors.ts
|
|
9
|
+
function isHostErrorPayload(error) {
|
|
10
|
+
if (error == null || typeof error !== "object") return false;
|
|
11
|
+
const obj = error;
|
|
12
|
+
return typeof obj.reason === "string" || typeof obj.tag === "string";
|
|
13
|
+
}
|
|
14
|
+
function formatHostError(error) {
|
|
15
|
+
if (error instanceof Error) return error.message;
|
|
16
|
+
if (typeof error === "string") return error;
|
|
17
|
+
if (isHostErrorPayload(error)) {
|
|
18
|
+
if ("tag" in error) {
|
|
19
|
+
if (error.value != null && typeof error.value.reason === "string") {
|
|
20
|
+
return `${error.tag}: ${error.value.reason}`;
|
|
21
|
+
}
|
|
22
|
+
return error.tag;
|
|
23
|
+
}
|
|
24
|
+
return error.reason;
|
|
25
|
+
}
|
|
26
|
+
if (error != null && typeof error === "object" && "message" in error) {
|
|
27
|
+
const message = error.message;
|
|
28
|
+
if (typeof message === "string") return message;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
return JSON.stringify(error);
|
|
32
|
+
} catch {
|
|
33
|
+
return String(error);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
var HostError = class extends Error {
|
|
37
|
+
constructor(message, options) {
|
|
38
|
+
super(message, options);
|
|
39
|
+
this.name = "HostError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var HostUnavailableError = class extends HostError {
|
|
43
|
+
constructor(message = "Host API is not available") {
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = "HostUnavailableError";
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var HostCallFailedError = class extends HostError {
|
|
49
|
+
payload;
|
|
50
|
+
constructor(label, payload) {
|
|
51
|
+
super(`${label}: ${formatHostError(payload)}`, { cause: payload });
|
|
52
|
+
this.name = "HostCallFailedError";
|
|
53
|
+
this.payload = payload;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
function isHostError(error) {
|
|
57
|
+
return error instanceof HostError;
|
|
58
|
+
}
|
|
59
|
+
async function getClient() {
|
|
60
|
+
return getClientSync();
|
|
61
|
+
}
|
|
62
|
+
function subscribeWithInterrupt(observable, onNext) {
|
|
63
|
+
let interruptCallback;
|
|
64
|
+
const sub = observable.subscribe({
|
|
65
|
+
next: onNext,
|
|
66
|
+
error: (reason) => interruptCallback?.(reason),
|
|
67
|
+
complete: () => interruptCallback?.()
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
unsubscribe: () => sub.unsubscribe(),
|
|
71
|
+
onInterrupt: (callback) => {
|
|
72
|
+
interruptCallback = callback;
|
|
73
|
+
return () => {
|
|
74
|
+
if (interruptCallback === callback) interruptCallback = void 0;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/papi-provider.ts
|
|
81
|
+
var log = createLogger("host:papi");
|
|
82
|
+
var JSON_RPC_INTERNAL_ERROR = -32603;
|
|
83
|
+
var JSON_RPC_METHOD_NOT_FOUND = -32601;
|
|
84
|
+
var STORAGE_TYPE_MAP = {
|
|
85
|
+
value: "Value",
|
|
86
|
+
hash: "Hash",
|
|
87
|
+
closestDescendantMerkleValue: "ClosestDescendantMerkleValue",
|
|
88
|
+
descendantsValues: "DescendantsValues",
|
|
89
|
+
descendantsHashes: "DescendantsHashes"
|
|
90
|
+
};
|
|
91
|
+
function convertRuntimeToJsonRpc(runtime) {
|
|
92
|
+
if (!runtime || typeof runtime !== "object") return null;
|
|
93
|
+
if (runtime.tag === "Valid") {
|
|
94
|
+
const spec = runtime.value;
|
|
95
|
+
const apis = {};
|
|
96
|
+
for (const api of spec.apis) {
|
|
97
|
+
apis[api.name] = api.version;
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
type: "valid",
|
|
101
|
+
spec: {
|
|
102
|
+
specName: spec.specName,
|
|
103
|
+
implName: spec.implName,
|
|
104
|
+
specVersion: spec.specVersion,
|
|
105
|
+
implVersion: spec.implVersion,
|
|
106
|
+
transactionVersion: spec.transactionVersion,
|
|
107
|
+
apis
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (runtime.tag === "Invalid") {
|
|
112
|
+
return { type: "invalid", error: runtime.value.error };
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
function convertFollowEventToJsonRpc(item) {
|
|
117
|
+
switch (item.tag) {
|
|
118
|
+
case "Initialized":
|
|
119
|
+
return {
|
|
120
|
+
event: "initialized",
|
|
121
|
+
finalizedBlockHashes: item.value.finalizedBlockHashes,
|
|
122
|
+
finalizedBlockRuntime: convertRuntimeToJsonRpc(item.value.finalizedBlockRuntime)
|
|
123
|
+
};
|
|
124
|
+
case "NewBlock":
|
|
125
|
+
return {
|
|
126
|
+
event: "newBlock",
|
|
127
|
+
blockHash: item.value.blockHash,
|
|
128
|
+
parentBlockHash: item.value.parentBlockHash,
|
|
129
|
+
newRuntime: convertRuntimeToJsonRpc(item.value.newRuntime)
|
|
130
|
+
};
|
|
131
|
+
case "BestBlockChanged":
|
|
132
|
+
return { event: "bestBlockChanged", bestBlockHash: item.value.bestBlockHash };
|
|
133
|
+
case "Finalized":
|
|
134
|
+
return {
|
|
135
|
+
event: "finalized",
|
|
136
|
+
finalizedBlockHashes: item.value.finalizedBlockHashes,
|
|
137
|
+
prunedBlockHashes: item.value.prunedBlockHashes
|
|
138
|
+
};
|
|
139
|
+
case "OperationBodyDone":
|
|
140
|
+
return {
|
|
141
|
+
event: "operationBodyDone",
|
|
142
|
+
operationId: item.value.operationId,
|
|
143
|
+
value: item.value.value
|
|
144
|
+
};
|
|
145
|
+
case "OperationCallDone":
|
|
146
|
+
return {
|
|
147
|
+
event: "operationCallDone",
|
|
148
|
+
operationId: item.value.operationId,
|
|
149
|
+
output: item.value.output
|
|
150
|
+
};
|
|
151
|
+
case "OperationStorageItems":
|
|
152
|
+
return {
|
|
153
|
+
event: "operationStorageItems",
|
|
154
|
+
operationId: item.value.operationId,
|
|
155
|
+
items: item.value.items
|
|
156
|
+
};
|
|
157
|
+
case "OperationStorageDone":
|
|
158
|
+
return { event: "operationStorageDone", operationId: item.value.operationId };
|
|
159
|
+
case "OperationWaitingForContinue":
|
|
160
|
+
return { event: "operationWaitingForContinue", operationId: item.value.operationId };
|
|
161
|
+
case "OperationInaccessible":
|
|
162
|
+
return { event: "operationInaccessible", operationId: item.value.operationId };
|
|
163
|
+
case "OperationError":
|
|
164
|
+
return {
|
|
165
|
+
event: "operationError",
|
|
166
|
+
operationId: item.value.operationId,
|
|
167
|
+
error: item.value.error
|
|
168
|
+
};
|
|
169
|
+
case "Stop":
|
|
170
|
+
return { event: "stop" };
|
|
171
|
+
default: {
|
|
172
|
+
return { event: "stop" };
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function convertStorageType(type) {
|
|
177
|
+
return STORAGE_TYPE_MAP[type] ?? "Value";
|
|
178
|
+
}
|
|
179
|
+
function convertOperationResultToJsonRpc(result) {
|
|
180
|
+
if (result.tag === "Started") {
|
|
181
|
+
return { result: "started", operationId: result.value.operationId };
|
|
182
|
+
}
|
|
183
|
+
return { result: "limitReached" };
|
|
184
|
+
}
|
|
185
|
+
function createHostPapiProvider(client, genesisHash) {
|
|
186
|
+
const chain = client.chain;
|
|
187
|
+
return (onMessage) => {
|
|
188
|
+
const activeFollows = /* @__PURE__ */ new Map();
|
|
189
|
+
const activeBroadcasts = /* @__PURE__ */ new Set();
|
|
190
|
+
let nextSubId = 0;
|
|
191
|
+
const getNextSubId = () => `follow_${nextSubId++}`;
|
|
192
|
+
function sendJsonRpcResponse(id, result) {
|
|
193
|
+
onMessage({ jsonrpc: "2.0", id, result });
|
|
194
|
+
}
|
|
195
|
+
function sendJsonRpcError(id, code, message) {
|
|
196
|
+
onMessage({ jsonrpc: "2.0", id, error: { code, message } });
|
|
197
|
+
}
|
|
198
|
+
function sendFollowEvent(subscription, event) {
|
|
199
|
+
onMessage({
|
|
200
|
+
jsonrpc: "2.0",
|
|
201
|
+
method: "chainHead_v1_followEvent",
|
|
202
|
+
params: { subscription, result: event }
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
const hostError = (id) => (error) => sendJsonRpcError(id, JSON_RPC_INTERNAL_ERROR, formatHostError(error));
|
|
206
|
+
function handleMessage(message) {
|
|
207
|
+
const { id, method } = message;
|
|
208
|
+
const params = message.params ?? [];
|
|
209
|
+
switch (method) {
|
|
210
|
+
case "chainHead_v1_follow": {
|
|
211
|
+
const [withRuntime] = params;
|
|
212
|
+
const syntheticSubId = getNextSubId();
|
|
213
|
+
const ref = {};
|
|
214
|
+
ref.handle = subscribeWithInterrupt(
|
|
215
|
+
chain.followHeadSubscribe({ request: { genesisHash, withRuntime } }),
|
|
216
|
+
(item) => {
|
|
217
|
+
if (item.tag === "Stop" && activeFollows.delete(syntheticSubId)) {
|
|
218
|
+
ref.handle?.unsubscribe();
|
|
219
|
+
}
|
|
220
|
+
sendFollowEvent(syntheticSubId, convertFollowEventToJsonRpc(item));
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
ref.handle.onInterrupt(() => {
|
|
224
|
+
if (activeFollows.delete(syntheticSubId)) {
|
|
225
|
+
sendFollowEvent(syntheticSubId, { event: "stop" });
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
activeFollows.set(syntheticSubId, ref.handle);
|
|
229
|
+
sendJsonRpcResponse(id, syntheticSubId);
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
case "chainHead_v1_unfollow": {
|
|
233
|
+
const [followSubId] = params;
|
|
234
|
+
const follow = activeFollows.get(followSubId);
|
|
235
|
+
if (follow) {
|
|
236
|
+
follow.unsubscribe();
|
|
237
|
+
activeFollows.delete(followSubId);
|
|
238
|
+
}
|
|
239
|
+
sendJsonRpcResponse(id, null);
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case "chainHead_v1_header": {
|
|
243
|
+
const [followSubscriptionId, hash] = params;
|
|
244
|
+
chain.getHeadHeader({ genesisHash, followSubscriptionId, hash }).match(
|
|
245
|
+
(response) => sendJsonRpcResponse(id, response.header ?? null),
|
|
246
|
+
hostError(id)
|
|
247
|
+
);
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
case "chainHead_v1_body": {
|
|
251
|
+
const [followSubscriptionId, hash] = params;
|
|
252
|
+
chain.getHeadBody({ genesisHash, followSubscriptionId, hash }).match(
|
|
253
|
+
(response) => sendJsonRpcResponse(
|
|
254
|
+
id,
|
|
255
|
+
convertOperationResultToJsonRpc(response.operation)
|
|
256
|
+
),
|
|
257
|
+
hostError(id)
|
|
258
|
+
);
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
case "chainHead_v1_storage": {
|
|
262
|
+
const [followSubscriptionId, hash, items, childTrie] = params;
|
|
263
|
+
const queryItems = items.map((item) => ({
|
|
264
|
+
key: item.key,
|
|
265
|
+
queryType: convertStorageType(item.type)
|
|
266
|
+
}));
|
|
267
|
+
chain.getHeadStorage({
|
|
268
|
+
genesisHash,
|
|
269
|
+
followSubscriptionId,
|
|
270
|
+
hash,
|
|
271
|
+
items: queryItems,
|
|
272
|
+
// PAPI passes `null` for an absent child trie, but the
|
|
273
|
+
// truapi codec encodes the optional `childTrie` field as
|
|
274
|
+
// `Option<Hex>` — it treats `undefined` as None yet runs
|
|
275
|
+
// the inner Hex codec on `null`, which throws
|
|
276
|
+
// (`null.startsWith`). Coerce `null` → `undefined`.
|
|
277
|
+
childTrie: childTrie ?? void 0
|
|
278
|
+
}).match(
|
|
279
|
+
(response) => sendJsonRpcResponse(
|
|
280
|
+
id,
|
|
281
|
+
convertOperationResultToJsonRpc(response.operation)
|
|
282
|
+
),
|
|
283
|
+
hostError(id)
|
|
284
|
+
);
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
case "chainHead_v1_call": {
|
|
288
|
+
const [followSubscriptionId, hash, fn, callParameters] = params;
|
|
289
|
+
chain.callHead({
|
|
290
|
+
genesisHash,
|
|
291
|
+
followSubscriptionId,
|
|
292
|
+
hash,
|
|
293
|
+
function: fn,
|
|
294
|
+
callParameters
|
|
295
|
+
}).match(
|
|
296
|
+
(response) => sendJsonRpcResponse(
|
|
297
|
+
id,
|
|
298
|
+
convertOperationResultToJsonRpc(response.operation)
|
|
299
|
+
),
|
|
300
|
+
hostError(id)
|
|
301
|
+
);
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
case "chainHead_v1_unpin": {
|
|
305
|
+
const [followSubscriptionId, hashOrHashes] = params;
|
|
306
|
+
const hashes = Array.isArray(hashOrHashes) ? hashOrHashes : [hashOrHashes];
|
|
307
|
+
chain.unpinHead({ genesisHash, followSubscriptionId, hashes }).match(() => sendJsonRpcResponse(id, null), hostError(id));
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
case "chainHead_v1_continue": {
|
|
311
|
+
const [followSubscriptionId, operationId] = params;
|
|
312
|
+
chain.continueHead({ genesisHash, followSubscriptionId, operationId }).match(() => sendJsonRpcResponse(id, null), hostError(id));
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
case "chainHead_v1_stopOperation": {
|
|
316
|
+
const [followSubscriptionId, operationId] = params;
|
|
317
|
+
chain.stopHeadOperation({ genesisHash, followSubscriptionId, operationId }).match(() => sendJsonRpcResponse(id, null), hostError(id));
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
case "chainSpec_v1_genesisHash": {
|
|
321
|
+
chain.getSpecGenesisHash({ genesisHash }).match(
|
|
322
|
+
(response) => sendJsonRpcResponse(id, response.genesisHash),
|
|
323
|
+
hostError(id)
|
|
324
|
+
);
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
case "chainSpec_v1_chainName": {
|
|
328
|
+
chain.getSpecChainName({ genesisHash }).match(
|
|
329
|
+
(response) => sendJsonRpcResponse(id, response.chainName),
|
|
330
|
+
hostError(id)
|
|
331
|
+
);
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
case "chainSpec_v1_properties": {
|
|
335
|
+
chain.getSpecProperties({ genesisHash }).match((response) => {
|
|
336
|
+
try {
|
|
337
|
+
sendJsonRpcResponse(id, JSON.parse(response.properties));
|
|
338
|
+
} catch {
|
|
339
|
+
sendJsonRpcResponse(id, response.properties);
|
|
340
|
+
}
|
|
341
|
+
}, hostError(id));
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
case "transaction_v1_broadcast": {
|
|
345
|
+
const [transaction] = params;
|
|
346
|
+
chain.broadcastTransaction({ genesisHash, transaction }).match((response) => {
|
|
347
|
+
const operationId = response.operationId ?? null;
|
|
348
|
+
if (operationId !== null) activeBroadcasts.add(operationId);
|
|
349
|
+
sendJsonRpcResponse(id, operationId);
|
|
350
|
+
}, hostError(id));
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
case "transaction_v1_stop": {
|
|
354
|
+
const [operationId] = params;
|
|
355
|
+
activeBroadcasts.delete(operationId);
|
|
356
|
+
chain.stopTransaction({ genesisHash, operationId }).match(() => sendJsonRpcResponse(id, null), hostError(id));
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
default:
|
|
360
|
+
sendJsonRpcError(
|
|
361
|
+
id,
|
|
362
|
+
JSON_RPC_METHOD_NOT_FOUND,
|
|
363
|
+
`Method "${method}" is not supported by the host`
|
|
364
|
+
);
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
send(message) {
|
|
370
|
+
try {
|
|
371
|
+
handleMessage(message);
|
|
372
|
+
} catch (error) {
|
|
373
|
+
log.warn("send: handler threw before settling the request", {
|
|
374
|
+
error: formatHostError(error)
|
|
375
|
+
});
|
|
376
|
+
sendJsonRpcError(message.id, JSON_RPC_INTERNAL_ERROR, formatHostError(error));
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
disconnect() {
|
|
380
|
+
for (const handle of activeFollows.values()) {
|
|
381
|
+
handle.unsubscribe();
|
|
382
|
+
}
|
|
383
|
+
activeFollows.clear();
|
|
384
|
+
for (const operationId of activeBroadcasts) {
|
|
385
|
+
chain.stopTransaction({ genesisHash, operationId }).match(
|
|
386
|
+
() => {
|
|
387
|
+
},
|
|
388
|
+
() => {
|
|
389
|
+
}
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
activeBroadcasts.clear();
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// src/result.ts
|
|
399
|
+
function ok(value) {
|
|
400
|
+
return { ok: true, value };
|
|
401
|
+
}
|
|
402
|
+
function err(error) {
|
|
403
|
+
return { ok: false, error };
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/truapi.ts
|
|
407
|
+
var log2 = createLogger("host");
|
|
408
|
+
function unwrapHostResult(result, label) {
|
|
409
|
+
return result.match(
|
|
410
|
+
(value) => value,
|
|
411
|
+
(error) => {
|
|
412
|
+
throw new Error(`${label}: ${formatHostError(error)}`, { cause: error });
|
|
413
|
+
}
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
function mapHostResult(result, map, label) {
|
|
417
|
+
return result.match(
|
|
418
|
+
(value) => ok(map(value)),
|
|
419
|
+
(error) => err(new HostCallFailedError(label, error))
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
function toHex(bytes) {
|
|
423
|
+
return scale.bytesToHex(bytes);
|
|
424
|
+
}
|
|
425
|
+
function fromHex(hex) {
|
|
426
|
+
return scale.hexToBytes(hex);
|
|
427
|
+
}
|
|
428
|
+
async function getTruApi() {
|
|
429
|
+
return getClient();
|
|
430
|
+
}
|
|
431
|
+
function adaptPreimageManager(client) {
|
|
432
|
+
const preimage = client.preimage;
|
|
433
|
+
return {
|
|
434
|
+
lookup(key, callback) {
|
|
435
|
+
return subscribeWithInterrupt(
|
|
436
|
+
preimage.lookupSubscribe({ request: { key } }),
|
|
437
|
+
(item) => callback(item.value !== void 0 ? fromHex(item.value) : null)
|
|
438
|
+
);
|
|
439
|
+
},
|
|
440
|
+
submit(value) {
|
|
441
|
+
return unwrapHostResult(preimage.submit(toHex(value)), "preimage submit failed");
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
async function getPreimageManager() {
|
|
446
|
+
const client = await getClient();
|
|
447
|
+
return client ? adaptPreimageManager(client) : null;
|
|
448
|
+
}
|
|
449
|
+
async function createHostPreimageManager() {
|
|
450
|
+
return getPreimageManager();
|
|
451
|
+
}
|
|
452
|
+
async function requestResourceAllocation(resources) {
|
|
453
|
+
const truApi = await getTruApi();
|
|
454
|
+
if (!truApi) {
|
|
455
|
+
return err(new HostUnavailableError("requestResourceAllocation: TruAPI unavailable"));
|
|
456
|
+
}
|
|
457
|
+
log2.debug("requestResourceAllocation", { resources: resources.map((r) => r.tag) });
|
|
458
|
+
return mapHostResult(
|
|
459
|
+
truApi.resourceAllocation.request({ resources }),
|
|
460
|
+
(response) => response.outcomes,
|
|
461
|
+
"requestResourceAllocation failed"
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
async function createProofAuthorized(statement) {
|
|
465
|
+
const truApi = await getTruApi();
|
|
466
|
+
if (!truApi) {
|
|
467
|
+
return err(new HostUnavailableError("createProofAuthorized: TruAPI unavailable"));
|
|
468
|
+
}
|
|
469
|
+
log2.debug("createProofAuthorized", { topics: statement.topics.length });
|
|
470
|
+
return mapHostResult(
|
|
471
|
+
truApi.statementStore.createProofAuthorized(statement),
|
|
472
|
+
(response) => response.proof,
|
|
473
|
+
"createProofAuthorized failed"
|
|
474
|
+
);
|
|
475
|
+
}
|
|
4
476
|
|
|
5
477
|
// src/container.ts
|
|
6
|
-
var
|
|
478
|
+
var textEncoder = new TextEncoder();
|
|
479
|
+
var textDecoder = new TextDecoder();
|
|
7
480
|
var ChainNotSupportedError = class extends Error {
|
|
8
481
|
/** Genesis hash of the chain the host refused, for programmatic detection. */
|
|
9
482
|
genesisHash;
|
|
@@ -15,93 +488,90 @@ var ChainNotSupportedError = class extends Error {
|
|
|
15
488
|
this.genesisHash = genesisHash;
|
|
16
489
|
}
|
|
17
490
|
};
|
|
18
|
-
async function isChainSupportedByHost(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const result = await sdk.hostApi.featureSupported(
|
|
26
|
-
enumValue("v1", enumValue("Chain", genesisHash))
|
|
27
|
-
);
|
|
28
|
-
return result.match(
|
|
29
|
-
(ok) => ok.value === true,
|
|
30
|
-
(err) => {
|
|
31
|
-
const value = err?.value;
|
|
32
|
-
const reason = value?.payload?.reason ?? value?.reason ?? "unknown reason";
|
|
33
|
-
throw new Error(`Host rejected the chain-support check for ${genesisHash}: ${reason}`);
|
|
491
|
+
async function isChainSupportedByHost(client, genesisHash) {
|
|
492
|
+
return client.system.featureSupported({ tag: "Chain", value: { genesisHash } }).match(
|
|
493
|
+
(response) => response.supported,
|
|
494
|
+
(error) => {
|
|
495
|
+
throw new Error(
|
|
496
|
+
`Host rejected the chain-support check for ${genesisHash}: ${formatHostError(error)}`
|
|
497
|
+
);
|
|
34
498
|
}
|
|
35
499
|
);
|
|
36
500
|
}
|
|
37
501
|
async function isInsideContainer() {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
502
|
+
return isCorrectEnvironment();
|
|
503
|
+
}
|
|
504
|
+
function adaptLocalStorage(client) {
|
|
505
|
+
const ls = client.localStorage;
|
|
506
|
+
async function readBytes(key) {
|
|
507
|
+
const response = await unwrapHostResult(ls.read({ key }), "host localStorage read failed");
|
|
508
|
+
return response.value !== void 0 ? fromHex(response.value) : void 0;
|
|
44
509
|
}
|
|
510
|
+
async function writeBytes(key, value) {
|
|
511
|
+
await unwrapHostResult(
|
|
512
|
+
ls.write({ key, value: toHex(value) }),
|
|
513
|
+
"host localStorage write failed"
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
async function readString(key) {
|
|
517
|
+
const bytes = await readBytes(key);
|
|
518
|
+
return bytes ? textDecoder.decode(bytes) : "";
|
|
519
|
+
}
|
|
520
|
+
async function writeString(key, value) {
|
|
521
|
+
return writeBytes(key, textEncoder.encode(value));
|
|
522
|
+
}
|
|
523
|
+
async function readJSON(key) {
|
|
524
|
+
const text = await readString(key);
|
|
525
|
+
return text ? JSON.parse(text) : null;
|
|
526
|
+
}
|
|
527
|
+
async function writeJSON(key, value) {
|
|
528
|
+
return writeString(key, JSON.stringify(value));
|
|
529
|
+
}
|
|
530
|
+
async function clear(key) {
|
|
531
|
+
await unwrapHostResult(ls.clear({ key }), "host localStorage clear failed");
|
|
532
|
+
}
|
|
533
|
+
return { readString, writeString, readJSON, writeJSON, readBytes, writeBytes, clear };
|
|
45
534
|
}
|
|
46
535
|
async function getHostLocalStorage() {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const sdk = await import('@novasamatech/host-api-wrapper');
|
|
50
|
-
return sdk.hostLocalStorage;
|
|
51
|
-
} catch (err) {
|
|
52
|
-
log.debug("getHostLocalStorage unavailable", err);
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
536
|
+
const client = await getClient();
|
|
537
|
+
return client ? adaptLocalStorage(client) : null;
|
|
55
538
|
}
|
|
56
|
-
async function createHostLocalStorage(
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
const sdk = await import('@novasamatech/host-api-wrapper');
|
|
60
|
-
return sdk.createLocalStorage(transport);
|
|
61
|
-
} catch (err) {
|
|
62
|
-
log.debug("createHostLocalStorage unavailable", err);
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
539
|
+
async function createHostLocalStorage() {
|
|
540
|
+
return getHostLocalStorage();
|
|
65
541
|
}
|
|
66
542
|
async function getHostProvider(genesisHash) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} catch (err) {
|
|
71
|
-
log.debug("getHostProvider unavailable", err);
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
return resolveHostProvider(sdk, genesisHash);
|
|
543
|
+
const client = await getClient();
|
|
544
|
+
if (!client) return null;
|
|
545
|
+
return resolveHostProvider(client, genesisHash);
|
|
75
546
|
}
|
|
76
|
-
async function resolveHostProvider(
|
|
77
|
-
if (!
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
if (!await isChainSupportedByHost(sdk, genesisHash)) {
|
|
547
|
+
async function resolveHostProvider(client, genesisHash) {
|
|
548
|
+
if (!await isChainSupportedByHost(client, genesisHash)) {
|
|
81
549
|
throw new ChainNotSupportedError(genesisHash);
|
|
82
550
|
}
|
|
83
|
-
return
|
|
551
|
+
return createHostPapiProvider(client, genesisHash);
|
|
84
552
|
}
|
|
85
|
-
function
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
553
|
+
function adaptStatementStore(client) {
|
|
554
|
+
const ss = client.statementStore;
|
|
555
|
+
return {
|
|
556
|
+
subscribe(filter, callback) {
|
|
557
|
+
const request = "matchAll" in filter ? { tag: "MatchAll", value: filter.matchAll } : { tag: "MatchAny", value: filter.matchAny };
|
|
558
|
+
return subscribeWithInterrupt(ss.subscribe({ request }), callback);
|
|
559
|
+
},
|
|
560
|
+
async createProofAuthorized(statement) {
|
|
561
|
+
const response = await unwrapHostResult(
|
|
562
|
+
ss.createProofAuthorized(statement),
|
|
563
|
+
"createProofAuthorized failed"
|
|
564
|
+
);
|
|
565
|
+
return response.proof;
|
|
566
|
+
},
|
|
567
|
+
async submit(signedStatement) {
|
|
568
|
+
await unwrapHostResult(ss.submit(signedStatement), "statement submit failed");
|
|
569
|
+
}
|
|
570
|
+
};
|
|
96
571
|
}
|
|
97
572
|
async function getStatementStore() {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return sdk.createStatementStore();
|
|
101
|
-
} catch (err) {
|
|
102
|
-
log.debug("getStatementStore unavailable", err);
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
573
|
+
const client = await getClient();
|
|
574
|
+
return client ? adaptStatementStore(client) : null;
|
|
105
575
|
}
|
|
106
576
|
|
|
107
577
|
// src/chains.ts
|
|
@@ -112,191 +582,392 @@ var BULLETIN_RPCS = {
|
|
|
112
582
|
kusama: []
|
|
113
583
|
};
|
|
114
584
|
var DEFAULT_BULLETIN_ENDPOINT = BULLETIN_RPCS.paseo[0];
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (typeof inner === "string") return inner;
|
|
120
|
-
if (inner != null && typeof inner === "object" && "message" in inner && typeof inner.message === "string") {
|
|
121
|
-
const named = inner;
|
|
122
|
-
return typeof named.name === "string" ? `${named.name}: ${named.message}` : named.message;
|
|
123
|
-
}
|
|
124
|
-
try {
|
|
125
|
-
return JSON.stringify(inner);
|
|
126
|
-
} catch {
|
|
127
|
-
return String(inner);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
function isVersionedEnvelope(value) {
|
|
131
|
-
return value != null && typeof value === "object" && "tag" in value && "value" in value && typeof value.tag === "string";
|
|
132
|
-
}
|
|
133
|
-
var cachedTruApi = null;
|
|
134
|
-
async function getTruApi() {
|
|
135
|
-
if (cachedTruApi) return cachedTruApi;
|
|
136
|
-
try {
|
|
137
|
-
const sdk = await import('@novasamatech/host-api-wrapper');
|
|
138
|
-
cachedTruApi = sdk.hostApi;
|
|
139
|
-
log2.debug("TruAPI loaded");
|
|
140
|
-
return cachedTruApi;
|
|
141
|
-
} catch {
|
|
142
|
-
log2.debug("TruAPI unavailable (not in container or SDK not installed)");
|
|
143
|
-
return null;
|
|
585
|
+
function deriveTxExtVersion(metadata) {
|
|
586
|
+
const versions = unifyMetadata(decAnyMetadata(metadata)).extrinsic.version;
|
|
587
|
+
if (versions.length === 0) {
|
|
588
|
+
throw new Error("No extrinsic version found in metadata");
|
|
144
589
|
}
|
|
590
|
+
const latestVersion = versions.reduce((acc, v) => Math.max(acc, v), 0);
|
|
591
|
+
return latestVersion === 4 ? 0 : latestVersion;
|
|
145
592
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
593
|
+
var deps = { deriveTxExtVersion };
|
|
594
|
+
function toHostExtensions(signedExtensions) {
|
|
595
|
+
return Object.values(signedExtensions).map((ext) => ({
|
|
596
|
+
id: ext.identifier,
|
|
597
|
+
extra: toHex(ext.value),
|
|
598
|
+
additionalSigned: toHex(ext.additionalSigned)
|
|
599
|
+
}));
|
|
154
600
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
601
|
+
function adaptAccountsProvider(client) {
|
|
602
|
+
const account = client.account;
|
|
603
|
+
const signing = client.signing;
|
|
604
|
+
return {
|
|
605
|
+
getUserId() {
|
|
606
|
+
return account.getUserId().map((response) => ({
|
|
607
|
+
primaryUsername: response.primaryUsername
|
|
608
|
+
}));
|
|
609
|
+
},
|
|
610
|
+
requestLogin(reason) {
|
|
611
|
+
return account.requestLogin({ reason });
|
|
612
|
+
},
|
|
613
|
+
getProductAccount(dotNsIdentifier, derivationIndex = 0) {
|
|
614
|
+
return account.getAccount({ productAccountId: { dotNsIdentifier, derivationIndex } }).map((response) => ({
|
|
615
|
+
publicKey: fromHex(response.account.publicKey),
|
|
616
|
+
dotNsIdentifier,
|
|
617
|
+
derivationIndex
|
|
618
|
+
}));
|
|
619
|
+
},
|
|
620
|
+
getProductAccountAlias(dotNsIdentifier, derivationIndex = 0) {
|
|
621
|
+
return account.getAccountAlias({ productAccountId: { dotNsIdentifier, derivationIndex } }).map((response) => ({
|
|
622
|
+
context: fromHex(response.context),
|
|
623
|
+
alias: fromHex(response.alias)
|
|
624
|
+
}));
|
|
625
|
+
},
|
|
626
|
+
getLegacyAccounts() {
|
|
627
|
+
return account.getLegacyAccounts().map(
|
|
628
|
+
(response) => response.accounts.map((a) => ({
|
|
629
|
+
publicKey: fromHex(a.publicKey),
|
|
630
|
+
name: a.name
|
|
631
|
+
}))
|
|
632
|
+
);
|
|
633
|
+
},
|
|
634
|
+
createRingVRFProof(dotNsIdentifier, derivationIndex, location, message) {
|
|
635
|
+
return account.createAccountProof({
|
|
636
|
+
productAccountId: { dotNsIdentifier, derivationIndex },
|
|
637
|
+
ringLocation: location,
|
|
638
|
+
context: toHex(message)
|
|
639
|
+
}).map((response) => fromHex(response.proof));
|
|
640
|
+
},
|
|
641
|
+
getProductAccountSigner(account_) {
|
|
642
|
+
const productAccountId = {
|
|
643
|
+
dotNsIdentifier: account_.dotNsIdentifier,
|
|
644
|
+
derivationIndex: account_.derivationIndex
|
|
645
|
+
};
|
|
646
|
+
return {
|
|
647
|
+
publicKey: account_.publicKey,
|
|
648
|
+
async signTx(callData, signedExtensions, metadata) {
|
|
649
|
+
const checkGenesis = signedExtensions.CheckGenesis;
|
|
650
|
+
if (!checkGenesis) {
|
|
651
|
+
throw new Error("Can't find genesis hash on transaction");
|
|
652
|
+
}
|
|
653
|
+
const response = await unwrapHostResult(
|
|
654
|
+
signing.createTransaction({
|
|
655
|
+
signer: productAccountId,
|
|
656
|
+
genesisHash: toHex(checkGenesis.additionalSigned),
|
|
657
|
+
callData: toHex(callData),
|
|
658
|
+
extensions: toHostExtensions(signedExtensions),
|
|
659
|
+
txExtVersion: deps.deriveTxExtVersion(metadata)
|
|
660
|
+
}),
|
|
661
|
+
"createTransaction failed"
|
|
662
|
+
);
|
|
663
|
+
return fromHex(response.transaction);
|
|
664
|
+
},
|
|
665
|
+
async signBytes(data) {
|
|
666
|
+
const response = await unwrapHostResult(
|
|
667
|
+
signing.signRaw({
|
|
668
|
+
account: productAccountId,
|
|
669
|
+
payload: { tag: "Bytes", value: { bytes: toHex(data) } }
|
|
670
|
+
}),
|
|
671
|
+
"signRaw failed"
|
|
672
|
+
);
|
|
673
|
+
return fromHex(response.signature);
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
},
|
|
677
|
+
getLegacyAccountSigner(account_) {
|
|
678
|
+
const signerHex = toHex(account_.publicKey);
|
|
679
|
+
const ss58Address = AccountId().dec(account_.publicKey);
|
|
680
|
+
return {
|
|
681
|
+
publicKey: account_.publicKey,
|
|
682
|
+
async signTx(callData, signedExtensions, metadata) {
|
|
683
|
+
const checkGenesis = signedExtensions.CheckGenesis;
|
|
684
|
+
if (!checkGenesis) {
|
|
685
|
+
throw new Error("Can't find genesis hash on transaction");
|
|
686
|
+
}
|
|
687
|
+
const response = await unwrapHostResult(
|
|
688
|
+
signing.createTransactionWithLegacyAccount({
|
|
689
|
+
signer: signerHex,
|
|
690
|
+
genesisHash: toHex(checkGenesis.additionalSigned),
|
|
691
|
+
callData: toHex(callData),
|
|
692
|
+
extensions: toHostExtensions(signedExtensions),
|
|
693
|
+
txExtVersion: deps.deriveTxExtVersion(metadata)
|
|
694
|
+
}),
|
|
695
|
+
"createTransactionWithLegacyAccount failed"
|
|
696
|
+
);
|
|
697
|
+
return fromHex(response.transaction);
|
|
698
|
+
},
|
|
699
|
+
async signBytes(data) {
|
|
700
|
+
const response = await unwrapHostResult(
|
|
701
|
+
signing.signRawWithLegacyAccount({
|
|
702
|
+
signer: ss58Address,
|
|
703
|
+
payload: { tag: "Bytes", value: { bytes: toHex(data) } }
|
|
704
|
+
}),
|
|
705
|
+
"signRawWithLegacyAccount failed"
|
|
706
|
+
);
|
|
707
|
+
return fromHex(response.signature);
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
},
|
|
711
|
+
subscribeAccountConnectionStatus(callback) {
|
|
712
|
+
return subscribeWithInterrupt(account.connectionStatusSubscribe(), callback);
|
|
186
713
|
}
|
|
187
|
-
|
|
714
|
+
};
|
|
188
715
|
}
|
|
189
|
-
async function
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
throw new Error("createProofAuthorized: TruAPI unavailable");
|
|
193
|
-
}
|
|
194
|
-
log2.debug("createProofAuthorized", {
|
|
195
|
-
topics: statement.topics.length,
|
|
196
|
-
dataLen: statement.data?.length ?? 0
|
|
197
|
-
});
|
|
198
|
-
return await truApi.statementStoreCreateProofAuthorized(enumValue("v1", statement)).match(
|
|
199
|
-
(envelope) => envelope.value,
|
|
200
|
-
(err) => {
|
|
201
|
-
throw new Error(`createProofAuthorized failed: ${formatHostError(err)}`, {
|
|
202
|
-
cause: err
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
);
|
|
716
|
+
async function getAccountsProvider() {
|
|
717
|
+
const client = await getClient();
|
|
718
|
+
return client ? adaptAccountsProvider(client) : null;
|
|
206
719
|
}
|
|
207
720
|
var log3 = createLogger("host:permissions");
|
|
208
721
|
async function requestPermission(permission) {
|
|
209
722
|
const truApi = await getTruApi();
|
|
210
723
|
if (!truApi) {
|
|
211
|
-
|
|
724
|
+
return err(new HostUnavailableError("requestPermission: TruAPI unavailable"));
|
|
212
725
|
}
|
|
213
726
|
log3.debug("requestPermission", { tag: permission.tag });
|
|
214
|
-
return
|
|
215
|
-
(
|
|
216
|
-
(
|
|
217
|
-
|
|
218
|
-
}
|
|
727
|
+
return mapHostResult(
|
|
728
|
+
truApi.permissions.requestRemotePermission({ permission }),
|
|
729
|
+
(response) => response.granted,
|
|
730
|
+
"requestPermission failed"
|
|
219
731
|
);
|
|
220
732
|
}
|
|
221
733
|
async function requestDevicePermission(permission) {
|
|
222
734
|
const truApi = await getTruApi();
|
|
223
735
|
if (!truApi) {
|
|
224
|
-
|
|
736
|
+
return err(new HostUnavailableError("requestDevicePermission: TruAPI unavailable"));
|
|
225
737
|
}
|
|
226
738
|
log3.debug("requestDevicePermission", { permission });
|
|
227
|
-
return
|
|
228
|
-
(
|
|
229
|
-
(
|
|
230
|
-
|
|
231
|
-
cause: err
|
|
232
|
-
});
|
|
233
|
-
}
|
|
739
|
+
return mapHostResult(
|
|
740
|
+
truApi.permissions.requestDevicePermission(permission),
|
|
741
|
+
(response) => response.granted,
|
|
742
|
+
"requestDevicePermission failed"
|
|
234
743
|
);
|
|
235
744
|
}
|
|
236
|
-
|
|
745
|
+
|
|
746
|
+
// src/theme.ts
|
|
747
|
+
function adaptThemeProvider(client) {
|
|
748
|
+
return {
|
|
749
|
+
subscribeTheme(callback) {
|
|
750
|
+
return subscribeWithInterrupt(client.theme.subscribe(), callback);
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
}
|
|
237
754
|
async function getThemeProvider() {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return sdk.createThemeProvider();
|
|
241
|
-
} catch (err) {
|
|
242
|
-
log4.debug("getThemeProvider unavailable", err);
|
|
243
|
-
return null;
|
|
244
|
-
}
|
|
755
|
+
const client = await getClient();
|
|
756
|
+
return client ? adaptThemeProvider(client) : null;
|
|
245
757
|
}
|
|
246
|
-
var
|
|
758
|
+
var log4 = createLogger("host:entropy");
|
|
247
759
|
async function deriveEntropy(key) {
|
|
248
760
|
const truApi = await getTruApi();
|
|
249
761
|
if (!truApi) {
|
|
250
|
-
|
|
762
|
+
return err(new HostUnavailableError("deriveEntropy: TruAPI unavailable"));
|
|
251
763
|
}
|
|
252
|
-
|
|
253
|
-
return
|
|
254
|
-
(
|
|
255
|
-
(
|
|
256
|
-
|
|
257
|
-
}
|
|
764
|
+
log4.debug("deriveEntropy", { keyLen: key.length });
|
|
765
|
+
return mapHostResult(
|
|
766
|
+
truApi.entropy.derive({ context: toHex(key) }),
|
|
767
|
+
(response) => fromHex(response.entropy),
|
|
768
|
+
"deriveEntropy failed"
|
|
258
769
|
);
|
|
259
770
|
}
|
|
260
|
-
|
|
771
|
+
|
|
772
|
+
// src/chat.ts
|
|
773
|
+
function adaptChatManager(client) {
|
|
774
|
+
const chat = client.chat;
|
|
775
|
+
const roomStatus = /* @__PURE__ */ new Map();
|
|
776
|
+
const botStatus = /* @__PURE__ */ new Map();
|
|
777
|
+
return {
|
|
778
|
+
async registerRoom(request) {
|
|
779
|
+
const cached = roomStatus.get(request.roomId);
|
|
780
|
+
if (cached) return cached;
|
|
781
|
+
const response = await unwrapHostResult(
|
|
782
|
+
chat.createRoom(request),
|
|
783
|
+
"chat registerRoom failed"
|
|
784
|
+
);
|
|
785
|
+
roomStatus.set(request.roomId, response.status);
|
|
786
|
+
return response.status;
|
|
787
|
+
},
|
|
788
|
+
async registerBot(request) {
|
|
789
|
+
const cached = botStatus.get(request.botId);
|
|
790
|
+
if (cached) return cached;
|
|
791
|
+
const response = await unwrapHostResult(
|
|
792
|
+
chat.registerBot(request),
|
|
793
|
+
"chat registerBot failed"
|
|
794
|
+
);
|
|
795
|
+
botStatus.set(request.botId, response.status);
|
|
796
|
+
return response.status;
|
|
797
|
+
},
|
|
798
|
+
async sendMessage(roomId, payload) {
|
|
799
|
+
const response = await unwrapHostResult(
|
|
800
|
+
chat.postMessage({ roomId, payload }),
|
|
801
|
+
"chat sendMessage failed"
|
|
802
|
+
);
|
|
803
|
+
return { messageId: response.messageId };
|
|
804
|
+
},
|
|
805
|
+
subscribeChatList(callback) {
|
|
806
|
+
return subscribeWithInterrupt(chat.listSubscribe(), (item) => callback(item.rooms));
|
|
807
|
+
},
|
|
808
|
+
subscribeAction(callback) {
|
|
809
|
+
return subscribeWithInterrupt(chat.actionSubscribe(), callback);
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
}
|
|
261
813
|
async function getChatManager() {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return sdk.createProductChatManager();
|
|
265
|
-
} catch (err) {
|
|
266
|
-
log6.debug("getChatManager unavailable", err);
|
|
267
|
-
return null;
|
|
268
|
-
}
|
|
814
|
+
const client = await getClient();
|
|
815
|
+
return client ? adaptChatManager(client) : null;
|
|
269
816
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
817
|
+
|
|
818
|
+
// src/payments.ts
|
|
819
|
+
function adaptPaymentManager(client) {
|
|
820
|
+
const payment = client.payment;
|
|
821
|
+
return {
|
|
822
|
+
subscribeBalance(callback, purse) {
|
|
823
|
+
return subscribeWithInterrupt(
|
|
824
|
+
payment.balanceSubscribe({ request: { purse } }),
|
|
825
|
+
callback
|
|
826
|
+
);
|
|
827
|
+
},
|
|
828
|
+
topUp(amount, source, into) {
|
|
829
|
+
return unwrapHostResult(
|
|
830
|
+
payment.topUp({ into, amount, source }),
|
|
831
|
+
"payment topUp failed"
|
|
832
|
+
);
|
|
833
|
+
},
|
|
834
|
+
async requestPayment(amount, destination, from) {
|
|
835
|
+
const response = await unwrapHostResult(
|
|
836
|
+
payment.request({ from, amount, destination }),
|
|
837
|
+
"payment requestPayment failed"
|
|
838
|
+
);
|
|
839
|
+
return { id: response.id };
|
|
840
|
+
},
|
|
841
|
+
subscribePaymentStatus(paymentId, callback) {
|
|
842
|
+
return subscribeWithInterrupt(
|
|
843
|
+
payment.statusSubscribe({ request: { paymentId } }),
|
|
844
|
+
callback
|
|
845
|
+
);
|
|
275
846
|
}
|
|
276
|
-
return renderer(params, render);
|
|
277
847
|
};
|
|
278
848
|
}
|
|
279
|
-
var log7 = createLogger("host:payments");
|
|
280
849
|
async function getPaymentManager() {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
850
|
+
const client = await getClient();
|
|
851
|
+
return client ? adaptPaymentManager(client) : null;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// src/notifications.ts
|
|
855
|
+
function adaptNotificationManager(client) {
|
|
856
|
+
const notifications = client.notifications;
|
|
857
|
+
return {
|
|
858
|
+
async push(input) {
|
|
859
|
+
const response = await unwrapHostResult(
|
|
860
|
+
notifications.sendPushNotification(input),
|
|
861
|
+
"notification push failed"
|
|
862
|
+
);
|
|
863
|
+
return response.id;
|
|
864
|
+
},
|
|
865
|
+
async cancel(id) {
|
|
866
|
+
await unwrapHostResult(
|
|
867
|
+
notifications.cancelPushNotification({ id }),
|
|
868
|
+
"notification cancel failed"
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
};
|
|
288
872
|
}
|
|
289
|
-
var log8 = createLogger("host:notifications");
|
|
290
873
|
async function getNotificationManager() {
|
|
874
|
+
const client = await getClient();
|
|
875
|
+
return client ? adaptNotificationManager(client) : null;
|
|
876
|
+
}
|
|
877
|
+
var log5 = createLogger("host:navigation");
|
|
878
|
+
async function navigateTo(url) {
|
|
879
|
+
const truApi = await getTruApi();
|
|
880
|
+
if (!truApi) {
|
|
881
|
+
return err(new HostUnavailableError("navigateTo: TruAPI unavailable"));
|
|
882
|
+
}
|
|
883
|
+
log5.debug("navigateTo", { url });
|
|
884
|
+
return mapHostResult(truApi.system.navigateTo({ url }), () => void 0, "navigateTo failed");
|
|
885
|
+
}
|
|
886
|
+
var log6 = createLogger("host:features");
|
|
887
|
+
async function featureSupported(feature) {
|
|
888
|
+
const truApi = await getTruApi();
|
|
889
|
+
if (!truApi) {
|
|
890
|
+
return err(new HostUnavailableError("featureSupported: TruAPI unavailable"));
|
|
891
|
+
}
|
|
892
|
+
log6.debug("featureSupported", { tag: feature.tag });
|
|
893
|
+
return mapHostResult(
|
|
894
|
+
truApi.system.featureSupported({ tag: feature.tag, value: { genesisHash: feature.value } }),
|
|
895
|
+
(response) => response.supported,
|
|
896
|
+
"featureSupported failed"
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
async function isChainSupported(genesisHash) {
|
|
900
|
+
return featureSupported({ tag: "Chain", value: genesisHash });
|
|
901
|
+
}
|
|
902
|
+
var log7 = createLogger("host:chain-spec");
|
|
903
|
+
async function getChainSpec(genesisHash) {
|
|
904
|
+
const truApi = await getTruApi();
|
|
905
|
+
if (!truApi) {
|
|
906
|
+
log7.debug("getChainSpec: TruAPI unavailable");
|
|
907
|
+
return ok(null);
|
|
908
|
+
}
|
|
909
|
+
log7.debug("getChainSpec", { genesisHash });
|
|
910
|
+
const [genesisHashResult, nameResult, propertiesResult] = await Promise.all([
|
|
911
|
+
mapHostResult(
|
|
912
|
+
truApi.chain.getSpecGenesisHash({ genesisHash }),
|
|
913
|
+
(response) => response.genesisHash,
|
|
914
|
+
"getChainSpec (genesisHash) failed"
|
|
915
|
+
),
|
|
916
|
+
mapHostResult(
|
|
917
|
+
truApi.chain.getSpecChainName({ genesisHash }),
|
|
918
|
+
(response) => response.chainName,
|
|
919
|
+
"getChainSpec (chainName) failed"
|
|
920
|
+
),
|
|
921
|
+
mapHostResult(
|
|
922
|
+
truApi.chain.getSpecProperties({ genesisHash }),
|
|
923
|
+
(response) => response.properties,
|
|
924
|
+
"getChainSpec (properties) failed"
|
|
925
|
+
)
|
|
926
|
+
]);
|
|
927
|
+
if (!genesisHashResult.ok) return genesisHashResult;
|
|
928
|
+
if (!nameResult.ok) return nameResult;
|
|
929
|
+
if (!propertiesResult.ok) return propertiesResult;
|
|
930
|
+
const propertiesRaw = propertiesResult.value;
|
|
931
|
+
let properties;
|
|
291
932
|
try {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
return null;
|
|
933
|
+
properties = JSON.parse(propertiesRaw);
|
|
934
|
+
} catch (parseError) {
|
|
935
|
+
log7.debug("getChainSpec: properties JSON parse failed", parseError);
|
|
936
|
+
properties = null;
|
|
297
937
|
}
|
|
938
|
+
return ok({
|
|
939
|
+
genesisHash: genesisHashResult.value,
|
|
940
|
+
name: nameResult.value,
|
|
941
|
+
properties,
|
|
942
|
+
propertiesRaw
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
var log8 = createLogger("host:chain-transaction");
|
|
946
|
+
async function broadcastTransaction(genesisHash, transaction) {
|
|
947
|
+
const truApi = await getTruApi();
|
|
948
|
+
if (!truApi) {
|
|
949
|
+
return err(new HostUnavailableError("broadcastTransaction: TruAPI unavailable"));
|
|
950
|
+
}
|
|
951
|
+
log8.debug("broadcastTransaction", { genesisHash });
|
|
952
|
+
return mapHostResult(
|
|
953
|
+
truApi.chain.broadcastTransaction({ genesisHash, transaction }),
|
|
954
|
+
(response) => response.operationId ?? null,
|
|
955
|
+
"broadcastTransaction failed"
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
async function stopTransaction(genesisHash, operationId) {
|
|
959
|
+
const truApi = await getTruApi();
|
|
960
|
+
if (!truApi) {
|
|
961
|
+
return err(new HostUnavailableError("stopTransaction: TruAPI unavailable"));
|
|
962
|
+
}
|
|
963
|
+
log8.debug("stopTransaction", { genesisHash, operationId });
|
|
964
|
+
return mapHostResult(
|
|
965
|
+
truApi.chain.stopTransaction({ genesisHash, operationId }),
|
|
966
|
+
() => void 0,
|
|
967
|
+
"stopTransaction failed"
|
|
968
|
+
);
|
|
298
969
|
}
|
|
299
970
|
|
|
300
|
-
export { BULLETIN_RPCS, ChainNotSupportedError, DEFAULT_BULLETIN_ENDPOINT, createHostLocalStorage, createHostPreimageManager, createProofAuthorized, deriveEntropy, formatHostError, getAccountsProvider, getChatManager, getHostLocalStorage, getHostProvider, getNotificationManager, getPaymentManager, getPreimageManager, getStatementStore, getThemeProvider, getTruApi, isInsideContainer,
|
|
971
|
+
export { BULLETIN_RPCS, ChainNotSupportedError, DEFAULT_BULLETIN_ENDPOINT, HostCallFailedError, HostError, HostUnavailableError, broadcastTransaction, createHostLocalStorage, createHostPreimageManager, createProofAuthorized, deriveEntropy, err, featureSupported, formatHostError, fromHex, getAccountsProvider, getChainSpec, getChatManager, getHostLocalStorage, getHostProvider, getNotificationManager, getPaymentManager, getPreimageManager, getStatementStore, getThemeProvider, getTruApi, isChainSupported, isHostError, isInsideContainer, navigateTo, ok, requestDevicePermission, requestPermission, requestResourceAllocation, stopTransaction, toHex };
|
|
301
972
|
//# sourceMappingURL=index.js.map
|
|
302
973
|
//# sourceMappingURL=index.js.map
|