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