@xyo-network/chain-services 1.0.1

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.
Files changed (88) hide show
  1. package/LICENSE +165 -0
  2. package/README.md +57 -0
  3. package/babel.config.json +6 -0
  4. package/dist/neutral/index.mjs +972 -0
  5. package/dist/neutral/index.mjs.map +1 -0
  6. package/dist/types/AccountBalance/XyoChainAccountBalanceService.d.ts +24 -0
  7. package/dist/types/AccountBalance/XyoChainAccountBalanceService.d.ts.map +1 -0
  8. package/dist/types/AccountBalance/index.d.ts +2 -0
  9. package/dist/types/AccountBalance/index.d.ts.map +1 -0
  10. package/dist/types/BaseService.d.ts +22 -0
  11. package/dist/types/BaseService.d.ts.map +1 -0
  12. package/dist/types/BlockProducer/XyoBlockProducer.d.ts +50 -0
  13. package/dist/types/BlockProducer/XyoBlockProducer.d.ts.map +1 -0
  14. package/dist/types/BlockProducer/index.d.ts +2 -0
  15. package/dist/types/BlockProducer/index.d.ts.map +1 -0
  16. package/dist/types/BlockReward/EvmBlockRewardService.d.ts +16 -0
  17. package/dist/types/BlockReward/EvmBlockRewardService.d.ts.map +1 -0
  18. package/dist/types/BlockReward/XyoBlockRewardService.d.ts +23 -0
  19. package/dist/types/BlockReward/XyoBlockRewardService.d.ts.map +1 -0
  20. package/dist/types/BlockReward/index.d.ts +3 -0
  21. package/dist/types/BlockReward/index.d.ts.map +1 -0
  22. package/dist/types/ChainIndexService.d.ts +42 -0
  23. package/dist/types/ChainIndexService.d.ts.map +1 -0
  24. package/dist/types/ChainValidator/XyoValidator.d.ts +26 -0
  25. package/dist/types/ChainValidator/XyoValidator.d.ts.map +1 -0
  26. package/dist/types/ChainValidator/index.d.ts +3 -0
  27. package/dist/types/ChainValidator/index.d.ts.map +1 -0
  28. package/dist/types/ChainValidator/model/Validator.d.ts +7 -0
  29. package/dist/types/ChainValidator/model/Validator.d.ts.map +1 -0
  30. package/dist/types/ChainValidator/model/index.d.ts +2 -0
  31. package/dist/types/ChainValidator/model/index.d.ts.map +1 -0
  32. package/dist/types/CreatableService.d.ts +9 -0
  33. package/dist/types/CreatableService.d.ts.map +1 -0
  34. package/dist/types/Election/XyoElectionService.d.ts +13 -0
  35. package/dist/types/Election/XyoElectionService.d.ts.map +1 -0
  36. package/dist/types/Election/index.d.ts +2 -0
  37. package/dist/types/Election/index.d.ts.map +1 -0
  38. package/dist/types/PendingTransactions/PendingTransactions.d.ts +25 -0
  39. package/dist/types/PendingTransactions/PendingTransactions.d.ts.map +1 -0
  40. package/dist/types/PendingTransactions/index.d.ts +2 -0
  41. package/dist/types/PendingTransactions/index.d.ts.map +1 -0
  42. package/dist/types/StakeIntent/XyoStakeIntentService.d.ts +48 -0
  43. package/dist/types/StakeIntent/XyoStakeIntentService.d.ts.map +1 -0
  44. package/dist/types/StakeIntent/index.d.ts +2 -0
  45. package/dist/types/StakeIntent/index.d.ts.map +1 -0
  46. package/dist/types/StakeIntent/lib/getBlockSignedStakeDeclarations.d.ts +4 -0
  47. package/dist/types/StakeIntent/lib/getBlockSignedStakeDeclarations.d.ts.map +1 -0
  48. package/dist/types/StakeIntent/lib/index.d.ts +2 -0
  49. package/dist/types/StakeIntent/lib/index.d.ts.map +1 -0
  50. package/dist/types/Staker/Evm/Evm.d.ts +39 -0
  51. package/dist/types/Staker/Evm/Evm.d.ts.map +1 -0
  52. package/dist/types/Staker/Evm/index.d.ts +2 -0
  53. package/dist/types/Staker/Evm/index.d.ts.map +1 -0
  54. package/dist/types/Staker/index.d.ts +2 -0
  55. package/dist/types/Staker/index.d.ts.map +1 -0
  56. package/dist/types/XyoChainBlockNumberIterator.d.ts +21 -0
  57. package/dist/types/XyoChainBlockNumberIterator.d.ts.map +1 -0
  58. package/dist/types/index.d.ts +12 -0
  59. package/dist/types/index.d.ts.map +1 -0
  60. package/package.json +101 -0
  61. package/src/AccountBalance/XyoChainAccountBalanceService.ts +49 -0
  62. package/src/AccountBalance/index.ts +1 -0
  63. package/src/BaseService.ts +64 -0
  64. package/src/BlockProducer/XyoBlockProducer.ts +184 -0
  65. package/src/BlockProducer/index.ts +1 -0
  66. package/src/BlockReward/EvmBlockRewardService.ts +42 -0
  67. package/src/BlockReward/XyoBlockRewardService.ts +73 -0
  68. package/src/BlockReward/index.ts +2 -0
  69. package/src/ChainIndexService.ts +48 -0
  70. package/src/ChainValidator/XyoValidator.ts +55 -0
  71. package/src/ChainValidator/index.ts +2 -0
  72. package/src/ChainValidator/model/Validator.ts +7 -0
  73. package/src/ChainValidator/model/index.ts +1 -0
  74. package/src/CreatableService.ts +16 -0
  75. package/src/Election/XyoElectionService.ts +45 -0
  76. package/src/Election/index.ts +1 -0
  77. package/src/PendingTransactions/PendingTransactions.ts +168 -0
  78. package/src/PendingTransactions/index.ts +1 -0
  79. package/src/StakeIntent/XyoStakeIntentService.ts +214 -0
  80. package/src/StakeIntent/index.ts +1 -0
  81. package/src/StakeIntent/lib/getBlockSignedStakeDeclarations.ts +44 -0
  82. package/src/StakeIntent/lib/index.ts +1 -0
  83. package/src/Staker/Evm/Evm.ts +117 -0
  84. package/src/Staker/Evm/index.ts +1 -0
  85. package/src/Staker/index.ts +1 -0
  86. package/src/XyoChainBlockNumberIterator.ts +98 -0
  87. package/src/index.ts +11 -0
  88. package/xy.config.ts +10 -0
@@ -0,0 +1,44 @@
1
+ import { filterAs } from '@xylabs/array'
2
+ import { asElevated, asOptionalChainStakeIntent, BlockBoundWitness, ChainStakeIntent, ChainStakeIntentSchema, Intent } from '@xyo-network/chain-model'
3
+ import { exists } from '@xylabs/exists'
4
+ import { Hash } from '@xylabs/hex'
5
+ import { ArchivistInstance } from '@xyo-network/archivist-model'
6
+ import { asOptionalBoundWitness, BoundWitness } from '@xyo-network/boundwitness-model'
7
+ import { payloadSchemasContains } from '@xyo-network/boundwitness-validator'
8
+ import { BoundWitnessWrapper } from '@xyo-network/boundwitness-wrapper'
9
+
10
+ export const getBlockSignedStakeDeclarations = async (block: BlockBoundWitness, archivist: ArchivistInstance, intent: Intent): Promise<ChainStakeIntent[]> => {
11
+ // Get payloads in block
12
+ const blockData = await archivist.get(block.payload_hashes)
13
+ // Filter Payloads in block to BoundWitnesses
14
+ const bwsFromBlock = filterAs(blockData, asOptionalBoundWitness)
15
+ // Filter to BoundWitnesses with StakeIntent payloads
16
+ const bwsFromBlockWithDeclarations = bwsFromBlock.filter(bw => payloadSchemasContains(bw, ChainStakeIntentSchema))
17
+ // Filter to only valid signed BWs
18
+ const validBlockBwsWithDeclarations = await filterToValidSignedBoundWitnesses(bwsFromBlockWithDeclarations)
19
+ return (await Promise.all(validBlockBwsWithDeclarations.map(async (bw) => {
20
+ // Get staked intent hashes from signed declarations
21
+ const stakeIntentHashes = validBlockBwsWithDeclarations
22
+ .flatMap(mapBoundWitnessToStakeIntentHashes)
23
+ .filter(exists)
24
+ // Get staked intent payloads
25
+ const payloads = await archivist.get(stakeIntentHashes)
26
+ // Filter payloads to staked intents
27
+ const stakeIntents = filterAs(filterAs(payloads, asOptionalChainStakeIntent), asElevated)
28
+ // that are producers
29
+ .filter(p => p.intent === intent)
30
+ // where the issuer of the intent is also the signer of this BW
31
+ .filter(p => bw.addresses.includes(p.from))
32
+
33
+ return stakeIntents
34
+ }))).flat()
35
+ }
36
+
37
+ const filterToValidSignedBoundWitnesses = async (bws: BoundWitness[]): Promise<BoundWitness[]> => {
38
+ const validBwIndexes = await Promise.all(bws.map(bw => BoundWitnessWrapper.parse(bw).getValid()))
39
+ return bws.filter((_, index) => validBwIndexes[index])
40
+ }
41
+
42
+ const mapBoundWitnessToStakeIntentHashes = (bw: BoundWitness): (Hash | undefined)[] => {
43
+ return bw.payload_schemas.map((schema, index) => schema === ChainStakeIntentSchema ? bw.payload_hashes[index] : undefined)
44
+ }
@@ -0,0 +1 @@
1
+ export * from './getBlockSignedStakeDeclarations.ts'
@@ -0,0 +1,117 @@
1
+ import { BaseServiceParams, ChainService } from '@xyo-network/chain-model'
2
+ import { Address, toAddress } from '@xylabs/hex'
3
+ import { Base } from '@xylabs/object'
4
+ import { Promisable } from '@xylabs/promise'
5
+ import { StakedXyoChain, StakedXyoChain__factory as StakedXyoChainFactory } from '@xyo-network/typechain'
6
+ import { getAddress } from 'ethers/address'
7
+ import { ContractRunner } from 'ethers/providers'
8
+
9
+ export interface EvmChainServiceParams extends BaseServiceParams {
10
+ contract: StakedXyoChain
11
+ id: Address
12
+ runner: ContractRunner
13
+ }
14
+
15
+ /**
16
+ * A class that represents a chain stake as backed by an EVM smart contract
17
+ */
18
+ export class EvmChainService extends Base<EvmChainServiceParams> implements ChainService {
19
+ private _contract: StakedXyoChain
20
+
21
+ protected constructor(params: EvmChainServiceParams) {
22
+ super(params)
23
+ this._contract = params.contract
24
+ }
25
+
26
+ get id(): Address {
27
+ return this.params.id
28
+ }
29
+
30
+ get runner(): ContractRunner {
31
+ return this.params.runner
32
+ }
33
+
34
+ static create({
35
+ id, runner, logger, traceProvider, meterProvider,
36
+ }: Omit<EvmChainServiceParams, 'contract'>): Promisable<EvmChainService> {
37
+ const contractAddress = getAddress(id)
38
+ const contract: StakedXyoChain = StakedXyoChainFactory.connect(contractAddress, runner)
39
+ return new this({
40
+ id, contract, runner, logger, traceProvider, meterProvider,
41
+ })
42
+ }
43
+
44
+ async active(): Promise<bigint> {
45
+ return await this._contract.active()
46
+ }
47
+
48
+ async activeByAddressStaked(address: string): Promise<bigint> {
49
+ return await this._contract.activeByAddressStaked(getAddress(address))
50
+ }
51
+
52
+ async activeByStaker(address: string): Promise<bigint> {
53
+ return await this._contract.activeByStaker(getAddress(address))
54
+ }
55
+
56
+ async addStake(staked: string, amount: bigint): Promise<boolean> {
57
+ const result = await this._contract.addStake(getAddress(staked), amount)
58
+ await result.wait()
59
+ return true
60
+ }
61
+
62
+ async chainId(): Promise<Address> {
63
+ return toAddress(await this._contract.chainId())
64
+ }
65
+
66
+ async forkedAtBlockNumber(): Promise<bigint> {
67
+ return await this._contract.forkedAtBlockNumber()
68
+ }
69
+
70
+ async forkedAtHash(): Promise<bigint> {
71
+ return await this._contract.forkedAtHash()
72
+ }
73
+
74
+ async forkedChainId(): Promise<Address> {
75
+ return toAddress(await this._contract.forkedChainId())
76
+ }
77
+
78
+ async minWithdrawalBlocks(): Promise<bigint> {
79
+ return await this._contract.minWithdrawalBlocks()
80
+ }
81
+
82
+ async pending(): Promise<bigint> {
83
+ return await this._contract.pending()
84
+ }
85
+
86
+ async pendingByStaker(staker: string): Promise<bigint> {
87
+ return await this._contract.pendingByStaker(getAddress(staker))
88
+ }
89
+
90
+ async removeStake(slot: bigint): Promise<boolean> {
91
+ const result = await this._contract.removeStake(slot)
92
+ await result.wait()
93
+ return true
94
+ }
95
+
96
+ async rewardsContract(): Promise<string> {
97
+ return await this._contract.rewardsContract()
98
+ }
99
+
100
+ async stakingTokenAddress(): Promise<string> {
101
+ return await this._contract.stakingTokenAddress()
102
+ }
103
+
104
+ async withdrawStake(slot: bigint): Promise<boolean> {
105
+ const result = await this._contract.withdrawStake(slot)
106
+ await result.wait()
107
+ return true
108
+ }
109
+
110
+ async withdrawn(): Promise<bigint> {
111
+ return await this._contract.withdrawn()
112
+ }
113
+
114
+ async withdrawnByStaker(staker: string): Promise<bigint> {
115
+ return await this._contract.withdrawnByStaker(getAddress(staker))
116
+ }
117
+ }
@@ -0,0 +1 @@
1
+ export * from './Evm.ts'
@@ -0,0 +1 @@
1
+ export * from './Evm/index.ts'
@@ -0,0 +1,98 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import {
3
+ asBlockBoundWitness, asOptionalBlockBoundWitness, BlockBoundWitness, ChainIdentification,
4
+ ChainIteratorEventData,
5
+ EventingChainBlockNumberIterator,
6
+ isBlockBoundWitness,
7
+ XyoChainIteratorParams,
8
+ } from '@xyo-network/chain-model'
9
+ import { BaseParams } from '@xylabs/object'
10
+ import { ArchivistInstance } from '@xyo-network/archivist-model'
11
+ import { BaseEmitter } from '@xyo-network/module-event-emitter'
12
+ import { PayloadBuilder } from '@xyo-network/payload-builder'
13
+ import { LRUCache } from 'lru-cache'
14
+
15
+ export class XyoChainBlockNumberIterator extends BaseEmitter<BaseParams, ChainIteratorEventData> implements EventingChainBlockNumberIterator {
16
+ protected _blocksByBlockNumber = new LRUCache<number, BlockBoundWitness>({ max: 10_000 })
17
+ protected _chainArchivist: ArchivistInstance
18
+ protected _chainInformation: ChainIdentification
19
+ protected _head: BlockBoundWitness
20
+
21
+ protected constructor(params: XyoChainIteratorParams) {
22
+ super({})
23
+ const { chainArchivist: archivist, head } = params
24
+ this._chainArchivist = archivist
25
+ this._head = head
26
+ this._chainInformation = { id: head.chain }
27
+ }
28
+
29
+ get archivist(): ArchivistInstance { return this._chainArchivist }
30
+
31
+ get chainIdentification(): ChainIdentification { return this._chainInformation }
32
+
33
+ static async create(params: XyoChainIteratorParams): Promise<XyoChainBlockNumberIterator> {
34
+ await Promise.resolve()
35
+ return new XyoChainBlockNumberIterator(params)
36
+ }
37
+
38
+ async get(block: number): Promise<BlockBoundWitness> {
39
+ // Bail early if the block requested is newer than the current head
40
+ assertEx(this._head.block >= block, () => `Block requested is newer than the current head [${block}]`)
41
+ const cached = this._blocksByBlockNumber.get(block)
42
+ if (cached) return cached
43
+ // Start at the current head and traverse backwards until the requested block is found
44
+ const startingBlock = this._head
45
+ const currentBlockHash = await PayloadBuilder.hash(startingBlock)
46
+ let [currentBlock] = await this._chainArchivist.get([currentBlockHash])
47
+ while (currentBlock) {
48
+ assertEx(asBlockBoundWitness(currentBlock), () => `Expected hash to be a block bound witness [${currentBlock._hash}]`)
49
+ if (isBlockBoundWitness(currentBlock)) {
50
+ this._blocksByBlockNumber.set(currentBlock.block, currentBlock)
51
+ if (currentBlock.block === block) {
52
+ return currentBlock
53
+ }
54
+ const { previous } = currentBlock
55
+ if (!previous) break
56
+ [currentBlock] = await this._chainArchivist.get([previous])
57
+ }
58
+ }
59
+ throw new Error(`Block not found: ${block}`)
60
+ }
61
+
62
+ async head(): Promise<BlockBoundWitness> {
63
+ return await Promise.resolve(this._head)
64
+ }
65
+
66
+ async next(block: number): Promise<BlockBoundWitness | undefined> {
67
+ const currentBlock = block
68
+ const nextBlockNumber = currentBlock + 1
69
+ return await this.get(nextBlockNumber)
70
+ }
71
+
72
+ // TODO: Decide on inclusive/exclusive (probably need inclusive to account for chain head)
73
+ // and then communicate via method name and documentation
74
+ async previous(block: number | undefined = undefined, count: number = 1): Promise<BlockBoundWitness[]> {
75
+ const results: BlockBoundWitness[] = []
76
+ let currentBlock: BlockBoundWitness | undefined = block ? (await this.get(block)) : this._head
77
+ while (currentBlock && results.length < count) {
78
+ if (isBlockBoundWitness(currentBlock)) {
79
+ results.push(currentBlock)
80
+ const { previous } = currentBlock
81
+ if (!previous) break
82
+ const nextBlock = await this._chainArchivist.get([previous])
83
+ currentBlock = asOptionalBlockBoundWitness(nextBlock[0])
84
+ } else {
85
+ const hash = PayloadBuilder.hash(currentBlock)
86
+ assertEx(asBlockBoundWitness(currentBlock), () => `Expected hash to be a block bound witness [${hash}]`)
87
+ }
88
+ }
89
+ return results
90
+ }
91
+
92
+ async updateHead(head: BlockBoundWitness): Promise<void> {
93
+ // Async to allow for re-indexing, etc.
94
+ await Promise.resolve()
95
+ this._head = head
96
+ void this.emit('headUpdated', { blocks: [head] })
97
+ }
98
+ }
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ export * from './AccountBalance/index.ts'
2
+ export * from './BaseService.ts'
3
+ export * from './BlockProducer/index.ts'
4
+ export * from './BlockReward/index.ts'
5
+ export * from './ChainValidator/index.ts'
6
+ export * from './CreatableService.ts'
7
+ export * from './Election/index.ts'
8
+ export * from './PendingTransactions/index.ts'
9
+ export * from './StakeIntent/index.ts'
10
+ export * from './Staker/index.ts'
11
+ export * from './XyoChainBlockNumberIterator.ts'
package/xy.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { XyTsupConfig } from '@xylabs/ts-scripts-yarn3'
2
+ const config: XyTsupConfig = {
3
+ compile: {
4
+ browser: { },
5
+ node: { },
6
+ neutral: { src: true },
7
+ },
8
+ }
9
+
10
+ export default config