@xyo-network/chain-services 1.3.31 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/neutral/index.mjs +78 -97
- package/dist/neutral/index.mjs.map +1 -1
- package/dist/types/BlockProducer/XyoBlockProducer.d.ts +1 -3
- package/dist/types/BlockProducer/XyoBlockProducer.d.ts.map +1 -1
- package/dist/types/BlockProducer/generateTransactionTransfers.d.ts +1 -1
- package/dist/types/BlockProducer/generateTransactionTransfers.d.ts.map +1 -1
- package/package.json +11 -11
- package/src/BlockProducer/XyoBlockProducer.ts +4 -26
- package/src/BlockProducer/generateTransactionTransfers.ts +12 -33
package/dist/neutral/index.mjs
CHANGED
|
@@ -252,9 +252,8 @@ var BaseEthProvider = class {
|
|
|
252
252
|
};
|
|
253
253
|
|
|
254
254
|
// src/BlockProducer/XyoBlockProducer.ts
|
|
255
|
-
import { assertEx as
|
|
256
|
-
import {
|
|
257
|
-
import { hexToBigInt, toHex as toHex2 } from "@xylabs/hex";
|
|
255
|
+
import { assertEx as assertEx2 } from "@xylabs/assert";
|
|
256
|
+
import { toHex as toHex2 } from "@xylabs/hex";
|
|
258
257
|
import { isUndefined } from "@xylabs/typeof";
|
|
259
258
|
import { FixedPercentageBlockRewardDiviner, FixedPercentageBlockRewardDivinerConfigSchema } from "@xyo-network/chain-modules";
|
|
260
259
|
import { buildBlock } from "@xyo-network/chain-protocol";
|
|
@@ -262,40 +261,35 @@ import { PayloadBuilder } from "@xyo-network/payload-builder";
|
|
|
262
261
|
import { asBlockBoundWitness, BlockNumberSchema, ChainStakeIntentSchema } from "@xyo-network/xl1-protocol";
|
|
263
262
|
|
|
264
263
|
// src/BlockProducer/generateTransactionTransfers.ts
|
|
265
|
-
import { assertEx as assertEx2 } from "@xylabs/assert";
|
|
266
264
|
import { hexFromBigInt } from "@xylabs/hex";
|
|
267
|
-
import { XYO_ZERO_ADDRESS } from "@xyo-network/chain-utils";
|
|
268
265
|
import { HydratedTransactionWrapper } from "@xyo-network/chain-wrappers";
|
|
269
|
-
import {
|
|
270
|
-
import { transactionRequiredGas } from "@xyo-network/xl1-protocol-sdk";
|
|
266
|
+
import { TransferSchema } from "@xyo-network/xl1-protocol";
|
|
271
267
|
async function generateTransactionTransfers(address, transactions) {
|
|
272
268
|
const txs = await Promise.all(transactions.map((tx) => HydratedTransactionWrapper.parse(tx)));
|
|
273
|
-
const
|
|
269
|
+
const txCosts = [];
|
|
274
270
|
for (const tx of txs) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
271
|
+
const existingItem = txCosts.find(([addr]) => addr === tx.boundWitness.from);
|
|
272
|
+
if (existingItem) {
|
|
273
|
+
existingItem[1] += tx.fees.base;
|
|
274
|
+
} else {
|
|
275
|
+
txCosts.push([
|
|
276
|
+
tx.boundWitness.from,
|
|
277
|
+
tx.fees.base
|
|
278
|
+
]);
|
|
279
|
+
}
|
|
282
280
|
}
|
|
283
|
-
const payloads =
|
|
281
|
+
const payloads = txCosts.map(([from, amount]) => {
|
|
284
282
|
const payload = {
|
|
285
283
|
schema: TransferSchema,
|
|
286
284
|
epoch: Date.now(),
|
|
287
285
|
from,
|
|
286
|
+
// TODO: add function to Wrapper to calculate entire cost of transaction
|
|
288
287
|
transfers: {
|
|
289
|
-
|
|
290
|
-
[XYO_ZERO_ADDRESS]: hexFromBigInt(amount)
|
|
288
|
+
[address]: hexFromBigInt(amount)
|
|
291
289
|
}
|
|
292
290
|
};
|
|
293
291
|
return payload;
|
|
294
292
|
});
|
|
295
|
-
for (const [from, amount] of Object.entries(txGasCosts)) {
|
|
296
|
-
const fromPayload = assertEx2(payloads.find((p) => p.from === from), () => "from payload not found");
|
|
297
|
-
fromPayload.transfers[address] = hexFromBigInt(amount);
|
|
298
|
-
}
|
|
299
293
|
return payloads;
|
|
300
294
|
}
|
|
301
295
|
__name(generateTransactionTransfers, "generateTransactionTransfers");
|
|
@@ -323,40 +317,37 @@ var XyoBlockProducer = class _XyoBlockProducer extends BaseService {
|
|
|
323
317
|
return this.account.address;
|
|
324
318
|
}
|
|
325
319
|
get account() {
|
|
326
|
-
return
|
|
327
|
-
}
|
|
328
|
-
get accountBalanceService() {
|
|
329
|
-
return assertEx3(this.params.accountBalanceService, () => "accountBalanceService is required");
|
|
320
|
+
return assertEx2(this.params.account, () => "account is required");
|
|
330
321
|
}
|
|
331
322
|
get chainFinalizedArchivist() {
|
|
332
|
-
return
|
|
323
|
+
return assertEx2(this.params.chainFinalizedArchivist, () => "chainFinalizedArchivist is required");
|
|
333
324
|
}
|
|
334
325
|
get chainInfo() {
|
|
335
|
-
return
|
|
326
|
+
return assertEx2(this.params.chainInformation, () => "chainInfo is required");
|
|
336
327
|
}
|
|
337
328
|
get electionService() {
|
|
338
|
-
return
|
|
329
|
+
return assertEx2(this.params.electionService, () => "electionService is required");
|
|
339
330
|
}
|
|
340
331
|
get pendingTransactions() {
|
|
341
|
-
return
|
|
332
|
+
return assertEx2(this.params.pendingTransactions, () => "pendingTransactions is required");
|
|
342
333
|
}
|
|
343
334
|
get pendingTransactionsService() {
|
|
344
|
-
return
|
|
335
|
+
return assertEx2(this.params.pendingTransactionsService, () => "Missing pendingTransactionsService");
|
|
345
336
|
}
|
|
346
337
|
get rejectedTransactionsArchivist() {
|
|
347
|
-
return
|
|
338
|
+
return assertEx2(this.params.rejectedTransactionsArchivist, () => "No rejected transactions archivist");
|
|
348
339
|
}
|
|
349
340
|
get rewardAddress() {
|
|
350
|
-
return
|
|
341
|
+
return assertEx2(this.params.rewardAddress, () => "No reward address provided");
|
|
351
342
|
}
|
|
352
343
|
get rewardService() {
|
|
353
|
-
return
|
|
344
|
+
return assertEx2(this.params.rewardService, () => "rewardService is required");
|
|
354
345
|
}
|
|
355
346
|
get stakeIntentService() {
|
|
356
|
-
return
|
|
347
|
+
return assertEx2(this.params.stakeIntentService, () => "No StakeIntentService provided");
|
|
357
348
|
}
|
|
358
349
|
get validateHydratedBlockState() {
|
|
359
|
-
return
|
|
350
|
+
return assertEx2(this.params.validateHydratedBlockState, () => "validateHydratedBlockState is required");
|
|
360
351
|
}
|
|
361
352
|
async next(head) {
|
|
362
353
|
if (head.chain !== this.chainInfo.id) return;
|
|
@@ -371,12 +362,12 @@ var XyoBlockProducer = class _XyoBlockProducer extends BaseService {
|
|
|
371
362
|
blockRewardService: this.rewardService,
|
|
372
363
|
config: {
|
|
373
364
|
rewardAddress: this.rewardAddress,
|
|
374
|
-
rewardPercentageRatio:
|
|
365
|
+
rewardPercentageRatio: 0,
|
|
375
366
|
schema: FixedPercentageBlockRewardDivinerConfigSchema
|
|
376
367
|
}
|
|
377
368
|
});
|
|
378
369
|
}
|
|
379
|
-
const blockHex =
|
|
370
|
+
const blockHex = assertEx2(toHex2(block), () => "Failed to convert block to hex");
|
|
380
371
|
const blockId = new PayloadBuilder({
|
|
381
372
|
schema: BlockNumberSchema
|
|
382
373
|
}).fields({
|
|
@@ -415,7 +406,7 @@ var XyoBlockProducer = class _XyoBlockProducer extends BaseService {
|
|
|
415
406
|
}
|
|
416
407
|
async proposeNextValidBlock(head) {
|
|
417
408
|
return await this.spanAsync("proposeNextValidBlock", async () => {
|
|
418
|
-
const { block: previousBlock } =
|
|
409
|
+
const { block: previousBlock } = assertEx2(asBlockBoundWitness(head), () => "Invalid head block");
|
|
419
410
|
const nextBlock = previousBlock + 1;
|
|
420
411
|
const nextBlockTransactions = await this.pendingTransactionsService.getPendingTransactions(head._hash, _XyoBlockProducer.DefaultBlockSize);
|
|
421
412
|
const blockPayloads = [];
|
|
@@ -425,18 +416,8 @@ var XyoBlockProducer = class _XyoBlockProducer extends BaseService {
|
|
|
425
416
|
const rewardTransferPayload = await this.getBlockRewardTransfer(nextBlock);
|
|
426
417
|
if (rewardTransferPayload) blockPayloads.push(rewardTransferPayload);
|
|
427
418
|
const transactionTransfers = await generateTransactionTransfers(this.address, nextBlockTransactions);
|
|
428
|
-
|
|
429
|
-
const
|
|
430
|
-
const transfer = transactionTransfers.find((txTransfer) => txTransfer.from === tx[0].from);
|
|
431
|
-
if (!transfer) return;
|
|
432
|
-
const totalTransferCost = Object.values(transfer?.transfers).reduce((acc, t) => acc + hexToBigInt(t), 0n);
|
|
433
|
-
if (hexToBigInt(this.accountBalanceService.getBalance(this.address)) >= totalTransferCost) {
|
|
434
|
-
fundedTransfers.push(transfer);
|
|
435
|
-
return tx;
|
|
436
|
-
}
|
|
437
|
-
}).filter(exists);
|
|
438
|
-
blockPayloads.push(...fundedTransfers);
|
|
439
|
-
const block = await buildBlock(head, fundedNextBlockTransactions, blockPayloads, [
|
|
419
|
+
blockPayloads.push(...transactionTransfers);
|
|
420
|
+
const block = await buildBlock(head, nextBlockTransactions, blockPayloads, [
|
|
440
421
|
this.account
|
|
441
422
|
]);
|
|
442
423
|
console.log("buildBlock", block);
|
|
@@ -456,7 +437,7 @@ XyoBlockProducer = _ts_decorate2([
|
|
|
456
437
|
], XyoBlockProducer);
|
|
457
438
|
|
|
458
439
|
// src/BlockReward/EvmBlockRewardService.ts
|
|
459
|
-
import { assertEx as
|
|
440
|
+
import { assertEx as assertEx3 } from "@xylabs/assert";
|
|
460
441
|
import { XyoChainRewards__factory as XyoChainRewardsFactory } from "@xyo-network/typechain";
|
|
461
442
|
import { toEthAddress } from "@xyo-network/xl1-protocol";
|
|
462
443
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
@@ -472,13 +453,13 @@ var EvmBlockRewardService = class extends BaseService {
|
|
|
472
453
|
}
|
|
473
454
|
_contractAddress;
|
|
474
455
|
get chainService() {
|
|
475
|
-
return
|
|
456
|
+
return assertEx3(this.params.chainService, () => "chainService is required");
|
|
476
457
|
}
|
|
477
458
|
get contractAddress() {
|
|
478
|
-
return
|
|
459
|
+
return assertEx3(this._contractAddress, () => "contractAddress is required");
|
|
479
460
|
}
|
|
480
461
|
get provider() {
|
|
481
|
-
return
|
|
462
|
+
return assertEx3(this.params.provider, () => "provider is required");
|
|
482
463
|
}
|
|
483
464
|
async createHandler() {
|
|
484
465
|
await super.createHandler();
|
|
@@ -494,7 +475,7 @@ EvmBlockRewardService = _ts_decorate3([
|
|
|
494
475
|
], EvmBlockRewardService);
|
|
495
476
|
|
|
496
477
|
// src/BlockReward/XyoBlockRewardService.ts
|
|
497
|
-
import { assertEx as
|
|
478
|
+
import { assertEx as assertEx4 } from "@xylabs/assert";
|
|
498
479
|
import { toFixedPoint } from "@xylabs/decimal-precision";
|
|
499
480
|
import { rewardFromBlockNumber } from "@xyo-network/chain-protocol";
|
|
500
481
|
function _ts_decorate4(decorators, target, key, desc) {
|
|
@@ -524,22 +505,22 @@ var XyoBlockRewardService = class extends BaseService {
|
|
|
524
505
|
});
|
|
525
506
|
}
|
|
526
507
|
get creatorReward() {
|
|
527
|
-
return
|
|
508
|
+
return assertEx4(this.params.creatorReward, () => "creatorReward is required");
|
|
528
509
|
}
|
|
529
510
|
get initialReward() {
|
|
530
|
-
return
|
|
511
|
+
return assertEx4(this.params.initialStepReward, () => "initialStepReward is required");
|
|
531
512
|
}
|
|
532
513
|
get minRewardPerBlock() {
|
|
533
|
-
return
|
|
514
|
+
return assertEx4(this.params.minRewardPerBlock, () => "minRewardPerBlock is required");
|
|
534
515
|
}
|
|
535
516
|
get stepFactorDenominator() {
|
|
536
|
-
return
|
|
517
|
+
return assertEx4(this.params.stepFactorDenominator, () => "stepFactorDenominator is required");
|
|
537
518
|
}
|
|
538
519
|
get stepFactorNumerator() {
|
|
539
|
-
return
|
|
520
|
+
return assertEx4(this.params.stepFactorNumerator, () => "stepFactorNumerator is required");
|
|
540
521
|
}
|
|
541
522
|
get stepSize() {
|
|
542
|
-
return
|
|
523
|
+
return assertEx4(this.params.stepSize, () => "stepSize is required");
|
|
543
524
|
}
|
|
544
525
|
getRewardForBlock(blockNumber) {
|
|
545
526
|
return this.rewardFromBlockNumber(blockNumber, this.initialReward, this.stepSize, this.stepFactorNumerator, this.stepFactorDenominator, this.minRewardPerBlock, this.creatorReward);
|
|
@@ -554,7 +535,7 @@ XyoBlockRewardService = _ts_decorate4([
|
|
|
554
535
|
], XyoBlockRewardService);
|
|
555
536
|
|
|
556
537
|
// src/ChainValidator/XyoValidator.ts
|
|
557
|
-
import { assertEx as
|
|
538
|
+
import { assertEx as assertEx5 } from "@xylabs/assert";
|
|
558
539
|
import { PayloadBuilder as PayloadBuilder2 } from "@xyo-network/payload-builder";
|
|
559
540
|
function _ts_decorate5(decorators, target, key, desc) {
|
|
560
541
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -577,22 +558,22 @@ var XyoValidator = class extends BaseService {
|
|
|
577
558
|
return this.account.address;
|
|
578
559
|
}
|
|
579
560
|
get account() {
|
|
580
|
-
return
|
|
561
|
+
return assertEx5(this.params.account, () => "account is required");
|
|
581
562
|
}
|
|
582
563
|
get chainFinalizedArchivist() {
|
|
583
|
-
return
|
|
564
|
+
return assertEx5(this.params.chainFinalizedArchivist, () => "chainFinalizedArchivist is required");
|
|
584
565
|
}
|
|
585
566
|
get chainInfo() {
|
|
586
|
-
return
|
|
567
|
+
return assertEx5(this.params.chainInformation, () => "chainInfo is required");
|
|
587
568
|
}
|
|
588
569
|
get electionService() {
|
|
589
|
-
return
|
|
570
|
+
return assertEx5(this.params.electionService, () => "electionService is required");
|
|
590
571
|
}
|
|
591
572
|
get pendingTransactions() {
|
|
592
|
-
return
|
|
573
|
+
return assertEx5(this.params.pendingTransactions, () => "pendingTransactions is required");
|
|
593
574
|
}
|
|
594
575
|
get rewardService() {
|
|
595
|
-
return
|
|
576
|
+
return assertEx5(this.params.rewardService, () => "rewardService is required");
|
|
596
577
|
}
|
|
597
578
|
validatePendingBlock(_block) {
|
|
598
579
|
return [];
|
|
@@ -611,7 +592,7 @@ XyoValidator = _ts_decorate5([
|
|
|
611
592
|
], XyoValidator);
|
|
612
593
|
|
|
613
594
|
// src/Election/XyoElectionService.ts
|
|
614
|
-
import { assertEx as
|
|
595
|
+
import { assertEx as assertEx6 } from "@xylabs/assert";
|
|
615
596
|
import { hexToLast4BytesInt, shuffleWithSeed } from "@xyo-network/chain-utils";
|
|
616
597
|
import { PayloadBuilder as PayloadBuilder3 } from "@xyo-network/payload-builder";
|
|
617
598
|
function _ts_decorate6(decorators, target, key, desc) {
|
|
@@ -633,13 +614,13 @@ var XyoElectionService = class extends BaseService {
|
|
|
633
614
|
super(params);
|
|
634
615
|
}
|
|
635
616
|
get chainIterator() {
|
|
636
|
-
return
|
|
617
|
+
return assertEx6(this.params.chainIterator, () => "No chain iterator");
|
|
637
618
|
}
|
|
638
619
|
get chainStakeViewer() {
|
|
639
|
-
return
|
|
620
|
+
return assertEx6(this.params.chainStakeViewer, () => "No chain stake viewer");
|
|
640
621
|
}
|
|
641
622
|
get stakeIntentService() {
|
|
642
|
-
return
|
|
623
|
+
return assertEx6(this.params.stakeIntentService, () => "No staked intent service");
|
|
643
624
|
}
|
|
644
625
|
async getCreatorCommitteeForNextBlock(current) {
|
|
645
626
|
return await this.spanAsync("getCreatorCommitteeForNextBlock", async () => {
|
|
@@ -667,8 +648,8 @@ XyoElectionService = _ts_decorate6([
|
|
|
667
648
|
// src/PendingTransactions/PendingTransactions.ts
|
|
668
649
|
import { ValueType } from "@opentelemetry/api";
|
|
669
650
|
import { filterAs, filterAsync } from "@xylabs/array";
|
|
670
|
-
import { assertEx as
|
|
671
|
-
import { exists
|
|
651
|
+
import { assertEx as assertEx7 } from "@xylabs/assert";
|
|
652
|
+
import { exists } from "@xylabs/exists";
|
|
672
653
|
import { forget } from "@xylabs/forget";
|
|
673
654
|
import { MemoryArchivist } from "@xyo-network/archivist-memory";
|
|
674
655
|
import { validateTransaction } from "@xyo-network/chain-validation";
|
|
@@ -724,23 +705,23 @@ var XyoPendingTransactionsService = class _XyoPendingTransactionsService extends
|
|
|
724
705
|
*/
|
|
725
706
|
_updateCuratedPendingTransactionsArchivistMutex = new Mutex2();
|
|
726
707
|
get chainArchivist() {
|
|
727
|
-
return
|
|
708
|
+
return assertEx7(this.params.chainArchivist, () => "No completed blocks with data archivist");
|
|
728
709
|
}
|
|
729
710
|
get chainIdentification() {
|
|
730
|
-
return
|
|
711
|
+
return assertEx7(this.params.chainIdentification, () => "No chain id");
|
|
731
712
|
}
|
|
732
713
|
get pendingTransactionsArchivist() {
|
|
733
|
-
return
|
|
714
|
+
return assertEx7(this.params.pendingTransactionsArchivist, () => "No pending transactions archivist");
|
|
734
715
|
}
|
|
735
716
|
get pendingTransactionsCount() {
|
|
736
717
|
forget(this.countPendingTransactions());
|
|
737
718
|
return this._pendingTransactionsCount;
|
|
738
719
|
}
|
|
739
720
|
get pendingTransactionsLocalArchivist() {
|
|
740
|
-
return
|
|
721
|
+
return assertEx7(this._curatedPendingTransactionsArchivist, () => "No pending transactions curated archivist");
|
|
741
722
|
}
|
|
742
723
|
get rejectedTransactionsArchivist() {
|
|
743
|
-
return
|
|
724
|
+
return assertEx7(this.params.rejectedTransactionsArchivist, () => "No rejected transactions archivist");
|
|
744
725
|
}
|
|
745
726
|
async createHandler() {
|
|
746
727
|
await super.createHandler();
|
|
@@ -777,11 +758,11 @@ var XyoPendingTransactionsService = class _XyoPendingTransactionsService extends
|
|
|
777
758
|
});
|
|
778
759
|
if (payloads.length === 0) break;
|
|
779
760
|
cursor = payloads.at(-1)?._sequence;
|
|
780
|
-
const transactions = payloads.map((payload) => asOptionalTransactionBoundWitnessWithStorageMeta(payload)).filter(
|
|
761
|
+
const transactions = payloads.map((payload) => asOptionalTransactionBoundWitnessWithStorageMeta(payload)).filter(exists);
|
|
781
762
|
foundPendingTransactions.push(...transactions);
|
|
782
763
|
}
|
|
783
764
|
const hydratedTransactions = await Promise.all(foundPendingTransactions.map((tx) => tryHydrateTransaction(this.pendingTransactionsLocalArchivist, tx._hash)));
|
|
784
|
-
return hydratedTransactions.filter(
|
|
765
|
+
return hydratedTransactions.filter(exists);
|
|
785
766
|
}, _XyoPendingTransactionsService.MutexPriority.ReadTransactions);
|
|
786
767
|
});
|
|
787
768
|
}
|
|
@@ -807,7 +788,7 @@ var XyoPendingTransactionsService = class _XyoPendingTransactionsService extends
|
|
|
807
788
|
const unprocessedTransactions = await this.filterAlreadyFinalizedTransactions(payloads);
|
|
808
789
|
const hydratedUnprocessedTransactions = (await Promise.all(unprocessedTransactions.map((tx) => {
|
|
809
790
|
return tryHydrateTransaction(this.pendingTransactionsArchivist, tx._hash);
|
|
810
|
-
}))).filter(
|
|
791
|
+
}))).filter(exists);
|
|
811
792
|
const validTransactions = await filterAsync(hydratedUnprocessedTransactions, async (tx) => {
|
|
812
793
|
const errors = await validateTransaction(tx, this.chainIdentification.id);
|
|
813
794
|
return errors.length > 0 ? false : true;
|
|
@@ -837,7 +818,7 @@ XyoPendingTransactionsService = _ts_decorate7([
|
|
|
837
818
|
|
|
838
819
|
// src/StakeIntent/lib/getBlockSignedStakeDeclarations.ts
|
|
839
820
|
import { filterAs as filterAs2 } from "@xylabs/array";
|
|
840
|
-
import { exists as
|
|
821
|
+
import { exists as exists2 } from "@xylabs/exists";
|
|
841
822
|
import { asOptionalBoundWitness } from "@xyo-network/boundwitness-model";
|
|
842
823
|
import { payloadSchemasContains } from "@xyo-network/boundwitness-validator";
|
|
843
824
|
import { BoundWitnessWrapper } from "@xyo-network/boundwitness-wrapper";
|
|
@@ -848,7 +829,7 @@ var getBlockSignedStakeDeclarations = /* @__PURE__ */ __name(async (block, archi
|
|
|
848
829
|
const bwsFromBlockWithDeclarations = bwsFromBlock.filter((bw) => payloadSchemasContains(bw, ChainStakeIntentSchema2));
|
|
849
830
|
const validBlockBwsWithDeclarations = await filterToValidSignedBoundWitnesses(bwsFromBlockWithDeclarations);
|
|
850
831
|
return (await Promise.all(validBlockBwsWithDeclarations.map(async (bw) => {
|
|
851
|
-
const stakeIntentHashes = validBlockBwsWithDeclarations.flatMap(mapBoundWitnessToStakeIntentHashes).filter(
|
|
832
|
+
const stakeIntentHashes = validBlockBwsWithDeclarations.flatMap(mapBoundWitnessToStakeIntentHashes).filter(exists2);
|
|
852
833
|
const payloads = await archivist.get(stakeIntentHashes);
|
|
853
834
|
const stakeIntents = filterAs2(payloads, asOptionalChainStakeIntent).filter((p) => p.intent === intent).filter((p) => bw.addresses.includes(p.from));
|
|
854
835
|
return stakeIntents;
|
|
@@ -864,7 +845,7 @@ var mapBoundWitnessToStakeIntentHashes = /* @__PURE__ */ __name((bw) => {
|
|
|
864
845
|
|
|
865
846
|
// src/StakeIntent/XyoStakeIntentService.ts
|
|
866
847
|
import { filterAs as filterAs3 } from "@xylabs/array";
|
|
867
|
-
import { assertEx as
|
|
848
|
+
import { assertEx as assertEx8 } from "@xylabs/assert";
|
|
868
849
|
import { asAddress } from "@xylabs/hex";
|
|
869
850
|
import { analyzeChain as analyzeChain2, ChainStakeIntentAnalyzer, isChainSummaryStakeIntent } from "@xyo-network/chain-analyze";
|
|
870
851
|
import { DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS, findFirstMatching, IntervalMap } from "@xyo-network/chain-utils";
|
|
@@ -911,16 +892,16 @@ var XyoStakeIntentService = class extends BaseService {
|
|
|
911
892
|
});
|
|
912
893
|
}
|
|
913
894
|
get chainArchivist() {
|
|
914
|
-
return
|
|
895
|
+
return assertEx8(this.params.chainArchivist, () => "chainArchivist not set");
|
|
915
896
|
}
|
|
916
897
|
get chainIterator() {
|
|
917
|
-
return
|
|
898
|
+
return assertEx8(this.params.chainIterator, () => "chainIterator not set");
|
|
918
899
|
}
|
|
919
900
|
get chainStakeViewer() {
|
|
920
|
-
return
|
|
901
|
+
return assertEx8(this.params.chainStakeViewer, () => "chainStakeViewer not set");
|
|
921
902
|
}
|
|
922
903
|
get stakeIntentStateArchivist() {
|
|
923
|
-
return
|
|
904
|
+
return assertEx8(this.params.stakeIntentStateArchivist, () => "stakeIntentStateArchivist not set");
|
|
924
905
|
}
|
|
925
906
|
async createHandler() {
|
|
926
907
|
const head = await this.chainIterator.head();
|
|
@@ -931,13 +912,13 @@ var XyoStakeIntentService = class extends BaseService {
|
|
|
931
912
|
}
|
|
932
913
|
async getDeclaredCandidateRanges(address, intent) {
|
|
933
914
|
await Promise.resolve();
|
|
934
|
-
|
|
915
|
+
assertEx8(intent === "producer", () => `Error: Support not yet added for intent ${intent}`);
|
|
935
916
|
const results = this._producers.get(address);
|
|
936
917
|
return results ?? [];
|
|
937
918
|
}
|
|
938
919
|
async getDeclaredCandidatesForBlock(block, intent) {
|
|
939
920
|
return await this.spanAsync("getDeclaredCandidatesForBlock", async () => {
|
|
940
|
-
|
|
921
|
+
assertEx8(intent === "producer", () => `Error: Support not yet added for intent ${intent}`);
|
|
941
922
|
const results = this._producers.findAllContaining(block);
|
|
942
923
|
const candidates = [
|
|
943
924
|
...results
|
|
@@ -990,7 +971,7 @@ var XyoStakeIntentService = class extends BaseService {
|
|
|
990
971
|
]);
|
|
991
972
|
}
|
|
992
973
|
async recoverState(current) {
|
|
993
|
-
const currentBlock =
|
|
974
|
+
const currentBlock = assertEx8(asOptionalBlockBoundWitness((await this.chainArchivist.get([
|
|
994
975
|
current
|
|
995
976
|
]))?.[0]), () => `Block ${current} not found`);
|
|
996
977
|
const currentBlockNum = currentBlock.block;
|
|
@@ -1152,7 +1133,7 @@ var EvmChainService = class extends Base {
|
|
|
1152
1133
|
};
|
|
1153
1134
|
|
|
1154
1135
|
// src/XyoChainBlockNumberIterator.ts
|
|
1155
|
-
import { assertEx as
|
|
1136
|
+
import { assertEx as assertEx9 } from "@xylabs/assert";
|
|
1156
1137
|
import { BaseEmitter as BaseEmitter2 } from "@xylabs/events";
|
|
1157
1138
|
import { isDefined, isNull } from "@xylabs/typeof";
|
|
1158
1139
|
import { PayloadBuilder as PayloadBuilder5 } from "@xyo-network/payload-builder";
|
|
@@ -1188,7 +1169,7 @@ var XyoChainBlockNumberIterator = class _XyoChainBlockNumberIterator extends Bas
|
|
|
1188
1169
|
return new _XyoChainBlockNumberIterator(params);
|
|
1189
1170
|
}
|
|
1190
1171
|
async get(block) {
|
|
1191
|
-
|
|
1172
|
+
assertEx9(this._head.block >= block, () => `Block requested is newer than the current head [${block}]`);
|
|
1192
1173
|
const cached = this._blocksByBlockNumber.get(block);
|
|
1193
1174
|
if (cached) return cached;
|
|
1194
1175
|
const startingBlock = this._head;
|
|
@@ -1197,7 +1178,7 @@ var XyoChainBlockNumberIterator = class _XyoChainBlockNumberIterator extends Bas
|
|
|
1197
1178
|
currentBlockHash
|
|
1198
1179
|
])).at(0);
|
|
1199
1180
|
while (isDefined(currentBlock)) {
|
|
1200
|
-
|
|
1181
|
+
assertEx9(asBlockBoundWitness2(currentBlock), () => `Expected hash to be a block bound witness [${currentBlock?._hash}]`);
|
|
1201
1182
|
if (isBlockBoundWitness(currentBlock)) {
|
|
1202
1183
|
this._blocksByBlockNumber.set(currentBlock.block, currentBlock);
|
|
1203
1184
|
if (currentBlock.block === block) {
|
|
@@ -1236,7 +1217,7 @@ var XyoChainBlockNumberIterator = class _XyoChainBlockNumberIterator extends Bas
|
|
|
1236
1217
|
currentBlock = asOptionalBlockBoundWitness2(nextBlock[0]);
|
|
1237
1218
|
} else {
|
|
1238
1219
|
const hash = PayloadBuilder5.hash(currentBlock);
|
|
1239
|
-
|
|
1220
|
+
assertEx9(asBlockBoundWitness2(currentBlock), () => `Expected hash to be a block bound witness [${hash}]`);
|
|
1240
1221
|
}
|
|
1241
1222
|
}
|
|
1242
1223
|
return results;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/AccountBalance/XyoChainAccountBalanceService.ts","../../src/BaseService.ts","../../src/BaseEthProvider.ts","../../src/BlockProducer/XyoBlockProducer.ts","../../src/BlockProducer/generateTransactionTransfers.ts","../../src/BlockReward/EvmBlockRewardService.ts","../../src/BlockReward/XyoBlockRewardService.ts","../../src/ChainValidator/XyoValidator.ts","../../src/Election/XyoElectionService.ts","../../src/PendingTransactions/PendingTransactions.ts","../../src/StakeIntent/lib/getBlockSignedStakeDeclarations.ts","../../src/StakeIntent/XyoStakeIntentService.ts","../../src/Staker/Evm/Evm.ts","../../src/XyoChainBlockNumberIterator.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport {\n Address, Hash, Hex,\n toHex,\n} from '@xylabs/hex'\nimport {\n analyzeChain, BalanceAnalyzer, isChainSummaryBalances,\n} from '@xyo-network/chain-analyze'\nimport { SignedBigInt, toPositiveBigInt } from '@xyo-network/chain-protocol'\nimport {\n AccountBalanceService, BaseServiceParams,\n ChainServiceCollection,\n} from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport type ChainAccountBalanceServiceParams = BaseServiceParams<Partial<Pick<ChainServiceCollection, 'chainArchivist'>>>\n\n@creatableService()\nexport class XyoChainAccountBalanceService extends BaseService<ChainAccountBalanceServiceParams> implements AccountBalanceService {\n private _balances: Record<Address, SignedBigInt> = {}\n private _previousHead: Hash | null = null\n\n protected get chainArchivist() {\n return assertEx(this.params.chainArchivist, () => 'chainArchivist is required')\n }\n\n getBalance(address: Address): Hex {\n return toPositiveBigInt(this._balances[address] ?? { positive: toHex(0n) }).positive\n }\n\n getBalances(): Record<Address, Hex> {\n const result: Record<Address, Hex> = {}\n const entries = Object.entries(this._balances) as [Address, SignedBigInt][]\n for (const [address, balance] of entries) {\n result[address] = toPositiveBigInt(balance).positive\n }\n return result\n }\n\n async sync(head: Hash): Promise<void> {\n const analysis = await analyzeChain(\n this.chainArchivist,\n [new BalanceAnalyzer()],\n head,\n this._previousHead,\n -1n,\n this.tracer,\n )\n this._balances = assertEx(analysis.find(isChainSummaryBalances)?.balances, () => 'Failed to sync balances')\n }\n}\n","import { BaseEmitter } from '@xylabs/events'\nimport type { Promisable } from '@xylabs/promise'\nimport { span, spanAsync } from '@xyo-network/chain-utils'\nimport type {\n BaseAccountableServiceParams, BaseServiceParams, Service,\n} from '@xyo-network/xl1-protocol'\nimport { Mutex } from 'async-mutex'\n\ndeclare global {\n var xyoServiceSingletons: Record<string, unknown>\n}\n\nexport class BaseService<TParams extends BaseServiceParams = BaseServiceParams> extends BaseEmitter<TParams> {\n private static singletonInitMutex = new Mutex()\n\n static get singletons() {\n return globalThis['xyoServiceSingletons'] ?? (globalThis['xyoServiceSingletons'] = {})\n }\n\n get name() {\n return this.constructor.name\n }\n\n static async create<TService extends BaseService<TParams>, TParams extends BaseServiceParams = TService['params']>(\n this: CreatableService<TService>,\n params: TParams,\n ): Promise<TService> {\n const result = new this(params)\n if (result.name === 'BaseService') throw new Error('Cannot create BaseService')\n await result.createHandler()\n return result\n }\n\n static initSingleton<TService extends BaseService<TParams>, TParams extends BaseServiceParams>(params: TParams) {\n if (this.singletons[this.name]) throw new Error(`Singleton already initialized for ${this.name}`)\n return this.singletonInitMutex.runExclusive(async () => {\n return await this.create(params) as TService\n })\n }\n\n createHandler(): Promisable<void> {\n return\n }\n\n span<T>(name: string, fn: () => T): T {\n return span(name, fn, this.tracer)\n }\n\n async spanAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {\n return await spanAsync(name, fn, this.tracer)\n }\n}\n\nexport abstract class BaseAccountableService<\n TParams extends BaseAccountableServiceParams = BaseAccountableServiceParams,\n> extends BaseService<TParams> {\n // Base class for services that have an account\n}\n\nexport interface CreatableService<T extends BaseService = BaseService> extends Service {\n new(params: T['params']): T\n create<T extends BaseService>(this: CreatableService<T>, params: T['params']): Promisable<T>\n}\n\nexport function creatableService<T extends BaseService = BaseService>() {\n return <U extends CreatableService<T>>(constructor: U) => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n constructor\n }\n}\n","import type {\n Address, BlockAPI,\n BlockNumberOrTag,\n CompileResultAPI,\n EthExecutionAPI,\n FeeHistoryResultAPI,\n Filter,\n FilterResultsAPI,\n HexString, HexString8Bytes,\n HexString32Bytes,\n HexString256Bytes,\n HexStringBytes,\n SignedTransactionInfoAPI,\n SyncingStatusAPI,\n TransactionCallAPI,\n TransactionInfoAPI,\n TransactionReceiptAPI,\n TransactionWithSenderAPI,\n Uint,\n Uint256,\n} from 'web3-types'\n\nexport class BaseEthProvider implements EthExecutionAPI {\n eth_accounts(): Address[] {\n throw new Error('Method not implemented.')\n }\n\n eth_blockNumber(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_call(_transaction: TransactionCallAPI, _blockNumber: BlockNumberOrTag): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_clearSubscriptions(_keepSyncing?: boolean): void {\n throw new Error('Method not implemented.')\n }\n\n eth_coinbase(): Address {\n throw new Error('Method not implemented.')\n }\n\n eth_compileLLL(_code: string): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_compileSerpent(_code: string): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_compileSolidity(_code: string): CompileResultAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_estimateGas(_transaction: Partial<TransactionWithSenderAPI>, _blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_feeHistory(_blockCount: Uint, _newestBlock: BlockNumberOrTag, _rewardPercentiles: number[]): FeeHistoryResultAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_gasPrice(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getBalance(_address: Address, _blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getBlockByHash(_blockHash: HexString32Bytes, _hydrated: boolean): BlockAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getBlockByNumber(_blockNumber: BlockNumberOrTag, _hydrated: boolean): BlockAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getBlockTransactionCountByHash(_blockHash: HexString32Bytes): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getBlockTransactionCountByNumber(_blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getCode(_address: Address, _blockNumber: BlockNumberOrTag): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_getCompilers(): string[] {\n throw new Error('Method not implemented.')\n }\n\n eth_getFilterChanges(_filterIdentifier: Uint): FilterResultsAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getFilterLogs(_filterIdentifier: Uint): FilterResultsAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getLogs(_filter: Filter): FilterResultsAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getStorageAt(_address: Address, _storageSlot: Uint256, _blockNumber: BlockNumberOrTag): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionByBlockHashAndIndex(_blockHash: HexString32Bytes, _transactionIndex: Uint): TransactionInfoAPI | undefined {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionByBlockNumberAndIndex(_blockNumber: BlockNumberOrTag, _transactionIndex: Uint): TransactionInfoAPI | undefined {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionByHash(_transactionHash: HexString32Bytes): TransactionInfoAPI | undefined {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionCount(_address: Address, _blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionReceipt(_transactionHash: HexString32Bytes): TransactionReceiptAPI | undefined {\n throw new Error('Method not implemented.')\n }\n\n eth_getUncleByBlockHashAndIndex(_blockHash: HexString32Bytes, _uncleIndex: Uint): BlockAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getUncleByBlockNumberAndIndex(_blockNumber: BlockNumberOrTag, _uncleIndex: Uint): BlockAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getUncleCountByBlockHash(_blockHash: HexString32Bytes): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getUncleCountByBlockNumber(_blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getWork(): [HexString32Bytes, HexString32Bytes, HexString32Bytes] {\n throw new Error('Method not implemented.')\n }\n\n eth_hashrate(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_maxPriorityFeePerGas(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_mining(): boolean {\n throw new Error('Method not implemented.')\n }\n\n eth_newBlockFilter(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_newFilter(_filter: Filter): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_newPendingTransactionFilter(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_protocolVersion(): string {\n throw new Error('Method not implemented.')\n }\n\n eth_sendRawTransaction(_transaction: HexStringBytes): HexString32Bytes {\n throw new Error('Method not implemented.')\n }\n\n eth_sendTransaction(_transaction: TransactionWithSenderAPI | Partial<TransactionWithSenderAPI>): HexString32Bytes {\n throw new Error('Method not implemented.')\n }\n\n eth_sign(_address: Address, _message: HexStringBytes): HexString256Bytes {\n throw new Error('Method not implemented.')\n }\n\n eth_signTransaction(_transaction: TransactionWithSenderAPI | Partial<TransactionWithSenderAPI>): HexStringBytes | SignedTransactionInfoAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_submitHashrate(_hashRate: HexString32Bytes, _id: HexString32Bytes): boolean {\n throw new Error('Method not implemented.')\n }\n\n eth_submitWork(_nonce: HexString8Bytes, _hash: HexString32Bytes, _digest: HexString32Bytes): boolean {\n throw new Error('Method not implemented.')\n }\n\n eth_subscribe(..._params: ['newHeads'] | ['newPendingTransactions'] | ['syncing'] | ['logs', { address?: HexString; topics?: HexString[] }]): HexString {\n throw new Error('Method not implemented.')\n }\n\n eth_syncing(): SyncingStatusAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_uninstallFilter(_filterIdentifier: Uint): boolean {\n throw new Error('Method not implemented.')\n }\n\n eth_unsubscribe(_subscriptionId: HexString): HexString {\n throw new Error('Method not implemented.')\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport {\n Address, hexToBigInt, toHex,\n} from '@xylabs/hex'\nimport { isUndefined } from '@xylabs/typeof'\nimport { ArchivistInstance, ReadArchivist } from '@xyo-network/archivist-model'\nimport {\n BlockRewardDiviner, FixedPercentageBlockRewardDiviner, FixedPercentageBlockRewardDivinerConfigSchema,\n} from '@xyo-network/chain-modules'\nimport { buildBlock } from '@xyo-network/chain-protocol'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { WithStorageMeta } from '@xyo-network/payload-model'\nimport {\n AccountBalanceService,\n AllowedBlockPayload, asBlockBoundWitness, BlockBoundWitness, BlockNumber, BlockNumberSchema, BlockProducer, ChainStakeIntent, ChainStakeIntentSchema,\n HydratedBlock, PendingTransactionsService, StakeIntentService, Transfer,\n} from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\nimport { XyoValidatorParams } from '../ChainValidator/index.ts'\nimport { generateTransactionTransfers } from './generateTransactionTransfers.ts'\n\n/**\n * The default block size for a block\n */\nexport const DEFAULT_BLOCK_SIZE = 10\n\n// /**\n// * The amount of time for which a producer will restake their intent\n// */\nexport const XYO_PRODUCER_RESTAKE_DURATION = 10_000\n\n/**\n * The number of blocks within which a producer will redeclare\n * their intent to produce blocks\n */\nexport const XYO_PRODUCER_RESTAKE_WINDOW = 500n\n\nexport interface XyoBlockProducerParams extends XyoValidatorParams {\n accountBalanceService?: AccountBalanceService\n pendingTransactionsArchivist?: ReadArchivist\n pendingTransactionsService?: PendingTransactionsService\n rejectedTransactionsArchivist?: ArchivistInstance\n rewardAddress?: Address\n stakeIntentService?: StakeIntentService\n}\n\n@creatableService()\nexport class XyoBlockProducer extends BaseService<XyoBlockProducerParams> implements BlockProducer {\n protected _blockRewardDiviner: BlockRewardDiviner | undefined\n\n static get DefaultBlockSize(): number {\n return DEFAULT_BLOCK_SIZE\n }\n\n get address() {\n return this.account.address\n }\n\n protected get account() {\n return assertEx(this.params.account, () => 'account is required')\n }\n\n protected get accountBalanceService() {\n return assertEx(this.params.accountBalanceService, () => 'accountBalanceService is required')\n }\n\n protected get chainFinalizedArchivist() {\n return assertEx(this.params.chainFinalizedArchivist, () => 'chainFinalizedArchivist is required')\n }\n\n protected get chainInfo() {\n return assertEx(this.params.chainInformation, () => 'chainInfo is required')\n }\n\n protected get electionService() {\n return assertEx(this.params.electionService, () => 'electionService is required')\n }\n\n protected get pendingTransactions() {\n return assertEx(this.params.pendingTransactions, () => 'pendingTransactions is required')\n }\n\n protected get pendingTransactionsService() {\n return assertEx(this.params.pendingTransactionsService, () => 'Missing pendingTransactionsService')\n }\n\n protected get rejectedTransactionsArchivist() {\n return assertEx(this.params.rejectedTransactionsArchivist, () => 'No rejected transactions archivist')\n }\n\n protected get rewardAddress(): Address {\n return assertEx(this.params.rewardAddress, () => 'No reward address provided')\n }\n\n protected get rewardService() {\n return assertEx(this.params.rewardService, () => 'rewardService is required')\n }\n\n protected get stakeIntentService(): StakeIntentService {\n return assertEx(this.params.stakeIntentService, () => 'No StakeIntentService provided')\n }\n\n protected get validateHydratedBlockState() {\n return assertEx(this.params.validateHydratedBlockState, () => 'validateHydratedBlockState is required')\n }\n\n async next(head: WithStorageMeta<BlockBoundWitness>): Promise<HydratedBlock | undefined> {\n // If the block is for another chain, ignore\n if (head.chain !== this.chainInfo.id) return\n const leaders = await this.electionService.getCreatorCommitteeForNextBlock(head)\n // TODO: Should we propose block if creator committee is empty?\n // TODO: Handle the case where we're not the 1st leader but they're not responding\n // at a higher level than here as that's a network issue\n if (leaders?.[0] !== this.address) return\n return this.proposeNextValidBlock(head)\n }\n\n protected async getBlockRewardTransfer(block: number): Promise<Transfer | undefined> {\n if (!this._blockRewardDiviner) {\n // TODO: Adjust to allow for genesis block reward vs. normal block reward\n this._blockRewardDiviner = await FixedPercentageBlockRewardDiviner.create({\n account: 'random',\n blockRewardService: this.rewardService,\n config: {\n rewardAddress: this.rewardAddress,\n rewardPercentageRatio: 50,\n schema: FixedPercentageBlockRewardDivinerConfigSchema,\n },\n })\n }\n const blockHex = assertEx(toHex(block), () => 'Failed to convert block to hex')\n const blockId = new PayloadBuilder<BlockNumber>({ schema: BlockNumberSchema }).fields({ block: blockHex }).build()\n const rewards = await this._blockRewardDiviner.divine([blockId])\n const [reward] = rewards\n return reward\n }\n\n /**\n * Handles the producer redeclaration logic\n * @param head The current head block\n * @returns\n */\n protected async getProducerRedeclaration(head: WithStorageMeta<BlockBoundWitness>): Promise<ChainStakeIntent | undefined> {\n const redeclareIntent = process.env.XYO_PRODUCER_REDECLARE_INTENT\n if (isUndefined(redeclareIntent)) return\n // Decide if we need to redeclare\n const ranges = await this.stakeIntentService.getDeclaredCandidateRanges(this.address, 'producer')\n // TODO: This doesn't handle the case where the producer had declared a range for the future\n // but we're in a range that's not the future\n // Sort in ascending order based on ending range to get range with highest ending block\n const lastRange = ranges.toSorted((a, b) => a[1] > b[1] ? 1 : -1).at(-1)\n if (!lastRange) return\n const [, currentDeclarationEnd] = lastRange\n const currentBlock = head.block\n const timeToProducerExpiration = currentDeclarationEnd - currentBlock\n if (timeToProducerExpiration > XYO_PRODUCER_RESTAKE_WINDOW) return\n // Create redeclaration\n const intent = new PayloadBuilder<ChainStakeIntent>({ schema: ChainStakeIntentSchema }).fields({\n from: this.address,\n intent: 'producer',\n nbf: currentBlock,\n exp: currentBlock + XYO_PRODUCER_RESTAKE_DURATION,\n }).build()\n return intent\n }\n\n protected async proposeNextValidBlock(head: WithStorageMeta<BlockBoundWitness>): Promise<HydratedBlock | undefined> {\n return await this.spanAsync('proposeNextValidBlock', async () => {\n // Calculate the next block components\n const { block: previousBlock } = assertEx(asBlockBoundWitness(head), () => 'Invalid head block')\n const nextBlock = previousBlock + 1\n const nextBlockTransactions = await this.pendingTransactionsService.getPendingTransactions(head._hash, XyoBlockProducer.DefaultBlockSize)\n\n const blockPayloads: AllowedBlockPayload[] = []\n\n // Calculate the optional producer redeclaration and add it if necessary\n const producerRedeclarationPayload = await this.getProducerRedeclaration(head)\n if (producerRedeclarationPayload) blockPayloads.push(producerRedeclarationPayload)\n\n // If there are no transactions and no payloads, we don't need to create a block\n if (blockPayloads.length === 0 && nextBlockTransactions.length === 0) return\n\n // Calculate the optional block reward transfer and add if necessary\n const rewardTransferPayload = await this.getBlockRewardTransfer(nextBlock)\n if (rewardTransferPayload) blockPayloads.push(rewardTransferPayload)\n\n const transactionTransfers = await generateTransactionTransfers(this.address, nextBlockTransactions)\n\n const fundedTransfers: Transfer[] = []\n\n const fundedNextBlockTransactions = nextBlockTransactions.map((tx) => {\n const transfer: Transfer | undefined = transactionTransfers.find(txTransfer => txTransfer.from === tx[0].from)\n if (!transfer) return\n const totalTransferCost = Object.values(transfer?.transfers).reduce((acc, t) => acc + hexToBigInt(t), 0n)\n if (hexToBigInt(this.accountBalanceService.getBalance(this.address)) >= totalTransferCost) {\n fundedTransfers.push(transfer)\n return tx\n }\n }).filter(exists)\n\n blockPayloads.push(...fundedTransfers)\n\n // Build the block\n const block = await buildBlock(head, fundedNextBlockTransactions, blockPayloads, [this.account])\n console.log('buildBlock', block)\n const errors = await this.validateHydratedBlockState(block, this.chainInfo.id, this.chainFinalizedArchivist)\n if (errors.length > 0) {\n this.logger?.error('Validation of produced block failed', errors)\n const rejectedTransactions = block[1]\n await this.rejectedTransactionsArchivist.insert(rejectedTransactions)\n } else {\n return block\n }\n })\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { type Address, hexFromBigInt } from '@xylabs/hex'\nimport { XYO_ZERO_ADDRESS } from '@xyo-network/chain-utils'\nimport { HydratedTransactionWrapper } from '@xyo-network/chain-wrappers'\nimport type {\n HydratedTransaction,\n Transfer,\n} from '@xyo-network/xl1-protocol'\nimport {\n MicroXL1,\n mXL1ToXL1, TransferSchema,\n XL1,\n} from '@xyo-network/xl1-protocol'\nimport { transactionRequiredGas } from '@xyo-network/xl1-protocol-sdk'\n\nexport async function generateTransactionTransfers(address: Address, transactions: HydratedTransaction[]): Promise<Transfer[]> {\n const txs = await Promise.all(transactions.map(tx => HydratedTransactionWrapper.parse(tx)))\n\n // merge transactions with the same from address\n const txBaseFeeCosts: Record<Address, XL1> = {}\n for (const tx of txs) {\n txBaseFeeCosts[tx.boundWitness.from] = XL1((txBaseFeeCosts[tx.boundWitness.from] ?? 0n) + mXL1ToXL1(tx.fees.base))\n }\n\n const txGasCosts: Record<Address, XL1> = {}\n for (const tx of txs) {\n const requiredGas = transactionRequiredGas(tx.data)\n const totalGasCostInMicroXL1 = MicroXL1(requiredGas * tx.fees.gasPrice)\n txGasCosts[tx.boundWitness.from] = XL1((txBaseFeeCosts[tx.boundWitness.from] ?? 0n) + mXL1ToXL1(totalGasCostInMicroXL1))\n }\n\n // generate actual Transfer Payloads & burn the base fee\n const payloads = (Object.entries(txBaseFeeCosts) as [Address, XL1][]).map(([from, amount]) => {\n const payload: Transfer = {\n schema: TransferSchema,\n epoch: Date.now(),\n from,\n transfers: {\n // burn the base fee\n [XYO_ZERO_ADDRESS]: hexFromBigInt(amount),\n },\n }\n return payload\n })\n\n // transfer gas cost to producer\n for (const [from, amount] of Object.entries(txGasCosts)) {\n // every gas from should also be a base fee from\n const fromPayload = assertEx(payloads.find(p => p.from === from), () => 'from payload not found')\n fromPayload.transfers[address] = hexFromBigInt(amount)\n }\n\n return payloads\n}\n","import { assertEx } from '@xylabs/assert'\nimport { XyoChainRewards__factory as XyoChainRewardsFactory } from '@xyo-network/typechain'\nimport {\n BaseAccountableServiceParams, BlockRewardService, ChainService,\n toEthAddress,\n} from '@xyo-network/xl1-protocol'\nimport { Provider } from 'ethers/providers'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface EvmBlockRewardServiceParams extends BaseAccountableServiceParams {\n chainService?: ChainService\n provider?: Provider\n}\n\n@creatableService<EvmBlockRewardService>()\nexport class EvmBlockRewardService extends BaseService<EvmBlockRewardServiceParams> implements BlockRewardService {\n protected _contractAddress: string | undefined\n\n protected get chainService() {\n return assertEx(this.params.chainService, () => 'chainService is required')\n }\n\n protected get contractAddress() {\n return assertEx(this._contractAddress, () => 'contractAddress is required')\n }\n\n protected get provider() {\n return assertEx(this.params.provider, () => 'provider is required')\n }\n\n override async createHandler() {\n await super.createHandler()\n this._contractAddress = await this.chainService.rewardsContract()\n }\n\n async getRewardForBlock(blockNumber: bigint): Promise<bigint> {\n const contract = XyoChainRewardsFactory.connect(toEthAddress(this.contractAddress), this.provider)\n return await contract.calcBlockReward(blockNumber)\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { toFixedPoint } from '@xylabs/decimal-precision'\nimport { Promisable } from '@xylabs/promise'\nimport { rewardFromBlockNumber } from '@xyo-network/chain-protocol'\nimport { BaseServiceParams, BlockRewardService } from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface XyoBlockRewardServiceParams extends BaseServiceParams {\n creatorReward?: bigint\n initialStepReward?: bigint\n minRewardPerBlock?: bigint\n stepFactorDenominator?: bigint\n stepFactorNumerator?: bigint\n stepSize?: bigint\n}\n\n@creatableService()\nexport class XyoBlockRewardService extends BaseService<XyoBlockRewardServiceParams> implements BlockRewardService {\n protected readonly rewardFromBlockNumber = rewardFromBlockNumber(18)\n\n constructor(\n {\n creatorReward = toFixedPoint(20_000_000_000n),\n initialStepReward = toFixedPoint(3000n),\n minRewardPerBlock = toFixedPoint(30n),\n stepFactorDenominator = 100n,\n stepFactorNumerator = 90n,\n stepSize = 1_000_000n,\n }: Partial<XyoBlockRewardServiceParams> = {},\n ) {\n super({\n initialStepReward, minRewardPerBlock, stepSize, stepFactorDenominator, stepFactorNumerator, creatorReward,\n })\n }\n\n get creatorReward() {\n return assertEx(this.params.creatorReward, () => 'creatorReward is required')\n }\n\n get initialReward() {\n return assertEx(this.params.initialStepReward, () => 'initialStepReward is required')\n }\n\n get minRewardPerBlock() {\n return assertEx(this.params.minRewardPerBlock, () => 'minRewardPerBlock is required')\n }\n\n get stepFactorDenominator() {\n return assertEx(this.params.stepFactorDenominator, () => 'stepFactorDenominator is required')\n }\n\n get stepFactorNumerator() {\n return assertEx(this.params.stepFactorNumerator, () => 'stepFactorNumerator is required')\n }\n\n get stepSize() {\n return assertEx(this.params.stepSize, () => 'stepSize is required')\n }\n\n getRewardForBlock(blockNumber: bigint): Promisable<bigint> {\n return this.rewardFromBlockNumber(\n blockNumber,\n this.initialReward,\n this.stepSize,\n this.stepFactorNumerator,\n this.stepFactorDenominator,\n this.minRewardPerBlock,\n this.creatorReward,\n )\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Promisable } from '@xylabs/promise'\nimport { AccountInstance } from '@xyo-network/account-model'\nimport { ArchivistInstance, ReadArchivist } from '@xyo-network/archivist-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport {\n BaseServiceParams,\n BlockBoundWitness,\n BlockRewardService,\n ChainInformation,\n ElectionService,\n HydratedBlockStateValidationFunction,\n HydratedTransaction,\n HydratedTransactionWithStorageMeta,\n StakeIntentService,\n} from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\nimport { Validator } from './model/index.ts'\n\nconst addStorageMeta = async ([tx, payloads]: HydratedTransaction): Promise<HydratedTransactionWithStorageMeta> => {\n return [await PayloadBuilder.addStorageMeta(tx), await PayloadBuilder.addStorageMeta(payloads)]\n}\n\nexport interface XyoValidatorParams extends BaseServiceParams {\n account?: AccountInstance\n chainFinalizedArchivist?: ReadArchivist\n chainInformation?: ChainInformation\n electionService?: ElectionService\n pendingTransactions?: ArchivistInstance\n rewardService?: BlockRewardService\n stakeIntentService?: StakeIntentService\n validateHydratedBlockState?: HydratedBlockStateValidationFunction\n}\n\n@creatableService()\nexport class XyoValidator<TParams extends XyoValidatorParams = XyoValidatorParams> extends BaseService<TParams> implements Validator {\n get address() {\n return this.account.address\n }\n\n protected get account() {\n return assertEx(this.params.account, () => 'account is required')\n }\n\n protected get chainFinalizedArchivist() {\n return assertEx(this.params.chainFinalizedArchivist, () => 'chainFinalizedArchivist is required')\n }\n\n protected get chainInfo() {\n return assertEx(this.params.chainInformation, () => 'chainInfo is required')\n }\n\n protected get electionService() {\n return assertEx(this.params.electionService, () => 'electionService is required')\n }\n\n protected get pendingTransactions() {\n return assertEx(this.params.pendingTransactions, () => 'pendingTransactions is required')\n }\n\n protected get rewardService() {\n return assertEx(this.params.rewardService, () => 'rewardService is required')\n }\n\n validatePendingBlock(_block: BlockBoundWitness): Promisable<Error[]> {\n return [] // await validateBlockProtocol(block, this.chainInfo)\n }\n\n // TODO: Move to validator and inherit this class from validator\n async validatePendingTransaction(hydratedTransaction: HydratedTransaction): Promise<boolean> {\n const [tx] = await addStorageMeta(hydratedTransaction)\n // Ensure not confirmed already (replay attack)\n if ((await this.chainFinalizedArchivist.get([tx._hash])).length > 0) return false\n // TODO: Ensure transaction is valid (double spend, has voucher, has required stake, etc.)\n // TODO: Ensure validator stake is valid\n return await Promise.resolve(true)\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Address, Hash } from '@xylabs/hex'\nimport { hexToLast4BytesInt, shuffleWithSeed } from '@xyo-network/chain-utils'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport type {\n BaseServiceParams, ChainBlockNumberIterator, ChainStakeViewer, StakeIntentService,\n} from '@xyo-network/xl1-protocol'\nimport { BlockBoundWitness, ElectionService } from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface XyoElectionServicesParams extends BaseServiceParams {\n chainIterator?: ChainBlockNumberIterator\n chainStakeViewer?: ChainStakeViewer\n stakeIntentService?: StakeIntentService\n}\n\n@creatableService()\nexport class XyoElectionService extends BaseService<XyoElectionServicesParams> implements ElectionService {\n constructor(params: XyoElectionServicesParams) {\n super(params)\n }\n\n get chainIterator() {\n return assertEx(this.params.chainIterator, () => 'No chain iterator')\n }\n\n get chainStakeViewer() {\n return assertEx(this.params.chainStakeViewer, () => 'No chain stake viewer')\n }\n\n get stakeIntentService() {\n return assertEx(this.params.stakeIntentService, () => 'No staked intent service')\n }\n\n async getCreatorCommitteeForNextBlock(current: BlockBoundWitness): Promise<Address[]> {\n return await this.spanAsync('getCreatorCommitteeForNextBlock', async () => {\n const nextBlock = current.block + 1\n const candidates = await this.stakeIntentService.getDeclaredCandidatesForBlock(nextBlock, 'producer')\n const previousBlockHash = await PayloadBuilder.hash(current)\n return this.generateCreatorCommittee(candidates, previousBlockHash)\n })\n }\n\n protected generateCreatorCommittee(candidates: Address[], previousBlockHash: Hash, maxSize = 3): Address[] {\n const creators = new Set<Address>(candidates)\n const seed = hexToLast4BytesInt(previousBlockHash)\n const creatorArray = shuffleWithSeed(creators, seed)\n return creatorArray.slice(0, maxSize)\n }\n}\n","import { ValueType } from '@opentelemetry/api'\nimport { filterAs, filterAsync } from '@xylabs/array'\nimport { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { MemoryArchivist } from '@xyo-network/archivist-memory'\nimport { ArchivistInstance } from '@xyo-network/archivist-model'\nimport { validateTransaction } from '@xyo-network/chain-validation'\nimport {\n Payload, Sequence, WithStorageMeta,\n} from '@xyo-network/payload-model'\nimport {\n asOptionalTransactionBoundWitnessWithStorageMeta, BaseServiceParams, ChainIdentification, HydratedTransactionWithStorageMeta,\n PendingTransactionsService, TransactionBoundWitness,\n} from '@xyo-network/xl1-protocol'\nimport { flattenHydratedTransactions, tryHydrateTransaction } from '@xyo-network/xl1-protocol-sdk'\nimport { Mutex } from 'async-mutex'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface XyoPendingTransactionsServiceParams extends BaseServiceParams {\n chainArchivist?: ArchivistInstance\n chainIdentification?: ChainIdentification\n pendingTransactionsArchivist?: ArchivistInstance\n rejectedTransactionsArchivist?: ArchivistInstance\n}\n\n@creatableService()\nexport class XyoPendingTransactionsService extends BaseService<XyoPendingTransactionsServiceParams> implements PendingTransactionsService {\n private static readonly MutexPriority = {\n /**\n * Priority for inserting new transactions\n */\n InsertNewTransactions: 5,\n /**\n * Priority for reading pending transactions\n */\n ReadTransactions: 3,\n /**\n * Priority for removing rejected transactions\n */\n RemoveRejectedTransactions: 2,\n /**\n * Priority for removing finalized transactions\n */\n RemoveFinalizedTransactions: 1,\n } as const\n\n /**\n * A mutex to ensure that the counting the number of pending transactions is\n * not called concurrently\n */\n private _countPendingTransactionsMutex = new Mutex()\n\n /**\n * A local Archivist optimized for fast retrieval that stores only validated\n * pending transactions\n */\n private _curatedPendingTransactionsArchivist: MemoryArchivist | undefined\n\n /**\n * The last count of total pending transactions\n */\n private _pendingTransactionsCount: number = 0\n\n /**\n * A mutex to ensure that the curated pending transactions archivist is\n * updated in a thread-safe manner\n */\n private _updateCuratedPendingTransactionsArchivistMutex = new Mutex()\n\n private get chainArchivist() {\n return assertEx(this.params.chainArchivist, () => 'No completed blocks with data archivist')\n }\n\n private get chainIdentification() {\n return assertEx(this.params.chainIdentification, () => 'No chain id')\n }\n\n private get pendingTransactionsArchivist() {\n return assertEx(this.params.pendingTransactionsArchivist, () => 'No pending transactions archivist')\n }\n\n private get pendingTransactionsCount() {\n forget(this.countPendingTransactions())\n return this._pendingTransactionsCount\n }\n\n private get pendingTransactionsLocalArchivist() {\n return assertEx(this._curatedPendingTransactionsArchivist, () => 'No pending transactions curated archivist')\n }\n\n private get rejectedTransactionsArchivist() {\n return assertEx(this.params.rejectedTransactionsArchivist, () => 'No rejected transactions archivist')\n }\n\n override async createHandler() {\n await super.createHandler()\n this._curatedPendingTransactionsArchivist = await MemoryArchivist.create({ account: 'random' })\n\n // On new pending transactions, insert them into the curated archivist\n this.pendingTransactionsArchivist.on('inserted', async ({ payloads }) => {\n await this.insertNewTransactions(payloads)\n })\n\n // On new finalized blocks, remove the transactions from the curated archivist\n this.chainArchivist.on('inserted', async ({ payloads }) => {\n await this.removeFinalizedTransactions(payloads)\n })\n\n // On new rejected blocks, remove the transactions from the curated archivist\n this.rejectedTransactionsArchivist.on('inserted', async ({ payloads }) => {\n await this.removeRejectedTransactions(payloads)\n })\n\n const pendingTransactionsGauge = this.meter?.createObservableGauge(\n 'xyo_pending_transactions_count',\n { description: 'The current number of pending transactions', valueType: ValueType.INT },\n )\n pendingTransactionsGauge?.addCallback((observer) => {\n observer.observe(this.pendingTransactionsCount)\n })\n }\n\n async getPendingTransactions(head: Hash, limit: number): Promise<HydratedTransactionWithStorageMeta[]> {\n return await this.spanAsync('getPendingTransactions', async () => {\n return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {\n const foundPendingTransactions: WithStorageMeta<TransactionBoundWitness>[] = []\n let cursor: Sequence | undefined\n while (foundPendingTransactions.length < limit) {\n const payloads = await this.pendingTransactionsLocalArchivist.next({\n limit: 100, order: 'asc', cursor,\n })\n if (payloads.length === 0) break\n cursor = payloads.at(-1)?._sequence\n const transactions = payloads.map(payload => asOptionalTransactionBoundWitnessWithStorageMeta(payload)).filter(exists)\n foundPendingTransactions.push(...transactions)\n }\n const hydratedTransactions = await Promise.all(\n foundPendingTransactions.map(tx => tryHydrateTransaction(this.pendingTransactionsLocalArchivist, tx._hash)),\n )\n return hydratedTransactions.filter(exists)\n }, XyoPendingTransactionsService.MutexPriority.ReadTransactions)\n })\n }\n\n private async countPendingTransactions() {\n if (this._countPendingTransactionsMutex.isLocked()) return\n await this._countPendingTransactionsMutex.runExclusive(async () => {\n const payloads = (await this._curatedPendingTransactionsArchivist?.all()) ?? []\n const pendingTransactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta)\n this._pendingTransactionsCount = pendingTransactions.length\n })\n }\n\n private async filterAlreadyFinalizedTransactions(payloads: WithStorageMeta<Payload>[]): Promise<WithStorageMeta<TransactionBoundWitness>[]> {\n const incomingTransactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta)\n const incomingTransactionHashes = incomingTransactions.map(payload => payload._hash)\n const finalizedTransactions = await this.chainArchivist.get(incomingTransactionHashes)\n const finalizedTransactionHashes = new Set(finalizedTransactions.map(item => item._hash))\n const nonFinalizedTransactions = incomingTransactions.filter(item => !finalizedTransactionHashes.has(item._hash))\n return nonFinalizedTransactions\n }\n\n private async insertNewTransactions(payloads: WithStorageMeta<Payload>[]) {\n return await this.spanAsync('InsertNewTransactions', async () => {\n return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {\n // Check incoming transactions against finalized transactions\n const unprocessedTransactions = await this.filterAlreadyFinalizedTransactions(payloads)\n // Hydrate all unprocessed transactions\n const hydratedUnprocessedTransactions = (await Promise.all(unprocessedTransactions.map((tx) => {\n return tryHydrateTransaction(this.pendingTransactionsArchivist, tx._hash)\n }))).filter(exists)\n // Filter to only valid transactions\n const validTransactions = await filterAsync(hydratedUnprocessedTransactions, async (tx) => {\n const errors = await validateTransaction(tx, this.chainIdentification.id)\n return errors.length > 0 ? false : true\n })\n await this.pendingTransactionsLocalArchivist.insert(flattenHydratedTransactions(validTransactions))\n }, XyoPendingTransactionsService.MutexPriority.InsertNewTransactions)\n })\n }\n\n private async removeFinalizedTransactions(payloads: WithStorageMeta<Payload>[]) {\n return await this.removeTransactions(payloads, 'RemoveFinalizedTransactions')\n }\n\n private async removeRejectedTransactions(payloads: WithStorageMeta<Payload>[]) {\n return await this.removeTransactions(payloads, 'RemoveRejectedTransactions')\n }\n\n private async removeTransactions(\n payloads: WithStorageMeta<Payload>[],\n priority: keyof typeof XyoPendingTransactionsService.MutexPriority,\n ) {\n return await this.spanAsync(priority, async () => {\n return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {\n const transactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta)\n await this.pendingTransactionsLocalArchivist.delete(transactions.map(tx => tx._hash))\n }, XyoPendingTransactionsService.MutexPriority[priority])\n })\n }\n}\n","import { filterAs } from '@xylabs/array'\nimport { exists } from '@xylabs/exists'\nimport type { Hash } from '@xylabs/hex'\nimport type { ArchivistInstance } from '@xyo-network/archivist-model'\nimport type { BoundWitness } from '@xyo-network/boundwitness-model'\nimport { asOptionalBoundWitness } from '@xyo-network/boundwitness-model'\nimport { payloadSchemasContains } from '@xyo-network/boundwitness-validator'\nimport { BoundWitnessWrapper } from '@xyo-network/boundwitness-wrapper'\nimport type {\n BlockBoundWitness, ChainStakeIntent, Intent,\n} from '@xyo-network/xl1-protocol'\nimport { asOptionalChainStakeIntent, ChainStakeIntentSchema } from '@xyo-network/xl1-protocol'\n\nexport const getBlockSignedStakeDeclarations = async (block: BlockBoundWitness, archivist: ArchivistInstance, intent: Intent): Promise<ChainStakeIntent[]> => {\n // Get payloads in block\n const blockData = await archivist.get(block.payload_hashes)\n // Filter Payloads in block to BoundWitnesses\n const bwsFromBlock = filterAs(blockData, asOptionalBoundWitness)\n // Filter to BoundWitnesses with StakeIntent payloads\n const bwsFromBlockWithDeclarations = bwsFromBlock.filter(bw => payloadSchemasContains(bw, ChainStakeIntentSchema))\n // Filter to only valid signed BWs\n const validBlockBwsWithDeclarations = await filterToValidSignedBoundWitnesses(bwsFromBlockWithDeclarations)\n return (await Promise.all(validBlockBwsWithDeclarations.map(async (bw) => {\n // Get staked intent hashes from signed declarations\n const stakeIntentHashes = validBlockBwsWithDeclarations\n .flatMap(mapBoundWitnessToStakeIntentHashes)\n .filter(exists)\n // Get staked intent payloads\n const payloads = await archivist.get(stakeIntentHashes)\n // Filter payloads to staked intents\n const stakeIntents = filterAs(payloads, asOptionalChainStakeIntent)\n // that are producers\n .filter(p => p.intent === intent)\n // where the issuer of the intent is also the signer of this BW\n .filter(p => bw.addresses.includes(p.from))\n\n return stakeIntents\n }))).flat()\n}\n\nconst filterToValidSignedBoundWitnesses = async (bws: BoundWitness[]): Promise<BoundWitness[]> => {\n const validBwIndexes = await Promise.all(bws.map(bw => BoundWitnessWrapper.parse(bw).getValid()))\n return bws.filter((_, index) => validBwIndexes[index])\n}\n\nconst mapBoundWitnessToStakeIntentHashes = (bw: BoundWitness): (Hash | undefined)[] => {\n return bw.payload_schemas.map((schema, index) => schema === ChainStakeIntentSchema ? bw.payload_hashes[index] : undefined)\n}\n","import { filterAs } from '@xylabs/array'\nimport { assertEx } from '@xylabs/assert'\nimport {\n Address, asAddress, Hash,\n} from '@xylabs/hex'\nimport { ArchivistInstance, ArchivistNextOptions } from '@xyo-network/archivist-model'\nimport {\n analyzeChain, ChainStakeIntentAnalyzer,\n isChainSummaryStakeIntent,\n} from '@xyo-network/chain-analyze'\nimport {\n DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS,\n findFirstMatching, IntervalMap,\n SerializedIntervalMap,\n} from '@xyo-network/chain-utils'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, WithStorageMeta } from '@xyo-network/payload-model'\nimport type {\n BaseServiceParams, EventingChainBlockNumberIterator, Intent,\n} from '@xyo-network/xl1-protocol'\nimport {\n asOptionalBlockBoundWitness, asOptionalBlockBoundWitnessWithStorageMeta,\n asOptionalChainIndexingServiceStateWithStorageMeta, asOptionalChainStakeIntent, ChainIndexingServiceState, ChainIndexingServiceStateSchema, ChainStakeViewer,\n isChainIndexingServiceState,\n StakeIntentService,\n} from '@xyo-network/xl1-protocol'\nimport { Mutex } from 'async-mutex'\nimport { LRUCache } from 'lru-cache'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface XyoStakeIntentServiceParams extends BaseServiceParams {\n chainArchivist?: ArchivistInstance\n chainIterator?: EventingChainBlockNumberIterator\n chainStakeViewer?: ChainStakeViewer\n stakeIntentStateArchivist?: ArchivistInstance\n}\n\n/**\n * The number of blocks to periodically persist state\n */\nconst STATE_PERSISTENCE_INTERVAL = 60n\n\nconst ACTIVE_STAKE_TTL = 1000 * 60 * 60 * 2 // 2 hours in milliseconds\nconst NO_ACTIVE_STAKE_TTL = 1000 * 2 // 2 seconds in milliseconds\nconst STAKE_CACHE_MAX_ENTRIES = 10_000\n\n@creatableService()\nexport class XyoStakeIntentService extends BaseService<XyoStakeIntentServiceParams> implements StakeIntentService {\n // TODO: Use hash instead of block number to handle chain reorgs\n protected _lastIndexedBlockHash: Hash | undefined = undefined\n // TODO: Interval tree per declaration (bank, validator, etc.)\n // NOTE: Ideally move to DataIntervalTree to handle declared\n // ranges as it enables range queries in O(min(n, k * log n)) time,\n // where k is the number of intervals in the output list time\n // Currently using set based because it's simpler, equivalent\n // in performance for small sets, and (most importantly) easily\n // persisted so we can recover state on restart.\n protected _producers: IntervalMap<Address> = new IntervalMap()\n protected _stakeCache = new LRUCache<Address, bigint>({ max: STAKE_CACHE_MAX_ENTRIES })\n protected _updateMutex = new Mutex()\n\n constructor(params: XyoStakeIntentServiceParams) {\n super(params)\n this.chainIterator.on('headUpdated', async () => {\n await this.updateIndex()\n })\n }\n\n protected get chainArchivist() {\n return assertEx(this.params.chainArchivist, () => 'chainArchivist not set')\n }\n\n protected get chainIterator() {\n return assertEx(this.params.chainIterator, () => 'chainIterator not set')\n }\n\n protected get chainStakeViewer() {\n return assertEx(this.params.chainStakeViewer, () => 'chainStakeViewer not set')\n }\n\n protected get stakeIntentStateArchivist() {\n return assertEx(this.params.stakeIntentStateArchivist, () => 'stakeIntentStateArchivist not set')\n }\n\n override async createHandler(): Promise<void> {\n const head = await this.chainIterator.head()\n const headHash = await PayloadBuilder.hash(head)\n if (head?.block === undefined) return\n await this.recoverState(headHash)\n await this.updateIndex(true)\n }\n\n async getDeclaredCandidateRanges(address: Address, intent: Intent): Promise<Readonly<Readonly<[number, number]>[]>> {\n await Promise.resolve()\n assertEx(intent === 'producer', () => `Error: Support not yet added for intent ${intent}`)\n const results = this._producers.get(address)\n return results ?? []\n }\n\n async getDeclaredCandidatesForBlock(block: number, intent: Intent): Promise<Address[]> {\n return await this.spanAsync('getDeclaredCandidatesForBlock', async () => {\n assertEx(intent === 'producer', () => `Error: Support not yet added for intent ${intent}`)\n const results = this._producers.findAllContaining(block)\n const candidates = [...results]\n const validCandidates = await this.filterToValidStake(candidates, this.chainStakeViewer)\n return validCandidates\n })\n }\n\n async isStakedForBlock(block: number, intent: Intent, address: Address): Promise<boolean> {\n const candidates = await this.getDeclaredCandidatesForBlock(block, intent)\n return candidates.includes(address)\n }\n\n private async filterToValidStake(\n candidates: Address[],\n chainStakeViewer: ChainStakeViewer,\n requiredMinimumStake: bigint = 1n,\n ): Promise<Address[]> {\n type CandidateStake = { candidate: Address; stake: bigint }\n\n // Find the stake for each candidate\n const candidatesWithStake: CandidateStake[] = await Promise.all(\n candidates.map(async (candidate) => {\n // Check if the stake is already cached\n const stake = this._stakeCache.get(candidate)\n if (stake === undefined) {\n // Fetch from chainStakeViewer if not cached\n const activeStake = await chainStakeViewer.activeByAddressStaked(`${candidate}`)\n if (activeStake > 0n) {\n // Store result in cache\n this._stakeCache.set(candidate, activeStake, { ttl: ACTIVE_STAKE_TTL })\n } else {\n this._stakeCache.set(candidate, activeStake, { ttl: NO_ACTIVE_STAKE_TTL })\n }\n return { candidate, stake: activeStake }\n } else {\n return { candidate, stake }\n }\n }),\n )\n\n // Filter out candidates whose stake is greater than or equal to the required minimum\n return candidatesWithStake\n .filter(({ stake }) => stake >= requiredMinimumStake)\n .map(({ candidate }) => candidate)\n }\n\n private async persistState(current: Hash): Promise<void> {\n const state = this._producers.serialize()\n const payload = new PayloadBuilder<ChainIndexingServiceState<SerializedIntervalMap>>({ schema: ChainIndexingServiceStateSchema })\n .fields({ endBlockHash: current, state })\n .build()\n await this.stakeIntentStateArchivist.insert([payload])\n }\n\n private async recoverState(current: Hash): Promise<void> {\n const currentBlock = assertEx(asOptionalBlockBoundWitness((await this.chainArchivist.get([current]))?.[0]), () => `Block ${current} not found`)\n const currentBlockNum = currentBlock.block\n // Find last state before current head (in case of rollback, we indexed past it on an uncle chain, etc.)\n const opts: ArchivistNextOptions = { ...DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS }\n while (true) {\n const predicate = (p: WithStorageMeta<Payload>) => {\n const state = asOptionalChainIndexingServiceStateWithStorageMeta(p)\n return state ? true : false\n }\n const state = await findFirstMatching(this.stakeIntentStateArchivist, predicate, opts)\n if (isChainIndexingServiceState<SerializedIntervalMap>(state)) {\n const indexed = (await this.chainArchivist.get([state.endBlockHash]))?.[0]\n const indexedBlock = asOptionalBlockBoundWitnessWithStorageMeta(indexed)\n if (indexedBlock) {\n const indexedBlockNum = indexedBlock.block\n if (indexedBlockNum <= currentBlockNum) {\n const data = state.state as SerializedIntervalMap\n this._producers = new IntervalMap(data)\n this._lastIndexedBlockHash = indexedBlock._hash\n break\n }\n }\n } else {\n // No state found, start from genesis\n break\n }\n opts.open = true\n }\n }\n\n private async updateIndex(displayProgress = false): Promise<void> {\n if (this._updateMutex.isLocked()) {\n return\n }\n await this._updateMutex.runExclusive(async () => {\n return await this.spanAsync('updateIndex', async () => {\n const currentHead = await this.chainIterator.head()\n const currentHeadHash = await PayloadBuilder.hash(currentHead)\n const result = await analyzeChain(this.chainArchivist, [new ChainStakeIntentAnalyzer('producer')], currentHeadHash, this._lastIndexedBlockHash)\n const signedDeclarations = filterAs(result.find(isChainSummaryStakeIntent)?.intents ?? [], asOptionalChainStakeIntent)\n if (currentHead.block === undefined) return\n const currentHeadBlockNum = currentHead.block\n if (displayProgress) this.logger?.info(`Updating index through 0x${currentHeadBlockNum}`)\n for (const signedDeclaration of signedDeclarations) {\n const { exp, nbf } = signedDeclaration\n const start = nbf\n const stop = exp\n const address = asAddress(signedDeclaration?.from)\n if (start !== undefined && stop !== undefined && address !== undefined) {\n this._producers.insert(address, start, stop)\n }\n }\n /*\n if (index % STATE_PERSISTENCE_INTERVAL === 0n) {\n if (displayProgress) this.logger?.info(`Persisting state at block ${index}`)\n await this.persistState(await PayloadBuilder.hash(block))\n }\n */\n this._lastIndexedBlockHash = currentHeadHash\n })\n })\n }\n}\n","import { Base } from '@xylabs/base'\nimport type { Address } from '@xylabs/hex'\nimport { toAddress } from '@xylabs/hex'\nimport type { Promisable } from '@xylabs/promise'\nimport type { StakedXyoChain } from '@xyo-network/typechain'\nimport { StakedXyoChain__factory as StakedXyoChainFactory } from '@xyo-network/typechain'\nimport type { BaseServiceParams, ChainService } from '@xyo-network/xl1-protocol'\nimport { getAddress } from 'ethers/address'\nimport type { ContractRunner } from 'ethers/providers'\n\nexport interface EvmChainServiceParams extends BaseServiceParams {\n contract: StakedXyoChain\n id: Address\n runner: ContractRunner\n}\n\n/**\n * A class that represents a chain stake as backed by an EVM smart contract\n */\nexport class EvmChainService extends Base<EvmChainServiceParams> implements ChainService {\n private _contract: StakedXyoChain\n\n protected constructor(params: EvmChainServiceParams) {\n super(params)\n this._contract = params.contract\n }\n\n get id(): Address {\n return this.params.id\n }\n\n get runner(): ContractRunner {\n return this.params.runner\n }\n\n static create({\n id, runner, logger, traceProvider, meterProvider,\n }: Omit<EvmChainServiceParams, 'contract'>): Promisable<EvmChainService> {\n const contractAddress = getAddress(id)\n const contract: StakedXyoChain = StakedXyoChainFactory.connect(contractAddress, runner)\n return new this({\n id, contract, runner, logger, traceProvider, meterProvider,\n })\n }\n\n async active(): Promise<bigint> {\n return await this._contract.active()\n }\n\n async activeByAddressStaked(address: string): Promise<bigint> {\n return await this._contract.activeByAddressStaked(getAddress(address))\n }\n\n async activeByStaker(address: string): Promise<bigint> {\n return await this._contract.activeByStaker(getAddress(address))\n }\n\n async addStake(staked: string, amount: bigint): Promise<boolean> {\n const result = await this._contract.addStake(getAddress(staked), amount)\n await result.wait()\n return true\n }\n\n async chainId(): Promise<Address> {\n return toAddress(await this._contract.chainId())\n }\n\n async forkedAtBlockNumber(): Promise<bigint> {\n return await this._contract.forkedAtBlockNumber()\n }\n\n async forkedAtHash(): Promise<bigint> {\n return await this._contract.forkedAtHash()\n }\n\n async forkedChainId(): Promise<Address> {\n return toAddress(await this._contract.forkedChainId())\n }\n\n async minWithdrawalBlocks(): Promise<bigint> {\n return await this._contract.minWithdrawalBlocks()\n }\n\n async pending(): Promise<bigint> {\n return await this._contract.pending()\n }\n\n async pendingByStaker(staker: string): Promise<bigint> {\n return await this._contract.pendingByStaker(getAddress(staker))\n }\n\n async removeStake(slot: bigint): Promise<boolean> {\n const result = await this._contract.removeStake(slot)\n await result.wait()\n return true\n }\n\n async rewardsContract(): Promise<string> {\n return await this._contract.rewardsContract()\n }\n\n async stakingTokenAddress(): Promise<string> {\n return await this._contract.stakingTokenAddress()\n }\n\n async withdrawStake(slot: bigint): Promise<boolean> {\n const result = await this._contract.withdrawStake(slot)\n await result.wait()\n return true\n }\n\n async withdrawn(): Promise<bigint> {\n return await this._contract.withdrawn()\n }\n\n async withdrawnByStaker(staker: string): Promise<bigint> {\n return await this._contract.withdrawnByStaker(getAddress(staker))\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport type { BaseParams } from '@xylabs/base'\nimport { BaseEmitter } from '@xylabs/events'\nimport { isDefined, isNull } from '@xylabs/typeof'\nimport type { ArchivistInstance } from '@xyo-network/archivist-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport type {\n BlockBoundWitness, ChainIdentification,\n ChainIteratorEventData,\n EventingChainBlockNumberIterator,\n XyoChainIteratorParams,\n} from '@xyo-network/xl1-protocol'\nimport {\n asBlockBoundWitness, asOptionalBlockBoundWitness,\n isBlockBoundWitness,\n} from '@xyo-network/xl1-protocol'\nimport { LRUCache } from 'lru-cache'\n\nexport class XyoChainBlockNumberIterator extends BaseEmitter<BaseParams, ChainIteratorEventData> implements EventingChainBlockNumberIterator {\n protected _blocksByBlockNumber = new LRUCache<number, BlockBoundWitness>({ max: 10_000 })\n protected _chainArchivist: ArchivistInstance\n protected _chainInformation: ChainIdentification\n protected _head: BlockBoundWitness\n\n protected constructor(params: XyoChainIteratorParams) {\n super({})\n const { chainArchivist: archivist, head } = params\n this._chainArchivist = archivist\n this._head = head\n this._chainInformation = { id: head.chain }\n }\n\n get archivist(): ArchivistInstance { return this._chainArchivist }\n\n get chainIdentification(): ChainIdentification { return this._chainInformation }\n\n static async create(params: XyoChainIteratorParams): Promise<XyoChainBlockNumberIterator> {\n await Promise.resolve()\n return new XyoChainBlockNumberIterator(params)\n }\n\n async get(block: number): Promise<BlockBoundWitness> {\n // Bail early if the block requested is newer than the current head\n assertEx(this._head.block >= block, () => `Block requested is newer than the current head [${block}]`)\n const cached = this._blocksByBlockNumber.get(block)\n if (cached) return cached\n // Start at the current head and traverse backwards until the requested block is found\n const startingBlock = this._head\n const currentBlockHash = await PayloadBuilder.hash(startingBlock)\n let currentBlock = (await this._chainArchivist.get([currentBlockHash])).at(0)\n while (isDefined(currentBlock)) {\n assertEx(asBlockBoundWitness(currentBlock), () => `Expected hash to be a block bound witness [${currentBlock?._hash}]`)\n if (isBlockBoundWitness(currentBlock)) {\n this._blocksByBlockNumber.set(currentBlock.block, currentBlock)\n if (currentBlock.block === block) {\n return currentBlock\n }\n const { previous } = currentBlock\n if (isNull(previous)) break\n currentBlock = (await this._chainArchivist.get([previous])).at(0)\n }\n }\n throw new Error(`Block not found: ${block}`)\n }\n\n async head(): Promise<BlockBoundWitness> {\n return await Promise.resolve(this._head)\n }\n\n async next(block: number): Promise<BlockBoundWitness | undefined> {\n const currentBlock = block\n const nextBlockNumber = currentBlock + 1\n return await this.get(nextBlockNumber)\n }\n\n // TODO: Decide on inclusive/exclusive (probably need inclusive to account for chain head)\n // and then communicate via method name and documentation\n async previous(block: number | undefined = undefined, count: number = 1): Promise<BlockBoundWitness[]> {\n const results: BlockBoundWitness[] = []\n let currentBlock: BlockBoundWitness | undefined = isDefined(block) ? (await this.get(block)) : this._head\n while (currentBlock && results.length < count) {\n if (isBlockBoundWitness(currentBlock)) {\n results.push(currentBlock)\n const { previous } = currentBlock\n if (isNull(previous)) break\n const nextBlock = await this._chainArchivist.get([previous])\n currentBlock = asOptionalBlockBoundWitness(nextBlock[0])\n } else {\n const hash = PayloadBuilder.hash(currentBlock)\n assertEx(asBlockBoundWitness(currentBlock), () => `Expected hash to be a block bound witness [${hash}]`)\n }\n }\n return results\n }\n\n async updateHead(head: BlockBoundWitness): Promise<void> {\n // Async to allow for re-indexing, etc.\n await Promise.resolve()\n this._head = head\n void this.emit('headUpdated', { blocks: [head] })\n }\n}\n"],"mappings":"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","names":["assertEx","toHex","analyzeChain","BalanceAnalyzer","isChainSummaryBalances","toPositiveBigInt","BaseEmitter","span","spanAsync","Mutex","BaseService","BaseEmitter","singletonInitMutex","Mutex","singletons","globalThis","name","constructor","create","params","result","Error","createHandler","initSingleton","runExclusive","span","fn","tracer","spanAsync","BaseAccountableService","creatableService","XyoChainAccountBalanceService","BaseService","_balances","_previousHead","chainArchivist","assertEx","params","getBalance","address","toPositiveBigInt","positive","toHex","getBalances","result","entries","Object","balance","sync","head","analysis","analyzeChain","BalanceAnalyzer","tracer","find","isChainSummaryBalances","balances","BaseEthProvider","eth_accounts","Error","eth_blockNumber","eth_call","_transaction","_blockNumber","eth_clearSubscriptions","_keepSyncing","eth_coinbase","eth_compileLLL","_code","eth_compileSerpent","eth_compileSolidity","eth_estimateGas","eth_feeHistory","_blockCount","_newestBlock","_rewardPercentiles","eth_gasPrice","eth_getBalance","_address","eth_getBlockByHash","_blockHash","_hydrated","eth_getBlockByNumber","eth_getBlockTransactionCountByHash","eth_getBlockTransactionCountByNumber","eth_getCode","eth_getCompilers","eth_getFilterChanges","_filterIdentifier","eth_getFilterLogs","eth_getLogs","_filter","eth_getStorageAt","_storageSlot","eth_getTransactionByBlockHashAndIndex","_transactionIndex","eth_getTransactionByBlockNumberAndIndex","eth_getTransactionByHash","_transactionHash","eth_getTransactionCount","eth_getTransactionReceipt","eth_getUncleByBlockHashAndIndex","_uncleIndex","eth_getUncleByBlockNumberAndIndex","eth_getUncleCountByBlockHash","eth_getUncleCountByBlockNumber","eth_getWork","eth_hashrate","eth_maxPriorityFeePerGas","eth_mining","eth_newBlockFilter","eth_newFilter","eth_newPendingTransactionFilter","eth_protocolVersion","eth_sendRawTransaction","eth_sendTransaction","eth_sign","_message","eth_signTransaction","eth_submitHashrate","_hashRate","_id","eth_submitWork","_nonce","_hash","_digest","eth_subscribe","_params","eth_syncing","eth_uninstallFilter","eth_unsubscribe","_subscriptionId","assertEx","exists","hexToBigInt","toHex","isUndefined","FixedPercentageBlockRewardDiviner","FixedPercentageBlockRewardDivinerConfigSchema","buildBlock","PayloadBuilder","asBlockBoundWitness","BlockNumberSchema","ChainStakeIntentSchema","assertEx","hexFromBigInt","XYO_ZERO_ADDRESS","HydratedTransactionWrapper","MicroXL1","mXL1ToXL1","TransferSchema","XL1","transactionRequiredGas","generateTransactionTransfers","address","transactions","txs","Promise","all","map","tx","HydratedTransactionWrapper","parse","txBaseFeeCosts","boundWitness","from","XL1","mXL1ToXL1","fees","base","txGasCosts","requiredGas","transactionRequiredGas","data","totalGasCostInMicroXL1","MicroXL1","gasPrice","payloads","Object","entries","amount","payload","schema","TransferSchema","epoch","Date","now","transfers","XYO_ZERO_ADDRESS","hexFromBigInt","fromPayload","assertEx","find","p","DEFAULT_BLOCK_SIZE","XYO_PRODUCER_RESTAKE_DURATION","XYO_PRODUCER_RESTAKE_WINDOW","XyoBlockProducer","BaseService","_blockRewardDiviner","DefaultBlockSize","address","account","assertEx","params","accountBalanceService","chainFinalizedArchivist","chainInfo","chainInformation","electionService","pendingTransactions","pendingTransactionsService","rejectedTransactionsArchivist","rewardAddress","rewardService","stakeIntentService","validateHydratedBlockState","next","head","chain","id","leaders","getCreatorCommitteeForNextBlock","proposeNextValidBlock","getBlockRewardTransfer","block","FixedPercentageBlockRewardDiviner","create","blockRewardService","config","rewardPercentageRatio","schema","FixedPercentageBlockRewardDivinerConfigSchema","blockHex","toHex","blockId","PayloadBuilder","BlockNumberSchema","fields","build","rewards","divine","reward","getProducerRedeclaration","redeclareIntent","process","env","XYO_PRODUCER_REDECLARE_INTENT","isUndefined","ranges","getDeclaredCandidateRanges","lastRange","toSorted","a","b","at","currentDeclarationEnd","currentBlock","timeToProducerExpiration","intent","ChainStakeIntentSchema","from","nbf","exp","spanAsync","previousBlock","asBlockBoundWitness","nextBlock","nextBlockTransactions","getPendingTransactions","_hash","blockPayloads","producerRedeclarationPayload","push","length","rewardTransferPayload","transactionTransfers","generateTransactionTransfers","fundedTransfers","fundedNextBlockTransactions","map","tx","transfer","find","txTransfer","totalTransferCost","Object","values","transfers","reduce","acc","t","hexToBigInt","getBalance","filter","exists","buildBlock","console","log","errors","logger","error","rejectedTransactions","insert","assertEx","XyoChainRewards__factory","XyoChainRewardsFactory","toEthAddress","EvmBlockRewardService","BaseService","_contractAddress","chainService","assertEx","params","contractAddress","provider","createHandler","rewardsContract","getRewardForBlock","blockNumber","contract","XyoChainRewardsFactory","connect","toEthAddress","calcBlockReward","assertEx","toFixedPoint","rewardFromBlockNumber","XyoBlockRewardService","BaseService","rewardFromBlockNumber","constructor","creatorReward","toFixedPoint","initialStepReward","minRewardPerBlock","stepFactorDenominator","stepFactorNumerator","stepSize","assertEx","params","initialReward","getRewardForBlock","blockNumber","assertEx","PayloadBuilder","addStorageMeta","tx","payloads","PayloadBuilder","XyoValidator","BaseService","address","account","assertEx","params","chainFinalizedArchivist","chainInfo","chainInformation","electionService","pendingTransactions","rewardService","validatePendingBlock","_block","validatePendingTransaction","hydratedTransaction","get","_hash","length","Promise","resolve","assertEx","hexToLast4BytesInt","shuffleWithSeed","PayloadBuilder","XyoElectionService","BaseService","constructor","params","chainIterator","assertEx","chainStakeViewer","stakeIntentService","getCreatorCommitteeForNextBlock","current","spanAsync","nextBlock","block","candidates","getDeclaredCandidatesForBlock","previousBlockHash","PayloadBuilder","hash","generateCreatorCommittee","maxSize","creators","Set","seed","hexToLast4BytesInt","creatorArray","shuffleWithSeed","slice","ValueType","filterAs","filterAsync","assertEx","exists","forget","MemoryArchivist","validateTransaction","asOptionalTransactionBoundWitnessWithStorageMeta","flattenHydratedTransactions","tryHydrateTransaction","Mutex","XyoPendingTransactionsService","BaseService","MutexPriority","InsertNewTransactions","ReadTransactions","RemoveRejectedTransactions","RemoveFinalizedTransactions","_countPendingTransactionsMutex","Mutex","_curatedPendingTransactionsArchivist","_pendingTransactionsCount","_updateCuratedPendingTransactionsArchivistMutex","chainArchivist","assertEx","params","chainIdentification","pendingTransactionsArchivist","pendingTransactionsCount","forget","countPendingTransactions","pendingTransactionsLocalArchivist","rejectedTransactionsArchivist","createHandler","MemoryArchivist","create","account","on","payloads","insertNewTransactions","removeFinalizedTransactions","removeRejectedTransactions","pendingTransactionsGauge","meter","createObservableGauge","description","valueType","ValueType","INT","addCallback","observer","observe","getPendingTransactions","head","limit","spanAsync","runExclusive","foundPendingTransactions","cursor","length","next","order","at","_sequence","transactions","map","payload","asOptionalTransactionBoundWitnessWithStorageMeta","filter","exists","push","hydratedTransactions","Promise","all","tx","tryHydrateTransaction","_hash","isLocked","pendingTransactions","filterAs","filterAlreadyFinalizedTransactions","incomingTransactions","incomingTransactionHashes","finalizedTransactions","get","finalizedTransactionHashes","Set","item","nonFinalizedTransactions","has","unprocessedTransactions","hydratedUnprocessedTransactions","validTransactions","filterAsync","errors","validateTransaction","id","insert","flattenHydratedTransactions","removeTransactions","priority","delete","filterAs","exists","asOptionalBoundWitness","payloadSchemasContains","BoundWitnessWrapper","asOptionalChainStakeIntent","ChainStakeIntentSchema","getBlockSignedStakeDeclarations","block","archivist","intent","blockData","get","payload_hashes","bwsFromBlock","filterAs","asOptionalBoundWitness","bwsFromBlockWithDeclarations","filter","bw","payloadSchemasContains","ChainStakeIntentSchema","validBlockBwsWithDeclarations","filterToValidSignedBoundWitnesses","Promise","all","map","stakeIntentHashes","flatMap","mapBoundWitnessToStakeIntentHashes","exists","payloads","stakeIntents","asOptionalChainStakeIntent","p","addresses","includes","from","flat","bws","validBwIndexes","BoundWitnessWrapper","parse","getValid","_","index","payload_schemas","schema","undefined","filterAs","assertEx","asAddress","analyzeChain","ChainStakeIntentAnalyzer","isChainSummaryStakeIntent","DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS","findFirstMatching","IntervalMap","PayloadBuilder","asOptionalBlockBoundWitness","asOptionalBlockBoundWitnessWithStorageMeta","asOptionalChainIndexingServiceStateWithStorageMeta","asOptionalChainStakeIntent","ChainIndexingServiceStateSchema","isChainIndexingServiceState","Mutex","LRUCache","ACTIVE_STAKE_TTL","NO_ACTIVE_STAKE_TTL","STAKE_CACHE_MAX_ENTRIES","XyoStakeIntentService","BaseService","_lastIndexedBlockHash","undefined","_producers","IntervalMap","_stakeCache","LRUCache","max","_updateMutex","Mutex","constructor","params","chainIterator","on","updateIndex","chainArchivist","assertEx","chainStakeViewer","stakeIntentStateArchivist","createHandler","head","headHash","PayloadBuilder","hash","block","recoverState","getDeclaredCandidateRanges","address","intent","Promise","resolve","results","get","getDeclaredCandidatesForBlock","spanAsync","findAllContaining","candidates","validCandidates","filterToValidStake","isStakedForBlock","includes","requiredMinimumStake","candidatesWithStake","all","map","candidate","stake","activeStake","activeByAddressStaked","set","ttl","filter","persistState","current","state","serialize","payload","schema","ChainIndexingServiceStateSchema","fields","endBlockHash","build","insert","currentBlock","asOptionalBlockBoundWitness","currentBlockNum","opts","DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS","predicate","p","asOptionalChainIndexingServiceStateWithStorageMeta","findFirstMatching","isChainIndexingServiceState","indexed","indexedBlock","asOptionalBlockBoundWitnessWithStorageMeta","indexedBlockNum","data","_hash","open","displayProgress","isLocked","runExclusive","currentHead","currentHeadHash","result","analyzeChain","ChainStakeIntentAnalyzer","signedDeclarations","filterAs","find","isChainSummaryStakeIntent","intents","asOptionalChainStakeIntent","currentHeadBlockNum","logger","info","signedDeclaration","exp","nbf","start","stop","asAddress","from","Base","toAddress","StakedXyoChain__factory","StakedXyoChainFactory","getAddress","EvmChainService","Base","_contract","params","contract","id","runner","create","logger","traceProvider","meterProvider","contractAddress","getAddress","StakedXyoChainFactory","connect","active","activeByAddressStaked","address","activeByStaker","addStake","staked","amount","result","wait","chainId","toAddress","forkedAtBlockNumber","forkedAtHash","forkedChainId","minWithdrawalBlocks","pending","pendingByStaker","staker","removeStake","slot","rewardsContract","stakingTokenAddress","withdrawStake","withdrawn","withdrawnByStaker","assertEx","BaseEmitter","isDefined","isNull","PayloadBuilder","asBlockBoundWitness","asOptionalBlockBoundWitness","isBlockBoundWitness","LRUCache","XyoChainBlockNumberIterator","BaseEmitter","_blocksByBlockNumber","LRUCache","max","_chainArchivist","_chainInformation","_head","params","chainArchivist","archivist","head","id","chain","chainIdentification","create","Promise","resolve","get","block","assertEx","cached","startingBlock","currentBlockHash","PayloadBuilder","hash","currentBlock","at","isDefined","asBlockBoundWitness","_hash","isBlockBoundWitness","set","previous","isNull","Error","next","nextBlockNumber","undefined","count","results","length","push","nextBlock","asOptionalBlockBoundWitness","updateHead","emit","blocks"]}
|
|
1
|
+
{"version":3,"sources":["../../src/AccountBalance/XyoChainAccountBalanceService.ts","../../src/BaseService.ts","../../src/BaseEthProvider.ts","../../src/BlockProducer/XyoBlockProducer.ts","../../src/BlockProducer/generateTransactionTransfers.ts","../../src/BlockReward/EvmBlockRewardService.ts","../../src/BlockReward/XyoBlockRewardService.ts","../../src/ChainValidator/XyoValidator.ts","../../src/Election/XyoElectionService.ts","../../src/PendingTransactions/PendingTransactions.ts","../../src/StakeIntent/lib/getBlockSignedStakeDeclarations.ts","../../src/StakeIntent/XyoStakeIntentService.ts","../../src/Staker/Evm/Evm.ts","../../src/XyoChainBlockNumberIterator.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport {\n Address, Hash, Hex,\n toHex,\n} from '@xylabs/hex'\nimport {\n analyzeChain, BalanceAnalyzer, isChainSummaryBalances,\n} from '@xyo-network/chain-analyze'\nimport { SignedBigInt, toPositiveBigInt } from '@xyo-network/chain-protocol'\nimport {\n AccountBalanceService, BaseServiceParams,\n ChainServiceCollection,\n} from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport type ChainAccountBalanceServiceParams = BaseServiceParams<Partial<Pick<ChainServiceCollection, 'chainArchivist'>>>\n\n@creatableService()\nexport class XyoChainAccountBalanceService extends BaseService<ChainAccountBalanceServiceParams> implements AccountBalanceService {\n private _balances: Record<Address, SignedBigInt> = {}\n private _previousHead: Hash | null = null\n\n protected get chainArchivist() {\n return assertEx(this.params.chainArchivist, () => 'chainArchivist is required')\n }\n\n getBalance(address: Address): Hex {\n return toPositiveBigInt(this._balances[address] ?? { positive: toHex(0n) }).positive\n }\n\n getBalances(): Record<Address, Hex> {\n const result: Record<Address, Hex> = {}\n const entries = Object.entries(this._balances) as [Address, SignedBigInt][]\n for (const [address, balance] of entries) {\n result[address] = toPositiveBigInt(balance).positive\n }\n return result\n }\n\n async sync(head: Hash): Promise<void> {\n const analysis = await analyzeChain(\n this.chainArchivist,\n [new BalanceAnalyzer()],\n head,\n this._previousHead,\n -1n,\n this.tracer,\n )\n this._balances = assertEx(analysis.find(isChainSummaryBalances)?.balances, () => 'Failed to sync balances')\n }\n}\n","import { BaseEmitter } from '@xylabs/events'\nimport type { Promisable } from '@xylabs/promise'\nimport { span, spanAsync } from '@xyo-network/chain-utils'\nimport type {\n BaseAccountableServiceParams, BaseServiceParams, Service,\n} from '@xyo-network/xl1-protocol'\nimport { Mutex } from 'async-mutex'\n\ndeclare global {\n var xyoServiceSingletons: Record<string, unknown>\n}\n\nexport class BaseService<TParams extends BaseServiceParams = BaseServiceParams> extends BaseEmitter<TParams> {\n private static singletonInitMutex = new Mutex()\n\n static get singletons() {\n return globalThis['xyoServiceSingletons'] ?? (globalThis['xyoServiceSingletons'] = {})\n }\n\n get name() {\n return this.constructor.name\n }\n\n static async create<TService extends BaseService<TParams>, TParams extends BaseServiceParams = TService['params']>(\n this: CreatableService<TService>,\n params: TParams,\n ): Promise<TService> {\n const result = new this(params)\n if (result.name === 'BaseService') throw new Error('Cannot create BaseService')\n await result.createHandler()\n return result\n }\n\n static initSingleton<TService extends BaseService<TParams>, TParams extends BaseServiceParams>(params: TParams) {\n if (this.singletons[this.name]) throw new Error(`Singleton already initialized for ${this.name}`)\n return this.singletonInitMutex.runExclusive(async () => {\n return await this.create(params) as TService\n })\n }\n\n createHandler(): Promisable<void> {\n return\n }\n\n span<T>(name: string, fn: () => T): T {\n return span(name, fn, this.tracer)\n }\n\n async spanAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {\n return await spanAsync(name, fn, this.tracer)\n }\n}\n\nexport abstract class BaseAccountableService<\n TParams extends BaseAccountableServiceParams = BaseAccountableServiceParams,\n> extends BaseService<TParams> {\n // Base class for services that have an account\n}\n\nexport interface CreatableService<T extends BaseService = BaseService> extends Service {\n new(params: T['params']): T\n create<T extends BaseService>(this: CreatableService<T>, params: T['params']): Promisable<T>\n}\n\nexport function creatableService<T extends BaseService = BaseService>() {\n return <U extends CreatableService<T>>(constructor: U) => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n constructor\n }\n}\n","import type {\n Address, BlockAPI,\n BlockNumberOrTag,\n CompileResultAPI,\n EthExecutionAPI,\n FeeHistoryResultAPI,\n Filter,\n FilterResultsAPI,\n HexString, HexString8Bytes,\n HexString32Bytes,\n HexString256Bytes,\n HexStringBytes,\n SignedTransactionInfoAPI,\n SyncingStatusAPI,\n TransactionCallAPI,\n TransactionInfoAPI,\n TransactionReceiptAPI,\n TransactionWithSenderAPI,\n Uint,\n Uint256,\n} from 'web3-types'\n\nexport class BaseEthProvider implements EthExecutionAPI {\n eth_accounts(): Address[] {\n throw new Error('Method not implemented.')\n }\n\n eth_blockNumber(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_call(_transaction: TransactionCallAPI, _blockNumber: BlockNumberOrTag): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_clearSubscriptions(_keepSyncing?: boolean): void {\n throw new Error('Method not implemented.')\n }\n\n eth_coinbase(): Address {\n throw new Error('Method not implemented.')\n }\n\n eth_compileLLL(_code: string): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_compileSerpent(_code: string): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_compileSolidity(_code: string): CompileResultAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_estimateGas(_transaction: Partial<TransactionWithSenderAPI>, _blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_feeHistory(_blockCount: Uint, _newestBlock: BlockNumberOrTag, _rewardPercentiles: number[]): FeeHistoryResultAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_gasPrice(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getBalance(_address: Address, _blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getBlockByHash(_blockHash: HexString32Bytes, _hydrated: boolean): BlockAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getBlockByNumber(_blockNumber: BlockNumberOrTag, _hydrated: boolean): BlockAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getBlockTransactionCountByHash(_blockHash: HexString32Bytes): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getBlockTransactionCountByNumber(_blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getCode(_address: Address, _blockNumber: BlockNumberOrTag): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_getCompilers(): string[] {\n throw new Error('Method not implemented.')\n }\n\n eth_getFilterChanges(_filterIdentifier: Uint): FilterResultsAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getFilterLogs(_filterIdentifier: Uint): FilterResultsAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getLogs(_filter: Filter): FilterResultsAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getStorageAt(_address: Address, _storageSlot: Uint256, _blockNumber: BlockNumberOrTag): HexStringBytes {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionByBlockHashAndIndex(_blockHash: HexString32Bytes, _transactionIndex: Uint): TransactionInfoAPI | undefined {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionByBlockNumberAndIndex(_blockNumber: BlockNumberOrTag, _transactionIndex: Uint): TransactionInfoAPI | undefined {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionByHash(_transactionHash: HexString32Bytes): TransactionInfoAPI | undefined {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionCount(_address: Address, _blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getTransactionReceipt(_transactionHash: HexString32Bytes): TransactionReceiptAPI | undefined {\n throw new Error('Method not implemented.')\n }\n\n eth_getUncleByBlockHashAndIndex(_blockHash: HexString32Bytes, _uncleIndex: Uint): BlockAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getUncleByBlockNumberAndIndex(_blockNumber: BlockNumberOrTag, _uncleIndex: Uint): BlockAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_getUncleCountByBlockHash(_blockHash: HexString32Bytes): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getUncleCountByBlockNumber(_blockNumber: BlockNumberOrTag): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_getWork(): [HexString32Bytes, HexString32Bytes, HexString32Bytes] {\n throw new Error('Method not implemented.')\n }\n\n eth_hashrate(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_maxPriorityFeePerGas(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_mining(): boolean {\n throw new Error('Method not implemented.')\n }\n\n eth_newBlockFilter(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_newFilter(_filter: Filter): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_newPendingTransactionFilter(): Uint {\n throw new Error('Method not implemented.')\n }\n\n eth_protocolVersion(): string {\n throw new Error('Method not implemented.')\n }\n\n eth_sendRawTransaction(_transaction: HexStringBytes): HexString32Bytes {\n throw new Error('Method not implemented.')\n }\n\n eth_sendTransaction(_transaction: TransactionWithSenderAPI | Partial<TransactionWithSenderAPI>): HexString32Bytes {\n throw new Error('Method not implemented.')\n }\n\n eth_sign(_address: Address, _message: HexStringBytes): HexString256Bytes {\n throw new Error('Method not implemented.')\n }\n\n eth_signTransaction(_transaction: TransactionWithSenderAPI | Partial<TransactionWithSenderAPI>): HexStringBytes | SignedTransactionInfoAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_submitHashrate(_hashRate: HexString32Bytes, _id: HexString32Bytes): boolean {\n throw new Error('Method not implemented.')\n }\n\n eth_submitWork(_nonce: HexString8Bytes, _hash: HexString32Bytes, _digest: HexString32Bytes): boolean {\n throw new Error('Method not implemented.')\n }\n\n eth_subscribe(..._params: ['newHeads'] | ['newPendingTransactions'] | ['syncing'] | ['logs', { address?: HexString; topics?: HexString[] }]): HexString {\n throw new Error('Method not implemented.')\n }\n\n eth_syncing(): SyncingStatusAPI {\n throw new Error('Method not implemented.')\n }\n\n eth_uninstallFilter(_filterIdentifier: Uint): boolean {\n throw new Error('Method not implemented.')\n }\n\n eth_unsubscribe(_subscriptionId: HexString): HexString {\n throw new Error('Method not implemented.')\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Address, toHex } from '@xylabs/hex'\nimport { isUndefined } from '@xylabs/typeof'\nimport { ArchivistInstance, ReadArchivist } from '@xyo-network/archivist-model'\nimport {\n BlockRewardDiviner, FixedPercentageBlockRewardDiviner, FixedPercentageBlockRewardDivinerConfigSchema,\n} from '@xyo-network/chain-modules'\nimport { buildBlock } from '@xyo-network/chain-protocol'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { WithStorageMeta } from '@xyo-network/payload-model'\nimport {\n AllowedBlockPayload, asBlockBoundWitness, BlockBoundWitness, BlockNumber, BlockNumberSchema, BlockProducer, ChainStakeIntent, ChainStakeIntentSchema,\n HydratedBlock, PendingTransactionsService, StakeIntentService, Transfer,\n} from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\nimport { XyoValidatorParams } from '../ChainValidator/index.ts'\nimport { generateTransactionTransfers } from './generateTransactionTransfers.ts'\n\n/**\n * The default block size for a block\n */\nexport const DEFAULT_BLOCK_SIZE = 10\n\n// /**\n// * The amount of time for which a producer will restake their intent\n// */\nexport const XYO_PRODUCER_RESTAKE_DURATION = 10_000\n\n/**\n * The number of blocks within which a producer will redeclare\n * their intent to produce blocks\n */\nexport const XYO_PRODUCER_RESTAKE_WINDOW = 500n\n\nexport interface XyoBlockProducerParams extends XyoValidatorParams {\n pendingTransactionsArchivist?: ReadArchivist\n pendingTransactionsService?: PendingTransactionsService\n rejectedTransactionsArchivist?: ArchivistInstance\n rewardAddress?: Address\n stakeIntentService?: StakeIntentService\n}\n\n@creatableService()\nexport class XyoBlockProducer extends BaseService<XyoBlockProducerParams> implements BlockProducer {\n protected _blockRewardDiviner: BlockRewardDiviner | undefined\n\n static get DefaultBlockSize(): number {\n return DEFAULT_BLOCK_SIZE\n }\n\n get address() {\n return this.account.address\n }\n\n protected get account() {\n return assertEx(this.params.account, () => 'account is required')\n }\n\n protected get chainFinalizedArchivist() {\n return assertEx(this.params.chainFinalizedArchivist, () => 'chainFinalizedArchivist is required')\n }\n\n protected get chainInfo() {\n return assertEx(this.params.chainInformation, () => 'chainInfo is required')\n }\n\n protected get electionService() {\n return assertEx(this.params.electionService, () => 'electionService is required')\n }\n\n protected get pendingTransactions() {\n return assertEx(this.params.pendingTransactions, () => 'pendingTransactions is required')\n }\n\n protected get pendingTransactionsService() {\n return assertEx(this.params.pendingTransactionsService, () => 'Missing pendingTransactionsService')\n }\n\n protected get rejectedTransactionsArchivist() {\n return assertEx(this.params.rejectedTransactionsArchivist, () => 'No rejected transactions archivist')\n }\n\n protected get rewardAddress(): Address {\n return assertEx(this.params.rewardAddress, () => 'No reward address provided')\n }\n\n protected get rewardService() {\n return assertEx(this.params.rewardService, () => 'rewardService is required')\n }\n\n protected get stakeIntentService(): StakeIntentService {\n return assertEx(this.params.stakeIntentService, () => 'No StakeIntentService provided')\n }\n\n protected get validateHydratedBlockState() {\n return assertEx(this.params.validateHydratedBlockState, () => 'validateHydratedBlockState is required')\n }\n\n async next(head: WithStorageMeta<BlockBoundWitness>): Promise<HydratedBlock | undefined> {\n // If the block is for another chain, ignore\n if (head.chain !== this.chainInfo.id) return\n const leaders = await this.electionService.getCreatorCommitteeForNextBlock(head)\n // TODO: Should we propose block if creator committee is empty?\n // TODO: Handle the case where we're not the 1st leader but they're not responding\n // at a higher level than here as that's a network issue\n if (leaders?.[0] !== this.address) return\n return this.proposeNextValidBlock(head)\n }\n\n protected async getBlockRewardTransfer(block: number): Promise<Transfer | undefined> {\n if (!this._blockRewardDiviner) {\n // TODO: Adjust to allow for genesis block reward vs. normal block reward\n this._blockRewardDiviner = await FixedPercentageBlockRewardDiviner.create({\n account: 'random',\n blockRewardService: this.rewardService,\n config: {\n rewardAddress: this.rewardAddress,\n rewardPercentageRatio: 0,\n schema: FixedPercentageBlockRewardDivinerConfigSchema,\n },\n })\n }\n const blockHex = assertEx(toHex(block), () => 'Failed to convert block to hex')\n const blockId = new PayloadBuilder<BlockNumber>({ schema: BlockNumberSchema }).fields({ block: blockHex }).build()\n const rewards = await this._blockRewardDiviner.divine([blockId])\n const [reward] = rewards\n return reward\n }\n\n /**\n * Handles the producer redeclaration logic\n * @param head The current head block\n * @returns\n */\n protected async getProducerRedeclaration(head: WithStorageMeta<BlockBoundWitness>): Promise<ChainStakeIntent | undefined> {\n const redeclareIntent = process.env.XYO_PRODUCER_REDECLARE_INTENT\n if (isUndefined(redeclareIntent)) return\n // Decide if we need to redeclare\n const ranges = await this.stakeIntentService.getDeclaredCandidateRanges(this.address, 'producer')\n // TODO: This doesn't handle the case where the producer had declared a range for the future\n // but we're in a range that's not the future\n // Sort in ascending order based on ending range to get range with highest ending block\n const lastRange = ranges.toSorted((a, b) => a[1] > b[1] ? 1 : -1).at(-1)\n if (!lastRange) return\n const [, currentDeclarationEnd] = lastRange\n const currentBlock = head.block\n const timeToProducerExpiration = currentDeclarationEnd - currentBlock\n if (timeToProducerExpiration > XYO_PRODUCER_RESTAKE_WINDOW) return\n // Create redeclaration\n const intent = new PayloadBuilder<ChainStakeIntent>({ schema: ChainStakeIntentSchema }).fields({\n from: this.address,\n intent: 'producer',\n nbf: currentBlock,\n exp: currentBlock + XYO_PRODUCER_RESTAKE_DURATION,\n }).build()\n return intent\n }\n\n protected async proposeNextValidBlock(head: WithStorageMeta<BlockBoundWitness>): Promise<HydratedBlock | undefined> {\n return await this.spanAsync('proposeNextValidBlock', async () => {\n // Calculate the next block components\n const { block: previousBlock } = assertEx(asBlockBoundWitness(head), () => 'Invalid head block')\n const nextBlock = previousBlock + 1\n const nextBlockTransactions = await this.pendingTransactionsService.getPendingTransactions(head._hash, XyoBlockProducer.DefaultBlockSize)\n\n const blockPayloads: AllowedBlockPayload[] = []\n\n // Calculate the optional producer redeclaration and add it if necessary\n const producerRedeclarationPayload = await this.getProducerRedeclaration(head)\n if (producerRedeclarationPayload) blockPayloads.push(producerRedeclarationPayload)\n\n // If there are no transactions and no payloads, we don't need to create a block\n if (blockPayloads.length === 0 && nextBlockTransactions.length === 0) return\n\n // Calculate the optional block reward transfer and add if necessary\n const rewardTransferPayload = await this.getBlockRewardTransfer(nextBlock)\n if (rewardTransferPayload) blockPayloads.push(rewardTransferPayload)\n\n const transactionTransfers = await generateTransactionTransfers(this.address, nextBlockTransactions)\n blockPayloads.push(...transactionTransfers)\n\n // Build the block\n const block = await buildBlock(head, nextBlockTransactions, blockPayloads, [this.account])\n console.log('buildBlock', block)\n const errors = await this.validateHydratedBlockState(block, this.chainInfo.id, this.chainFinalizedArchivist)\n if (errors.length > 0) {\n this.logger?.error('Validation of produced block failed', errors)\n const rejectedTransactions = block[1]\n await this.rejectedTransactionsArchivist.insert(rejectedTransactions)\n } else {\n return block\n }\n })\n }\n}\n","import { type Address, hexFromBigInt } from '@xylabs/hex'\nimport { HydratedTransactionWrapper } from '@xyo-network/chain-wrappers'\nimport {\n type HydratedTransaction, type Transfer, TransferSchema,\n} from '@xyo-network/xl1-protocol'\n\nexport async function generateTransactionTransfers(address: Address, transactions: HydratedTransaction[]): Promise<Transfer[]> {\n const txs = await Promise.all(transactions.map(tx => HydratedTransactionWrapper.parse(tx)))\n\n // merge transactions with the same from address\n const txCosts: [Address, bigint][] = []\n for (const tx of txs) {\n const existingItem = txCosts.find(([addr]) => addr === tx.boundWitness.from)\n if (existingItem) {\n existingItem[1] += tx.fees.base\n } else {\n txCosts.push([tx.boundWitness.from, tx.fees.base])\n }\n }\n\n // generate actual Transfer Payloads\n const payloads = txCosts.map(([from, amount]) => {\n const payload: Transfer = {\n schema: TransferSchema,\n epoch: Date.now(),\n from,\n // TODO: add function to Wrapper to calculate entire cost of transaction\n transfers: { [address]: hexFromBigInt(amount) },\n }\n return payload\n })\n return payloads\n}\n","import { assertEx } from '@xylabs/assert'\nimport { XyoChainRewards__factory as XyoChainRewardsFactory } from '@xyo-network/typechain'\nimport {\n BaseAccountableServiceParams, BlockRewardService, ChainService,\n toEthAddress,\n} from '@xyo-network/xl1-protocol'\nimport { Provider } from 'ethers/providers'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface EvmBlockRewardServiceParams extends BaseAccountableServiceParams {\n chainService?: ChainService\n provider?: Provider\n}\n\n@creatableService<EvmBlockRewardService>()\nexport class EvmBlockRewardService extends BaseService<EvmBlockRewardServiceParams> implements BlockRewardService {\n protected _contractAddress: string | undefined\n\n protected get chainService() {\n return assertEx(this.params.chainService, () => 'chainService is required')\n }\n\n protected get contractAddress() {\n return assertEx(this._contractAddress, () => 'contractAddress is required')\n }\n\n protected get provider() {\n return assertEx(this.params.provider, () => 'provider is required')\n }\n\n override async createHandler() {\n await super.createHandler()\n this._contractAddress = await this.chainService.rewardsContract()\n }\n\n async getRewardForBlock(blockNumber: bigint): Promise<bigint> {\n const contract = XyoChainRewardsFactory.connect(toEthAddress(this.contractAddress), this.provider)\n return await contract.calcBlockReward(blockNumber)\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { toFixedPoint } from '@xylabs/decimal-precision'\nimport { Promisable } from '@xylabs/promise'\nimport { rewardFromBlockNumber } from '@xyo-network/chain-protocol'\nimport { BaseServiceParams, BlockRewardService } from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface XyoBlockRewardServiceParams extends BaseServiceParams {\n creatorReward?: bigint\n initialStepReward?: bigint\n minRewardPerBlock?: bigint\n stepFactorDenominator?: bigint\n stepFactorNumerator?: bigint\n stepSize?: bigint\n}\n\n@creatableService()\nexport class XyoBlockRewardService extends BaseService<XyoBlockRewardServiceParams> implements BlockRewardService {\n protected readonly rewardFromBlockNumber = rewardFromBlockNumber(18)\n\n constructor(\n {\n creatorReward = toFixedPoint(20_000_000_000n),\n initialStepReward = toFixedPoint(3000n),\n minRewardPerBlock = toFixedPoint(30n),\n stepFactorDenominator = 100n,\n stepFactorNumerator = 90n,\n stepSize = 1_000_000n,\n }: Partial<XyoBlockRewardServiceParams> = {},\n ) {\n super({\n initialStepReward, minRewardPerBlock, stepSize, stepFactorDenominator, stepFactorNumerator, creatorReward,\n })\n }\n\n get creatorReward() {\n return assertEx(this.params.creatorReward, () => 'creatorReward is required')\n }\n\n get initialReward() {\n return assertEx(this.params.initialStepReward, () => 'initialStepReward is required')\n }\n\n get minRewardPerBlock() {\n return assertEx(this.params.minRewardPerBlock, () => 'minRewardPerBlock is required')\n }\n\n get stepFactorDenominator() {\n return assertEx(this.params.stepFactorDenominator, () => 'stepFactorDenominator is required')\n }\n\n get stepFactorNumerator() {\n return assertEx(this.params.stepFactorNumerator, () => 'stepFactorNumerator is required')\n }\n\n get stepSize() {\n return assertEx(this.params.stepSize, () => 'stepSize is required')\n }\n\n getRewardForBlock(blockNumber: bigint): Promisable<bigint> {\n return this.rewardFromBlockNumber(\n blockNumber,\n this.initialReward,\n this.stepSize,\n this.stepFactorNumerator,\n this.stepFactorDenominator,\n this.minRewardPerBlock,\n this.creatorReward,\n )\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Promisable } from '@xylabs/promise'\nimport { AccountInstance } from '@xyo-network/account-model'\nimport { ArchivistInstance, ReadArchivist } from '@xyo-network/archivist-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport {\n BaseServiceParams,\n BlockBoundWitness,\n BlockRewardService,\n ChainInformation,\n ElectionService,\n HydratedBlockStateValidationFunction,\n HydratedTransaction,\n HydratedTransactionWithStorageMeta,\n StakeIntentService,\n} from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\nimport { Validator } from './model/index.ts'\n\nconst addStorageMeta = async ([tx, payloads]: HydratedTransaction): Promise<HydratedTransactionWithStorageMeta> => {\n return [await PayloadBuilder.addStorageMeta(tx), await PayloadBuilder.addStorageMeta(payloads)]\n}\n\nexport interface XyoValidatorParams extends BaseServiceParams {\n account?: AccountInstance\n chainFinalizedArchivist?: ReadArchivist\n chainInformation?: ChainInformation\n electionService?: ElectionService\n pendingTransactions?: ArchivistInstance\n rewardService?: BlockRewardService\n stakeIntentService?: StakeIntentService\n validateHydratedBlockState?: HydratedBlockStateValidationFunction\n}\n\n@creatableService()\nexport class XyoValidator<TParams extends XyoValidatorParams = XyoValidatorParams> extends BaseService<TParams> implements Validator {\n get address() {\n return this.account.address\n }\n\n protected get account() {\n return assertEx(this.params.account, () => 'account is required')\n }\n\n protected get chainFinalizedArchivist() {\n return assertEx(this.params.chainFinalizedArchivist, () => 'chainFinalizedArchivist is required')\n }\n\n protected get chainInfo() {\n return assertEx(this.params.chainInformation, () => 'chainInfo is required')\n }\n\n protected get electionService() {\n return assertEx(this.params.electionService, () => 'electionService is required')\n }\n\n protected get pendingTransactions() {\n return assertEx(this.params.pendingTransactions, () => 'pendingTransactions is required')\n }\n\n protected get rewardService() {\n return assertEx(this.params.rewardService, () => 'rewardService is required')\n }\n\n validatePendingBlock(_block: BlockBoundWitness): Promisable<Error[]> {\n return [] // await validateBlockProtocol(block, this.chainInfo)\n }\n\n // TODO: Move to validator and inherit this class from validator\n async validatePendingTransaction(hydratedTransaction: HydratedTransaction): Promise<boolean> {\n const [tx] = await addStorageMeta(hydratedTransaction)\n // Ensure not confirmed already (replay attack)\n if ((await this.chainFinalizedArchivist.get([tx._hash])).length > 0) return false\n // TODO: Ensure transaction is valid (double spend, has voucher, has required stake, etc.)\n // TODO: Ensure validator stake is valid\n return await Promise.resolve(true)\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Address, Hash } from '@xylabs/hex'\nimport { hexToLast4BytesInt, shuffleWithSeed } from '@xyo-network/chain-utils'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport type {\n BaseServiceParams, ChainBlockNumberIterator, ChainStakeViewer, StakeIntentService,\n} from '@xyo-network/xl1-protocol'\nimport { BlockBoundWitness, ElectionService } from '@xyo-network/xl1-protocol'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface XyoElectionServicesParams extends BaseServiceParams {\n chainIterator?: ChainBlockNumberIterator\n chainStakeViewer?: ChainStakeViewer\n stakeIntentService?: StakeIntentService\n}\n\n@creatableService()\nexport class XyoElectionService extends BaseService<XyoElectionServicesParams> implements ElectionService {\n constructor(params: XyoElectionServicesParams) {\n super(params)\n }\n\n get chainIterator() {\n return assertEx(this.params.chainIterator, () => 'No chain iterator')\n }\n\n get chainStakeViewer() {\n return assertEx(this.params.chainStakeViewer, () => 'No chain stake viewer')\n }\n\n get stakeIntentService() {\n return assertEx(this.params.stakeIntentService, () => 'No staked intent service')\n }\n\n async getCreatorCommitteeForNextBlock(current: BlockBoundWitness): Promise<Address[]> {\n return await this.spanAsync('getCreatorCommitteeForNextBlock', async () => {\n const nextBlock = current.block + 1\n const candidates = await this.stakeIntentService.getDeclaredCandidatesForBlock(nextBlock, 'producer')\n const previousBlockHash = await PayloadBuilder.hash(current)\n return this.generateCreatorCommittee(candidates, previousBlockHash)\n })\n }\n\n protected generateCreatorCommittee(candidates: Address[], previousBlockHash: Hash, maxSize = 3): Address[] {\n const creators = new Set<Address>(candidates)\n const seed = hexToLast4BytesInt(previousBlockHash)\n const creatorArray = shuffleWithSeed(creators, seed)\n return creatorArray.slice(0, maxSize)\n }\n}\n","import { ValueType } from '@opentelemetry/api'\nimport { filterAs, filterAsync } from '@xylabs/array'\nimport { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { MemoryArchivist } from '@xyo-network/archivist-memory'\nimport { ArchivistInstance } from '@xyo-network/archivist-model'\nimport { validateTransaction } from '@xyo-network/chain-validation'\nimport {\n Payload, Sequence, WithStorageMeta,\n} from '@xyo-network/payload-model'\nimport {\n asOptionalTransactionBoundWitnessWithStorageMeta, BaseServiceParams, ChainIdentification, HydratedTransactionWithStorageMeta,\n PendingTransactionsService, TransactionBoundWitness,\n} from '@xyo-network/xl1-protocol'\nimport { flattenHydratedTransactions, tryHydrateTransaction } from '@xyo-network/xl1-protocol-sdk'\nimport { Mutex } from 'async-mutex'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface XyoPendingTransactionsServiceParams extends BaseServiceParams {\n chainArchivist?: ArchivistInstance\n chainIdentification?: ChainIdentification\n pendingTransactionsArchivist?: ArchivistInstance\n rejectedTransactionsArchivist?: ArchivistInstance\n}\n\n@creatableService()\nexport class XyoPendingTransactionsService extends BaseService<XyoPendingTransactionsServiceParams> implements PendingTransactionsService {\n private static readonly MutexPriority = {\n /**\n * Priority for inserting new transactions\n */\n InsertNewTransactions: 5,\n /**\n * Priority for reading pending transactions\n */\n ReadTransactions: 3,\n /**\n * Priority for removing rejected transactions\n */\n RemoveRejectedTransactions: 2,\n /**\n * Priority for removing finalized transactions\n */\n RemoveFinalizedTransactions: 1,\n } as const\n\n /**\n * A mutex to ensure that the counting the number of pending transactions is\n * not called concurrently\n */\n private _countPendingTransactionsMutex = new Mutex()\n\n /**\n * A local Archivist optimized for fast retrieval that stores only validated\n * pending transactions\n */\n private _curatedPendingTransactionsArchivist: MemoryArchivist | undefined\n\n /**\n * The last count of total pending transactions\n */\n private _pendingTransactionsCount: number = 0\n\n /**\n * A mutex to ensure that the curated pending transactions archivist is\n * updated in a thread-safe manner\n */\n private _updateCuratedPendingTransactionsArchivistMutex = new Mutex()\n\n private get chainArchivist() {\n return assertEx(this.params.chainArchivist, () => 'No completed blocks with data archivist')\n }\n\n private get chainIdentification() {\n return assertEx(this.params.chainIdentification, () => 'No chain id')\n }\n\n private get pendingTransactionsArchivist() {\n return assertEx(this.params.pendingTransactionsArchivist, () => 'No pending transactions archivist')\n }\n\n private get pendingTransactionsCount() {\n forget(this.countPendingTransactions())\n return this._pendingTransactionsCount\n }\n\n private get pendingTransactionsLocalArchivist() {\n return assertEx(this._curatedPendingTransactionsArchivist, () => 'No pending transactions curated archivist')\n }\n\n private get rejectedTransactionsArchivist() {\n return assertEx(this.params.rejectedTransactionsArchivist, () => 'No rejected transactions archivist')\n }\n\n override async createHandler() {\n await super.createHandler()\n this._curatedPendingTransactionsArchivist = await MemoryArchivist.create({ account: 'random' })\n\n // On new pending transactions, insert them into the curated archivist\n this.pendingTransactionsArchivist.on('inserted', async ({ payloads }) => {\n await this.insertNewTransactions(payloads)\n })\n\n // On new finalized blocks, remove the transactions from the curated archivist\n this.chainArchivist.on('inserted', async ({ payloads }) => {\n await this.removeFinalizedTransactions(payloads)\n })\n\n // On new rejected blocks, remove the transactions from the curated archivist\n this.rejectedTransactionsArchivist.on('inserted', async ({ payloads }) => {\n await this.removeRejectedTransactions(payloads)\n })\n\n const pendingTransactionsGauge = this.meter?.createObservableGauge(\n 'xyo_pending_transactions_count',\n { description: 'The current number of pending transactions', valueType: ValueType.INT },\n )\n pendingTransactionsGauge?.addCallback((observer) => {\n observer.observe(this.pendingTransactionsCount)\n })\n }\n\n async getPendingTransactions(head: Hash, limit: number): Promise<HydratedTransactionWithStorageMeta[]> {\n return await this.spanAsync('getPendingTransactions', async () => {\n return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {\n const foundPendingTransactions: WithStorageMeta<TransactionBoundWitness>[] = []\n let cursor: Sequence | undefined\n while (foundPendingTransactions.length < limit) {\n const payloads = await this.pendingTransactionsLocalArchivist.next({\n limit: 100, order: 'asc', cursor,\n })\n if (payloads.length === 0) break\n cursor = payloads.at(-1)?._sequence\n const transactions = payloads.map(payload => asOptionalTransactionBoundWitnessWithStorageMeta(payload)).filter(exists)\n foundPendingTransactions.push(...transactions)\n }\n const hydratedTransactions = await Promise.all(\n foundPendingTransactions.map(tx => tryHydrateTransaction(this.pendingTransactionsLocalArchivist, tx._hash)),\n )\n return hydratedTransactions.filter(exists)\n }, XyoPendingTransactionsService.MutexPriority.ReadTransactions)\n })\n }\n\n private async countPendingTransactions() {\n if (this._countPendingTransactionsMutex.isLocked()) return\n await this._countPendingTransactionsMutex.runExclusive(async () => {\n const payloads = (await this._curatedPendingTransactionsArchivist?.all()) ?? []\n const pendingTransactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta)\n this._pendingTransactionsCount = pendingTransactions.length\n })\n }\n\n private async filterAlreadyFinalizedTransactions(payloads: WithStorageMeta<Payload>[]): Promise<WithStorageMeta<TransactionBoundWitness>[]> {\n const incomingTransactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta)\n const incomingTransactionHashes = incomingTransactions.map(payload => payload._hash)\n const finalizedTransactions = await this.chainArchivist.get(incomingTransactionHashes)\n const finalizedTransactionHashes = new Set(finalizedTransactions.map(item => item._hash))\n const nonFinalizedTransactions = incomingTransactions.filter(item => !finalizedTransactionHashes.has(item._hash))\n return nonFinalizedTransactions\n }\n\n private async insertNewTransactions(payloads: WithStorageMeta<Payload>[]) {\n return await this.spanAsync('InsertNewTransactions', async () => {\n return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {\n // Check incoming transactions against finalized transactions\n const unprocessedTransactions = await this.filterAlreadyFinalizedTransactions(payloads)\n // Hydrate all unprocessed transactions\n const hydratedUnprocessedTransactions = (await Promise.all(unprocessedTransactions.map((tx) => {\n return tryHydrateTransaction(this.pendingTransactionsArchivist, tx._hash)\n }))).filter(exists)\n // Filter to only valid transactions\n const validTransactions = await filterAsync(hydratedUnprocessedTransactions, async (tx) => {\n const errors = await validateTransaction(tx, this.chainIdentification.id)\n return errors.length > 0 ? false : true\n })\n await this.pendingTransactionsLocalArchivist.insert(flattenHydratedTransactions(validTransactions))\n }, XyoPendingTransactionsService.MutexPriority.InsertNewTransactions)\n })\n }\n\n private async removeFinalizedTransactions(payloads: WithStorageMeta<Payload>[]) {\n return await this.removeTransactions(payloads, 'RemoveFinalizedTransactions')\n }\n\n private async removeRejectedTransactions(payloads: WithStorageMeta<Payload>[]) {\n return await this.removeTransactions(payloads, 'RemoveRejectedTransactions')\n }\n\n private async removeTransactions(\n payloads: WithStorageMeta<Payload>[],\n priority: keyof typeof XyoPendingTransactionsService.MutexPriority,\n ) {\n return await this.spanAsync(priority, async () => {\n return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {\n const transactions = filterAs(payloads, asOptionalTransactionBoundWitnessWithStorageMeta)\n await this.pendingTransactionsLocalArchivist.delete(transactions.map(tx => tx._hash))\n }, XyoPendingTransactionsService.MutexPriority[priority])\n })\n }\n}\n","import { filterAs } from '@xylabs/array'\nimport { exists } from '@xylabs/exists'\nimport type { Hash } from '@xylabs/hex'\nimport type { ArchivistInstance } from '@xyo-network/archivist-model'\nimport type { BoundWitness } from '@xyo-network/boundwitness-model'\nimport { asOptionalBoundWitness } from '@xyo-network/boundwitness-model'\nimport { payloadSchemasContains } from '@xyo-network/boundwitness-validator'\nimport { BoundWitnessWrapper } from '@xyo-network/boundwitness-wrapper'\nimport type {\n BlockBoundWitness, ChainStakeIntent, Intent,\n} from '@xyo-network/xl1-protocol'\nimport { asOptionalChainStakeIntent, ChainStakeIntentSchema } from '@xyo-network/xl1-protocol'\n\nexport const getBlockSignedStakeDeclarations = async (block: BlockBoundWitness, archivist: ArchivistInstance, intent: Intent): Promise<ChainStakeIntent[]> => {\n // Get payloads in block\n const blockData = await archivist.get(block.payload_hashes)\n // Filter Payloads in block to BoundWitnesses\n const bwsFromBlock = filterAs(blockData, asOptionalBoundWitness)\n // Filter to BoundWitnesses with StakeIntent payloads\n const bwsFromBlockWithDeclarations = bwsFromBlock.filter(bw => payloadSchemasContains(bw, ChainStakeIntentSchema))\n // Filter to only valid signed BWs\n const validBlockBwsWithDeclarations = await filterToValidSignedBoundWitnesses(bwsFromBlockWithDeclarations)\n return (await Promise.all(validBlockBwsWithDeclarations.map(async (bw) => {\n // Get staked intent hashes from signed declarations\n const stakeIntentHashes = validBlockBwsWithDeclarations\n .flatMap(mapBoundWitnessToStakeIntentHashes)\n .filter(exists)\n // Get staked intent payloads\n const payloads = await archivist.get(stakeIntentHashes)\n // Filter payloads to staked intents\n const stakeIntents = filterAs(payloads, asOptionalChainStakeIntent)\n // that are producers\n .filter(p => p.intent === intent)\n // where the issuer of the intent is also the signer of this BW\n .filter(p => bw.addresses.includes(p.from))\n\n return stakeIntents\n }))).flat()\n}\n\nconst filterToValidSignedBoundWitnesses = async (bws: BoundWitness[]): Promise<BoundWitness[]> => {\n const validBwIndexes = await Promise.all(bws.map(bw => BoundWitnessWrapper.parse(bw).getValid()))\n return bws.filter((_, index) => validBwIndexes[index])\n}\n\nconst mapBoundWitnessToStakeIntentHashes = (bw: BoundWitness): (Hash | undefined)[] => {\n return bw.payload_schemas.map((schema, index) => schema === ChainStakeIntentSchema ? bw.payload_hashes[index] : undefined)\n}\n","import { filterAs } from '@xylabs/array'\nimport { assertEx } from '@xylabs/assert'\nimport {\n Address, asAddress, Hash,\n} from '@xylabs/hex'\nimport { ArchivistInstance, ArchivistNextOptions } from '@xyo-network/archivist-model'\nimport {\n analyzeChain, ChainStakeIntentAnalyzer,\n isChainSummaryStakeIntent,\n} from '@xyo-network/chain-analyze'\nimport {\n DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS,\n findFirstMatching, IntervalMap,\n SerializedIntervalMap,\n} from '@xyo-network/chain-utils'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, WithStorageMeta } from '@xyo-network/payload-model'\nimport type {\n BaseServiceParams, EventingChainBlockNumberIterator, Intent,\n} from '@xyo-network/xl1-protocol'\nimport {\n asOptionalBlockBoundWitness, asOptionalBlockBoundWitnessWithStorageMeta,\n asOptionalChainIndexingServiceStateWithStorageMeta, asOptionalChainStakeIntent, ChainIndexingServiceState, ChainIndexingServiceStateSchema, ChainStakeViewer,\n isChainIndexingServiceState,\n StakeIntentService,\n} from '@xyo-network/xl1-protocol'\nimport { Mutex } from 'async-mutex'\nimport { LRUCache } from 'lru-cache'\n\nimport { BaseService, creatableService } from '../BaseService.ts'\n\nexport interface XyoStakeIntentServiceParams extends BaseServiceParams {\n chainArchivist?: ArchivistInstance\n chainIterator?: EventingChainBlockNumberIterator\n chainStakeViewer?: ChainStakeViewer\n stakeIntentStateArchivist?: ArchivistInstance\n}\n\n/**\n * The number of blocks to periodically persist state\n */\nconst STATE_PERSISTENCE_INTERVAL = 60n\n\nconst ACTIVE_STAKE_TTL = 1000 * 60 * 60 * 2 // 2 hours in milliseconds\nconst NO_ACTIVE_STAKE_TTL = 1000 * 2 // 2 seconds in milliseconds\nconst STAKE_CACHE_MAX_ENTRIES = 10_000\n\n@creatableService()\nexport class XyoStakeIntentService extends BaseService<XyoStakeIntentServiceParams> implements StakeIntentService {\n // TODO: Use hash instead of block number to handle chain reorgs\n protected _lastIndexedBlockHash: Hash | undefined = undefined\n // TODO: Interval tree per declaration (bank, validator, etc.)\n // NOTE: Ideally move to DataIntervalTree to handle declared\n // ranges as it enables range queries in O(min(n, k * log n)) time,\n // where k is the number of intervals in the output list time\n // Currently using set based because it's simpler, equivalent\n // in performance for small sets, and (most importantly) easily\n // persisted so we can recover state on restart.\n protected _producers: IntervalMap<Address> = new IntervalMap()\n protected _stakeCache = new LRUCache<Address, bigint>({ max: STAKE_CACHE_MAX_ENTRIES })\n protected _updateMutex = new Mutex()\n\n constructor(params: XyoStakeIntentServiceParams) {\n super(params)\n this.chainIterator.on('headUpdated', async () => {\n await this.updateIndex()\n })\n }\n\n protected get chainArchivist() {\n return assertEx(this.params.chainArchivist, () => 'chainArchivist not set')\n }\n\n protected get chainIterator() {\n return assertEx(this.params.chainIterator, () => 'chainIterator not set')\n }\n\n protected get chainStakeViewer() {\n return assertEx(this.params.chainStakeViewer, () => 'chainStakeViewer not set')\n }\n\n protected get stakeIntentStateArchivist() {\n return assertEx(this.params.stakeIntentStateArchivist, () => 'stakeIntentStateArchivist not set')\n }\n\n override async createHandler(): Promise<void> {\n const head = await this.chainIterator.head()\n const headHash = await PayloadBuilder.hash(head)\n if (head?.block === undefined) return\n await this.recoverState(headHash)\n await this.updateIndex(true)\n }\n\n async getDeclaredCandidateRanges(address: Address, intent: Intent): Promise<Readonly<Readonly<[number, number]>[]>> {\n await Promise.resolve()\n assertEx(intent === 'producer', () => `Error: Support not yet added for intent ${intent}`)\n const results = this._producers.get(address)\n return results ?? []\n }\n\n async getDeclaredCandidatesForBlock(block: number, intent: Intent): Promise<Address[]> {\n return await this.spanAsync('getDeclaredCandidatesForBlock', async () => {\n assertEx(intent === 'producer', () => `Error: Support not yet added for intent ${intent}`)\n const results = this._producers.findAllContaining(block)\n const candidates = [...results]\n const validCandidates = await this.filterToValidStake(candidates, this.chainStakeViewer)\n return validCandidates\n })\n }\n\n async isStakedForBlock(block: number, intent: Intent, address: Address): Promise<boolean> {\n const candidates = await this.getDeclaredCandidatesForBlock(block, intent)\n return candidates.includes(address)\n }\n\n private async filterToValidStake(\n candidates: Address[],\n chainStakeViewer: ChainStakeViewer,\n requiredMinimumStake: bigint = 1n,\n ): Promise<Address[]> {\n type CandidateStake = { candidate: Address; stake: bigint }\n\n // Find the stake for each candidate\n const candidatesWithStake: CandidateStake[] = await Promise.all(\n candidates.map(async (candidate) => {\n // Check if the stake is already cached\n const stake = this._stakeCache.get(candidate)\n if (stake === undefined) {\n // Fetch from chainStakeViewer if not cached\n const activeStake = await chainStakeViewer.activeByAddressStaked(`${candidate}`)\n if (activeStake > 0n) {\n // Store result in cache\n this._stakeCache.set(candidate, activeStake, { ttl: ACTIVE_STAKE_TTL })\n } else {\n this._stakeCache.set(candidate, activeStake, { ttl: NO_ACTIVE_STAKE_TTL })\n }\n return { candidate, stake: activeStake }\n } else {\n return { candidate, stake }\n }\n }),\n )\n\n // Filter out candidates whose stake is greater than or equal to the required minimum\n return candidatesWithStake\n .filter(({ stake }) => stake >= requiredMinimumStake)\n .map(({ candidate }) => candidate)\n }\n\n private async persistState(current: Hash): Promise<void> {\n const state = this._producers.serialize()\n const payload = new PayloadBuilder<ChainIndexingServiceState<SerializedIntervalMap>>({ schema: ChainIndexingServiceStateSchema })\n .fields({ endBlockHash: current, state })\n .build()\n await this.stakeIntentStateArchivist.insert([payload])\n }\n\n private async recoverState(current: Hash): Promise<void> {\n const currentBlock = assertEx(asOptionalBlockBoundWitness((await this.chainArchivist.get([current]))?.[0]), () => `Block ${current} not found`)\n const currentBlockNum = currentBlock.block\n // Find last state before current head (in case of rollback, we indexed past it on an uncle chain, etc.)\n const opts: ArchivistNextOptions = { ...DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS }\n while (true) {\n const predicate = (p: WithStorageMeta<Payload>) => {\n const state = asOptionalChainIndexingServiceStateWithStorageMeta(p)\n return state ? true : false\n }\n const state = await findFirstMatching(this.stakeIntentStateArchivist, predicate, opts)\n if (isChainIndexingServiceState<SerializedIntervalMap>(state)) {\n const indexed = (await this.chainArchivist.get([state.endBlockHash]))?.[0]\n const indexedBlock = asOptionalBlockBoundWitnessWithStorageMeta(indexed)\n if (indexedBlock) {\n const indexedBlockNum = indexedBlock.block\n if (indexedBlockNum <= currentBlockNum) {\n const data = state.state as SerializedIntervalMap\n this._producers = new IntervalMap(data)\n this._lastIndexedBlockHash = indexedBlock._hash\n break\n }\n }\n } else {\n // No state found, start from genesis\n break\n }\n opts.open = true\n }\n }\n\n private async updateIndex(displayProgress = false): Promise<void> {\n if (this._updateMutex.isLocked()) {\n return\n }\n await this._updateMutex.runExclusive(async () => {\n return await this.spanAsync('updateIndex', async () => {\n const currentHead = await this.chainIterator.head()\n const currentHeadHash = await PayloadBuilder.hash(currentHead)\n const result = await analyzeChain(this.chainArchivist, [new ChainStakeIntentAnalyzer('producer')], currentHeadHash, this._lastIndexedBlockHash)\n const signedDeclarations = filterAs(result.find(isChainSummaryStakeIntent)?.intents ?? [], asOptionalChainStakeIntent)\n if (currentHead.block === undefined) return\n const currentHeadBlockNum = currentHead.block\n if (displayProgress) this.logger?.info(`Updating index through 0x${currentHeadBlockNum}`)\n for (const signedDeclaration of signedDeclarations) {\n const { exp, nbf } = signedDeclaration\n const start = nbf\n const stop = exp\n const address = asAddress(signedDeclaration?.from)\n if (start !== undefined && stop !== undefined && address !== undefined) {\n this._producers.insert(address, start, stop)\n }\n }\n /*\n if (index % STATE_PERSISTENCE_INTERVAL === 0n) {\n if (displayProgress) this.logger?.info(`Persisting state at block ${index}`)\n await this.persistState(await PayloadBuilder.hash(block))\n }\n */\n this._lastIndexedBlockHash = currentHeadHash\n })\n })\n }\n}\n","import { Base } from '@xylabs/base'\nimport type { Address } from '@xylabs/hex'\nimport { toAddress } from '@xylabs/hex'\nimport type { Promisable } from '@xylabs/promise'\nimport type { StakedXyoChain } from '@xyo-network/typechain'\nimport { StakedXyoChain__factory as StakedXyoChainFactory } from '@xyo-network/typechain'\nimport type { BaseServiceParams, ChainService } from '@xyo-network/xl1-protocol'\nimport { getAddress } from 'ethers/address'\nimport type { ContractRunner } from 'ethers/providers'\n\nexport interface EvmChainServiceParams extends BaseServiceParams {\n contract: StakedXyoChain\n id: Address\n runner: ContractRunner\n}\n\n/**\n * A class that represents a chain stake as backed by an EVM smart contract\n */\nexport class EvmChainService extends Base<EvmChainServiceParams> implements ChainService {\n private _contract: StakedXyoChain\n\n protected constructor(params: EvmChainServiceParams) {\n super(params)\n this._contract = params.contract\n }\n\n get id(): Address {\n return this.params.id\n }\n\n get runner(): ContractRunner {\n return this.params.runner\n }\n\n static create({\n id, runner, logger, traceProvider, meterProvider,\n }: Omit<EvmChainServiceParams, 'contract'>): Promisable<EvmChainService> {\n const contractAddress = getAddress(id)\n const contract: StakedXyoChain = StakedXyoChainFactory.connect(contractAddress, runner)\n return new this({\n id, contract, runner, logger, traceProvider, meterProvider,\n })\n }\n\n async active(): Promise<bigint> {\n return await this._contract.active()\n }\n\n async activeByAddressStaked(address: string): Promise<bigint> {\n return await this._contract.activeByAddressStaked(getAddress(address))\n }\n\n async activeByStaker(address: string): Promise<bigint> {\n return await this._contract.activeByStaker(getAddress(address))\n }\n\n async addStake(staked: string, amount: bigint): Promise<boolean> {\n const result = await this._contract.addStake(getAddress(staked), amount)\n await result.wait()\n return true\n }\n\n async chainId(): Promise<Address> {\n return toAddress(await this._contract.chainId())\n }\n\n async forkedAtBlockNumber(): Promise<bigint> {\n return await this._contract.forkedAtBlockNumber()\n }\n\n async forkedAtHash(): Promise<bigint> {\n return await this._contract.forkedAtHash()\n }\n\n async forkedChainId(): Promise<Address> {\n return toAddress(await this._contract.forkedChainId())\n }\n\n async minWithdrawalBlocks(): Promise<bigint> {\n return await this._contract.minWithdrawalBlocks()\n }\n\n async pending(): Promise<bigint> {\n return await this._contract.pending()\n }\n\n async pendingByStaker(staker: string): Promise<bigint> {\n return await this._contract.pendingByStaker(getAddress(staker))\n }\n\n async removeStake(slot: bigint): Promise<boolean> {\n const result = await this._contract.removeStake(slot)\n await result.wait()\n return true\n }\n\n async rewardsContract(): Promise<string> {\n return await this._contract.rewardsContract()\n }\n\n async stakingTokenAddress(): Promise<string> {\n return await this._contract.stakingTokenAddress()\n }\n\n async withdrawStake(slot: bigint): Promise<boolean> {\n const result = await this._contract.withdrawStake(slot)\n await result.wait()\n return true\n }\n\n async withdrawn(): Promise<bigint> {\n return await this._contract.withdrawn()\n }\n\n async withdrawnByStaker(staker: string): Promise<bigint> {\n return await this._contract.withdrawnByStaker(getAddress(staker))\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport type { BaseParams } from '@xylabs/base'\nimport { BaseEmitter } from '@xylabs/events'\nimport { isDefined, isNull } from '@xylabs/typeof'\nimport type { ArchivistInstance } from '@xyo-network/archivist-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport type {\n BlockBoundWitness, ChainIdentification,\n ChainIteratorEventData,\n EventingChainBlockNumberIterator,\n XyoChainIteratorParams,\n} from '@xyo-network/xl1-protocol'\nimport {\n asBlockBoundWitness, asOptionalBlockBoundWitness,\n isBlockBoundWitness,\n} from '@xyo-network/xl1-protocol'\nimport { LRUCache } from 'lru-cache'\n\nexport class XyoChainBlockNumberIterator extends BaseEmitter<BaseParams, ChainIteratorEventData> implements EventingChainBlockNumberIterator {\n protected _blocksByBlockNumber = new LRUCache<number, BlockBoundWitness>({ max: 10_000 })\n protected _chainArchivist: ArchivistInstance\n protected _chainInformation: ChainIdentification\n protected _head: BlockBoundWitness\n\n protected constructor(params: XyoChainIteratorParams) {\n super({})\n const { chainArchivist: archivist, head } = params\n this._chainArchivist = archivist\n this._head = head\n this._chainInformation = { id: head.chain }\n }\n\n get archivist(): ArchivistInstance { return this._chainArchivist }\n\n get chainIdentification(): ChainIdentification { return this._chainInformation }\n\n static async create(params: XyoChainIteratorParams): Promise<XyoChainBlockNumberIterator> {\n await Promise.resolve()\n return new XyoChainBlockNumberIterator(params)\n }\n\n async get(block: number): Promise<BlockBoundWitness> {\n // Bail early if the block requested is newer than the current head\n assertEx(this._head.block >= block, () => `Block requested is newer than the current head [${block}]`)\n const cached = this._blocksByBlockNumber.get(block)\n if (cached) return cached\n // Start at the current head and traverse backwards until the requested block is found\n const startingBlock = this._head\n const currentBlockHash = await PayloadBuilder.hash(startingBlock)\n let currentBlock = (await this._chainArchivist.get([currentBlockHash])).at(0)\n while (isDefined(currentBlock)) {\n assertEx(asBlockBoundWitness(currentBlock), () => `Expected hash to be a block bound witness [${currentBlock?._hash}]`)\n if (isBlockBoundWitness(currentBlock)) {\n this._blocksByBlockNumber.set(currentBlock.block, currentBlock)\n if (currentBlock.block === block) {\n return currentBlock\n }\n const { previous } = currentBlock\n if (isNull(previous)) break\n currentBlock = (await this._chainArchivist.get([previous])).at(0)\n }\n }\n throw new Error(`Block not found: ${block}`)\n }\n\n async head(): Promise<BlockBoundWitness> {\n return await Promise.resolve(this._head)\n }\n\n async next(block: number): Promise<BlockBoundWitness | undefined> {\n const currentBlock = block\n const nextBlockNumber = currentBlock + 1\n return await this.get(nextBlockNumber)\n }\n\n // TODO: Decide on inclusive/exclusive (probably need inclusive to account for chain head)\n // and then communicate via method name and documentation\n async previous(block: number | undefined = undefined, count: number = 1): Promise<BlockBoundWitness[]> {\n const results: BlockBoundWitness[] = []\n let currentBlock: BlockBoundWitness | undefined = isDefined(block) ? (await this.get(block)) : this._head\n while (currentBlock && results.length < count) {\n if (isBlockBoundWitness(currentBlock)) {\n results.push(currentBlock)\n const { previous } = currentBlock\n if (isNull(previous)) break\n const nextBlock = await this._chainArchivist.get([previous])\n currentBlock = asOptionalBlockBoundWitness(nextBlock[0])\n } else {\n const hash = PayloadBuilder.hash(currentBlock)\n assertEx(asBlockBoundWitness(currentBlock), () => `Expected hash to be a block bound witness [${hash}]`)\n }\n }\n return results\n }\n\n async updateHead(head: BlockBoundWitness): Promise<void> {\n // Async to allow for re-indexing, etc.\n await Promise.resolve()\n this._head = head\n void this.emit('headUpdated', { blocks: [head] })\n }\n}\n"],"mappings":"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","names":["assertEx","toHex","analyzeChain","BalanceAnalyzer","isChainSummaryBalances","toPositiveBigInt","BaseEmitter","span","spanAsync","Mutex","BaseService","BaseEmitter","singletonInitMutex","Mutex","singletons","globalThis","name","constructor","create","params","result","Error","createHandler","initSingleton","runExclusive","span","fn","tracer","spanAsync","BaseAccountableService","creatableService","XyoChainAccountBalanceService","BaseService","_balances","_previousHead","chainArchivist","assertEx","params","getBalance","address","toPositiveBigInt","positive","toHex","getBalances","result","entries","Object","balance","sync","head","analysis","analyzeChain","BalanceAnalyzer","tracer","find","isChainSummaryBalances","balances","BaseEthProvider","eth_accounts","Error","eth_blockNumber","eth_call","_transaction","_blockNumber","eth_clearSubscriptions","_keepSyncing","eth_coinbase","eth_compileLLL","_code","eth_compileSerpent","eth_compileSolidity","eth_estimateGas","eth_feeHistory","_blockCount","_newestBlock","_rewardPercentiles","eth_gasPrice","eth_getBalance","_address","eth_getBlockByHash","_blockHash","_hydrated","eth_getBlockByNumber","eth_getBlockTransactionCountByHash","eth_getBlockTransactionCountByNumber","eth_getCode","eth_getCompilers","eth_getFilterChanges","_filterIdentifier","eth_getFilterLogs","eth_getLogs","_filter","eth_getStorageAt","_storageSlot","eth_getTransactionByBlockHashAndIndex","_transactionIndex","eth_getTransactionByBlockNumberAndIndex","eth_getTransactionByHash","_transactionHash","eth_getTransactionCount","eth_getTransactionReceipt","eth_getUncleByBlockHashAndIndex","_uncleIndex","eth_getUncleByBlockNumberAndIndex","eth_getUncleCountByBlockHash","eth_getUncleCountByBlockNumber","eth_getWork","eth_hashrate","eth_maxPriorityFeePerGas","eth_mining","eth_newBlockFilter","eth_newFilter","eth_newPendingTransactionFilter","eth_protocolVersion","eth_sendRawTransaction","eth_sendTransaction","eth_sign","_message","eth_signTransaction","eth_submitHashrate","_hashRate","_id","eth_submitWork","_nonce","_hash","_digest","eth_subscribe","_params","eth_syncing","eth_uninstallFilter","eth_unsubscribe","_subscriptionId","assertEx","toHex","isUndefined","FixedPercentageBlockRewardDiviner","FixedPercentageBlockRewardDivinerConfigSchema","buildBlock","PayloadBuilder","asBlockBoundWitness","BlockNumberSchema","ChainStakeIntentSchema","hexFromBigInt","HydratedTransactionWrapper","TransferSchema","generateTransactionTransfers","address","transactions","txs","Promise","all","map","tx","HydratedTransactionWrapper","parse","txCosts","existingItem","find","addr","boundWitness","from","fees","base","push","payloads","amount","payload","schema","TransferSchema","epoch","Date","now","transfers","hexFromBigInt","DEFAULT_BLOCK_SIZE","XYO_PRODUCER_RESTAKE_DURATION","XYO_PRODUCER_RESTAKE_WINDOW","XyoBlockProducer","BaseService","_blockRewardDiviner","DefaultBlockSize","address","account","assertEx","params","chainFinalizedArchivist","chainInfo","chainInformation","electionService","pendingTransactions","pendingTransactionsService","rejectedTransactionsArchivist","rewardAddress","rewardService","stakeIntentService","validateHydratedBlockState","next","head","chain","id","leaders","getCreatorCommitteeForNextBlock","proposeNextValidBlock","getBlockRewardTransfer","block","FixedPercentageBlockRewardDiviner","create","blockRewardService","config","rewardPercentageRatio","schema","FixedPercentageBlockRewardDivinerConfigSchema","blockHex","toHex","blockId","PayloadBuilder","BlockNumberSchema","fields","build","rewards","divine","reward","getProducerRedeclaration","redeclareIntent","process","env","XYO_PRODUCER_REDECLARE_INTENT","isUndefined","ranges","getDeclaredCandidateRanges","lastRange","toSorted","a","b","at","currentDeclarationEnd","currentBlock","timeToProducerExpiration","intent","ChainStakeIntentSchema","from","nbf","exp","spanAsync","previousBlock","asBlockBoundWitness","nextBlock","nextBlockTransactions","getPendingTransactions","_hash","blockPayloads","producerRedeclarationPayload","push","length","rewardTransferPayload","transactionTransfers","generateTransactionTransfers","buildBlock","console","log","errors","logger","error","rejectedTransactions","insert","assertEx","XyoChainRewards__factory","XyoChainRewardsFactory","toEthAddress","EvmBlockRewardService","BaseService","_contractAddress","chainService","assertEx","params","contractAddress","provider","createHandler","rewardsContract","getRewardForBlock","blockNumber","contract","XyoChainRewardsFactory","connect","toEthAddress","calcBlockReward","assertEx","toFixedPoint","rewardFromBlockNumber","XyoBlockRewardService","BaseService","rewardFromBlockNumber","constructor","creatorReward","toFixedPoint","initialStepReward","minRewardPerBlock","stepFactorDenominator","stepFactorNumerator","stepSize","assertEx","params","initialReward","getRewardForBlock","blockNumber","assertEx","PayloadBuilder","addStorageMeta","tx","payloads","PayloadBuilder","XyoValidator","BaseService","address","account","assertEx","params","chainFinalizedArchivist","chainInfo","chainInformation","electionService","pendingTransactions","rewardService","validatePendingBlock","_block","validatePendingTransaction","hydratedTransaction","get","_hash","length","Promise","resolve","assertEx","hexToLast4BytesInt","shuffleWithSeed","PayloadBuilder","XyoElectionService","BaseService","constructor","params","chainIterator","assertEx","chainStakeViewer","stakeIntentService","getCreatorCommitteeForNextBlock","current","spanAsync","nextBlock","block","candidates","getDeclaredCandidatesForBlock","previousBlockHash","PayloadBuilder","hash","generateCreatorCommittee","maxSize","creators","Set","seed","hexToLast4BytesInt","creatorArray","shuffleWithSeed","slice","ValueType","filterAs","filterAsync","assertEx","exists","forget","MemoryArchivist","validateTransaction","asOptionalTransactionBoundWitnessWithStorageMeta","flattenHydratedTransactions","tryHydrateTransaction","Mutex","XyoPendingTransactionsService","BaseService","MutexPriority","InsertNewTransactions","ReadTransactions","RemoveRejectedTransactions","RemoveFinalizedTransactions","_countPendingTransactionsMutex","Mutex","_curatedPendingTransactionsArchivist","_pendingTransactionsCount","_updateCuratedPendingTransactionsArchivistMutex","chainArchivist","assertEx","params","chainIdentification","pendingTransactionsArchivist","pendingTransactionsCount","forget","countPendingTransactions","pendingTransactionsLocalArchivist","rejectedTransactionsArchivist","createHandler","MemoryArchivist","create","account","on","payloads","insertNewTransactions","removeFinalizedTransactions","removeRejectedTransactions","pendingTransactionsGauge","meter","createObservableGauge","description","valueType","ValueType","INT","addCallback","observer","observe","getPendingTransactions","head","limit","spanAsync","runExclusive","foundPendingTransactions","cursor","length","next","order","at","_sequence","transactions","map","payload","asOptionalTransactionBoundWitnessWithStorageMeta","filter","exists","push","hydratedTransactions","Promise","all","tx","tryHydrateTransaction","_hash","isLocked","pendingTransactions","filterAs","filterAlreadyFinalizedTransactions","incomingTransactions","incomingTransactionHashes","finalizedTransactions","get","finalizedTransactionHashes","Set","item","nonFinalizedTransactions","has","unprocessedTransactions","hydratedUnprocessedTransactions","validTransactions","filterAsync","errors","validateTransaction","id","insert","flattenHydratedTransactions","removeTransactions","priority","delete","filterAs","exists","asOptionalBoundWitness","payloadSchemasContains","BoundWitnessWrapper","asOptionalChainStakeIntent","ChainStakeIntentSchema","getBlockSignedStakeDeclarations","block","archivist","intent","blockData","get","payload_hashes","bwsFromBlock","filterAs","asOptionalBoundWitness","bwsFromBlockWithDeclarations","filter","bw","payloadSchemasContains","ChainStakeIntentSchema","validBlockBwsWithDeclarations","filterToValidSignedBoundWitnesses","Promise","all","map","stakeIntentHashes","flatMap","mapBoundWitnessToStakeIntentHashes","exists","payloads","stakeIntents","asOptionalChainStakeIntent","p","addresses","includes","from","flat","bws","validBwIndexes","BoundWitnessWrapper","parse","getValid","_","index","payload_schemas","schema","undefined","filterAs","assertEx","asAddress","analyzeChain","ChainStakeIntentAnalyzer","isChainSummaryStakeIntent","DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS","findFirstMatching","IntervalMap","PayloadBuilder","asOptionalBlockBoundWitness","asOptionalBlockBoundWitnessWithStorageMeta","asOptionalChainIndexingServiceStateWithStorageMeta","asOptionalChainStakeIntent","ChainIndexingServiceStateSchema","isChainIndexingServiceState","Mutex","LRUCache","ACTIVE_STAKE_TTL","NO_ACTIVE_STAKE_TTL","STAKE_CACHE_MAX_ENTRIES","XyoStakeIntentService","BaseService","_lastIndexedBlockHash","undefined","_producers","IntervalMap","_stakeCache","LRUCache","max","_updateMutex","Mutex","constructor","params","chainIterator","on","updateIndex","chainArchivist","assertEx","chainStakeViewer","stakeIntentStateArchivist","createHandler","head","headHash","PayloadBuilder","hash","block","recoverState","getDeclaredCandidateRanges","address","intent","Promise","resolve","results","get","getDeclaredCandidatesForBlock","spanAsync","findAllContaining","candidates","validCandidates","filterToValidStake","isStakedForBlock","includes","requiredMinimumStake","candidatesWithStake","all","map","candidate","stake","activeStake","activeByAddressStaked","set","ttl","filter","persistState","current","state","serialize","payload","schema","ChainIndexingServiceStateSchema","fields","endBlockHash","build","insert","currentBlock","asOptionalBlockBoundWitness","currentBlockNum","opts","DEFAULT_FIND_FIRST_MATCHING_NEXT_OPTIONS","predicate","p","asOptionalChainIndexingServiceStateWithStorageMeta","findFirstMatching","isChainIndexingServiceState","indexed","indexedBlock","asOptionalBlockBoundWitnessWithStorageMeta","indexedBlockNum","data","_hash","open","displayProgress","isLocked","runExclusive","currentHead","currentHeadHash","result","analyzeChain","ChainStakeIntentAnalyzer","signedDeclarations","filterAs","find","isChainSummaryStakeIntent","intents","asOptionalChainStakeIntent","currentHeadBlockNum","logger","info","signedDeclaration","exp","nbf","start","stop","asAddress","from","Base","toAddress","StakedXyoChain__factory","StakedXyoChainFactory","getAddress","EvmChainService","Base","_contract","params","contract","id","runner","create","logger","traceProvider","meterProvider","contractAddress","getAddress","StakedXyoChainFactory","connect","active","activeByAddressStaked","address","activeByStaker","addStake","staked","amount","result","wait","chainId","toAddress","forkedAtBlockNumber","forkedAtHash","forkedChainId","minWithdrawalBlocks","pending","pendingByStaker","staker","removeStake","slot","rewardsContract","stakingTokenAddress","withdrawStake","withdrawn","withdrawnByStaker","assertEx","BaseEmitter","isDefined","isNull","PayloadBuilder","asBlockBoundWitness","asOptionalBlockBoundWitness","isBlockBoundWitness","LRUCache","XyoChainBlockNumberIterator","BaseEmitter","_blocksByBlockNumber","LRUCache","max","_chainArchivist","_chainInformation","_head","params","chainArchivist","archivist","head","id","chain","chainIdentification","create","Promise","resolve","get","block","assertEx","cached","startingBlock","currentBlockHash","PayloadBuilder","hash","currentBlock","at","isDefined","asBlockBoundWitness","_hash","isBlockBoundWitness","set","previous","isNull","Error","next","nextBlockNumber","undefined","count","results","length","push","nextBlock","asOptionalBlockBoundWitness","updateHead","emit","blocks"]}
|
|
@@ -2,7 +2,7 @@ import { Address } from '@xylabs/hex';
|
|
|
2
2
|
import { ArchivistInstance, ReadArchivist } from '@xyo-network/archivist-model';
|
|
3
3
|
import { BlockRewardDiviner } from '@xyo-network/chain-modules';
|
|
4
4
|
import { WithStorageMeta } from '@xyo-network/payload-model';
|
|
5
|
-
import {
|
|
5
|
+
import { BlockBoundWitness, BlockProducer, ChainStakeIntent, HydratedBlock, PendingTransactionsService, StakeIntentService, Transfer } from '@xyo-network/xl1-protocol';
|
|
6
6
|
import { BaseService } from '../BaseService.ts';
|
|
7
7
|
import { XyoValidatorParams } from '../ChainValidator/index.ts';
|
|
8
8
|
/**
|
|
@@ -16,7 +16,6 @@ export declare const XYO_PRODUCER_RESTAKE_DURATION = 10000;
|
|
|
16
16
|
*/
|
|
17
17
|
export declare const XYO_PRODUCER_RESTAKE_WINDOW = 500n;
|
|
18
18
|
export interface XyoBlockProducerParams extends XyoValidatorParams {
|
|
19
|
-
accountBalanceService?: AccountBalanceService;
|
|
20
19
|
pendingTransactionsArchivist?: ReadArchivist;
|
|
21
20
|
pendingTransactionsService?: PendingTransactionsService;
|
|
22
21
|
rejectedTransactionsArchivist?: ArchivistInstance;
|
|
@@ -28,7 +27,6 @@ export declare class XyoBlockProducer extends BaseService<XyoBlockProducerParams
|
|
|
28
27
|
static get DefaultBlockSize(): number;
|
|
29
28
|
get address(): Lowercase<string>;
|
|
30
29
|
protected get account(): import("@xyo-network/account-model").AccountInstance;
|
|
31
|
-
protected get accountBalanceService(): AccountBalanceService;
|
|
32
30
|
protected get chainFinalizedArchivist(): ReadArchivist<import("@xyo-network/payload-model").Payload, Lowercase<string>>;
|
|
33
31
|
protected get chainInfo(): import("@xyo-network/xl1-protocol").ChainInformation;
|
|
34
32
|
protected get electionService(): import("@xyo-network/xl1-protocol").ElectionService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XyoBlockProducer.d.ts","sourceRoot":"","sources":["../../../src/BlockProducer/XyoBlockProducer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"XyoBlockProducer.d.ts","sourceRoot":"","sources":["../../../src/BlockProducer/XyoBlockProducer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAA;AAE5C,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC/E,OAAO,EACL,kBAAkB,EACnB,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EACqC,iBAAiB,EAAkC,aAAa,EAAE,gBAAgB,EAC5H,aAAa,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,QAAQ,EACxE,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAA;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAG/D;;GAEG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAKpC,eAAO,MAAM,6BAA6B,QAAS,CAAA;AAEnD;;;GAGG;AACH,eAAO,MAAM,2BAA2B,OAAO,CAAA;AAE/C,MAAM,WAAW,sBAAuB,SAAQ,kBAAkB;IAChE,4BAA4B,CAAC,EAAE,aAAa,CAAA;IAC5C,0BAA0B,CAAC,EAAE,0BAA0B,CAAA;IACvD,6BAA6B,CAAC,EAAE,iBAAiB,CAAA;IACjD,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;CACxC;AAED,qBACa,gBAAiB,SAAQ,WAAW,CAAC,sBAAsB,CAAE,YAAW,aAAa;IAChG,SAAS,CAAC,mBAAmB,EAAE,kBAAkB,GAAG,SAAS,CAAA;IAE7D,MAAM,KAAK,gBAAgB,IAAI,MAAM,CAEpC;IAED,IAAI,OAAO,sBAEV;IAED,SAAS,KAAK,OAAO,yDAEpB;IAED,SAAS,KAAK,uBAAuB,mFAEpC;IAED,SAAS,KAAK,SAAS,yDAEtB;IAED,SAAS,KAAK,eAAe,wDAE5B;IAED,SAAS,KAAK,mBAAmB;;;;;;;;wPAEhC;IAED,SAAS,KAAK,0BAA0B,+BAEvC;IAED,SAAS,KAAK,6BAA6B;;;;;;;;wPAE1C;IAED,SAAS,KAAK,aAAa,IAAI,OAAO,CAErC;IAED,SAAS,KAAK,aAAa,2DAE1B;IAED,SAAS,KAAK,kBAAkB,IAAI,kBAAkB,CAErD;IAED,SAAS,KAAK,0BAA0B,6EAEvC;IAEK,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;cAWxE,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAoBpF;;;;OAIG;cACa,wBAAwB,CAAC,IAAI,EAAE,eAAe,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;cAwBzG,qBAAqB,CAAC,IAAI,EAAE,eAAe,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;CAoCpH"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type Address } from '@xylabs/hex';
|
|
2
|
-
import type
|
|
2
|
+
import { type HydratedTransaction, type Transfer } from '@xyo-network/xl1-protocol';
|
|
3
3
|
export declare function generateTransactionTransfers(address: Address, transactions: HydratedTransaction[]): Promise<Transfer[]>;
|
|
4
4
|
//# sourceMappingURL=generateTransactionTransfers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateTransactionTransfers.d.ts","sourceRoot":"","sources":["../../../src/BlockProducer/generateTransactionTransfers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generateTransactionTransfers.d.ts","sourceRoot":"","sources":["../../../src/BlockProducer/generateTransactionTransfers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAiB,MAAM,aAAa,CAAA;AAEzD,OAAO,EACL,KAAK,mBAAmB,EAAE,KAAK,QAAQ,EACxC,MAAM,2BAA2B,CAAA;AAElC,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA0B7H"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@xyo-network/chain-services",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"description": "XYO Layer One SDK Services",
|
|
6
6
|
"homepage": "https://xylabs.com",
|
|
7
7
|
"bugs": {
|
|
@@ -51,17 +51,17 @@
|
|
|
51
51
|
"@xyo-network/boundwitness-model": "^3.16.1",
|
|
52
52
|
"@xyo-network/boundwitness-validator": "^3.16.1",
|
|
53
53
|
"@xyo-network/boundwitness-wrapper": "^3.16.1",
|
|
54
|
-
"@xyo-network/chain-analyze": "^1.
|
|
55
|
-
"@xyo-network/chain-modules": "^1.
|
|
56
|
-
"@xyo-network/chain-protocol": "^1.
|
|
57
|
-
"@xyo-network/chain-utils": "^1.
|
|
58
|
-
"@xyo-network/chain-validation": "^1.
|
|
59
|
-
"@xyo-network/chain-wrappers": "^1.
|
|
54
|
+
"@xyo-network/chain-analyze": "^1.4.0",
|
|
55
|
+
"@xyo-network/chain-modules": "^1.4.0",
|
|
56
|
+
"@xyo-network/chain-protocol": "^1.4.0",
|
|
57
|
+
"@xyo-network/chain-utils": "^1.4.0",
|
|
58
|
+
"@xyo-network/chain-validation": "^1.4.0",
|
|
59
|
+
"@xyo-network/chain-wrappers": "^1.4.0",
|
|
60
60
|
"@xyo-network/payload-builder": "^3.16.1",
|
|
61
61
|
"@xyo-network/payload-model": "^3.16.1",
|
|
62
62
|
"@xyo-network/typechain": "^3.5.2",
|
|
63
|
-
"@xyo-network/xl1-protocol": "^1.3.
|
|
64
|
-
"@xyo-network/xl1-protocol-sdk": "^1.
|
|
63
|
+
"@xyo-network/xl1-protocol": "^1.3.29",
|
|
64
|
+
"@xyo-network/xl1-protocol-sdk": "^1.4.0",
|
|
65
65
|
"async-mutex": "^0.5.0",
|
|
66
66
|
"ethers": "6.14.1",
|
|
67
67
|
"lru-cache": "^11.1.0",
|
|
@@ -75,9 +75,9 @@
|
|
|
75
75
|
"@xylabs/vitest-extended": "^4.9.18",
|
|
76
76
|
"@xyo-network/account": "^3.16.1",
|
|
77
77
|
"@xyo-network/account-model": "^3.16.1",
|
|
78
|
-
"@xyo-network/chain-validation": "^1.
|
|
78
|
+
"@xyo-network/chain-validation": "^1.4.0",
|
|
79
79
|
"@xyo-network/wallet": "^3.16.1",
|
|
80
|
-
"knip": "^5.
|
|
80
|
+
"knip": "^5.56.0",
|
|
81
81
|
"typescript": "^5.8.3",
|
|
82
82
|
"vitest": "^3.1.4",
|
|
83
83
|
"vitest-mock-extended": "^3.1.0"
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { assertEx } from '@xylabs/assert'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
Address, hexToBigInt, toHex,
|
|
5
|
-
} from '@xylabs/hex'
|
|
2
|
+
import { Address, toHex } from '@xylabs/hex'
|
|
6
3
|
import { isUndefined } from '@xylabs/typeof'
|
|
7
4
|
import { ArchivistInstance, ReadArchivist } from '@xyo-network/archivist-model'
|
|
8
5
|
import {
|
|
@@ -12,7 +9,6 @@ import { buildBlock } from '@xyo-network/chain-protocol'
|
|
|
12
9
|
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
13
10
|
import { WithStorageMeta } from '@xyo-network/payload-model'
|
|
14
11
|
import {
|
|
15
|
-
AccountBalanceService,
|
|
16
12
|
AllowedBlockPayload, asBlockBoundWitness, BlockBoundWitness, BlockNumber, BlockNumberSchema, BlockProducer, ChainStakeIntent, ChainStakeIntentSchema,
|
|
17
13
|
HydratedBlock, PendingTransactionsService, StakeIntentService, Transfer,
|
|
18
14
|
} from '@xyo-network/xl1-protocol'
|
|
@@ -38,7 +34,6 @@ export const XYO_PRODUCER_RESTAKE_DURATION = 10_000
|
|
|
38
34
|
export const XYO_PRODUCER_RESTAKE_WINDOW = 500n
|
|
39
35
|
|
|
40
36
|
export interface XyoBlockProducerParams extends XyoValidatorParams {
|
|
41
|
-
accountBalanceService?: AccountBalanceService
|
|
42
37
|
pendingTransactionsArchivist?: ReadArchivist
|
|
43
38
|
pendingTransactionsService?: PendingTransactionsService
|
|
44
39
|
rejectedTransactionsArchivist?: ArchivistInstance
|
|
@@ -62,10 +57,6 @@ export class XyoBlockProducer extends BaseService<XyoBlockProducerParams> implem
|
|
|
62
57
|
return assertEx(this.params.account, () => 'account is required')
|
|
63
58
|
}
|
|
64
59
|
|
|
65
|
-
protected get accountBalanceService() {
|
|
66
|
-
return assertEx(this.params.accountBalanceService, () => 'accountBalanceService is required')
|
|
67
|
-
}
|
|
68
|
-
|
|
69
60
|
protected get chainFinalizedArchivist() {
|
|
70
61
|
return assertEx(this.params.chainFinalizedArchivist, () => 'chainFinalizedArchivist is required')
|
|
71
62
|
}
|
|
@@ -125,7 +116,7 @@ export class XyoBlockProducer extends BaseService<XyoBlockProducerParams> implem
|
|
|
125
116
|
blockRewardService: this.rewardService,
|
|
126
117
|
config: {
|
|
127
118
|
rewardAddress: this.rewardAddress,
|
|
128
|
-
rewardPercentageRatio:
|
|
119
|
+
rewardPercentageRatio: 0,
|
|
129
120
|
schema: FixedPercentageBlockRewardDivinerConfigSchema,
|
|
130
121
|
},
|
|
131
122
|
})
|
|
@@ -187,23 +178,10 @@ export class XyoBlockProducer extends BaseService<XyoBlockProducerParams> implem
|
|
|
187
178
|
if (rewardTransferPayload) blockPayloads.push(rewardTransferPayload)
|
|
188
179
|
|
|
189
180
|
const transactionTransfers = await generateTransactionTransfers(this.address, nextBlockTransactions)
|
|
190
|
-
|
|
191
|
-
const fundedTransfers: Transfer[] = []
|
|
192
|
-
|
|
193
|
-
const fundedNextBlockTransactions = nextBlockTransactions.map((tx) => {
|
|
194
|
-
const transfer: Transfer | undefined = transactionTransfers.find(txTransfer => txTransfer.from === tx[0].from)
|
|
195
|
-
if (!transfer) return
|
|
196
|
-
const totalTransferCost = Object.values(transfer?.transfers).reduce((acc, t) => acc + hexToBigInt(t), 0n)
|
|
197
|
-
if (hexToBigInt(this.accountBalanceService.getBalance(this.address)) >= totalTransferCost) {
|
|
198
|
-
fundedTransfers.push(transfer)
|
|
199
|
-
return tx
|
|
200
|
-
}
|
|
201
|
-
}).filter(exists)
|
|
202
|
-
|
|
203
|
-
blockPayloads.push(...fundedTransfers)
|
|
181
|
+
blockPayloads.push(...transactionTransfers)
|
|
204
182
|
|
|
205
183
|
// Build the block
|
|
206
|
-
const block = await buildBlock(head,
|
|
184
|
+
const block = await buildBlock(head, nextBlockTransactions, blockPayloads, [this.account])
|
|
207
185
|
console.log('buildBlock', block)
|
|
208
186
|
const errors = await this.validateHydratedBlockState(block, this.chainInfo.id, this.chainFinalizedArchivist)
|
|
209
187
|
if (errors.length > 0) {
|
|
@@ -1,54 +1,33 @@
|
|
|
1
|
-
import { assertEx } from '@xylabs/assert'
|
|
2
1
|
import { type Address, hexFromBigInt } from '@xylabs/hex'
|
|
3
|
-
import { XYO_ZERO_ADDRESS } from '@xyo-network/chain-utils'
|
|
4
2
|
import { HydratedTransactionWrapper } from '@xyo-network/chain-wrappers'
|
|
5
|
-
import type {
|
|
6
|
-
HydratedTransaction,
|
|
7
|
-
Transfer,
|
|
8
|
-
} from '@xyo-network/xl1-protocol'
|
|
9
3
|
import {
|
|
10
|
-
|
|
11
|
-
mXL1ToXL1, TransferSchema,
|
|
12
|
-
XL1,
|
|
4
|
+
type HydratedTransaction, type Transfer, TransferSchema,
|
|
13
5
|
} from '@xyo-network/xl1-protocol'
|
|
14
|
-
import { transactionRequiredGas } from '@xyo-network/xl1-protocol-sdk'
|
|
15
6
|
|
|
16
7
|
export async function generateTransactionTransfers(address: Address, transactions: HydratedTransaction[]): Promise<Transfer[]> {
|
|
17
8
|
const txs = await Promise.all(transactions.map(tx => HydratedTransactionWrapper.parse(tx)))
|
|
18
9
|
|
|
19
10
|
// merge transactions with the same from address
|
|
20
|
-
const
|
|
21
|
-
for (const tx of txs) {
|
|
22
|
-
txBaseFeeCosts[tx.boundWitness.from] = XL1((txBaseFeeCosts[tx.boundWitness.from] ?? 0n) + mXL1ToXL1(tx.fees.base))
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const txGasCosts: Record<Address, XL1> = {}
|
|
11
|
+
const txCosts: [Address, bigint][] = []
|
|
26
12
|
for (const tx of txs) {
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
13
|
+
const existingItem = txCosts.find(([addr]) => addr === tx.boundWitness.from)
|
|
14
|
+
if (existingItem) {
|
|
15
|
+
existingItem[1] += tx.fees.base
|
|
16
|
+
} else {
|
|
17
|
+
txCosts.push([tx.boundWitness.from, tx.fees.base])
|
|
18
|
+
}
|
|
30
19
|
}
|
|
31
20
|
|
|
32
|
-
// generate actual Transfer Payloads
|
|
33
|
-
const payloads =
|
|
21
|
+
// generate actual Transfer Payloads
|
|
22
|
+
const payloads = txCosts.map(([from, amount]) => {
|
|
34
23
|
const payload: Transfer = {
|
|
35
24
|
schema: TransferSchema,
|
|
36
25
|
epoch: Date.now(),
|
|
37
26
|
from,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
[XYO_ZERO_ADDRESS]: hexFromBigInt(amount),
|
|
41
|
-
},
|
|
27
|
+
// TODO: add function to Wrapper to calculate entire cost of transaction
|
|
28
|
+
transfers: { [address]: hexFromBigInt(amount) },
|
|
42
29
|
}
|
|
43
30
|
return payload
|
|
44
31
|
})
|
|
45
|
-
|
|
46
|
-
// transfer gas cost to producer
|
|
47
|
-
for (const [from, amount] of Object.entries(txGasCosts)) {
|
|
48
|
-
// every gas from should also be a base fee from
|
|
49
|
-
const fromPayload = assertEx(payloads.find(p => p.from === from), () => 'from payload not found')
|
|
50
|
-
fromPayload.transfers[address] = hexFromBigInt(amount)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
32
|
return payloads
|
|
54
33
|
}
|