@xyo-network/xl1-protocol-sdk 1.5.35 → 1.5.36

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 (57) hide show
  1. package/dist/neutral/index.mjs +304 -124
  2. package/dist/neutral/index.mjs.map +1 -1
  3. package/dist/types/ChainServiceCollection.d.ts +60 -0
  4. package/dist/types/ChainServiceCollection.d.ts.map +1 -0
  5. package/dist/types/ChainServiceCollectionV2.d.ts +60 -0
  6. package/dist/types/ChainServiceCollectionV2.d.ts.map +1 -0
  7. package/dist/types/SignedBigInt.d.ts +14 -0
  8. package/dist/types/SignedBigInt.d.ts.map +1 -0
  9. package/dist/types/block/hydrateBlock.d.ts +1 -1
  10. package/dist/types/block/hydrateBlock.d.ts.map +1 -1
  11. package/dist/types/block/primitives/balanceStepSummaryFromRange.d.ts +6 -0
  12. package/dist/types/block/primitives/balanceStepSummaryFromRange.d.ts.map +1 -0
  13. package/dist/types/block/primitives/balanceSummary.d.ts +4 -0
  14. package/dist/types/block/primitives/balanceSummary.d.ts.map +1 -0
  15. package/dist/types/block/primitives/frames/deepCalculateFramesFromRange.d.ts.map +1 -1
  16. package/dist/types/block/primitives/frames/index.d.ts +2 -1
  17. package/dist/types/block/primitives/frames/index.d.ts.map +1 -1
  18. package/dist/types/block/primitives/hashFromBlockNumber.d.ts +4 -0
  19. package/dist/types/block/primitives/hashFromBlockNumber.d.ts.map +1 -0
  20. package/dist/types/block/primitives/index.d.ts +5 -0
  21. package/dist/types/block/primitives/index.d.ts.map +1 -1
  22. package/dist/types/block/primitives/model.d.ts +16 -0
  23. package/dist/types/block/primitives/model.d.ts.map +1 -0
  24. package/dist/types/block/primitives/payloads.d.ts +21 -0
  25. package/dist/types/block/primitives/payloads.d.ts.map +1 -0
  26. package/dist/types/index.d.ts +4 -0
  27. package/dist/types/index.d.ts.map +1 -1
  28. package/dist/types/payload/index.d.ts +2 -0
  29. package/dist/types/payload/index.d.ts.map +1 -0
  30. package/dist/types/payload/netBalancesForPayloads.d.ts +3 -0
  31. package/dist/types/payload/netBalancesForPayloads.d.ts.map +1 -0
  32. package/dist/types/transaction/buildTransaction.d.ts +1 -1
  33. package/dist/types/transaction/buildTransaction.d.ts.map +1 -1
  34. package/package.json +19 -19
  35. package/src/ChainServiceCollection.ts +65 -0
  36. package/src/ChainServiceCollectionV2.ts +65 -0
  37. package/src/SignedBigInt.ts +51 -0
  38. package/src/block/hydrateBlock.ts +14 -13
  39. package/src/block/primitives/balanceStepSummaryFromRange.ts +78 -0
  40. package/src/block/primitives/balanceSummary.ts +27 -0
  41. package/src/block/primitives/frames/calculateFramesFromRange.ts +2 -2
  42. package/src/block/primitives/frames/deepCalculateFramesFromRange.ts +2 -2
  43. package/src/block/primitives/frames/index.ts +2 -1
  44. package/src/block/primitives/hashFromBlockNumber.ts +31 -0
  45. package/src/block/primitives/index.ts +5 -0
  46. package/src/block/primitives/model.ts +18 -0
  47. package/src/block/primitives/payloads.ts +29 -0
  48. package/src/index.ts +4 -0
  49. package/src/payload/index.ts +1 -0
  50. package/src/payload/netBalancesForPayloads.ts +19 -0
  51. package/src/transaction/buildTransaction.ts +16 -9
  52. package/dist/types/block/primitives/frames/loadFrameSummaries.d.ts +0 -5
  53. package/dist/types/block/primitives/frames/loadFrameSummaries.d.ts.map +0 -1
  54. package/dist/types/block/primitives/frames/stepHashFramesFromBlock.d.ts +0 -5
  55. package/dist/types/block/primitives/frames/stepHashFramesFromBlock.d.ts.map +0 -1
  56. package/src/block/primitives/frames/loadFrameSummaries.ts +0 -12
  57. package/src/block/primitives/frames/stepHashFramesFromBlock.ts +0 -72
@@ -0,0 +1,65 @@
1
+ import type { ArchivistInstance, WriteArchivist } from '@xyo-network/archivist-model'
2
+ import type { WalletInstance } from '@xyo-network/wallet-model'
3
+ import type {
4
+ AccountBalanceService, BlockProducerService,
5
+ BlockRewardService, ChainContractViewer, ChainStaker, ChainStakeViewer, ElectionService, EventingChainBlockNumberIterator,
6
+ StakeIntentService,
7
+ } from '@xyo-network/xl1-protocol'
8
+
9
+ export interface ChainServiceCollection {
10
+
11
+ /**
12
+ * The account which is used to sign transactions
13
+ */
14
+ account: WalletInstance
15
+ /**
16
+ * Services for working with account balances
17
+ */
18
+ balanceService: AccountBalanceService
19
+ /**
20
+ * The archivist which the chain data is stored in
21
+ */
22
+ chainArchivist: ArchivistInstance
23
+ /**
24
+ * Service for viewing codified chain information
25
+ * from a contract
26
+ */
27
+ chainContractViewer: ChainContractViewer
28
+ /**
29
+ * The chain iterator
30
+ */
31
+ chainIterator?: EventingChainBlockNumberIterator
32
+ /**
33
+ * Service for viewing stake information
34
+ */
35
+ chainStakeViewer: ChainStakeViewer
36
+ /**
37
+ * Service for staking
38
+ */
39
+ chainStaker: ChainStaker
40
+ /**
41
+ * The archivist which the chain submissions are stored in
42
+ */
43
+ chainSubmissionsArchivistWrite: WriteArchivist
44
+ /**
45
+ * Service for determining leader election
46
+ */
47
+ electionService: ElectionService
48
+ /**
49
+ * The archivist which the pending transactions are stored
50
+ * as bundled transactions
51
+ */
52
+ pendingBundledTransactionsArchivistWrite: ArchivistInstance
53
+ /**
54
+ * The block producer service
55
+ */
56
+ producer: BlockProducerService
57
+ /**
58
+ * Service response for calculating block rewards
59
+ */
60
+ rewardService: BlockRewardService
61
+ /**
62
+ * Services for working with staked intents
63
+ */
64
+ stakeIntentService: StakeIntentService
65
+ }
@@ -0,0 +1,65 @@
1
+ import type { ArchivistInstance, WriteArchivist } from '@xyo-network/archivist-model'
2
+ import type { WalletInstance } from '@xyo-network/wallet-model'
3
+ import type {
4
+ AccountBalanceServiceV2, BlockProducerService,
5
+ BlockRewardService, ChainContractViewer, ChainStaker, ChainStakeViewer, ElectionService, EventingChainBlockNumberIterator,
6
+ StakeIntentService,
7
+ } from '@xyo-network/xl1-protocol'
8
+
9
+ export interface ChainServiceCollectionV2 {
10
+
11
+ /**
12
+ * The account which is used to sign transactions
13
+ */
14
+ account: WalletInstance
15
+ /**
16
+ * Services for working with account balances
17
+ */
18
+ balanceService: AccountBalanceServiceV2
19
+ /**
20
+ * The archivist which the chain data is stored in
21
+ */
22
+ chainArchivist: ArchivistInstance
23
+ /**
24
+ * Service for viewing codified chain information
25
+ * from a contract
26
+ */
27
+ chainContractViewer: ChainContractViewer
28
+ /**
29
+ * The chain iterator
30
+ */
31
+ chainIterator?: EventingChainBlockNumberIterator
32
+ /**
33
+ * Service for viewing stake information
34
+ */
35
+ chainStakeViewer: ChainStakeViewer
36
+ /**
37
+ * Service for staking
38
+ */
39
+ chainStaker: ChainStaker
40
+ /**
41
+ * The archivist which the chain submissions are stored in
42
+ */
43
+ chainSubmissionsArchivistWrite: WriteArchivist
44
+ /**
45
+ * Service for determining leader election
46
+ */
47
+ electionService: ElectionService
48
+ /**
49
+ * The archivist which the pending transactions are stored
50
+ * as bundled transactions
51
+ */
52
+ pendingBundledTransactionsArchivistWrite: ArchivistInstance
53
+ /**
54
+ * The block producer service
55
+ */
56
+ producer: BlockProducerService
57
+ /**
58
+ * Service response for calculating block rewards
59
+ */
60
+ rewardService: BlockRewardService
61
+ /**
62
+ * Services for working with staked intents
63
+ */
64
+ stakeIntentService: StakeIntentService
65
+ }
@@ -0,0 +1,51 @@
1
+ import {
2
+ type Hex,
3
+ hexToBigInt,
4
+ toHex,
5
+ } from '@xylabs/hex'
6
+ import { isObject } from '@xylabs/object'
7
+
8
+ export interface NegativeBigInt {
9
+ negative: Hex
10
+ }
11
+
12
+ export interface PositiveBigInt {
13
+ positive: Hex
14
+ }
15
+
16
+ export type SignedBigInt = NegativeBigInt | PositiveBigInt
17
+
18
+ export const isNegativeBigInt = (value: unknown): value is NegativeBigInt => {
19
+ return isObject(value) && 'negative' in value && typeof value.negative === 'string'
20
+ }
21
+
22
+ export const isPositiveBigInt = (value: unknown): value is PositiveBigInt => {
23
+ return isObject(value) && 'positive' in value && typeof value.positive === 'string'
24
+ }
25
+
26
+ export const parseSignedBigInt = (value: SignedBigInt): bigint => {
27
+ if (isNegativeBigInt(value)) {
28
+ return -hexToBigInt(value.negative)
29
+ } else if (isPositiveBigInt(value)) {
30
+ return hexToBigInt(value.positive)
31
+ } else {
32
+ throw new Error('Invalid balance type')
33
+ }
34
+ }
35
+
36
+ export const toSignedBigInt = (value: bigint): SignedBigInt => {
37
+ return value < 0n ? { negative: toHex(-value) } : { positive: toHex(value) }
38
+ }
39
+
40
+ export const toPositiveBigInt = (value: unknown): PositiveBigInt => {
41
+ if (isNegativeBigInt(value)) {
42
+ return { positive: toHex(0n) }
43
+ }
44
+ if (isPositiveBigInt(value)) {
45
+ return { positive: value.positive }
46
+ }
47
+ if (typeof value === 'bigint') {
48
+ return { positive: toHex(value) }
49
+ }
50
+ throw new Error('Invalid value for positive big int')
51
+ }
@@ -17,27 +17,28 @@ export const tryHydrateBlock = async (
17
17
  archivist: ReadArchivist,
18
18
  hash: Hash,
19
19
  maxDepth: number = 1,
20
- minDepth?: number,
21
20
  ): Promise<HydratedBlock | undefined> => {
22
- try {
23
- return await hydrateBlock(archivist, hash, maxDepth, minDepth)
24
- } catch (e) {
25
- if (e instanceof Error) {
26
- console.warn(`Failed to hydrate block ${hash}: ${e.message}`)
27
- } else {
28
- console.warn(`Failed to hydrate block ${hash}: ${e}`)
29
- }
30
- return undefined
31
- }
21
+ assertEx(maxDepth >= 0, () => 'maxDepth must be greater than or equal to 0')
22
+ const bw = filterAs(await archivist.get([hash]), asBlockBoundWitnessWithStorageMeta).at(0)
23
+ if (!bw) return undefined
24
+ if (maxDepth === 0) return [bw, []]
25
+ const blkPayloads = await archivist.get(bw.payload_hashes)
26
+ if (maxDepth === 1) return [bw, blkPayloads]
27
+ const transactions = filterAs(blkPayloads, asTransactionBoundWitnessWithStorageMeta)
28
+ const transactionsPayloadHashes = transactions.flatMap(tx => tx.payload_hashes)
29
+ const transactionsPayloads = await archivist.get(transactionsPayloadHashes)
30
+ const allPayloadsHashes = new Set([...blkPayloads, ...transactionsPayloads].flatMap(p => p._hash))
31
+ const allPayloads = await archivist.get([...allPayloadsHashes])
32
+ const allPayloadsFiltered = allPayloads.filter(p => allPayloadsHashes.has(p._hash))
33
+ return [bw, allPayloadsFiltered]
32
34
  }
33
35
 
34
36
  export const hydrateBlock = async (
35
37
  archivist: ReadArchivist,
36
38
  hash: Hash,
37
39
  maxDepth: number = 1,
38
- minDepth?: number,
40
+ minDepth = maxDepth,
39
41
  ): Promise<HydratedBlock> => {
40
- if (minDepth === undefined) minDepth = maxDepth
41
42
  assertEx(maxDepth >= 0, () => 'maxDepth must be greater than or equal to 0')
42
43
  assertEx(minDepth >= 0, () => 'minDepth must be greater than or equal to 0')
43
44
  assertEx(maxDepth >= minDepth, () => 'maxDepth must be greater than or equal to minDepth')
@@ -0,0 +1,78 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import { type Address } from '@xylabs/hex'
3
+ import { PayloadBuilder } from '@xyo-network/payload-builder'
4
+ import type { WithStorageMeta } from '@xyo-network/payload-model'
5
+ import { isAnyPayload } from '@xyo-network/payload-model'
6
+ import { StepSizes } from '@xyo-network/xl1-protocol'
7
+
8
+ import { netBalancesForPayloads } from '../../payload/netBalancesForPayloads.ts'
9
+ import {
10
+ parseSignedBigInt, type SignedBigInt, toSignedBigInt,
11
+ } from '../../SignedBigInt.ts'
12
+ import { hydrateBlock } from '../hydrateBlock.ts'
13
+ import type { BlockNumberRange } from './frames/BlockNumberRange.ts'
14
+ import { deepCalculateFramesFromRange } from './frames/deepCalculateFramesFromRange.ts'
15
+ import { hashFromBlockNumber } from './hashFromBlockNumber.ts'
16
+ import type { BalanceStepSummaryContext } from './model.ts'
17
+ import { type BalancesStepSummary, BalancesStepSummarySchema } from './payloads.ts'
18
+
19
+ export async function balanceStepSummaryFromRange(
20
+ context: BalanceStepSummaryContext,
21
+ range: BlockNumberRange,
22
+ ): Promise<WithStorageMeta<BalancesStepSummary>> {
23
+ // console.log(`balanceStepSummaryFromRange: head=${head}, range=${range[0]}-${range[1]}`)
24
+ const frameHeadHash = await hashFromBlockNumber(context, range[1])
25
+ const frameSize = range[1] - range[0] + 1
26
+
27
+ let result: BalancesStepSummary | undefined = undefined
28
+
29
+ if (frameSize === 1) {
30
+ const [, payloads] = await hydrateBlock(context.chainArchivist, context.head)
31
+ const balances: Record<Address, SignedBigInt> = {}
32
+ for (const [address, balance] of Object.entries(netBalancesForPayloads(payloads))) {
33
+ balances[address as Address] = toSignedBigInt(balance)
34
+ }
35
+ result = {
36
+ schema: BalancesStepSummarySchema, hash: context.head, stepSize: -1, balances,
37
+ }
38
+ } else {
39
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
+ const step = (StepSizes as any).indexOf(frameSize)
41
+ assertEx(step !== -1, () => `Invalid step size: ${frameSize}. Must be one of ${StepSizes.join(', ')}`)
42
+
43
+ const [summaryResult] = await context.summaryRepository.get([frameHeadHash])
44
+ if (isAnyPayload(summaryResult)) {
45
+ result = summaryResult as WithStorageMeta<BalancesStepSummary>
46
+ } else {
47
+ // We do not have it, so lets build it
48
+ const subRanges = deepCalculateFramesFromRange(range, step - 1)
49
+ const promises = subRanges.map(subRange => balanceStepSummaryFromRange(
50
+ context,
51
+ subRange,
52
+ ))
53
+ const subResults = await Promise.all(promises)
54
+
55
+ // add them all up
56
+ const bigIntBalances: Record<Address, bigint> = {}
57
+ for (const subResult of subResults) {
58
+ for (const [address, balance] of Object.entries(subResult.balances)) {
59
+ bigIntBalances[address as Address] = (bigIntBalances[address as Address] ?? 0n) + parseSignedBigInt(balance)
60
+ }
61
+ }
62
+
63
+ const balances: Record<Address, SignedBigInt> = {}
64
+ for (const [address, balance] of Object.entries(bigIntBalances)) {
65
+ balances[address as Address] = toSignedBigInt(balance)
66
+ }
67
+
68
+ result = {
69
+ schema: BalancesStepSummarySchema, hash: frameHeadHash, stepSize: frameSize, balances,
70
+ }
71
+
72
+ await context.summaryRepository.insert([result])
73
+ }
74
+ }
75
+ // console.log(`balanceStepSummaryFromRange-result: head=${head}, range=${range[0]}-${range[1]}: ${toJsonString(result, 10)}`)
76
+ const finalResult = await PayloadBuilder.addStorageMeta(result)
77
+ return finalResult
78
+ }
@@ -0,0 +1,27 @@
1
+ import type { Address } from '@xylabs/hex'
2
+ import { asAddress } from '@xylabs/hex'
3
+ import { isDefined } from '@xylabs/typeof'
4
+ import { asBlockBoundWitnessWithStorageMeta } from '@xyo-network/xl1-protocol'
5
+
6
+ import { parseSignedBigInt } from '../../SignedBigInt.ts'
7
+ import { balanceStepSummaryFromRange } from './balanceStepSummaryFromRange.ts'
8
+ import { deepCalculateFramesFromRange } from './frames/deepCalculateFramesFromRange.ts'
9
+ import type { BalanceStepSummaryContext } from './model.ts'
10
+
11
+ export async function balanceSummary(
12
+ context: BalanceStepSummaryContext,
13
+ ): Promise<Partial<Record<Address, bigint>>> {
14
+ const headResult = await context.chainArchivist.get([context.head])
15
+ const headBoundWitness = asBlockBoundWitnessWithStorageMeta(headResult.at(0), () => `Head block not found for hash: ${context.head}`, { required: true })
16
+ const rangeStart = isDefined(context.windowSize) ? Math.max(headBoundWitness.block - context.windowSize + 1, 0) : 0
17
+ const ranges = deepCalculateFramesFromRange([rangeStart, headBoundWitness.block])
18
+ const summaries = await Promise.all(ranges.map(range => balanceStepSummaryFromRange(context, range)))
19
+ const balances: Partial<Record<Address, bigint>> = {}
20
+ for (let summary of summaries) {
21
+ for (const [address, balance] of Object.entries(summary.balances)) {
22
+ const validAddress = asAddress(address, () => `Invalid address: ${address}`)
23
+ balances[validAddress] = (balances[validAddress] ?? 0n) + parseSignedBigInt(balance)
24
+ }
25
+ }
26
+ return balances
27
+ }
@@ -1,4 +1,4 @@
1
- import { stepSizeV2 } from '@xyo-network/xl1-protocol'
1
+ import { stepSize } from '@xyo-network/xl1-protocol'
2
2
 
3
3
  import type { BlockNumberRange } from './BlockNumberRange.ts'
4
4
 
@@ -7,7 +7,7 @@ export function calculateFramesFromRange(range: BlockNumberRange, step: number):
7
7
  BlockNumberRange[],
8
8
  // ranges of remaining blocks
9
9
  BlockNumberRange[]] {
10
- const size = stepSizeV2(step)
10
+ const size = stepSize(step)
11
11
  let start = (Math.trunc(range[0] / size)) * size
12
12
  const fitted: BlockNumberRange[] = []
13
13
  const remaining: BlockNumberRange[] = []
@@ -1,9 +1,9 @@
1
- import { StepSizesV2 } from '@xyo-network/xl1-protocol'
1
+ import { StepSizes } from '@xyo-network/xl1-protocol'
2
2
 
3
3
  import type { BlockNumberRange } from './BlockNumberRange.ts'
4
4
  import { calculateFramesFromRange } from './calculateFramesFromRange.ts'
5
5
 
6
- export function deepCalculateFramesFromRange(range: BlockNumberRange, startingStep = StepSizesV2.length - 1): BlockNumberRange[] {
6
+ export function deepCalculateFramesFromRange(range: BlockNumberRange, startingStep = StepSizes.length - 1): BlockNumberRange[] {
7
7
  const fitted: BlockNumberRange[] = []
8
8
  let remaining: BlockNumberRange[] = [range]
9
9
 
@@ -1,2 +1,3 @@
1
1
  export * from './BlockNumberRange.ts'
2
- export * from './stepHashFramesFromBlock.ts'
2
+ export * from './calculateFramesFromRange.ts'
3
+ export * from './deepCalculateFramesFromRange.ts'
@@ -0,0 +1,31 @@
1
+ import { asHash, type Hash } from '@xylabs/hex'
2
+ import { toJsonString } from '@xylabs/object'
3
+ import { asBlockBoundWitnessWithStorageMeta, StepSizes } from '@xyo-network/xl1-protocol'
4
+
5
+ import type { ChainContext } from './model.ts'
6
+
7
+ export async function hashFromBlockNumber(context: ChainContext, blockNumber: number): Promise<Hash> {
8
+ const result = await context.chainArchivist.get([context.head])
9
+ let currentBlock = asBlockBoundWitnessWithStorageMeta(result.at(0), () => `Head block not found for hash: ${context.head}`, { required: true })
10
+ while (currentBlock.block > blockNumber) {
11
+ let jumpHash: Hash | null = currentBlock.previous
12
+ let jumpBlockNumber = currentBlock.block - 1
13
+ for (const [step, stepSize] of StepSizes.entries()) {
14
+ const possibleJumpBlockNumber = currentBlock.block - stepSize
15
+ if (possibleJumpBlockNumber >= blockNumber && possibleJumpBlockNumber <= jumpBlockNumber) {
16
+ jumpBlockNumber = possibleJumpBlockNumber
17
+ jumpHash = asHash(currentBlock.step_hashes.at(step), () => `Step hash not found for step ${step} in block ${currentBlock.block}`)
18
+ }
19
+ }
20
+ const [newBlock] = await context.chainArchivist.get([
21
+ asHash(jumpHash, () => `Jump hash not found for block number [${blockNumber}]: ${jumpBlockNumber} ${toJsonString(currentBlock, 10)}`)])
22
+ currentBlock = asBlockBoundWitnessWithStorageMeta(newBlock, () => `Block not found for hash: ${jumpHash}`, { required: true })
23
+ if (currentBlock.block === blockNumber) {
24
+ break
25
+ }
26
+ if (currentBlock.block < blockNumber) {
27
+ throw new Error(`Block number ${blockNumber} is not a valid step block number for block ${context.head}.`)
28
+ }
29
+ }
30
+ return currentBlock._hash
31
+ }
@@ -1 +1,6 @@
1
+ export * from './balanceStepSummaryFromRange.ts'
2
+ export * from './balanceSummary.ts'
1
3
  export * from './frames/index.ts'
4
+ export * from './hashFromBlockNumber.ts'
5
+ export * from './model.ts'
6
+ export * from './payloads.ts'
@@ -0,0 +1,18 @@
1
+ import type { Hash } from '@xylabs/hex'
2
+ import type { ReadArchivist } from '@xyo-network/archivist-model'
3
+ import type { Payload } from '@xyo-network/payload-model'
4
+ import type { PayloadRepository } from '@xyo-network/xl1-protocol'
5
+
6
+ import type { BalancesStepSummary } from './payloads.ts'
7
+
8
+ export interface ChainContext {
9
+ chainArchivist: ReadArchivist
10
+ head: Hash
11
+ windowSize?: number
12
+ }
13
+
14
+ export interface ChainSummaryContext<T extends Payload> extends ChainContext {
15
+ summaryRepository: PayloadRepository<Hash, T>
16
+ }
17
+
18
+ export interface BalanceStepSummaryContext extends ChainSummaryContext<BalancesStepSummary> {}
@@ -0,0 +1,29 @@
1
+ import type { Address, Hash } from '@xylabs/hex'
2
+ import type { EmptyObject } from '@xylabs/object'
3
+ import type { Payload, Schema } from '@xyo-network/payload-model'
4
+
5
+ import type { SignedBigInt } from '../../SignedBigInt.ts'
6
+
7
+ export const StepSummarySchema: Schema = 'network.xyo.step.summary'
8
+ export type StepSummarySchema = typeof StepSummarySchema
9
+
10
+ export interface StepSummaryFields {
11
+ hash: Hash // the stepHash - the hash of the last block in the step frame
12
+ stepSize: number // the stepSize in blocks
13
+ }
14
+
15
+ export interface ChainWindow {
16
+ depth: number // number of blocks the window covers, including the head
17
+ head: Hash // the head of the chain
18
+ }
19
+
20
+ export type StepSummary<TAdditionalFields extends EmptyObject | void = void,
21
+ TSchema extends Schema | void = void> = Payload<TAdditionalFields extends void ? StepSummaryFields : TAdditionalFields & StepSummaryFields,
22
+ TSchema extends void ? StepSummarySchema : TSchema>
23
+
24
+ export const BalancesStepSummarySchema: Schema = 'network.xyo.step.summary.balances'
25
+ export type BalancesStepSummarySchema = typeof BalancesStepSummarySchema
26
+
27
+ export type BalancesStepSummary = StepSummary<{
28
+ balances: Record<Address, SignedBigInt>
29
+ }, BalancesStepSummarySchema>
package/src/index.ts CHANGED
@@ -1,3 +1,7 @@
1
1
  export * from './block/index.ts'
2
+ export * from './ChainServiceCollection.ts'
3
+ export * from './ChainServiceCollectionV2.ts'
2
4
  export * from './instances/index.ts'
5
+ export * from './payload/index.ts'
6
+ export * from './SignedBigInt.ts'
3
7
  export * from './transaction/index.ts'
@@ -0,0 +1 @@
1
+ export * from './netBalancesForPayloads.ts'
@@ -0,0 +1,19 @@
1
+ import {
2
+ type Address, type Hex, hexToBigInt, toAddress,
3
+ } from '@xylabs/hex'
4
+ import type { Payload } from '@xyo-network/payload-model'
5
+ import { isTransfer } from '@xyo-network/xl1-protocol'
6
+
7
+ export const netBalancesForPayloads = (payloads: Payload[]) => {
8
+ const balances: Record<Address, bigint> = {}
9
+ for (const payload of payloads) {
10
+ if (isTransfer(payload)) {
11
+ const { from } = payload
12
+ for (let [address, amount] of Object.entries(payload.transfers) as [Address, Hex][]) {
13
+ balances[toAddress(address)] = (balances[toAddress(address)] ?? 0n) + hexToBigInt(amount)
14
+ balances[toAddress(from)] = (balances[toAddress(from)] ?? 0n) - hexToBigInt(amount)
15
+ }
16
+ }
17
+ }
18
+ return balances
19
+ }
@@ -5,11 +5,13 @@ import type { AccountInstance } from '@xyo-network/account-model'
5
5
  import { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'
6
6
  import { PayloadBuilder } from '@xyo-network/payload-builder'
7
7
  import type { Payload } from '@xyo-network/payload-model'
8
- import {
9
- type AllowedBlockPayload,
10
- defaultTransactionFees,
11
- type HydratedTransaction, type TransactionBoundWitness, type TransactionBoundWitnessFields, type TransactionFeesBigInt,
8
+ import type {
9
+ AllowedBlockPayload,
10
+ ExecutableFields,
11
+ FromFields,
12
+ HydratedTransaction, TransactionBoundWitness, TransactionBoundWitnessFields, TransactionFeesBigInt,
12
13
  } from '@xyo-network/xl1-protocol'
14
+ import { defaultTransactionFees } from '@xyo-network/xl1-protocol'
13
15
 
14
16
  export async function buildTransaction(
15
17
  chain: Address,
@@ -43,12 +45,17 @@ export async function buildTransaction(
43
45
  script.push(`elevate|${elevatedHash}`)
44
46
  }
45
47
 
48
+ const fields: TransactionBoundWitnessFields & FromFields & Partial<ExecutableFields> = {
49
+ ...txBoundWitnessFields,
50
+ from: from ?? (Array.isArray(signer) ? assertEx(signer.at(0)?.address) : signer.address),
51
+ }
52
+
53
+ if (script.length > 0) {
54
+ fields.script = script
55
+ }
56
+
46
57
  const [tx, txPayloads] = await new BoundWitnessBuilder<TransactionBoundWitness>()
47
- .fields({
48
- ...txBoundWitnessFields,
49
- script,
50
- from: from ?? (Array.isArray(signer) ? assertEx(signer.at(0)?.address) : signer.address),
51
- })
58
+ .fields(fields)
52
59
  .meta({ $signatures: [] })
53
60
  .payloads([...elevatedPayloads, ...additionalPayloads])
54
61
  .signers(Array.isArray(signer) ? signer : [signer])
@@ -1,5 +0,0 @@
1
- import type { ArchivistInstance } from '@xyo-network/archivist-model';
2
- import type { Payload } from '@xyo-network/payload-model';
3
- import type { BlockNumberRange } from './BlockNumberRange.ts';
4
- export declare function loadFrameSummaries(ranges: BlockNumberRange[], finalizedArchivist: ArchivistInstance, summaryArchivist: ArchivistInstance): Promise<Payload[]>;
5
- //# sourceMappingURL=loadFrameSummaries.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loadFrameSummaries.d.ts","sourceRoot":"","sources":["../../../../../src/block/primitives/frames/loadFrameSummaries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAE7D,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,EAAE,EAC1B,kBAAkB,EAAE,iBAAiB,EACrC,gBAAgB,EAAE,iBAAiB,GAClC,OAAO,CAAC,OAAO,EAAE,CAAC,CAEpB"}
@@ -1,5 +0,0 @@
1
- import { type Hash } from '@xylabs/hex';
2
- import type { ArchivistInstance } from '@xyo-network/archivist-model';
3
- export declare function stepHashFramesFromBlockAtSize(archivist: ArchivistInstance, head: Hash, sizeIndex: number): Promise<[Lowercase<string>, number, number][]>;
4
- export declare function stepHashFramesFromBlock(archivist: ArchivistInstance, head: Hash): Promise<[Lowercase<string>, number, number][]>;
5
- //# sourceMappingURL=stepHashFramesFromBlock.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stepHashFramesFromBlock.d.ts","sourceRoot":"","sources":["../../../../../src/block/primitives/frames/stepHashFramesFromBlock.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAU,MAAM,aAAa,CAAA;AAE/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAIrE,wBAAsB,6BAA6B,CAAC,SAAS,EAAE,iBAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kDA0B9G;AAGD,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,iBAAiB,EAAE,IAAI,EAAE,IAAI,kDAmCrF"}
@@ -1,12 +0,0 @@
1
- import type { ArchivistInstance } from '@xyo-network/archivist-model'
2
- import type { Payload } from '@xyo-network/payload-model'
3
-
4
- import type { BlockNumberRange } from './BlockNumberRange.ts'
5
-
6
- export async function loadFrameSummaries(
7
- ranges: BlockNumberRange[],
8
- finalizedArchivist: ArchivistInstance,
9
- summaryArchivist: ArchivistInstance,
10
- ): Promise<Payload[]> {
11
- return await Promise.resolve([])
12
- }
@@ -1,72 +0,0 @@
1
- import { assertEx } from '@xylabs/assert'
2
- import { type Hash, isHash } from '@xylabs/hex'
3
- import { isDefined } from '@xylabs/typeof'
4
- import type { ArchivistInstance } from '@xyo-network/archivist-model'
5
- import { isBlockBoundWitness, StepSizes } from '@xyo-network/xl1-protocol'
6
-
7
- // get the list of step frames for a block at a specific step size index
8
- export async function stepHashFramesFromBlockAtSize(archivist: ArchivistInstance, head: Hash, sizeIndex: number) {
9
- if (!Number.isInteger(sizeIndex) || sizeIndex < 0 || sizeIndex >= StepSizes.length) {
10
- throw new Error(`Invalid sizeIndex: ${sizeIndex}`)
11
- }
12
- let currentHead = head
13
- const steps: [Hash, number, number][] = []
14
- while (isHash(currentHead)) {
15
- const [block] = await archivist.get([currentHead])
16
- if (!isBlockBoundWitness(block)) {
17
- throw new Error(`Block with hash ${currentHead} not found`)
18
- }
19
- let stepHash = block.step_hashes.at(sizeIndex)
20
- while (isDefined(stepHash)) {
21
- const [stepHashBlock] = await archivist.get([stepHash])
22
- if (!isBlockBoundWitness(stepHashBlock)) {
23
- throw new Error(`StepHashBlock with hash ${currentHead} not found`)
24
- }
25
- const [lastBlockInStep] = await archivist.get([assertEx(stepHashBlock.previous, () => 'StepHashBlock must have a previous block')])
26
- if (!isBlockBoundWitness(lastBlockInStep)) {
27
- throw new Error(`StepHashBlock with hash ${currentHead} not found`)
28
- }
29
- steps.push([stepHash, stepHashBlock.block - StepSizes[sizeIndex], stepHashBlock.block - 1])
30
- stepHash = lastBlockInStep.step_hashes.at(sizeIndex)
31
- }
32
- }
33
- return steps
34
- }
35
-
36
- // TODO: Figure out how to get ranges of smaller blocks for each available range
37
- export async function stepHashFramesFromBlock(archivist: ArchivistInstance, head: Hash) {
38
- const [block] = await archivist.get([head])
39
- if (!isBlockBoundWitness(block)) {
40
- throw new Error(`Block with hash ${head} not found`)
41
- }
42
- let availableRanges: [number, number][] = [[0, block.block]]
43
- const foundRanges: [Hash, number, number][] = []
44
- // fit biggest to smallest
45
- for (let i = StepSizes.length - 1; i >= 0; i--) {
46
- const steps = await stepHashFramesFromBlockAtSize(archivist, head, i)
47
- for (let step of steps) {
48
- const [, start, end] = step
49
- if (availableRanges.some(range => range[0] <= start && range[1] >= end)) {
50
- foundRanges.push(step)
51
- availableRanges = availableRanges.flatMap((range) => {
52
- if (range[0] >= start && range[1] <= end) {
53
- // remove the range
54
- return [[range[0], start - 1]]
55
- } else if (range[0] < start && range[1] >= end) {
56
- // split the range
57
- return [[range[0], start - 1], [end + 1, range[1]]]
58
- } else if (range[0] < start && range[1] < end) {
59
- // adjust the end of the range
60
- return [[range[0], start - 1]]
61
- } else if (range[0] > start && range[1] > end) {
62
- // adjust the start of the range
63
- return [[end + 1, range[1]]]
64
- }
65
- // otherwise, return the range as is
66
- return [range]
67
- })
68
- }
69
- }
70
- }
71
- return foundRanges
72
- }