@xyo-network/chain-services 1.15.1 → 1.15.3
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/README.md +5302 -2235
- package/dist/neutral/AccountBalance/BaseAccountBalanceService.d.ts +3 -5
- package/dist/neutral/AccountBalance/BaseAccountBalanceService.d.ts.map +1 -1
- package/dist/neutral/AccountBalance/accountBalanceServiceFromArchivist.d.ts +3 -2
- package/dist/neutral/AccountBalance/accountBalanceServiceFromArchivist.d.ts.map +1 -1
- package/dist/neutral/AccountTransfers/BaseAccountTransfersService.d.ts +3 -6
- package/dist/neutral/AccountTransfers/BaseAccountTransfersService.d.ts.map +1 -1
- package/dist/neutral/AccountTransfers/accountTransfersServiceFromArchivist.d.ts +3 -3
- package/dist/neutral/AccountTransfers/accountTransfersServiceFromArchivist.d.ts.map +1 -1
- package/dist/neutral/BlockProducer/spec/BaseBlockProducerService.spec.d.ts.map +1 -1
- package/dist/neutral/ChainBlockIteration/ChainBlockNumberIterationService.d.ts +20 -0
- package/dist/neutral/ChainBlockIteration/ChainBlockNumberIterationService.d.ts.map +1 -0
- package/dist/neutral/ChainBlockIteration/index.d.ts +3 -0
- package/dist/neutral/ChainBlockIteration/index.d.ts.map +1 -0
- package/dist/neutral/ChainBlockIteration/model/BlockNumberIteration.d.ts +7 -0
- package/dist/neutral/ChainBlockIteration/model/BlockNumberIteration.d.ts.map +1 -0
- package/dist/neutral/ChainBlockIteration/model/Params.d.ts +8 -0
- package/dist/neutral/ChainBlockIteration/model/Params.d.ts.map +1 -0
- package/dist/neutral/ChainBlockIteration/model/index.d.ts +3 -0
- package/dist/neutral/ChainBlockIteration/model/index.d.ts.map +1 -0
- package/dist/neutral/ChainBlockNumberIteration/ChainBlockNumberIterationService.d.ts +10 -7
- package/dist/neutral/ChainBlockNumberIteration/ChainBlockNumberIterationService.d.ts.map +1 -1
- package/dist/neutral/ChainBlockNumberIteration/model/Params.d.ts +3 -2
- package/dist/neutral/ChainBlockNumberIteration/model/Params.d.ts.map +1 -1
- package/dist/neutral/ChainValidator/XyoValidator.d.ts +2 -2
- package/dist/neutral/ChainValidator/XyoValidator.d.ts.map +1 -1
- package/dist/neutral/NetworkStakeStepReward/BaseNetworkStakeStepRewardService.d.ts +15 -14
- package/dist/neutral/NetworkStakeStepReward/BaseNetworkStakeStepRewardService.d.ts.map +1 -1
- package/dist/neutral/PendingTransactions/BasePendingTransactions.d.ts +2 -2
- package/dist/neutral/PendingTransactions/BasePendingTransactions.d.ts.map +1 -1
- package/dist/neutral/StakeIntent/XyoStakeIntentService.d.ts.map +1 -1
- package/dist/neutral/index.mjs +131 -157
- package/dist/neutral/index.mjs.map +1 -1
- package/package.json +41 -41
- package/src/AccountBalance/BaseAccountBalanceService.ts +6 -8
- package/src/AccountBalance/accountBalanceServiceFromArchivist.ts +18 -33
- package/src/AccountTransfers/BaseAccountTransfersService.ts +4 -13
- package/src/AccountTransfers/accountTransfersServiceFromArchivist.ts +18 -35
- package/src/BlockProducer/spec/BaseBlockProducerService.spec.ts +62 -8
- package/src/ChainBlockIteration/ChainBlockNumberIterationService.ts +108 -0
- package/src/ChainBlockIteration/index.ts +2 -0
- package/src/ChainBlockIteration/model/BlockNumberIteration.ts +7 -0
- package/src/ChainBlockIteration/model/Params.ts +9 -0
- package/src/ChainBlockIteration/model/index.ts +2 -0
- package/src/ChainBlockNumberIteration/ChainBlockNumberIterationService.ts +44 -30
- package/src/ChainBlockNumberIteration/model/Params.ts +3 -2
- package/src/ChainValidator/XyoValidator.ts +2 -2
- package/src/NetworkStakeStepReward/BaseNetworkStakeStepRewardService.ts +20 -14
- package/src/PendingTransactions/BasePendingTransactions.ts +2 -2
- package/src/StakeIntent/XyoStakeIntentService.ts +3 -1
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.15.
|
|
4
|
+
"version": "1.15.3",
|
|
5
5
|
"description": "XYO Layer One SDK Services",
|
|
6
6
|
"homepage": "https://xylabs.com",
|
|
7
7
|
"bugs": {
|
|
@@ -37,51 +37,51 @@
|
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@opentelemetry/api": "~1.9.0",
|
|
40
|
-
"@xylabs/array": "~5.0.
|
|
41
|
-
"@xylabs/assert": "~5.0.
|
|
42
|
-
"@xylabs/creatable": "~5.0.
|
|
43
|
-
"@xylabs/decimal-precision": "~5.0.
|
|
44
|
-
"@xylabs/events": "~5.0.
|
|
45
|
-
"@xylabs/exists": "~5.0.
|
|
46
|
-
"@xylabs/forget": "~5.0.
|
|
47
|
-
"@xylabs/hex": "~5.0.
|
|
48
|
-
"@xylabs/promise": "~5.0.
|
|
49
|
-
"@xylabs/telemetry": "~5.0.
|
|
50
|
-
"@xylabs/typeof": "~5.0.
|
|
51
|
-
"@xyo-network/account-model": "~5.1.
|
|
52
|
-
"@xyo-network/archivist-memory": "~5.1.
|
|
53
|
-
"@xyo-network/archivist-model": "~5.1.
|
|
54
|
-
"@xyo-network/boundwitness-model": "~5.1.
|
|
55
|
-
"@xyo-network/boundwitness-validator": "~5.1.
|
|
56
|
-
"@xyo-network/boundwitness-wrapper": "~5.1.
|
|
57
|
-
"@xyo-network/chain-analyze": "~1.15.
|
|
58
|
-
"@xyo-network/chain-modules": "~1.15.
|
|
59
|
-
"@xyo-network/chain-protocol": "~1.15.
|
|
60
|
-
"@xyo-network/chain-utils": "~1.15.
|
|
61
|
-
"@xyo-network/payload-builder": "~5.1.
|
|
62
|
-
"@xyo-network/payload-model": "~5.1.
|
|
63
|
-
"@xyo-network/typechain": "~4.0.
|
|
64
|
-
"@xyo-network/xl1-protocol": "~1.12.
|
|
65
|
-
"@xyo-network/xl1-protocol-sdk": "~1.15.
|
|
66
|
-
"@xyo-network/xl1-validation": "~1.15.
|
|
67
|
-
"@xyo-network/xl1-wrappers": "~1.15.
|
|
40
|
+
"@xylabs/array": "~5.0.12",
|
|
41
|
+
"@xylabs/assert": "~5.0.12",
|
|
42
|
+
"@xylabs/creatable": "~5.0.12",
|
|
43
|
+
"@xylabs/decimal-precision": "~5.0.12",
|
|
44
|
+
"@xylabs/events": "~5.0.12",
|
|
45
|
+
"@xylabs/exists": "~5.0.12",
|
|
46
|
+
"@xylabs/forget": "~5.0.12",
|
|
47
|
+
"@xylabs/hex": "~5.0.12",
|
|
48
|
+
"@xylabs/promise": "~5.0.12",
|
|
49
|
+
"@xylabs/telemetry": "~5.0.12",
|
|
50
|
+
"@xylabs/typeof": "~5.0.12",
|
|
51
|
+
"@xyo-network/account-model": "~5.1.6",
|
|
52
|
+
"@xyo-network/archivist-memory": "~5.1.6",
|
|
53
|
+
"@xyo-network/archivist-model": "~5.1.6",
|
|
54
|
+
"@xyo-network/boundwitness-model": "~5.1.6",
|
|
55
|
+
"@xyo-network/boundwitness-validator": "~5.1.6",
|
|
56
|
+
"@xyo-network/boundwitness-wrapper": "~5.1.6",
|
|
57
|
+
"@xyo-network/chain-analyze": "~1.15.3",
|
|
58
|
+
"@xyo-network/chain-modules": "~1.15.3",
|
|
59
|
+
"@xyo-network/chain-protocol": "~1.15.3",
|
|
60
|
+
"@xyo-network/chain-utils": "~1.15.3",
|
|
61
|
+
"@xyo-network/payload-builder": "~5.1.6",
|
|
62
|
+
"@xyo-network/payload-model": "~5.1.6",
|
|
63
|
+
"@xyo-network/typechain": "~4.0.10",
|
|
64
|
+
"@xyo-network/xl1-protocol": "~1.12.66",
|
|
65
|
+
"@xyo-network/xl1-protocol-sdk": "~1.15.3",
|
|
66
|
+
"@xyo-network/xl1-validation": "~1.15.3",
|
|
67
|
+
"@xyo-network/xl1-wrappers": "~1.15.3",
|
|
68
68
|
"async-mutex": "~0.5.0",
|
|
69
69
|
"ethers": "6.15.0",
|
|
70
|
-
"lru-cache": "~11.2.
|
|
70
|
+
"lru-cache": "~11.2.2"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@types/node": "~24.
|
|
74
|
-
"@xylabs/delay": "~5.0.
|
|
75
|
-
"@xylabs/ts-scripts-yarn3": "~7.1.
|
|
76
|
-
"@xylabs/tsconfig": "~7.1.
|
|
77
|
-
"@xylabs/vitest-extended": "~5.0.
|
|
78
|
-
"@xyo-network/account": "~5.1.
|
|
79
|
-
"@xyo-network/account-model": "~5.1.
|
|
80
|
-
"@xyo-network/chain-validation": "~1.15.
|
|
81
|
-
"@xyo-network/wallet": "~5.1.
|
|
82
|
-
"eslint": "^9.
|
|
73
|
+
"@types/node": "~24.7.2",
|
|
74
|
+
"@xylabs/delay": "~5.0.12",
|
|
75
|
+
"@xylabs/ts-scripts-yarn3": "~7.1.8",
|
|
76
|
+
"@xylabs/tsconfig": "~7.1.8",
|
|
77
|
+
"@xylabs/vitest-extended": "~5.0.12",
|
|
78
|
+
"@xyo-network/account": "~5.1.6",
|
|
79
|
+
"@xyo-network/account-model": "~5.1.6",
|
|
80
|
+
"@xyo-network/chain-validation": "~1.15.3",
|
|
81
|
+
"@xyo-network/wallet": "~5.1.6",
|
|
82
|
+
"eslint": "^9.37.0",
|
|
83
83
|
"tslib": "~2.8.1",
|
|
84
|
-
"typescript": "~5.9.
|
|
84
|
+
"typescript": "~5.9.3",
|
|
85
85
|
"vitest": "~3.2.4",
|
|
86
86
|
"vitest-mock-extended": "~3.1.0",
|
|
87
87
|
"web3-types": "~1.10.0"
|
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
import { creatable } from '@xylabs/creatable'
|
|
2
2
|
import { Address, Hash } from '@xylabs/hex'
|
|
3
3
|
import { spanRootAsync } from '@xylabs/telemetry'
|
|
4
|
-
import { ReadArchivist } from '@xyo-network/archivist-model'
|
|
5
4
|
import {
|
|
6
5
|
AccountBalanceServiceV2,
|
|
7
|
-
AttoXL1,
|
|
6
|
+
AttoXL1,
|
|
8
7
|
} from '@xyo-network/xl1-protocol'
|
|
9
8
|
import {
|
|
10
|
-
BalancesStepSummary,
|
|
11
9
|
balancesSummary,
|
|
10
|
+
BalanceStepSummaryContext,
|
|
12
11
|
} from '@xyo-network/xl1-protocol-sdk'
|
|
13
12
|
|
|
14
13
|
import { BaseService } from '../BaseService.ts'
|
|
15
14
|
import { BaseServiceParams } from '../model/index.ts'
|
|
16
15
|
|
|
17
16
|
export interface BaseAccountBalanceServiceParams extends BaseServiceParams {
|
|
18
|
-
|
|
19
|
-
summaryRepository: PayloadRepository<Hash, BalancesStepSummary>
|
|
17
|
+
context: BalanceStepSummaryContext
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
@creatable()
|
|
23
21
|
export class BaseAccountBalanceService extends BaseService<BaseAccountBalanceServiceParams> implements AccountBalanceServiceV2 {
|
|
24
22
|
async balances(head: Hash, address: Address[]): Promise<Partial<Record<Address, AttoXL1>>> {
|
|
25
23
|
return await spanRootAsync('balances', async () => {
|
|
26
|
-
const summary = await balancesSummary(
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const summary = await balancesSummary(
|
|
25
|
+
this.params.context,
|
|
26
|
+
)
|
|
29
27
|
const result: Record<Address, AttoXL1> = {}
|
|
30
28
|
for (const addr of address) {
|
|
31
29
|
const summaryBalance = summary[addr] ?? 0n
|
|
@@ -1,45 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
asHash, type Hash,
|
|
4
|
-
isHash,
|
|
5
|
-
} from '@xylabs/hex'
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
6
2
|
import type { ReadArchivist } from '@xyo-network/archivist-model'
|
|
7
|
-
import {
|
|
8
|
-
import type { WithStorageMeta } from '@xyo-network/payload-model'
|
|
9
|
-
import type { AccountBalanceServiceV2 } from '@xyo-network/xl1-protocol'
|
|
10
|
-
import type
|
|
11
|
-
import { LRUCache } from 'lru-cache'
|
|
3
|
+
import { LruCacheMap } from '@xyo-network/chain-protocol'
|
|
4
|
+
import type { Payload, WithStorageMeta } from '@xyo-network/payload-model'
|
|
5
|
+
import type { AccountBalanceServiceV2, ChainId } from '@xyo-network/xl1-protocol'
|
|
6
|
+
import { type BalancesStepSummary, readPayloadMapFromStore } from '@xyo-network/xl1-protocol-sdk'
|
|
12
7
|
|
|
13
8
|
import { BaseAccountBalanceService } from './BaseAccountBalanceService.ts'
|
|
14
9
|
|
|
15
|
-
export const
|
|
16
|
-
|
|
10
|
+
export const accountBalancesServiceFromArchivist = async (
|
|
11
|
+
chainId: ChainId,
|
|
12
|
+
archivist: ReadArchivist<WithStorageMeta<Payload>>,
|
|
13
|
+
): Promise<AccountBalanceServiceV2> => {
|
|
14
|
+
const summaryMap = new LruCacheMap<string, BalancesStepSummary>({
|
|
17
15
|
max: 100_000,
|
|
18
16
|
allowStale: true,
|
|
19
17
|
noDisposeOnSet: false,
|
|
20
18
|
updateAgeOnGet: true,
|
|
21
19
|
})
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
20
|
+
const chainMap = readPayloadMapFromStore<WithStorageMeta<Payload>>(archivist)
|
|
21
|
+
const service = await BaseAccountBalanceService.create({
|
|
22
|
+
context: {
|
|
23
|
+
chainId,
|
|
24
|
+
store: { chainMap },
|
|
25
|
+
summaryMap,
|
|
26
|
+
head: () => ZERO_HASH,
|
|
28
27
|
},
|
|
29
|
-
|
|
30
|
-
const results = (await PayloadBuilder.addStorageMeta(payloads)).map((payload) => {
|
|
31
|
-
const hash = asHash((payload as WithStorageMeta<StepSummary>).hash)
|
|
32
|
-
if (isHash(hash)) {
|
|
33
|
-
summaryArchivistCache.set(hash, payload)
|
|
34
|
-
return payload
|
|
35
|
-
}
|
|
36
|
-
}).filter(exists)
|
|
37
|
-
return results
|
|
38
|
-
},
|
|
39
|
-
next: () => {
|
|
40
|
-
throw new Error('Not implemented')
|
|
41
|
-
},
|
|
42
|
-
}
|
|
43
|
-
const service = await BaseAccountBalanceService.create({ chainArchivist: archivist, summaryRepository })
|
|
28
|
+
})
|
|
44
29
|
return service
|
|
45
30
|
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { creatable } from '@xylabs/creatable'
|
|
2
2
|
import { Address, Hash } from '@xylabs/hex'
|
|
3
|
-
import { Promisable } from '@xylabs/promise'
|
|
4
3
|
import { spanRootAsync } from '@xylabs/telemetry'
|
|
5
|
-
import { ReadArchivist } from '@xyo-network/archivist-model'
|
|
6
4
|
import {
|
|
7
5
|
AccountTransfersService,
|
|
8
|
-
AttoXL1,
|
|
6
|
+
AttoXL1,
|
|
9
7
|
} from '@xyo-network/xl1-protocol'
|
|
10
8
|
import {
|
|
11
|
-
|
|
9
|
+
TransfersStepSummaryContext,
|
|
12
10
|
transfersSummary,
|
|
13
11
|
} from '@xyo-network/xl1-protocol-sdk'
|
|
14
12
|
|
|
@@ -16,9 +14,7 @@ import { BaseService } from '../BaseService.ts'
|
|
|
16
14
|
import { BaseServiceParams } from '../model/index.ts'
|
|
17
15
|
|
|
18
16
|
export interface BaseAccountTransferServiceParams extends BaseServiceParams {
|
|
19
|
-
|
|
20
|
-
chainArchivist: ReadArchivist
|
|
21
|
-
summaryRepository: PayloadRepository<Hash, TransfersStepSummary>
|
|
17
|
+
context: TransfersStepSummaryContext
|
|
22
18
|
}
|
|
23
19
|
|
|
24
20
|
@creatable()
|
|
@@ -29,12 +25,7 @@ export class BaseAccountTransfersService extends BaseService<BaseAccountTransfer
|
|
|
29
25
|
|
|
30
26
|
async transfers(head: Hash, addresses: Address[]): Promise<Partial<Record<Address, AttoXL1>>> {
|
|
31
27
|
return await spanRootAsync('transfers', async () => {
|
|
32
|
-
const
|
|
33
|
-
chainArchivist, summaryRepository, account,
|
|
34
|
-
} = this.params
|
|
35
|
-
const summary = await transfersSummary({
|
|
36
|
-
chainArchivist, summaryRepository, head, account,
|
|
37
|
-
})
|
|
28
|
+
const summary = await transfersSummary(this.params.context)
|
|
38
29
|
const result: Record<Address, AttoXL1> = {}
|
|
39
30
|
for (const addr of addresses) {
|
|
40
31
|
const summaryBalance = summary[addr] ?? 0n
|
|
@@ -1,48 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { Address, Hash } from '@xylabs/hex'
|
|
3
|
-
import {
|
|
4
|
-
asHash,
|
|
5
|
-
isHash,
|
|
6
|
-
} from '@xylabs/hex'
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
7
2
|
import type { ReadArchivist } from '@xyo-network/archivist-model'
|
|
8
|
-
import {
|
|
9
|
-
import type { WithStorageMeta } from '@xyo-network/payload-model'
|
|
10
|
-
import type { AccountTransfersService } from '@xyo-network/xl1-protocol'
|
|
11
|
-
import type {
|
|
12
|
-
import {
|
|
3
|
+
import { LruCacheMap } from '@xyo-network/chain-protocol'
|
|
4
|
+
import type { Payload, WithStorageMeta } from '@xyo-network/payload-model'
|
|
5
|
+
import type { AccountTransfersService, ChainId } from '@xyo-network/xl1-protocol'
|
|
6
|
+
import type { TransfersStepSummary } from '@xyo-network/xl1-protocol-sdk'
|
|
7
|
+
import { readPayloadMapFromStore } from '@xyo-network/xl1-protocol-sdk'
|
|
13
8
|
|
|
14
9
|
import { BaseAccountTransfersService } from './BaseAccountTransfersService.ts'
|
|
15
10
|
|
|
16
|
-
export const
|
|
17
|
-
|
|
11
|
+
export const accountTransfersServiceFromArchivist = async (
|
|
12
|
+
chainId: ChainId,
|
|
13
|
+
archivist: ReadArchivist<WithStorageMeta<Payload>>,
|
|
14
|
+
): Promise<AccountTransfersService> => {
|
|
15
|
+
const summaryMap = new LruCacheMap<string, TransfersStepSummary>({
|
|
18
16
|
max: 100_000,
|
|
19
17
|
allowStale: true,
|
|
20
18
|
noDisposeOnSet: false,
|
|
21
19
|
updateAgeOnGet: true,
|
|
22
20
|
})
|
|
23
|
-
const
|
|
24
|
-
get: (hashes: Hash[]) => {
|
|
25
|
-
const results = hashes.map((hash) => {
|
|
26
|
-
return summaryArchivistCache.get(hash)
|
|
27
|
-
}).filter(exists)
|
|
28
|
-
return results
|
|
29
|
-
},
|
|
30
|
-
insert: async (payloads: TransfersStepSummary[]) => {
|
|
31
|
-
const results = (await PayloadBuilder.addStorageMeta(payloads)).map((payload) => {
|
|
32
|
-
const hash = asHash((payload as WithStorageMeta<StepSummary>).hash)
|
|
33
|
-
if (isHash(hash)) {
|
|
34
|
-
summaryArchivistCache.set(hash, payload)
|
|
35
|
-
return payload
|
|
36
|
-
}
|
|
37
|
-
}).filter(exists)
|
|
38
|
-
return results
|
|
39
|
-
},
|
|
40
|
-
next: () => {
|
|
41
|
-
throw new Error('Not implemented')
|
|
42
|
-
},
|
|
43
|
-
}
|
|
21
|
+
const chainMap = readPayloadMapFromStore<WithStorageMeta<Payload>>(archivist)
|
|
44
22
|
const service = await BaseAccountTransfersService.create({
|
|
45
|
-
|
|
23
|
+
context: {
|
|
24
|
+
chainId,
|
|
25
|
+
store: { chainMap },
|
|
26
|
+
summaryMap,
|
|
27
|
+
head: () => ZERO_HASH,
|
|
28
|
+
},
|
|
46
29
|
})
|
|
47
30
|
return service
|
|
48
31
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
/* eslint-disable max-statements */
|
|
1
2
|
import '@xylabs/vitest-extended'
|
|
2
3
|
|
|
3
4
|
import { filterAs } from '@xylabs/array'
|
|
4
5
|
import { assertEx } from '@xylabs/assert'
|
|
5
6
|
import type { CreatableName } from '@xylabs/creatable'
|
|
6
7
|
import { delay } from '@xylabs/delay'
|
|
7
|
-
import type { Address } from '@xylabs/hex'
|
|
8
|
+
import type { Address, Hash } from '@xylabs/hex'
|
|
8
9
|
import {
|
|
9
10
|
asAddress, hexToBigInt, ZERO_HASH,
|
|
10
11
|
} from '@xylabs/hex'
|
|
12
|
+
import type { Promisable } from '@xylabs/promise'
|
|
11
13
|
import { Account } from '@xyo-network/account'
|
|
12
14
|
import type { AccountInstance } from '@xyo-network/account-model'
|
|
13
15
|
import { MemoryArchivist } from '@xyo-network/archivist-memory'
|
|
@@ -19,10 +21,11 @@ import {
|
|
|
19
21
|
} from '@xyo-network/payload-model'
|
|
20
22
|
import { HDWallet } from '@xyo-network/wallet'
|
|
21
23
|
import type {
|
|
22
|
-
BlockBoundWitness, BlockRewardService,
|
|
24
|
+
BlockBoundWitness, BlockRewardService, ChainId, ElectionService,
|
|
23
25
|
HydratedBlock,
|
|
24
26
|
HydratedBlockStateValidationFunctionV2,
|
|
25
27
|
StakeIntentService,
|
|
28
|
+
TimeDomain, TimePayload,
|
|
26
29
|
TimeSyncViewInterfaceV2,
|
|
27
30
|
} from '@xyo-network/xl1-protocol'
|
|
28
31
|
import {
|
|
@@ -31,6 +34,7 @@ import {
|
|
|
31
34
|
asTransactionBoundWitness,
|
|
32
35
|
asTransfer,
|
|
33
36
|
HydratedBlockStateValidationError,
|
|
37
|
+
TimeSchema,
|
|
34
38
|
XYO_ZERO_ADDRESS,
|
|
35
39
|
} from '@xyo-network/xl1-protocol'
|
|
36
40
|
import type { Config } from '@xyo-network/xl1-protocol-sdk'
|
|
@@ -42,7 +46,7 @@ import {
|
|
|
42
46
|
} from 'vitest'
|
|
43
47
|
import { mock } from 'vitest-mock-extended'
|
|
44
48
|
|
|
45
|
-
import {
|
|
49
|
+
import { accountBalancesServiceFromArchivist } from '../../AccountBalance/index.ts'
|
|
46
50
|
import { MemoryBlockRewardService } from '../../BlockReward/index.ts'
|
|
47
51
|
import type { BasePendingTransactionsServiceParams } from '../../PendingTransactions/index.ts'
|
|
48
52
|
import { BasePendingTransactionsService } from '../../PendingTransactions/index.ts'
|
|
@@ -95,9 +99,56 @@ describe('XyoBlockProducer', () => {
|
|
|
95
99
|
|
|
96
100
|
stakeIntentService = mock<StakeIntentService>()
|
|
97
101
|
stakeIntentService.getDeclaredCandidateRanges.mockResolvedValue([])
|
|
98
|
-
time =
|
|
102
|
+
time = {
|
|
103
|
+
currentTimeAndHash(domain: TimeDomain): Promisable<[number, Hash | null]> {
|
|
104
|
+
switch (domain) {
|
|
105
|
+
case 'epoch': {
|
|
106
|
+
return [Date.now(), null]
|
|
107
|
+
}
|
|
108
|
+
case 'xl1': {
|
|
109
|
+
return [1, '00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff' as Hash]
|
|
110
|
+
}
|
|
111
|
+
case 'ethereum': {
|
|
112
|
+
return [1, '00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff' as Hash]
|
|
113
|
+
}
|
|
114
|
+
// No default
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
currentTime(domain: TimeDomain): Promisable<[string, number]> {
|
|
118
|
+
switch (domain) {
|
|
119
|
+
case 'epoch': {
|
|
120
|
+
return ['epoch', Date.now()]
|
|
121
|
+
}
|
|
122
|
+
case 'xl1': {
|
|
123
|
+
return ['xl1', 1]
|
|
124
|
+
}
|
|
125
|
+
case 'ethereum': {
|
|
126
|
+
return ['ethereum', 1]
|
|
127
|
+
}
|
|
128
|
+
// No default
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
currentTimePayload(): Promisable<TimePayload> {
|
|
132
|
+
return {
|
|
133
|
+
schema: TimeSchema, epoch: Date.now(), xl1: 1,
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
/** Convert time between different domains */
|
|
137
|
+
convertTime(fromDomain: TimeDomain, toDomain: TimeDomain, from: number): Promisable<number> {
|
|
138
|
+
if (fromDomain === toDomain) {
|
|
139
|
+
return from
|
|
140
|
+
}
|
|
141
|
+
if (fromDomain === 'epoch' && toDomain === 'xl1') {
|
|
142
|
+
return 1
|
|
143
|
+
}
|
|
144
|
+
if (fromDomain === 'xl1' && toDomain === 'epoch') {
|
|
145
|
+
return Date.now()
|
|
146
|
+
}
|
|
147
|
+
return from
|
|
148
|
+
},
|
|
149
|
+
}
|
|
99
150
|
rewardService = await MemoryBlockRewardService.create()
|
|
100
|
-
const balanceService = await
|
|
151
|
+
const balanceService = await accountBalancesServiceFromArchivist(chainId, chainArchivist)
|
|
101
152
|
const params: BaseBlockProducerServiceParams = {
|
|
102
153
|
name: 'TestXyoBlockProducerParams' as CreatableName,
|
|
103
154
|
account,
|
|
@@ -179,11 +230,11 @@ describe('XyoBlockProducer', () => {
|
|
|
179
230
|
let rejectBlock = true
|
|
180
231
|
const validateHydratedBlockState: HydratedBlockStateValidationFunctionV2 = async (
|
|
181
232
|
hydratedBlock: HydratedBlock,
|
|
182
|
-
chainId:
|
|
233
|
+
chainId: ChainId,
|
|
183
234
|
) => {
|
|
184
235
|
return rejectBlock ? [await Promise.resolve(new HydratedBlockStateValidationError(ZERO_HASH, chainId, hydratedBlock, 'Invalid block'))] : []
|
|
185
236
|
}
|
|
186
|
-
const balanceService = await
|
|
237
|
+
const balanceService = await accountBalancesServiceFromArchivist(chainId, chainArchivist)
|
|
187
238
|
const params: BaseBlockProducerServiceParams = {
|
|
188
239
|
name: 'TestXyoBlockProducerParams' as CreatableName,
|
|
189
240
|
account,
|
|
@@ -234,11 +285,14 @@ describe('XyoBlockProducer', () => {
|
|
|
234
285
|
const transfers = filterAs(assertEx(transactionsAndData), asTransfer)
|
|
235
286
|
const blockRewardTransfer = transfers.find(transfer => transfer.from === XYO_ZERO_ADDRESS)
|
|
236
287
|
expect(blockRewardTransfer).toBeDefined()
|
|
288
|
+
let totalTransfer = 0n
|
|
237
289
|
for (const value of Object.values(blockRewardTransfer?.transfers ?? {})) {
|
|
238
290
|
if (value) {
|
|
239
|
-
|
|
291
|
+
const bigIntValue = hexToBigInt(value)
|
|
292
|
+
totalTransfer += bigIntValue
|
|
240
293
|
}
|
|
241
294
|
}
|
|
295
|
+
expect(totalTransfer).toEqual(3_000_000_000_000_000_000_000n)
|
|
242
296
|
}
|
|
243
297
|
})
|
|
244
298
|
})
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import type { Hex } from '@xylabs/hex'
|
|
3
|
+
import {
|
|
4
|
+
isDefined, isNull, isUndefined,
|
|
5
|
+
} from '@xylabs/typeof'
|
|
6
|
+
import type { ArchivistInstance } from '@xyo-network/archivist-model'
|
|
7
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
8
|
+
import type { WithStorageMeta } from '@xyo-network/payload-model'
|
|
9
|
+
import type {
|
|
10
|
+
BlockBoundWitness,
|
|
11
|
+
ChainIteratorServiceEventData,
|
|
12
|
+
EventingChainBlockNumberIteratorService,
|
|
13
|
+
} from '@xyo-network/xl1-protocol'
|
|
14
|
+
import {
|
|
15
|
+
asBlockBoundWitness,
|
|
16
|
+
asBlockBoundWitnessWithStorageMeta,
|
|
17
|
+
isBlockBoundWitness,
|
|
18
|
+
} from '@xyo-network/xl1-protocol'
|
|
19
|
+
import { LRUCache } from 'lru-cache'
|
|
20
|
+
|
|
21
|
+
import { BaseService } from '../BaseService.ts'
|
|
22
|
+
import type { XyoChainIteratorParams } from './model/index.ts'
|
|
23
|
+
|
|
24
|
+
export class ChainBlockNumberIterationService extends BaseService<XyoChainIteratorParams, ChainIteratorServiceEventData>
|
|
25
|
+
implements EventingChainBlockNumberIteratorService {
|
|
26
|
+
protected _blocksByBlockNumber = new LRUCache<number, WithStorageMeta<BlockBoundWitness>>({ max: 10_000 })
|
|
27
|
+
protected _currentHead: WithStorageMeta<BlockBoundWitness> | undefined
|
|
28
|
+
|
|
29
|
+
get chainArchivist(): ArchivistInstance { return assertEx(this.params.chainArchivist) }
|
|
30
|
+
|
|
31
|
+
get chainId(): Hex { return assertEx(this._currentHead?.chain ?? this.params?.head?.chain, () => 'Current head is not set') }
|
|
32
|
+
|
|
33
|
+
async get(block: number): Promise<WithStorageMeta<BlockBoundWitness>> {
|
|
34
|
+
const head = await this.head()
|
|
35
|
+
// if(isUndefined(head)) return undefined
|
|
36
|
+
// Bail early if the block requested is newer than the current head
|
|
37
|
+
assertEx(head.block >= block, () => `Block requested is newer than the current head [${block}]`)
|
|
38
|
+
const cached = this._blocksByBlockNumber.get(block)
|
|
39
|
+
if (cached) return cached
|
|
40
|
+
// Start at the current head and traverse backwards until the requested block is found
|
|
41
|
+
const startingBlock = head
|
|
42
|
+
const currentBlockHash = await PayloadBuilder.hash(startingBlock)
|
|
43
|
+
let currentBlock = (await this.chainArchivist.get([currentBlockHash])).at(0)
|
|
44
|
+
while (isDefined(currentBlock)) {
|
|
45
|
+
assertEx(asBlockBoundWitness(currentBlock), () => `Expected hash to be a block bound witness [${currentBlock?._hash}]`)
|
|
46
|
+
if (isBlockBoundWitness(currentBlock)) {
|
|
47
|
+
this._blocksByBlockNumber.set(currentBlock.block, currentBlock)
|
|
48
|
+
if (currentBlock.block === block) {
|
|
49
|
+
return currentBlock
|
|
50
|
+
}
|
|
51
|
+
const { previous } = currentBlock
|
|
52
|
+
if (isNull(previous)) break
|
|
53
|
+
currentBlock = (await this.chainArchivist.get([previous])).at(0)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
throw new Error(`Block not found: ${block}`)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async head(): Promise<WithStorageMeta<BlockBoundWitness>> {
|
|
60
|
+
if (isDefined(this._currentHead)) return this._currentHead
|
|
61
|
+
if (isDefined(this.params.head)) {
|
|
62
|
+
const newHead = await this.getBoundWitnessAsBlockBoundWitnessWithStorageMeta(this.params.head)
|
|
63
|
+
this._currentHead = newHead
|
|
64
|
+
return newHead
|
|
65
|
+
}
|
|
66
|
+
throw new Error('Head is not set')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async next(block: number): Promise<WithStorageMeta<BlockBoundWitness> | undefined> {
|
|
70
|
+
const currentBlock = block
|
|
71
|
+
const nextBlockNumber = currentBlock + 1
|
|
72
|
+
return await this.get(nextBlockNumber)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// TODO: Decide on inclusive/exclusive (probably need inclusive to account for chain head)
|
|
76
|
+
// and then communicate via method name and documentation
|
|
77
|
+
async previous(block: number | undefined = undefined, count: number = 1): Promise<WithStorageMeta<BlockBoundWitness>[]> {
|
|
78
|
+
const results: WithStorageMeta<BlockBoundWitness>[] = []
|
|
79
|
+
let currentBlock: WithStorageMeta<BlockBoundWitness> | undefined = isDefined(block) ? (await this.get(block)) : await this.head()
|
|
80
|
+
while (currentBlock && results.length < count) {
|
|
81
|
+
if (isBlockBoundWitness(currentBlock)) {
|
|
82
|
+
results.push(currentBlock)
|
|
83
|
+
const { previous } = currentBlock
|
|
84
|
+
if (isNull(previous)) break
|
|
85
|
+
const nextBlock = await this.chainArchivist.get([previous])
|
|
86
|
+
currentBlock = asBlockBoundWitnessWithStorageMeta(nextBlock[0])
|
|
87
|
+
} else {
|
|
88
|
+
const hash = PayloadBuilder.hash(currentBlock)
|
|
89
|
+
assertEx(asBlockBoundWitnessWithStorageMeta(currentBlock), () => `Expected hash to be a block bound witness [${hash}]`)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return results
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async updateHead(head: BlockBoundWitness): Promise<void> {
|
|
96
|
+
const newHead = await this.getBoundWitnessAsBlockBoundWitnessWithStorageMeta(head)
|
|
97
|
+
this._currentHead = newHead
|
|
98
|
+
void this.emit('headUpdated', { blocks: [newHead] })
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private async getBoundWitnessAsBlockBoundWitnessWithStorageMeta(head: BlockBoundWitness): Promise<WithStorageMeta<BlockBoundWitness>> {
|
|
102
|
+
const hash = await PayloadBuilder.hash(head)
|
|
103
|
+
const stored = (await this.chainArchivist.get([hash])).at(-1)
|
|
104
|
+
const newHead = asBlockBoundWitnessWithStorageMeta(stored)
|
|
105
|
+
if (isUndefined(newHead)) throw new Error(`Head block not found in archivist [${hash}]`)
|
|
106
|
+
return newHead
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Promisable } from '@xylabs/promise'
|
|
2
|
+
import type { BlockBoundWitness, SignedHydratedTransactionWithStorageMeta } from '@xyo-network/xl1-protocol'
|
|
3
|
+
|
|
4
|
+
export interface BlockNumberIteration {
|
|
5
|
+
validatePendingBlock(block: BlockBoundWitness): Promisable<Error[]>
|
|
6
|
+
validatePendingTransaction(tx: SignedHydratedTransactionWithStorageMeta): Promise<boolean>
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ArchivistInstance } from '@xyo-network/archivist-model'
|
|
2
|
+
import type { BlockBoundWitness } from '@xyo-network/xl1-protocol'
|
|
3
|
+
|
|
4
|
+
import type { BaseServiceParams } from '../../model/index.ts'
|
|
5
|
+
|
|
6
|
+
export interface XyoChainIteratorParams extends BaseServiceParams {
|
|
7
|
+
chainArchivist: ArchivistInstance
|
|
8
|
+
head: BlockBoundWitness
|
|
9
|
+
}
|