koilib 5.5.3 → 5.5.4
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/package.json +3 -2
- package/src/Contract.ts +614 -0
- package/src/Provider.ts +512 -0
- package/src/Serializer.ts +366 -0
- package/src/Signer.ts +827 -0
- package/src/Transaction.ts +241 -0
- package/src/index.ts +9 -0
- package/src/index2.ts +17 -0
- package/src/indexUtils.ts +2 -0
- package/src/interface.ts +767 -0
- package/src/jsonDescriptors/chain-proto.json +726 -0
- package/src/jsonDescriptors/pow-proto.json +68 -0
- package/src/jsonDescriptors/token-proto.json +255 -0
- package/src/jsonDescriptors/value-proto.json +161 -0
- package/src/protoModules/protocol-proto.js +8138 -0
- package/src/protoModules/value-proto.js +1736 -0
- package/src/utils.ts +533 -0
- package/src/utilsNode.ts +378 -0
package/src/Provider.ts
ADDED
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import fetch from "cross-fetch";
|
|
2
|
+
import {
|
|
3
|
+
BlockJson,
|
|
4
|
+
TransactionJson,
|
|
5
|
+
CallContractOperationJson,
|
|
6
|
+
TransactionReceipt,
|
|
7
|
+
TransactionJsonWait,
|
|
8
|
+
} from "./interface";
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
import { koinos } from "./protoModules/protocol-proto.js";
|
|
12
|
+
import { decodeBase64url, encodeBase64url } from "./utils";
|
|
13
|
+
|
|
14
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
|
|
15
|
+
|
|
16
|
+
async function sleep(ms: number): Promise<void> {
|
|
17
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Class to connect with the RPC node
|
|
22
|
+
*/
|
|
23
|
+
export class Provider {
|
|
24
|
+
/**
|
|
25
|
+
* Array of URLs of RPC nodes
|
|
26
|
+
*/
|
|
27
|
+
public rpcNodes: string[];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Function triggered when a node is down. Returns a
|
|
31
|
+
* boolean determining if the call should be aborted.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* const provider = new Provider([
|
|
36
|
+
* "http://45.56.104.152:8080",
|
|
37
|
+
* "http://159.203.119.0:8080"
|
|
38
|
+
* ]);
|
|
39
|
+
*
|
|
40
|
+
* provider.onError = (error, node, newNode) => {
|
|
41
|
+
* console.log(`Error from node ${node}: ${error.message}`);
|
|
42
|
+
* console.log(`changing node to ${newNode}`);
|
|
43
|
+
* const abort = false;
|
|
44
|
+
* return abort;
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
public onError: (
|
|
49
|
+
error: Error,
|
|
50
|
+
|
|
51
|
+
/** node that threw the error */
|
|
52
|
+
currentNode: string,
|
|
53
|
+
|
|
54
|
+
/** node used for the next iteration */
|
|
55
|
+
newNode: string
|
|
56
|
+
) => boolean;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Index of current node in rpcNodes
|
|
60
|
+
*/
|
|
61
|
+
public currentNodeId: number;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
* @param rpcNodes - URL of the rpc node, or array of urls
|
|
66
|
+
* to switch between them when someone is down
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* const provider = new Provider([
|
|
70
|
+
* "http://45.56.104.152:8080",
|
|
71
|
+
* "http://159.203.119.0:8080"
|
|
72
|
+
* ]);
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
constructor(rpcNodes: string | string[]) {
|
|
76
|
+
if (Array.isArray(rpcNodes)) this.rpcNodes = rpcNodes;
|
|
77
|
+
else this.rpcNodes = [rpcNodes];
|
|
78
|
+
this.currentNodeId = 0;
|
|
79
|
+
this.onError = () => true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Function to make jsonrpc requests to the RPC node
|
|
84
|
+
* @param method - jsonrpc method
|
|
85
|
+
* @param params - jsonrpc params
|
|
86
|
+
* @returns Result of jsonrpc response
|
|
87
|
+
*/
|
|
88
|
+
async call<T = unknown>(method: string, params: unknown): Promise<T> {
|
|
89
|
+
/* eslint-disable no-await-in-loop */
|
|
90
|
+
// eslint-disable-next-line no-constant-condition
|
|
91
|
+
while (true) {
|
|
92
|
+
try {
|
|
93
|
+
const body = {
|
|
94
|
+
id: Math.round(Math.random() * 1000),
|
|
95
|
+
jsonrpc: "2.0",
|
|
96
|
+
method,
|
|
97
|
+
params,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const url = this.rpcNodes[this.currentNodeId];
|
|
101
|
+
|
|
102
|
+
const response = await fetch(url, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
body: JSON.stringify(body),
|
|
105
|
+
});
|
|
106
|
+
const json = (await response.json()) as {
|
|
107
|
+
result: T;
|
|
108
|
+
error?: {
|
|
109
|
+
message?: string;
|
|
110
|
+
data?: string;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
if (json.result !== undefined) return json.result;
|
|
115
|
+
|
|
116
|
+
if (!json.error) throw new Error("undefined error");
|
|
117
|
+
const { message, data } = json.error;
|
|
118
|
+
if (!data) throw new Error(message);
|
|
119
|
+
let dataJson: Record<string, unknown>;
|
|
120
|
+
try {
|
|
121
|
+
dataJson = JSON.parse(data);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
dataJson = { data };
|
|
124
|
+
}
|
|
125
|
+
throw new Error(
|
|
126
|
+
JSON.stringify({
|
|
127
|
+
...(message && { error: message }),
|
|
128
|
+
...dataJson,
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
} catch (e) {
|
|
132
|
+
const currentNode = this.rpcNodes[this.currentNodeId];
|
|
133
|
+
this.currentNodeId = (this.currentNodeId + 1) % this.rpcNodes.length;
|
|
134
|
+
const newNode = this.rpcNodes[this.currentNodeId];
|
|
135
|
+
const abort = this.onError(e as Error, currentNode, newNode);
|
|
136
|
+
if (abort) throw e;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Function to call "chain.get_account_nonce" to return the number of
|
|
143
|
+
* transactions for a particular account. If you are creating a new
|
|
144
|
+
* transaction consider using [[Provider.getNextNonce]].
|
|
145
|
+
* @param account - account address
|
|
146
|
+
* @param deserialize - If set true it will deserialize the nonce
|
|
147
|
+
* and return it as number (default). If set false it will return
|
|
148
|
+
* the nonce encoded as received from the RPC.
|
|
149
|
+
* @returns Nonce
|
|
150
|
+
*/
|
|
151
|
+
async getNonce(
|
|
152
|
+
account: string,
|
|
153
|
+
deserialize = true
|
|
154
|
+
): Promise<number | string> {
|
|
155
|
+
const { nonce: nonceBase64url } = await this.call<{ nonce: string }>(
|
|
156
|
+
"chain.get_account_nonce",
|
|
157
|
+
{ account }
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
if (!deserialize) {
|
|
161
|
+
return nonceBase64url;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const valueBuffer = decodeBase64url(nonceBase64url);
|
|
165
|
+
const message = koinos.chain.value_type.decode(valueBuffer);
|
|
166
|
+
const object = koinos.chain.value_type.toObject(message, {
|
|
167
|
+
longs: String,
|
|
168
|
+
defaults: true,
|
|
169
|
+
}) as { uint64_value: string };
|
|
170
|
+
// todo: consider the case where nonce is greater than max safe integer
|
|
171
|
+
return Number(object.uint64_value);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Function to call "chain.get_account_nonce" (number of
|
|
176
|
+
* transactions for a particular account) and return the next nonce.
|
|
177
|
+
* This call is used when creating new transactions. The result is
|
|
178
|
+
* encoded in base64url
|
|
179
|
+
* @param account - account address
|
|
180
|
+
* @returns Nonce
|
|
181
|
+
*/
|
|
182
|
+
async getNextNonce(account: string): Promise<string> {
|
|
183
|
+
const oldNonce = (await this.getNonce(account)) as number;
|
|
184
|
+
const message = koinos.chain.value_type.create({
|
|
185
|
+
// todo: consider using bigint for big nonces
|
|
186
|
+
uint64_value: String(oldNonce + 1),
|
|
187
|
+
});
|
|
188
|
+
const nonceEncoded = koinos.chain.value_type
|
|
189
|
+
.encode(message)
|
|
190
|
+
.finish() as Uint8Array;
|
|
191
|
+
|
|
192
|
+
return encodeBase64url(nonceEncoded);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async getAccountRc(account: string): Promise<string> {
|
|
196
|
+
const { rc } = await this.call<{ rc: string }>("chain.get_account_rc", {
|
|
197
|
+
account,
|
|
198
|
+
});
|
|
199
|
+
if (!rc) return "0";
|
|
200
|
+
return rc;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get transactions by id and their corresponding block ids
|
|
205
|
+
*/
|
|
206
|
+
async getTransactionsById(transactionIds: string[]): Promise<{
|
|
207
|
+
transactions: {
|
|
208
|
+
transaction: TransactionJson;
|
|
209
|
+
containing_blocks: string[];
|
|
210
|
+
}[];
|
|
211
|
+
}> {
|
|
212
|
+
return this.call<{
|
|
213
|
+
transactions: {
|
|
214
|
+
transaction: TransactionJson;
|
|
215
|
+
containing_blocks: string[];
|
|
216
|
+
}[];
|
|
217
|
+
}>("transaction_store.get_transactions_by_id", {
|
|
218
|
+
transaction_ids: transactionIds,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async getBlocksById(blockIds: string[]): Promise<{
|
|
223
|
+
block_items: {
|
|
224
|
+
block_id: string;
|
|
225
|
+
block_height: string;
|
|
226
|
+
block: BlockJson;
|
|
227
|
+
}[];
|
|
228
|
+
}> {
|
|
229
|
+
return this.call("block_store.get_blocks_by_id", {
|
|
230
|
+
block_ids: blockIds,
|
|
231
|
+
return_block: true,
|
|
232
|
+
return_receipt: false,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Function to get info from the head block in the blockchain
|
|
238
|
+
*/
|
|
239
|
+
async getHeadInfo(): Promise<{
|
|
240
|
+
head_block_time: string;
|
|
241
|
+
head_topology: {
|
|
242
|
+
id: string;
|
|
243
|
+
height: string;
|
|
244
|
+
previous: string;
|
|
245
|
+
};
|
|
246
|
+
head_state_merkle_root: string;
|
|
247
|
+
last_irreversible_block: string;
|
|
248
|
+
}> {
|
|
249
|
+
return this.call<{
|
|
250
|
+
head_block_time: string;
|
|
251
|
+
head_topology: {
|
|
252
|
+
id: string;
|
|
253
|
+
height: string;
|
|
254
|
+
previous: string;
|
|
255
|
+
};
|
|
256
|
+
head_state_merkle_root: string;
|
|
257
|
+
last_irreversible_block: string;
|
|
258
|
+
}>("chain.get_head_info", {});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Function to get the chain
|
|
263
|
+
*/
|
|
264
|
+
async getChainId(): Promise<string> {
|
|
265
|
+
const { chain_id: chainId } = await this.call<{ chain_id: string }>(
|
|
266
|
+
"chain.get_chain_id",
|
|
267
|
+
{}
|
|
268
|
+
);
|
|
269
|
+
return chainId;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Function to get consecutive blocks in descending order
|
|
274
|
+
* @param height - Starting block height
|
|
275
|
+
* @param numBlocks - Number of blocks to fetch
|
|
276
|
+
* @param idRef - Block ID reference to speed up searching blocks.
|
|
277
|
+
* This ID must be from a greater block height. By default it
|
|
278
|
+
* gets the ID from the block head.
|
|
279
|
+
*/
|
|
280
|
+
async getBlocks(
|
|
281
|
+
height: number,
|
|
282
|
+
numBlocks = 1,
|
|
283
|
+
idRef?: string
|
|
284
|
+
): Promise<
|
|
285
|
+
{
|
|
286
|
+
block_id: string;
|
|
287
|
+
block_height: string;
|
|
288
|
+
block: BlockJson;
|
|
289
|
+
block_receipt: {
|
|
290
|
+
[x: string]: unknown;
|
|
291
|
+
};
|
|
292
|
+
}[]
|
|
293
|
+
> {
|
|
294
|
+
let blockIdRef = idRef;
|
|
295
|
+
if (!blockIdRef) {
|
|
296
|
+
const head = await this.getHeadInfo();
|
|
297
|
+
blockIdRef = head.head_topology.id;
|
|
298
|
+
}
|
|
299
|
+
return (
|
|
300
|
+
await this.call<{
|
|
301
|
+
block_items: {
|
|
302
|
+
block_id: string;
|
|
303
|
+
block_height: string;
|
|
304
|
+
block: BlockJson;
|
|
305
|
+
block_receipt: {
|
|
306
|
+
[x: string]: unknown;
|
|
307
|
+
};
|
|
308
|
+
}[];
|
|
309
|
+
}>("block_store.get_blocks_by_height", {
|
|
310
|
+
head_block_id: blockIdRef,
|
|
311
|
+
ancestor_start_height: height,
|
|
312
|
+
num_blocks: numBlocks,
|
|
313
|
+
return_block: true,
|
|
314
|
+
return_receipt: false,
|
|
315
|
+
})
|
|
316
|
+
).block_items;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Function to get a block by its height
|
|
321
|
+
*/
|
|
322
|
+
async getBlock(height: number): Promise<{
|
|
323
|
+
block_id: string;
|
|
324
|
+
block_height: string;
|
|
325
|
+
block: BlockJson;
|
|
326
|
+
block_receipt: {
|
|
327
|
+
[x: string]: unknown;
|
|
328
|
+
};
|
|
329
|
+
}> {
|
|
330
|
+
return (await this.getBlocks(height, 1))[0];
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Function to wait for a transaction to be mined.
|
|
335
|
+
* @param txId - transaction id
|
|
336
|
+
* @param type - Type must be "byBlock" (default) or "byTransactionId".
|
|
337
|
+
* _byBlock_ will query the blockchain to get blocks and search for the
|
|
338
|
+
* transaction there. _byTransactionId_ will query the "transaction store"
|
|
339
|
+
* microservice to search the transaction by its id. If non of them is
|
|
340
|
+
* specified the function will use "byBlock" (as "byTransactionId"
|
|
341
|
+
* requires the transaction store, which is an optional microservice).
|
|
342
|
+
*
|
|
343
|
+
* When _byBlock_ is used it returns the block number.
|
|
344
|
+
*
|
|
345
|
+
* When _byTransactionId_ is used it returns the block id.
|
|
346
|
+
*
|
|
347
|
+
* @param timeout - Timeout in milliseconds. By default it is 15000
|
|
348
|
+
* @example
|
|
349
|
+
* ```ts
|
|
350
|
+
* const blockNumber = await provider.wait(txId);
|
|
351
|
+
* // const blockNumber = await provider.wait(txId, "byBlock", 15000);
|
|
352
|
+
* // const blockId = await provider.wait(txId, "byTransactionId", 15000);
|
|
353
|
+
* console.log("Transaction mined")
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
async wait(
|
|
357
|
+
txId: string,
|
|
358
|
+
type: "byTransactionId" | "byBlock" = "byBlock",
|
|
359
|
+
timeout = 15000
|
|
360
|
+
): Promise<{
|
|
361
|
+
blockId: string;
|
|
362
|
+
blockNumber?: number;
|
|
363
|
+
}> {
|
|
364
|
+
const iniTime = Date.now();
|
|
365
|
+
if (type === "byTransactionId") {
|
|
366
|
+
while (Date.now() < iniTime + timeout) {
|
|
367
|
+
await sleep(1000);
|
|
368
|
+
const { transactions } = await this.getTransactionsById([txId]);
|
|
369
|
+
if (
|
|
370
|
+
transactions &&
|
|
371
|
+
transactions[0] &&
|
|
372
|
+
transactions[0].containing_blocks
|
|
373
|
+
)
|
|
374
|
+
return {
|
|
375
|
+
blockId: transactions[0].containing_blocks[0],
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
throw new Error(`Transaction not mined after ${timeout} ms`);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// byBlock
|
|
382
|
+
const findTxInBlocks = async (
|
|
383
|
+
ini: number,
|
|
384
|
+
numBlocks: number,
|
|
385
|
+
idRef: string
|
|
386
|
+
): Promise<[number, string, string]> => {
|
|
387
|
+
const blocks = await this.getBlocks(ini, numBlocks, idRef);
|
|
388
|
+
let bNum = 0;
|
|
389
|
+
let bId = "";
|
|
390
|
+
blocks.forEach((block) => {
|
|
391
|
+
if (
|
|
392
|
+
!block ||
|
|
393
|
+
!block.block ||
|
|
394
|
+
!block.block_id ||
|
|
395
|
+
!block.block.transactions
|
|
396
|
+
)
|
|
397
|
+
return;
|
|
398
|
+
const tx = block.block.transactions.find((t) => t.id === txId);
|
|
399
|
+
if (tx) {
|
|
400
|
+
bNum = Number(block.block_height);
|
|
401
|
+
bId = block.block_id;
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
const lastId = blocks[blocks.length - 1].block_id;
|
|
405
|
+
return [bNum, bId, lastId];
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
let blockNumber = 0;
|
|
409
|
+
let iniBlock = 0;
|
|
410
|
+
let previousId = "";
|
|
411
|
+
|
|
412
|
+
while (Date.now() < iniTime + timeout) {
|
|
413
|
+
await sleep(1000);
|
|
414
|
+
const { head_topology: headTopology } = await this.getHeadInfo();
|
|
415
|
+
if (blockNumber === 0) {
|
|
416
|
+
blockNumber = Number(headTopology.height);
|
|
417
|
+
iniBlock = blockNumber;
|
|
418
|
+
}
|
|
419
|
+
if (
|
|
420
|
+
Number(headTopology.height) === blockNumber - 1 &&
|
|
421
|
+
previousId &&
|
|
422
|
+
previousId !== headTopology.id
|
|
423
|
+
) {
|
|
424
|
+
const [bNum, bId, lastId] = await findTxInBlocks(
|
|
425
|
+
iniBlock,
|
|
426
|
+
Number(headTopology.height) - iniBlock + 1,
|
|
427
|
+
headTopology.id
|
|
428
|
+
);
|
|
429
|
+
if (bNum)
|
|
430
|
+
return {
|
|
431
|
+
blockId: bId,
|
|
432
|
+
blockNumber: bNum,
|
|
433
|
+
};
|
|
434
|
+
previousId = lastId;
|
|
435
|
+
blockNumber = Number(headTopology.height) + 1;
|
|
436
|
+
}
|
|
437
|
+
// eslint-disable-next-line no-continue
|
|
438
|
+
if (blockNumber > Number(headTopology.height)) continue;
|
|
439
|
+
const [bNum, bId, lastId] = await findTxInBlocks(
|
|
440
|
+
blockNumber,
|
|
441
|
+
1,
|
|
442
|
+
headTopology.id
|
|
443
|
+
);
|
|
444
|
+
if (bNum)
|
|
445
|
+
return {
|
|
446
|
+
blockId: bId,
|
|
447
|
+
blockNumber: bNum,
|
|
448
|
+
};
|
|
449
|
+
if (!previousId) previousId = lastId;
|
|
450
|
+
blockNumber += 1;
|
|
451
|
+
}
|
|
452
|
+
throw new Error(
|
|
453
|
+
`Transaction not mined after ${timeout} ms. Blocks checked from ${iniBlock} to ${blockNumber}`
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Function to call "chain.submit_transaction" to send a signed
|
|
459
|
+
* transaction to the blockchain.
|
|
460
|
+
*
|
|
461
|
+
* It also has the option to not broadcast the transaction (to not
|
|
462
|
+
* include the transaction the mempool), which is useful if you
|
|
463
|
+
* want to test the interaction with a contract and check the
|
|
464
|
+
* possible events triggered.
|
|
465
|
+
* @param transaction - Transaction
|
|
466
|
+
* @param broadcast - Option to broadcast the transaction to the
|
|
467
|
+
* whole network. By default it is true.
|
|
468
|
+
* @returns It returns the receipt received from the RPC node
|
|
469
|
+
* and the transaction with the arrow function "wait" (see [[wait]])
|
|
470
|
+
*/
|
|
471
|
+
async sendTransaction(
|
|
472
|
+
transaction: TransactionJson | TransactionJsonWait,
|
|
473
|
+
broadcast = true
|
|
474
|
+
): Promise<{
|
|
475
|
+
receipt: TransactionReceipt;
|
|
476
|
+
transaction: TransactionJsonWait;
|
|
477
|
+
}> {
|
|
478
|
+
const response = await this.call<{ receipt: TransactionReceipt }>(
|
|
479
|
+
"chain.submit_transaction",
|
|
480
|
+
{ transaction, broadcast }
|
|
481
|
+
);
|
|
482
|
+
(transaction as TransactionJsonWait).wait = async (
|
|
483
|
+
type: "byTransactionId" | "byBlock" = "byBlock",
|
|
484
|
+
timeout = 15000
|
|
485
|
+
) => {
|
|
486
|
+
return this.wait(transaction.id as string, type, timeout);
|
|
487
|
+
};
|
|
488
|
+
return { ...response, transaction: transaction as TransactionJsonWait };
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Function to call "chain.submit_block" to send a signed
|
|
493
|
+
* block to the blockchain.
|
|
494
|
+
*/
|
|
495
|
+
async submitBlock(block: BlockJson): Promise<Record<string, never>> {
|
|
496
|
+
return this.call("chain.submit_block", { block });
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Function to call "chain.read_contract" to read a contract.
|
|
501
|
+
* This function is used by [[Contract]] class when read methods
|
|
502
|
+
* are invoked.
|
|
503
|
+
*/
|
|
504
|
+
async readContract(operation: CallContractOperationJson): Promise<{
|
|
505
|
+
result: string;
|
|
506
|
+
logs: string;
|
|
507
|
+
}> {
|
|
508
|
+
return this.call("chain.read_contract", operation);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
export default Provider;
|