@leofcoin/chain 1.4.71 → 1.4.74

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/exports/chain.js CHANGED
@@ -1,242 +1,18 @@
1
1
  import { formatBytes, BigNumber, formatUnits, parseUnits } from '@leofcoin/utils';
2
+ import { TransactionMessage, BlockMessage, ContractMessage, BWMessage, BWRequestMessage } from '@leofcoin/messages';
2
3
  import addresses, { contractFactory, nativeToken, validators, nameService } from '@leofcoin/addresses';
4
+ import { calculateFee, createContractMessage, contractFactoryMessage, nativeTokenMessage, validatorsMessage, nameServiceMessage, signTransaction } from '@leofcoin/lib';
5
+ import PQueue from 'p-queue';
3
6
  import { randombytes } from '@leofcoin/crypto';
4
7
  import EasyWorker from '@vandeurenglenn/easy-worker';
5
- import { ContractMessage, TransactionMessage, BlockMessage, BWMessage, BWRequestMessage } from '@leofcoin/messages';
6
- import { calculateFee, createContractMessage, contractFactoryMessage, nativeTokenMessage, validatorsMessage, nameServiceMessage, signTransaction } from '@leofcoin/lib';
7
- import pako from 'pako';
8
-
9
- // import State from './state'
10
- class Machine {
11
- #contracts = {};
12
- #nonces = {};
13
- lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
14
- constructor(blocks) {
15
- return this.#init(blocks);
16
- }
17
- #createMessage(sender = peernet.selectedAccount) {
18
- return {
19
- sender,
20
- call: this.execute,
21
- staticCall: this.get.bind(this)
22
- };
23
- }
24
- async #onmessage(data) {
25
- switch (data.type) {
26
- case 'contractError': {
27
- console.warn(`removing contract ${await data.hash()}`);
28
- await contractStore.delete(await data.hash());
29
- break;
30
- }
31
- case 'initError': {
32
- console.error(`init error: ${data.message}`);
33
- break;
34
- }
35
- case 'executionError': {
36
- // console.warn(`error executing transaction ${data.message}`);
37
- pubsub.publish(data.id, { error: data.message });
38
- break;
39
- }
40
- case 'debug': {
41
- for (const message of data.messages)
42
- debug(message);
43
- break;
44
- }
45
- case 'machine-ready': {
46
- this.lastBlock = data.lastBlock;
47
- pubsub.publish('machine.ready', true);
48
- break;
49
- }
50
- case 'response': {
51
- pubsub.publish(data.id, data.value || false);
52
- break;
53
- }
54
- }
55
- }
56
- async #init(blocks) {
57
- return new Promise(async (resolve) => {
58
- const machineReady = () => {
59
- pubsub.unsubscribe('machine.ready', machineReady);
60
- resolve(this);
61
- };
62
- pubsub.subscribe('machine.ready', machineReady);
63
- this.worker = await new EasyWorker('node_modules/@leofcoin/workers/src/machine-worker.js', { serialization: 'advanced', type: 'module' });
64
- this.worker.onmessage(this.#onmessage.bind(this));
65
- // const blocks = await blockStore.values()
66
- const contracts = await Promise.all([
67
- contractStore.get(contractFactory),
68
- contractStore.get(nativeToken),
69
- contractStore.get(validators),
70
- contractStore.get(nameService)
71
- ]);
72
- const message = {
73
- type: 'init',
74
- input: {
75
- contracts,
76
- blocks,
77
- peerid: peernet.peerId
78
- }
79
- };
80
- this.worker.postMessage(message);
81
- });
82
- }
83
- async #runContract(contractMessage) {
84
- const hash = await contractMessage.hash();
85
- return new Promise((resolve, reject) => {
86
- const id = randombytes(20).toString('hex');
87
- const onmessage = message => {
88
- pubsub.unsubscribe(id, onmessage);
89
- if (message?.error)
90
- reject(message.error);
91
- else
92
- resolve(message);
93
- };
94
- pubsub.subscribe(id, onmessage);
95
- this.worker.postMessage({
96
- type: 'run',
97
- id,
98
- input: {
99
- decoded: contractMessage.decoded,
100
- encoded: contractMessage.encoded,
101
- hash
102
- }
103
- });
104
- });
105
- }
106
- /**
107
- *
108
- * @param {Address} contract
109
- * @param {String} method
110
- * @param {Array} parameters
111
- * @returns Promise<message>
112
- */
113
- async execute(contract, method, parameters) {
114
- try {
115
- if (contract === contractFactory && method === 'registerContract') {
116
- if (await this.has(parameters[0]))
117
- throw new Error(`duplicate contract @${parameters[0]}`);
118
- let message;
119
- if (!await contractStore.has(parameters[0])) {
120
- message = await peernet.get(parameters[0], 'contract');
121
- message = await new ContractMessage(message);
122
- await contractStore.put(await message.hash(), message.encoded);
123
- }
124
- if (!message) {
125
- message = await contractStore.get(parameters[0]);
126
- message = await new ContractMessage(message);
127
- }
128
- if (!await this.has(await message.hash()))
129
- await this.#runContract(message);
130
- }
131
- }
132
- catch (error) {
133
- throw new Error(`contract deployment failed for ${parameters[0]}\n${error.message}`);
134
- }
135
- return new Promise((resolve, reject) => {
136
- const id = randombytes(20).toString('hex');
137
- const onmessage = message => {
138
- pubsub.unsubscribe(id, onmessage);
139
- if (message?.error)
140
- reject(message.error);
141
- else
142
- resolve(message);
143
- };
144
- pubsub.subscribe(id, onmessage);
145
- this.worker.postMessage({
146
- type: 'execute',
147
- id,
148
- input: {
149
- contract,
150
- method,
151
- params: parameters
152
- }
153
- });
154
- });
155
- }
156
- get(contract, method, parameters) {
157
- return new Promise((resolve, reject) => {
158
- const id = randombytes(20).toString();
159
- const onmessage = message => {
160
- pubsub.unsubscribe(id, onmessage);
161
- resolve(message);
162
- };
163
- pubsub.subscribe(id, onmessage);
164
- this.worker.postMessage({
165
- type: 'get',
166
- id,
167
- input: {
168
- contract,
169
- method,
170
- params: parameters
171
- }
172
- });
173
- });
174
- }
175
- async has(address) {
176
- return new Promise((resolve, reject) => {
177
- const id = randombytes(20).toString('hex');
178
- const onmessage = message => {
179
- pubsub.unsubscribe(id, onmessage);
180
- if (message?.error)
181
- reject(message.error);
182
- else
183
- resolve(message);
184
- };
185
- pubsub.subscribe(id, onmessage);
186
- this.worker.postMessage({
187
- type: 'has',
188
- id,
189
- input: {
190
- address
191
- }
192
- });
193
- });
194
- }
195
- async delete(hash) {
196
- return contractStore.delete(hash);
197
- }
198
- /**
199
- *
200
- * @returns Promise
201
- */
202
- async deleteAll() {
203
- let hashes = await contractStore.get();
204
- hashes = Object.keys(hashes).map(hash => this.delete(hash));
205
- return Promise.all(hashes);
206
- }
207
- }
208
-
209
- class State {
210
- constructor() {
211
- // return this.#init()
212
- }
213
- // async #init() {
214
- // const state = await stateStore.get()
215
- // for (const [key, value] of Object.entries(state)) {
216
- //
217
- // }
218
- //
219
- // return this
220
- // }
221
- async put(key, value, isCompressed = true) {
222
- value = isCompressed ? value : await pako.deflate(value);
223
- await stateStore.put(key, value);
224
- }
225
- async get(key, isCompressed = true) {
226
- const value = await stateStore.get(key);
227
- return isCompressed = pako.inflate(value) ;
228
- }
229
- updateState(block) {
230
- // block.decoded.index
231
- // this.#isUpdateNeeded()
232
- }
233
- }
234
8
 
235
9
  const limit = 1800;
236
10
  const transactionLimit = 1800;
237
11
  const requestTimeout = 30_000;
238
12
  const syncTimeout = 30_000;
239
13
  class Protocol {
14
+ version;
15
+ resolveTimeout = 30_000;
240
16
  get limit() {
241
17
  return limit;
242
18
  }
@@ -425,6 +201,8 @@ class Contract extends Transaction {
425
201
  constructor() {
426
202
  super();
427
203
  }
204
+ async init() {
205
+ }
428
206
  /**
429
207
  *
430
208
  * @param {Address} creator
@@ -466,98 +244,582 @@ class Contract extends Transaction {
466
244
  }
467
245
  }
468
246
 
469
- globalThis.BigNumber = BigNumber;
470
- // check if browser or local
471
- class Chain extends Contract {
472
- #lastBlockInQue;
473
- #syncErrorCount = 0;
474
- version;
475
- #resolveErrored;
476
- #state;
477
- #lastResolved;
478
- #slotTime = 10000;
479
- id;
480
- utils;
481
- /** {Address[]} */
482
- #validators = [];
483
- /** {Block[]} */
484
- #blocks = [];
485
- #blockHashMap = new Map();
486
- #machine;
487
- /** {Boolean} */
488
- #runningEpoch = false;
489
- /** {Boolean} */
490
- #chainSyncing = false;
491
- /** {Number} */
492
- #totalSize = 0;
493
- /**
494
- * {Block} {index, hash, previousHash}
495
- */
496
- #lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
497
- /**
498
- * amount the native token has been iteracted with
499
- */
500
- #nativeCalls = 0;
501
- /**
502
- * amount the native token has been iteracted with
503
- */
504
- #nativeTransfers = 0;
505
- /**
506
- * amount of native token burned
507
- * {Number}
508
- */
509
- #nativeBurns = 0;
510
- /**
511
- * amount of native tokens minted
512
- * {Number}
513
- */
514
- #nativeMints = 0;
515
- /**
516
- * total amount of transactions
517
- * {Number}
518
- */
519
- #totalTransactions = 0;
520
- #participants = [];
247
+ // import State from './state'
248
+ class Machine {
249
+ #contracts = {};
250
+ #nonces = {};
251
+ lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
252
+ constructor(blocks) {
253
+ return this.#init(blocks);
254
+ }
255
+ #createMessage(sender = peernet.selectedAccount) {
256
+ return {
257
+ sender,
258
+ call: this.execute,
259
+ staticCall: this.get.bind(this)
260
+ };
261
+ }
262
+ async #onmessage(data) {
263
+ switch (data.type) {
264
+ case 'contractError': {
265
+ console.warn(`removing contract ${await data.hash()}`);
266
+ await contractStore.delete(await data.hash());
267
+ break;
268
+ }
269
+ case 'initError': {
270
+ console.error(`init error: ${data.message}`);
271
+ break;
272
+ }
273
+ case 'executionError': {
274
+ // console.warn(`error executing transaction ${data.message}`);
275
+ pubsub.publish(data.id, { error: data.message });
276
+ break;
277
+ }
278
+ case 'debug': {
279
+ for (const message of data.messages)
280
+ debug(message);
281
+ break;
282
+ }
283
+ case 'machine-ready': {
284
+ this.lastBlock = data.lastBlock;
285
+ pubsub.publish('machine.ready', true);
286
+ break;
287
+ }
288
+ case 'response': {
289
+ pubsub.publish(data.id, data.value || false);
290
+ break;
291
+ }
292
+ }
293
+ }
294
+ async #init(blocks) {
295
+ return new Promise(async (resolve) => {
296
+ const machineReady = () => {
297
+ pubsub.unsubscribe('machine.ready', machineReady);
298
+ resolve(this);
299
+ };
300
+ pubsub.subscribe('machine.ready', machineReady);
301
+ this.worker = await new EasyWorker('node_modules/@leofcoin/workers/src/machine-worker.js', { serialization: 'advanced', type: 'module' });
302
+ this.worker.onmessage(this.#onmessage.bind(this));
303
+ // const blocks = await blockStore.values()
304
+ const contracts = await Promise.all([
305
+ contractStore.get(contractFactory),
306
+ contractStore.get(nativeToken),
307
+ contractStore.get(validators),
308
+ contractStore.get(nameService)
309
+ ]);
310
+ const message = {
311
+ type: 'init',
312
+ input: {
313
+ contracts,
314
+ blocks,
315
+ peerid: peernet.peerId
316
+ }
317
+ };
318
+ this.worker.postMessage(message);
319
+ });
320
+ }
321
+ async #runContract(contractMessage) {
322
+ const hash = await contractMessage.hash();
323
+ return new Promise((resolve, reject) => {
324
+ const id = randombytes(20).toString('hex');
325
+ const onmessage = message => {
326
+ pubsub.unsubscribe(id, onmessage);
327
+ if (message?.error)
328
+ reject(message.error);
329
+ else
330
+ resolve(message);
331
+ };
332
+ pubsub.subscribe(id, onmessage);
333
+ this.worker.postMessage({
334
+ type: 'run',
335
+ id,
336
+ input: {
337
+ decoded: contractMessage.decoded,
338
+ encoded: contractMessage.encoded,
339
+ hash
340
+ }
341
+ });
342
+ });
343
+ }
344
+ /**
345
+ *
346
+ * @param {Address} contract
347
+ * @param {String} method
348
+ * @param {Array} parameters
349
+ * @returns Promise<message>
350
+ */
351
+ async execute(contract, method, parameters) {
352
+ try {
353
+ if (contract === contractFactory && method === 'registerContract') {
354
+ if (await this.has(parameters[0]))
355
+ throw new Error(`duplicate contract @${parameters[0]}`);
356
+ let message;
357
+ if (!await contractStore.has(parameters[0])) {
358
+ message = await peernet.get(parameters[0], 'contract');
359
+ message = await new ContractMessage(message);
360
+ await contractStore.put(await message.hash(), message.encoded);
361
+ }
362
+ if (!message) {
363
+ message = await contractStore.get(parameters[0]);
364
+ message = await new ContractMessage(message);
365
+ }
366
+ if (!await this.has(await message.hash()))
367
+ await this.#runContract(message);
368
+ }
369
+ }
370
+ catch (error) {
371
+ throw new Error(`contract deployment failed for ${parameters[0]}\n${error.message}`);
372
+ }
373
+ return new Promise((resolve, reject) => {
374
+ const id = randombytes(20).toString('hex');
375
+ const onmessage = message => {
376
+ pubsub.unsubscribe(id, onmessage);
377
+ if (message?.error)
378
+ reject(message.error);
379
+ else
380
+ resolve(message);
381
+ };
382
+ pubsub.subscribe(id, onmessage);
383
+ this.worker.postMessage({
384
+ type: 'execute',
385
+ id,
386
+ input: {
387
+ contract,
388
+ method,
389
+ params: parameters
390
+ }
391
+ });
392
+ });
393
+ }
394
+ get(contract, method, parameters) {
395
+ return new Promise((resolve, reject) => {
396
+ const id = randombytes(20).toString();
397
+ const onmessage = message => {
398
+ pubsub.unsubscribe(id, onmessage);
399
+ resolve(message);
400
+ };
401
+ pubsub.subscribe(id, onmessage);
402
+ this.worker.postMessage({
403
+ type: 'get',
404
+ id,
405
+ input: {
406
+ contract,
407
+ method,
408
+ params: parameters
409
+ }
410
+ });
411
+ });
412
+ }
413
+ async has(address) {
414
+ return new Promise((resolve, reject) => {
415
+ const id = randombytes(20).toString('hex');
416
+ const onmessage = message => {
417
+ pubsub.unsubscribe(id, onmessage);
418
+ if (message?.error)
419
+ reject(message.error);
420
+ else
421
+ resolve(message);
422
+ };
423
+ pubsub.subscribe(id, onmessage);
424
+ this.worker.postMessage({
425
+ type: 'has',
426
+ id,
427
+ input: {
428
+ address
429
+ }
430
+ });
431
+ });
432
+ }
433
+ async delete(hash) {
434
+ return contractStore.delete(hash);
435
+ }
436
+ /**
437
+ *
438
+ * @returns Promise
439
+ */
440
+ async deleteAll() {
441
+ let hashes = await contractStore.get();
442
+ hashes = Object.keys(hashes).map(hash => this.delete(hash));
443
+ return Promise.all(hashes);
444
+ }
445
+ }
446
+
447
+ const queue = new PQueue({ concurrency: 1, throwOnTimeout: true });
448
+ class State extends Contract {
449
+ #resolveErrored;
450
+ #lastResolvedTime;
451
+ #lastResolved;
452
+ #resolveErrorCount = 0;
453
+ #syncState;
454
+ #lastBlockInQue;
455
+ #syncErrorCount = 0;
456
+ #blockHashMap = new Map();
457
+ #chainSyncing = false;
458
+ #lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
459
+ #blocks = [];
460
+ #knownBlocks = [];
461
+ #totalSize = 0;
462
+ #machine;
463
+ /**
464
+ * amount the native token has been iteracted with
465
+ */
466
+ #nativeCalls = 0;
467
+ /**
468
+ * amount the native token has been iteracted with
469
+ */
470
+ #nativeTransfers = 0;
471
+ /**
472
+ * amount of native token burned
473
+ * {Number}
474
+ */
475
+ #nativeBurns = 0;
476
+ /**
477
+ * amount of native tokens minted
478
+ * {Number}
479
+ */
480
+ #nativeMints = 0;
481
+ /**
482
+ * total amount of transactions
483
+ * {Number}
484
+ */
485
+ #totalTransactions = 0;
486
+ get nativeMints() {
487
+ return this.#nativeMints;
488
+ }
489
+ get nativeBurns() {
490
+ return this.#nativeBurns;
491
+ }
492
+ get nativeTransfers() {
493
+ return this.#nativeTransfers;
494
+ }
495
+ get totalTransactions() {
496
+ return this.#totalTransactions;
497
+ }
498
+ get nativeCalls() {
499
+ return this.#nativeCalls;
500
+ }
501
+ get blocks() {
502
+ return [...this.#blocks];
503
+ }
504
+ get lastBlock() {
505
+ return this.#lastBlock;
506
+ }
507
+ get totalSize() {
508
+ return this.#totalSize;
509
+ }
510
+ get machine() {
511
+ return this.#machine;
512
+ }
513
+ constructor() {
514
+ super();
515
+ }
516
+ async init() {
517
+ if (super.init)
518
+ await super.init();
519
+ await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler.bind(this));
520
+ await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler.bind(this));
521
+ try {
522
+ let localBlock;
523
+ try {
524
+ localBlock = await globalThis.chainStore.get('lastBlock');
525
+ }
526
+ catch {
527
+ await globalThis.chainStore.put('lastBlock', '0x0');
528
+ localBlock = await globalThis.chainStore.get('lastBlock');
529
+ }
530
+ localBlock = new TextDecoder().decode(localBlock);
531
+ if (localBlock && localBlock !== '0x0') {
532
+ localBlock = await globalThis.peernet.get(localBlock, 'block');
533
+ localBlock = await new BlockMessage(localBlock);
534
+ this.#lastBlock = { ...localBlock.decoded, hash: await localBlock.hash() };
535
+ }
536
+ else {
537
+ if (globalThis.peernet?.connections.length > 0) {
538
+ const latestBlock = await this.#getLatestBlock();
539
+ await this.#syncChain(latestBlock);
540
+ }
541
+ }
542
+ }
543
+ catch (error) {
544
+ console.log({ e: error });
545
+ }
546
+ // load local blocks
547
+ await this.resolveBlocks();
548
+ this.#machine = await new Machine(this.#blocks);
549
+ await this.#loadBlocks(this.#blocks);
550
+ }
551
+ async updateState(message) {
552
+ const hash = await message.hash();
553
+ this.#lastBlock = { hash, ...message.decoded };
554
+ // await this.state.updateState(message)
555
+ await globalThis.chainStore.put('lastBlock', hash);
556
+ }
557
+ async #lastBlockHandler() {
558
+ return new globalThis.peernet.protos['peernet-response']({ response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index } });
559
+ }
560
+ async #knownBlocksHandler() {
561
+ return new globalThis.peernet.protos['peernet-response']({ response: { blocks: this.#blocks.map((block) => block.hash) } });
562
+ }
563
+ getLatestBlock() {
564
+ return this.#getLatestBlock();
565
+ }
566
+ async getAndPutBlock(hash) {
567
+ // todo peernet resolves undefined blocks....
568
+ let block = await globalThis.peernet.get(hash, 'block');
569
+ if (block !== undefined) {
570
+ block = await new BlockMessage(block);
571
+ const { index } = block.decoded;
572
+ if (this.#blocks[index] && this.#blocks[index].hash !== block.hash)
573
+ throw `invalid block ${hash} @${index}`;
574
+ if (!await globalThis.peernet.has(hash, 'block'))
575
+ await globalThis.peernet.put(hash, block.encoded, 'block');
576
+ }
577
+ return block;
578
+ }
579
+ async #resolveBlock(hash) {
580
+ let index = this.#blockHashMap.get(hash);
581
+ if (this.#blocks[index]) {
582
+ if (this.#blocks[index].previousHash !== '0x0') {
583
+ return this.resolveBlock(this.#blocks[index].previousHash);
584
+ }
585
+ else {
586
+ return;
587
+ }
588
+ }
589
+ const block = await this.getAndPutBlock(hash);
590
+ index = block.decoded.index;
591
+ const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
592
+ this.#totalSize += size;
593
+ this.#blocks[index] = { hash, ...block.decoded };
594
+ this.#blockHashMap.set(hash, index);
595
+ globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
596
+ this.#lastResolved = this.#blocks[index];
597
+ this.#lastResolvedTime = Date.now();
598
+ return;
599
+ }
600
+ async resolveBlock(hash) {
601
+ if (!hash)
602
+ throw new Error(`expected hash, got: ${hash}`);
603
+ if (hash === '0x0')
604
+ return;
605
+ await queue.add(() => this.#resolveBlock(hash));
606
+ if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
607
+ return this.resolveBlock(this.#lastResolved.previousHash);
608
+ return;
609
+ }
610
+ async resolveBlocks() {
611
+ try {
612
+ const localBlock = await globalThis.chainStore.get('lastBlock');
613
+ const hash = new TextDecoder().decode(localBlock);
614
+ if (hash && hash !== '0x0')
615
+ await this.resolveBlock(hash);
616
+ this.#lastBlock = this.#blocks[this.#blocks.length - 1];
617
+ }
618
+ catch {
619
+ this.#resolveErrored = true;
620
+ this.#resolveErrorCount += 1;
621
+ // console.log(e);
622
+ }
623
+ }
624
+ async syncChain(lastBlock) {
625
+ if (!this.shouldSync) {
626
+ return;
627
+ }
628
+ await queue.clear();
629
+ this.#chainSyncing = true;
630
+ if (!lastBlock)
631
+ lastBlock = await this.#getLatestBlock();
632
+ console.log('starting sync');
633
+ if (globalThis.peernet.connections.length === 0)
634
+ return 'connectionless';
635
+ try {
636
+ await this.#syncChain(lastBlock);
637
+ }
638
+ catch (error) {
639
+ this.#syncErrorCount += 1;
640
+ if (this.#syncErrorCount < 3)
641
+ await this.#syncChain(lastBlock);
642
+ this.#chainSyncing = false;
643
+ this.#syncErrorCount = 0;
644
+ return 'errored';
645
+ }
646
+ if (lastBlock.index === this.#lastBlockInQue?.index)
647
+ this.#lastBlockInQue = undefined;
648
+ this.#syncErrorCount = 0;
649
+ this.#chainSyncing = false;
650
+ if (this.#lastBlockInQue)
651
+ return this.syncChain(this.#lastBlockInQue);
652
+ return 'synced';
653
+ }
654
+ async #syncChain(lastBlock) {
655
+ try {
656
+ if (this.#knownBlocks?.length === Number(lastBlock.index) + 1) {
657
+ let promises = [];
658
+ promises = await Promise.allSettled(this.#knownBlocks.map(async (address) => {
659
+ const has = await globalThis.peernet.has(address, 'block');
660
+ return { has, address };
661
+ }));
662
+ promises = promises.filter(({ status, value }) => status === 'fulfilled' && !value.has);
663
+ await Promise.allSettled(promises.map(({ value }) => this.getAndPutBlock(value.address)));
664
+ }
665
+ if (!this.#lastBlock || Number(this.#lastBlock.index) < Number(lastBlock.index)) {
666
+ // TODO: check if valid
667
+ const localIndex = this.#lastBlock ? this.lastBlock.index : 0;
668
+ const index = lastBlock.index;
669
+ await this.resolveBlock(lastBlock.hash);
670
+ console.log('ok');
671
+ let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index - localIndex) : index;
672
+ globalThis.debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
673
+ const start = (this.#blocks.length - blocksSynced) - 1;
674
+ if (this.#machine)
675
+ await this.#loadBlocks(this.blocks.slice(start));
676
+ await this.updateState(new BlockMessage(this.#blocks[this.#blocks.length - 1]));
677
+ }
678
+ }
679
+ catch (error) {
680
+ console.log(error);
681
+ throw error;
682
+ }
683
+ }
684
+ async #getLatestBlock() {
685
+ let promises = [];
686
+ let data = await new globalThis.peernet.protos['peernet-request']({ request: 'lastBlock' });
687
+ let node = await globalThis.peernet.prepareMessage(data);
688
+ for (const peer of globalThis.peernet?.connections) {
689
+ if (peer.connected && peer.version === this.version) {
690
+ promises.push(async () => {
691
+ try {
692
+ const result = await peer.request(node.encoded);
693
+ return { result, peer };
694
+ }
695
+ catch (error) {
696
+ throw error;
697
+ }
698
+ });
699
+ }
700
+ }
701
+ promises = await this.promiseRequests(promises);
702
+ let latest = { index: 0, hash: '0x0', previousHash: '0x0' };
703
+ promises = promises.sort((a, b) => b.index - a.index);
704
+ if (promises.length > 0)
705
+ latest = promises[0].value;
706
+ if (latest.hash && latest.hash !== '0x0') {
707
+ let message = await globalThis.peernet.get(latest.hash, 'block');
708
+ message = await new BlockMessage(message);
709
+ const hash = await message.hash();
710
+ if (hash !== latest.hash)
711
+ throw new Error('invalid block @getLatestBlock');
712
+ latest = { ...message.decoded, hash };
713
+ const peer = promises[0].peer;
714
+ if (peer.connected && peer.version === this.version) {
715
+ let data = await new globalThis.peernet.protos['peernet-request']({ request: 'knownBlocks' });
716
+ let node = await globalThis.peernet.prepareMessage(data);
717
+ let message = await peer.request(node);
718
+ message = await new globalThis.peernet.protos['peernet-response'](message);
719
+ this.#knownBlocks = message.decoded.response;
720
+ }
721
+ }
722
+ return latest;
723
+ }
724
+ /**
725
+ *
726
+ * @param {Block[]} blocks
727
+ */
728
+ async #loadBlocks(blocks) {
729
+ let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
730
+ for (const block of blocks) {
731
+ if (block && !block.loaded) {
732
+ for (const transaction of block.transactions) {
733
+ if (poolTransactionKeys.includes(transaction.hash))
734
+ await globalThis.transactionPoolStore.delete(transaction.hash);
735
+ try {
736
+ await this.#machine.execute(transaction.to, transaction.method, transaction.params);
737
+ if (transaction.to === nativeToken) {
738
+ this.#nativeCalls += 1;
739
+ if (transaction.method === 'burn')
740
+ this.#nativeBurns += 1;
741
+ if (transaction.method === 'mint')
742
+ this.#nativeMints += 1;
743
+ if (transaction.method === 'transfer')
744
+ this.#nativeTransfers += 1;
745
+ }
746
+ this.#totalTransactions += 1;
747
+ }
748
+ catch (error) {
749
+ console.log(error);
750
+ return false;
751
+ }
752
+ }
753
+ this.#blocks[block.index].loaded = true;
754
+ globalThis.debug(`loaded block: ${block.hash} @${block.index}`);
755
+ }
756
+ }
757
+ return true;
758
+ }
759
+ promiseRequests(promises) {
760
+ return new Promise(async (resolve, reject) => {
761
+ const timeout = setTimeout(() => {
762
+ resolve([{ index: 0, hash: '0x0' }]);
763
+ globalThis.debug('sync timed out');
764
+ }, this.requestTimeout);
765
+ promises = await Promise.allSettled(promises);
766
+ promises = promises.filter(({ status }) => status === 'fulfilled');
767
+ clearTimeout(timeout);
768
+ if (promises.length > 0) {
769
+ promises = promises.map(async ({ value }) => {
770
+ const node = await new globalThis.peernet.protos['peernet-response'](value);
771
+ return { value: node.decoded.response, peer: value.peer };
772
+ });
773
+ promises = await Promise.all(promises);
774
+ resolve(promises);
775
+ }
776
+ else {
777
+ resolve([]);
778
+ }
779
+ });
780
+ }
781
+ get canSync() {
782
+ if (this.#chainSyncing)
783
+ return false;
784
+ return true;
785
+ }
786
+ get shouldSync() {
787
+ if (this.canSync ||
788
+ this.#resolveErrored ||
789
+ !this.canSync && this.#lastResolvedTime + this.resolveTimeout > new Date().getTime())
790
+ return true;
791
+ return false;
792
+ }
793
+ async triggerSync() {
794
+ const latest = await this.#getLatestBlock();
795
+ return this.syncChain(latest);
796
+ }
797
+ }
798
+
799
+ globalThis.BigNumber = BigNumber;
800
+ // check if browser or local
801
+ class Chain extends State {
802
+ #state;
803
+ #slotTime = 10000;
804
+ id;
805
+ utils;
806
+ /** {Address[]} */
807
+ #validators = [];
808
+ /** {Boolean} */
809
+ #runningEpoch = false;
810
+ #participants = [];
521
811
  #participating = false;
522
812
  #jail = [];
523
- #knownBlocks = [];
524
813
  constructor() {
525
814
  super();
526
815
  return this.#init();
527
816
  }
528
- get nativeMints() {
529
- return this.#nativeMints;
530
- }
531
- get nativeBurns() {
532
- return this.#nativeBurns;
533
- }
534
- get nativeTransfers() {
535
- return this.#nativeTransfers;
536
- }
537
- get totalTransactions() {
538
- return this.#totalTransactions;
539
- }
540
- get nativeCalls() {
541
- return this.#nativeCalls;
542
- }
543
- get totalSize() {
544
- return this.#totalSize;
545
- }
546
- get lib() {
547
- return lib;
548
- }
549
- get lastBlock() {
550
- return this.#lastBlock;
551
- }
552
817
  get nativeToken() {
553
818
  return addresses.nativeToken;
554
819
  }
555
820
  get validators() {
556
821
  return [...this.#validators];
557
822
  }
558
- get blocks() {
559
- return [...this.#blocks];
560
- }
561
823
  async hasTransactionToHandle() {
562
824
  const size = await globalThis.transactionPoolStore.size();
563
825
  if (size > 0)
@@ -607,71 +869,6 @@ class Chain extends Contract {
607
869
  console.log('handle native contracts');
608
870
  // handle native contracts
609
871
  }
610
- promiseRequests(promises) {
611
- return new Promise(async (resolve, reject) => {
612
- const timeout = setTimeout(() => {
613
- resolve([{ index: 0, hash: '0x0' }]);
614
- globalThis.debug('sync timed out');
615
- }, this.requestTimeout);
616
- promises = await Promise.allSettled(promises);
617
- promises = promises.filter(({ status }) => status === 'fulfilled');
618
- clearTimeout(timeout);
619
- if (promises.length > 0) {
620
- promises = promises.map(async ({ value }) => {
621
- const node = await new globalThis.peernet.protos['peernet-response'](value.result);
622
- return { value: node.decoded.response, peer: value.peer };
623
- });
624
- promises = await Promise.all(promises);
625
- resolve(promises);
626
- }
627
- else {
628
- resolve([]);
629
- }
630
- });
631
- }
632
- getLatestBlock() {
633
- return this.#getLatestBlock();
634
- }
635
- async #getLatestBlock() {
636
- let promises = [];
637
- let data = await new globalThis.peernet.protos['peernet-request']({ request: 'lastBlock' });
638
- let node = await globalThis.peernet.prepareMessage(data);
639
- for (const peer of globalThis.peernet?.connections) {
640
- if (peer.connected && peer.version === this.version) {
641
- promises.push(async () => {
642
- try {
643
- const result = await peer.request(node.encoded);
644
- return { result, peer };
645
- }
646
- catch (error) {
647
- throw error;
648
- }
649
- });
650
- }
651
- }
652
- promises = await this.promiseRequests(promises);
653
- let latest = { index: 0, hash: '0x0', previousHash: '0x0' };
654
- promises = promises.sort((a, b) => b.index - a.index);
655
- if (promises.length > 0)
656
- latest = promises[0].value;
657
- if (latest.hash && latest.hash !== '0x0') {
658
- let message = await globalThis.peernet.get(latest.hash, 'block');
659
- message = await new BlockMessage(message);
660
- const hash = await message.hash();
661
- if (hash !== latest.hash)
662
- throw new Error('invalid block @getLatestBlock');
663
- latest = { ...message.decoded, hash };
664
- const peer = promises[0].peer;
665
- if (peer.connected && peer.version === this.version) {
666
- let data = await new globalThis.peernet.protos['peernet-request']({ request: 'knownBlocks' });
667
- let node = await globalThis.peernet.prepareMessage(data);
668
- let message = await peer.request(node);
669
- message = await new globalThis.peernet.protos['peernet-response'](message);
670
- this.#knownBlocks = message.decoded.response;
671
- }
672
- }
673
- return latest;
674
- }
675
872
  async #clearPool() {
676
873
  await globalThis.transactionPoolStore.clear();
677
874
  }
@@ -703,7 +900,7 @@ class Chain extends Contract {
703
900
  if (!initialized)
704
901
  await this.#setup();
705
902
  this.utils = { BigNumber, formatUnits, parseUnits };
706
- this.#state = new State();
903
+ // this.#state = new State()
707
904
  await globalThis.peernet.addRequestHandler('bw-request-message', () => {
708
905
  return new BWMessage(globalThis.peernet.client.bw) || { up: 0, down: 0 };
709
906
  });
@@ -713,43 +910,13 @@ class Chain extends Contract {
713
910
  // })
714
911
  await globalThis.peernet.addRequestHandler('transactionPool', this.#transactionPoolHandler.bind(this));
715
912
  await globalThis.peernet.addRequestHandler('version', this.#versionHandler.bind(this));
716
- await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler.bind(this));
717
- await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler.bind(this));
718
913
  globalThis.peernet.subscribe('add-block', this.#addBlock.bind(this));
719
914
  globalThis.peernet.subscribe('invalid-transaction', this.#invalidTransaction.bind(this));
720
915
  globalThis.peernet.subscribe('send-transaction', this.#sendTransaction.bind(this));
721
916
  globalThis.peernet.subscribe('validator:timeout', this.#validatorTimeout.bind(this));
722
917
  globalThis.pubsub.subscribe('peer:connected', this.#peerConnected.bind(this));
723
918
  // todo some functions rely on state
724
- try {
725
- let localBlock;
726
- try {
727
- localBlock = await globalThis.chainStore.get('lastBlock');
728
- }
729
- catch {
730
- await globalThis.chainStore.put('lastBlock', '0x0');
731
- localBlock = await globalThis.chainStore.get('lastBlock');
732
- }
733
- localBlock = new TextDecoder().decode(localBlock);
734
- if (localBlock && localBlock !== '0x0') {
735
- localBlock = await globalThis.peernet.get(localBlock, 'block');
736
- localBlock = await new BlockMessage(localBlock);
737
- this.#lastBlock = { ...localBlock.decoded, hash: await localBlock.hash() };
738
- }
739
- else {
740
- if (globalThis.peernet?.connections.length > 0) {
741
- const latestBlock = await this.#getLatestBlock();
742
- await this.#syncChain(latestBlock);
743
- }
744
- }
745
- }
746
- catch (error) {
747
- console.log({ e: error });
748
- }
749
- // load local blocks
750
- await this.resolveBlocks();
751
- this.#machine = await new Machine(this.#blocks);
752
- await this.#loadBlocks(this.#blocks);
919
+ await super.init();
753
920
  globalThis.globalThis.pubsub.publish('chain:ready', true);
754
921
  return this;
755
922
  }
@@ -763,82 +930,6 @@ class Chain extends Contract {
763
930
  }, validatorInfo.timeout);
764
931
  this.#jail.push(validatorInfo.address);
765
932
  }
766
- async triggerSync() {
767
- const latest = await this.#getLatestBlock();
768
- return this.syncChain(latest);
769
- }
770
- async syncChain(lastBlock) {
771
- if (!lastBlock)
772
- lastBlock = await this.#getLatestBlock();
773
- if (this.#chainSyncing) {
774
- console.log('already syncing');
775
- if (!this.#lastBlockInQue || lastBlock.index > this.#lastBlockInQue.index)
776
- this.#lastBlockInQue = lastBlock;
777
- return 'syncing';
778
- }
779
- console.log('starting sync');
780
- this.#chainSyncing = true;
781
- const syncPromise = (lastBlock) => new Promise(async (resolve, reject) => {
782
- const timeout = setTimeout(() => {
783
- this.#chainSyncing = false;
784
- this.#syncErrorCount = 0;
785
- reject('timedOut');
786
- }, 60000);
787
- try {
788
- await this.#syncChain(lastBlock);
789
- clearTimeout(timeout);
790
- resolve(true);
791
- }
792
- catch (error) {
793
- clearTimeout(timeout);
794
- reject(error);
795
- }
796
- });
797
- if (globalThis.peernet.connections.length === 0)
798
- return 'connectionless';
799
- try {
800
- await syncPromise(lastBlock);
801
- }
802
- catch (error) {
803
- console.log(error);
804
- this.#syncErrorCount += 1;
805
- if (this.#syncErrorCount < 3)
806
- await syncPromise(lastBlock);
807
- this.#chainSyncing = false;
808
- this.#syncErrorCount = 0;
809
- return 'errored';
810
- }
811
- if (lastBlock.index === this.#lastBlockInQue?.index)
812
- this.#lastBlockInQue = undefined;
813
- this.#syncErrorCount = 0;
814
- this.#chainSyncing = false;
815
- if (this.#lastBlockInQue)
816
- return this.syncChain(this.#lastBlockInQue);
817
- return 'synced';
818
- }
819
- async #syncChain(lastBlock) {
820
- if (this.#knownBlocks?.length === Number(lastBlock.index) + 1) {
821
- let promises = [];
822
- promises = await Promise.allSettled(this.#knownBlocks.map(async (address) => {
823
- const has = await globalThis.peernet.has(address, 'block');
824
- return { has, address };
825
- }));
826
- promises = promises.filter(({ status, value }) => status === 'fulfilled' && !value.has);
827
- await Promise.allSettled(promises.map(({ value }) => this.getAndPutBlock(value.address)));
828
- }
829
- if (!this.lastBlock || Number(this.lastBlock.index) < Number(lastBlock.index)) {
830
- // TODO: check if valid
831
- const localIndex = this.lastBlock ? this.lastBlock.index : 0;
832
- const index = lastBlock.index;
833
- await this.resolveBlock(lastBlock.hash);
834
- let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index - localIndex) : index;
835
- globalThis.debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
836
- const start = (this.#blocks.length - blocksSynced) - 1;
837
- if (this.#machine)
838
- await this.#loadBlocks(this.blocks.slice(start));
839
- await this.#updateState(new BlockMessage(this.#blocks[this.#blocks.length - 1]));
840
- }
841
- }
842
933
  async #prepareRequest(request) {
843
934
  let node = await new globalThis.peernet.protos['peernet-request']({ request });
844
935
  return globalThis.peernet.prepareMessage(node);
@@ -854,12 +945,10 @@ class Chain extends Contract {
854
945
  return;
855
946
  const lastBlock = await this.#makeRequest(peer, 'lastBlock');
856
947
  if (Object.keys(lastBlock).length > 0) {
857
- if (this.#resolveErrored || !this.#lastBlock || lastBlock && lastBlock.index > this.#lastBlock?.index) {
948
+ if (!this.lastBlock || !this.blocks[this.blocks.length - 1].loaded || lastBlock && lastBlock.index > this.lastBlock?.index) {
858
949
  // this.#knownBlocks = await this.#makeRequest(peer, 'knownBlocks')
859
- this.#resolveErrored = false;
860
950
  await this.syncChain(lastBlock);
861
- if (await this.hasTransactionToHandle() && !this.#resolveErrored && this.#participating)
862
- this.#runEpoch();
951
+ // if (await this.hasTransactionToHandle() && this.#participating) this.#runEpoch()
863
952
  }
864
953
  }
865
954
  }
@@ -871,110 +960,10 @@ class Chain extends Contract {
871
960
  async #versionHandler() {
872
961
  return new globalThis.peernet.protos['peernet-response']({ response: { version: this.version } });
873
962
  }
874
- async #lastBlockHandler() {
875
- return new globalThis.peernet.protos['peernet-response']({ response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index } });
876
- }
877
- async #knownBlocksHandler() {
878
- return new globalThis.peernet.protos['peernet-response']({ response: { blocks: this.#blocks.map((block) => block.hash) } });
879
- }
880
- async getAndPutBlock(hash) {
881
- // todo peernet resolves undefined blocks....
882
- let block = await globalThis.peernet.get(hash, 'block');
883
- if (block !== undefined) {
884
- block = await new BlockMessage(block);
885
- const { index } = block.decoded;
886
- if (this.#blocks[index] && this.#blocks[index].hash !== block.hash)
887
- throw `invalid block ${hash} @${index}`;
888
- if (!await globalThis.peernet.has(hash, 'block'))
889
- await globalThis.peernet.put(hash, block.encoded, 'block');
890
- }
891
- return block;
892
- }
893
- async resolveBlock(hash) {
894
- if (!hash)
895
- throw new Error(`expected hash, got: ${hash}`);
896
- if (hash === '0x0')
897
- return;
898
- const index = this.#blockHashMap.get(hash);
899
- if (this.#blocks[index]) {
900
- if (this.#blocks[index].previousHash !== '0x0') {
901
- return this.resolveBlock(this.#blocks[index].previousHash);
902
- }
903
- else {
904
- return;
905
- }
906
- }
907
- try {
908
- const block = await this.getAndPutBlock(hash);
909
- const { previousHash, index } = block.decoded;
910
- const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
911
- this.#totalSize += size;
912
- this.#blocks[index] = { hash, ...block.decoded };
913
- this.#blockHashMap.set(hash, index);
914
- console.log(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
915
- this.#lastResolved = Date.now();
916
- if (previousHash !== '0x0') {
917
- return this.resolveBlock(previousHash);
918
- }
919
- }
920
- catch (error) {
921
- this.#resolveErrored = true;
922
- console.error(error);
923
- }
924
- }
925
- async resolveBlocks() {
926
- try {
927
- const localBlock = await globalThis.chainStore.get('lastBlock');
928
- const hash = new TextDecoder().decode(localBlock);
929
- if (hash && hash !== '0x0')
930
- await this.resolveBlock(hash);
931
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
932
- }
933
- catch {
934
- await globalThis.chainStore.put('lastBlock', new TextEncoder().encode('0x0'));
935
- return this.resolveBlocks();
936
- // console.log(e);
937
- }
938
- }
939
- /**
940
- *
941
- * @param {Block[]} blocks
942
- */
943
- async #loadBlocks(blocks) {
944
- let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
945
- for (const block of blocks) {
946
- if (block && !block.loaded) {
947
- for (const transaction of block.transactions) {
948
- if (poolTransactionKeys.includes(transaction.hash))
949
- await globalThis.transactionPoolStore.delete(transaction.hash);
950
- try {
951
- await this.#machine.execute(transaction.to, transaction.method, transaction.params);
952
- if (transaction.to === nativeToken) {
953
- this.#nativeCalls += 1;
954
- if (transaction.method === 'burn')
955
- this.#nativeBurns += 1;
956
- if (transaction.method === 'mint')
957
- this.#nativeMints += 1;
958
- if (transaction.method === 'transfer')
959
- this.#nativeTransfers += 1;
960
- }
961
- this.#totalTransactions += 1;
962
- }
963
- catch (error) {
964
- console.log(error);
965
- return false;
966
- }
967
- }
968
- this.#blocks[block.index].loaded = true;
969
- globalThis.debug(`loaded block: ${block.hash} @${block.index}`);
970
- }
971
- }
972
- return true;
973
- }
974
963
  async #executeTransaction({ hash, from, to, method, params, nonce }) {
975
964
  try {
976
- let result = await this.#machine.execute(to, method, params, from, nonce);
977
- // if (!result) result = this.#machine.state
965
+ let result = await this.machine.execute(to, method, params);
966
+ // if (!result) result = this.machine.state
978
967
  globalThis.pubsub.publish(`transaction.completed.${hash}`, { status: 'fulfilled', hash });
979
968
  return result || 'no state change';
980
969
  }
@@ -992,7 +981,7 @@ class Chain extends Contract {
992
981
  const hash = await blockMessage.hash();
993
982
  await globalThis.blockStore.put(hash, blockMessage.encoded);
994
983
  if (this.lastBlock.index < blockMessage.decoded.index)
995
- await this.#updateState(blockMessage);
984
+ await this.updateState(blockMessage);
996
985
  globalThis.debug(`added block: ${hash}`);
997
986
  let promises = [];
998
987
  let contracts = [];
@@ -1014,7 +1003,7 @@ class Chain extends Contract {
1014
1003
  }
1015
1004
  // todo finish state
1016
1005
  // for (const contract of contracts) {
1017
- // const state = await this.#machine.get(contract, 'state')
1006
+ // const state = await this.machine.get(contract, 'state')
1018
1007
  // // await stateStore.put(contract, state)
1019
1008
  // console.log(state);
1020
1009
  // }
@@ -1024,12 +1013,6 @@ class Chain extends Contract {
1024
1013
  console.log({ e: error });
1025
1014
  }
1026
1015
  }
1027
- async #updateState(message) {
1028
- const hash = await message.hash();
1029
- this.#lastBlock = { hash, ...message.decoded };
1030
- // await this.state.updateState(message)
1031
- await globalThis.chainStore.put('lastBlock', hash);
1032
- }
1033
1016
  async participate(address) {
1034
1017
  // TODO: validate participant
1035
1018
  // hold min amount of 50k ART for 7 days
@@ -1077,7 +1060,7 @@ class Chain extends Contract {
1077
1060
  for (let transaction of transactions) {
1078
1061
  const hash = await transaction.hash();
1079
1062
  const doubleTransactions = [];
1080
- for (const block of this.#blocks) {
1063
+ for (const block of this.blocks) {
1081
1064
  for (const transaction of block.transactions) {
1082
1065
  if (transaction.hash === hash) {
1083
1066
  doubleTransactions.push(hash);
@@ -1168,7 +1151,7 @@ class Chain extends Contract {
1168
1151
  let blockMessage = await new BlockMessage(block);
1169
1152
  const hash = await blockMessage.hash();
1170
1153
  await globalThis.peernet.put(hash, blockMessage.encoded, 'block');
1171
- await this.#updateState(blockMessage);
1154
+ await this.updateState(blockMessage);
1172
1155
  globalThis.debug(`created block: ${hash}`);
1173
1156
  globalThis.peernet.publish('add-block', blockMessage.encoded);
1174
1157
  globalThis.pubsub.publish('add-block', blockMessage.decoded);
@@ -1177,7 +1160,7 @@ class Chain extends Contract {
1177
1160
  console.log(error);
1178
1161
  throw new Error(`invalid block ${block}`);
1179
1162
  }
1180
- // data = await this.#machine.execute(to, method, params)
1163
+ // data = await this.machine.execute(to, method, params)
1181
1164
  // transactionStore.put(message.hash, message.encoded)
1182
1165
  }
1183
1166
  async #sendTransaction(transaction) {
@@ -1241,7 +1224,7 @@ class Chain extends Contract {
1241
1224
  */
1242
1225
  internalCall(sender, contract, method, parameters) {
1243
1226
  globalThis.msg = this.#createMessage(sender);
1244
- return this.#machine.execute(contract, method, parameters);
1227
+ return this.machine.execute(contract, method, parameters);
1245
1228
  }
1246
1229
  /**
1247
1230
  *
@@ -1252,19 +1235,19 @@ class Chain extends Contract {
1252
1235
  */
1253
1236
  call(contract, method, parameters) {
1254
1237
  globalThis.msg = this.#createMessage();
1255
- return this.#machine.execute(contract, method, parameters);
1238
+ return this.machine.execute(contract, method, parameters);
1256
1239
  }
1257
1240
  staticCall(contract, method, parameters) {
1258
1241
  globalThis.msg = this.#createMessage();
1259
- return this.#machine.get(contract, method, parameters);
1242
+ return this.machine.get(contract, method, parameters);
1260
1243
  }
1261
1244
  delegate(contract, method, parameters) {
1262
1245
  globalThis.msg = this.#createMessage();
1263
- return this.#machine.execute(contract, method, parameters);
1246
+ return this.machine.execute(contract, method, parameters);
1264
1247
  }
1265
1248
  staticDelegate(contract, method, parameters) {
1266
1249
  globalThis.msg = this.#createMessage();
1267
- return this.#machine.get(contract, method, parameters);
1250
+ return this.machine.get(contract, method, parameters);
1268
1251
  }
1269
1252
  mint(to, amount) {
1270
1253
  return this.call(addresses.nativeToken, 'mint', [to, amount]);
@@ -1279,7 +1262,7 @@ class Chain extends Contract {
1279
1262
  return this.staticCall(addresses.contractFactory, 'contracts');
1280
1263
  }
1281
1264
  deleteAll() {
1282
- return this.#machine.deleteAll();
1265
+ return this.machine.deleteAll();
1283
1266
  }
1284
1267
  /**
1285
1268
  * lookup an address for a registered name using the builtin nameService