@xyo-network/chain-services 1.19.15 → 1.19.17
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/Election/BaseElectionService.d.ts +1 -1
- package/dist/neutral/Election/BaseElectionService.d.ts.map +1 -1
- package/dist/neutral/NetworkStakeStepReward/BaseNetworkStakeStepRewardService.d.ts +1 -1
- package/dist/neutral/NetworkStakeStepReward/BaseNetworkStakeStepRewardService.d.ts.map +1 -1
- package/dist/neutral/StepStake/BaseStepStakeService.d.ts +1 -1
- package/dist/neutral/StepStake/BaseStepStakeService.d.ts.map +1 -1
- package/dist/neutral/index.d.ts +0 -1
- package/dist/neutral/index.d.ts.map +1 -1
- package/dist/neutral/index.mjs +25 -323
- package/dist/neutral/index.mjs.map +1 -1
- package/dist/neutral/simple/block/runner/SimpleBlockRunner.d.ts +5 -6
- package/dist/neutral/simple/block/runner/SimpleBlockRunner.d.ts.map +1 -1
- package/package.json +22 -24
- package/src/Election/BaseElectionService.ts +1 -1
- package/src/NetworkStakeStepReward/BaseNetworkStakeStepRewardService.ts +1 -1
- package/src/StepStake/BaseStepStakeService.ts +1 -1
- package/src/index.ts +0 -1
- package/src/simple/block/runner/SimpleBlockRunner.ts +3 -3
- package/dist/neutral/PendingTransactions/BasePendingTransactions.d.ts +0 -64
- package/dist/neutral/PendingTransactions/BasePendingTransactions.d.ts.map +0 -1
- package/dist/neutral/PendingTransactions/bundledPayloadToHydratedTransaction.d.ts +0 -4
- package/dist/neutral/PendingTransactions/bundledPayloadToHydratedTransaction.d.ts.map +0 -1
- package/dist/neutral/PendingTransactions/hydratedTransactionToPayloadBundle.d.ts +0 -4
- package/dist/neutral/PendingTransactions/hydratedTransactionToPayloadBundle.d.ts.map +0 -1
- package/dist/neutral/PendingTransactions/index.d.ts +0 -2
- package/dist/neutral/PendingTransactions/index.d.ts.map +0 -1
- package/src/PendingTransactions/BasePendingTransactions.ts +0 -382
- package/src/PendingTransactions/bundledPayloadToHydratedTransaction.ts +0 -14
- package/src/PendingTransactions/hydratedTransactionToPayloadBundle.ts +0 -18
- package/src/PendingTransactions/index.ts +0 -1
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { PayloadBundle } from '@xyo-network/payload-model';
|
|
2
|
-
import type { SignedHydratedTransactionWithHashMeta } from '@xyo-network/xl1-sdk';
|
|
3
|
-
export declare const hydratedTransactionToPayloadBundle: (transaction: SignedHydratedTransactionWithHashMeta) => PayloadBundle;
|
|
4
|
-
//# sourceMappingURL=hydratedTransactionToPayloadBundle.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hydratedTransactionToPayloadBundle.d.ts","sourceRoot":"","sources":["../../../src/PendingTransactions/hydratedTransactionToPayloadBundle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAG/D,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,sBAAsB,CAAA;AAGjF,eAAO,MAAM,kCAAkC,GAAI,aAAa,qCAAqC,KAAG,aAGvG,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/PendingTransactions/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAA"}
|
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
import { ValueType } from '@opentelemetry/api'
|
|
2
|
-
import {
|
|
3
|
-
assertEx,
|
|
4
|
-
exists,
|
|
5
|
-
filterAs, filterAsync, forget, Hash,
|
|
6
|
-
isDefined, isUndefined,
|
|
7
|
-
} from '@xylabs/sdk-js'
|
|
8
|
-
import { MemoryArchivist } from '@xyo-network/archivist-memory'
|
|
9
|
-
import { ArchivistInstance } from '@xyo-network/archivist-model'
|
|
10
|
-
import {
|
|
11
|
-
Payload, PayloadBundle, Sequence, WithStorageMeta,
|
|
12
|
-
} from '@xyo-network/payload-model'
|
|
13
|
-
import {
|
|
14
|
-
AbstractCreatableProvider,
|
|
15
|
-
asBlockBoundWitnessWithHashMeta, asXL1BlockNumber, ChainId, creatableProvider,
|
|
16
|
-
findMostRecentBlock, HydratedTransactionValidationFunction, isTransactionBoundWitnessWithStorageMeta,
|
|
17
|
-
MempoolViewer, MempoolViewerMoniker, PendingBlocksOptions, PendingTransactionsOptions,
|
|
18
|
-
SignedHydratedBlockWithHashMeta,
|
|
19
|
-
SignedHydratedTransactionWithHashMeta,
|
|
20
|
-
SignedHydratedTransactionWithStorageMeta,
|
|
21
|
-
TransactionJsonSchemaValidator, validateTransaction,
|
|
22
|
-
XL1BlockNumber,
|
|
23
|
-
} from '@xyo-network/xl1-sdk'
|
|
24
|
-
import { Mutex } from 'async-mutex'
|
|
25
|
-
|
|
26
|
-
import { BaseServiceParams } from '../model/index.ts'
|
|
27
|
-
import { bundledPayloadToHydratedTransaction } from './bundledPayloadToHydratedTransaction.ts'
|
|
28
|
-
import { hydratedTransactionToPayloadBundle } from './hydratedTransactionToPayloadBundle.ts'
|
|
29
|
-
|
|
30
|
-
export interface BasePendingTransactionsServiceParams extends BaseServiceParams {
|
|
31
|
-
additionalPendingTransactionValidators?: HydratedTransactionValidationFunction[]
|
|
32
|
-
chainArchivist: ArchivistInstance
|
|
33
|
-
chainId: ChainId
|
|
34
|
-
pendingBundledTransactionsArchivist: ArchivistInstance
|
|
35
|
-
rejectedTransactionsArchivist: ArchivistInstance
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
@creatableProvider()
|
|
39
|
-
export class BasePendingTransactionsService extends AbstractCreatableProvider<BasePendingTransactionsServiceParams> implements MempoolViewer {
|
|
40
|
-
static readonly defaultMoniker = MempoolViewerMoniker
|
|
41
|
-
static readonly dependencies = []
|
|
42
|
-
static readonly monikers = [MempoolViewerMoniker]
|
|
43
|
-
|
|
44
|
-
private static readonly MutexPriority = {
|
|
45
|
-
/**
|
|
46
|
-
* Priority for inserting new transactions
|
|
47
|
-
*/
|
|
48
|
-
InsertNewTransactions: 5,
|
|
49
|
-
/**
|
|
50
|
-
* Priority for reading pending transactions
|
|
51
|
-
*/
|
|
52
|
-
ReadTransactions: 3,
|
|
53
|
-
/**
|
|
54
|
-
* Priority for removing finalized/expired/rejected transactions
|
|
55
|
-
*/
|
|
56
|
-
PurgeTransactions: 1,
|
|
57
|
-
} as const
|
|
58
|
-
|
|
59
|
-
override moniker = BasePendingTransactionsService.defaultMoniker
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* A mutex to ensure that the counting the number of pending transactions is
|
|
63
|
-
* not called concurrently
|
|
64
|
-
*/
|
|
65
|
-
private _countPendingTransactionsMutex = new Mutex()
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* A local Archivist optimized for fast retrieval that stores only validated
|
|
69
|
-
* pending transactions
|
|
70
|
-
*/
|
|
71
|
-
private _curatedPendingBundledTransactionsArchivist: MemoryArchivist | undefined
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* The last count of total pending transactions
|
|
75
|
-
*/
|
|
76
|
-
private _pendingTransactionsCount: number = 0
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* A set of transaction hashes that are pending removal from the
|
|
80
|
-
* curated pending transactions archivist. This is used to track
|
|
81
|
-
* which transactions need to be removed from the archivist.
|
|
82
|
-
*/
|
|
83
|
-
private _removablePendingTransactionHashes: Set<Hash> = new Set()
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* A mutex to ensure that the curated pending transactions archivist is
|
|
87
|
-
* updated in a thread-safe manner
|
|
88
|
-
*/
|
|
89
|
-
private _updateCuratedPendingTransactionsArchivistMutex = new Mutex()
|
|
90
|
-
|
|
91
|
-
private get additionalPendingTransactionValidators() {
|
|
92
|
-
return this.params.additionalPendingTransactionValidators ?? []
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
private get chainArchivist() {
|
|
96
|
-
return assertEx(this.params.chainArchivist, () => 'No completed blocks with data archivist')
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private get pendingBundledTransactionsArchivist() {
|
|
100
|
-
return assertEx(this.params.pendingBundledTransactionsArchivist, () => 'No pending bundled transactions archivist')
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private get pendingBundledTransactionsLocalArchivist() {
|
|
104
|
-
return assertEx(this._curatedPendingBundledTransactionsArchivist, () => 'No pending bundled transactions curated archivist')
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
private get pendingTransactionsCount() {
|
|
108
|
-
forget(this.countPendingTransactions())
|
|
109
|
-
return this._pendingTransactionsCount
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
private get rejectedTransactionsArchivist() {
|
|
113
|
-
return assertEx(this.params.rejectedTransactionsArchivist, () => 'No rejected transactions archivist')
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
override async createHandler() {
|
|
117
|
-
await super.createHandler()
|
|
118
|
-
this._curatedPendingBundledTransactionsArchivist = await MemoryArchivist.create({ account: 'random' })
|
|
119
|
-
|
|
120
|
-
// On new pending transactions, insert them into the curated archivist
|
|
121
|
-
this.pendingBundledTransactionsArchivist.on('inserted', ({ payloads }) => {
|
|
122
|
-
forget(this.insertNewTransactions(payloads as WithStorageMeta<PayloadBundle>[]))
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
// On new finalized blocks, remove the transactions from the curated archivist
|
|
126
|
-
this.chainArchivist.on('inserted', ({ payloads }) => {
|
|
127
|
-
this.markAnyIncludedTransactionsForRemoval(payloads)
|
|
128
|
-
forget(this.cleanupWorker())
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
// On new rejected transactions, remove the transactions from the curated archivist
|
|
132
|
-
this.rejectedTransactionsArchivist.on('inserted', ({ payloads }) => {
|
|
133
|
-
this.markAnyIncludedTransactionsForRemoval(payloads)
|
|
134
|
-
forget(this.cleanupWorker())
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
const pendingTransactionsCounter = this.meter?.createObservableUpDownCounter(
|
|
138
|
-
'xyo_pending_transactions_counter',
|
|
139
|
-
{
|
|
140
|
-
description: 'The current number of pending transactions', valueType: ValueType.INT, unit: '1',
|
|
141
|
-
},
|
|
142
|
-
)
|
|
143
|
-
pendingTransactionsCounter?.addCallback((observer) => {
|
|
144
|
-
observer.observe(this.pendingTransactionsCount)
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
pendingBlocks(_options?: PendingBlocksOptions): Promise<SignedHydratedBlockWithHashMeta[]> {
|
|
149
|
-
throw new Error('Method [pendingBlocks] not implemented.')
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async pendingTransactions({ limit = 100 }: PendingTransactionsOptions = {}): Promise<SignedHydratedTransactionWithStorageMeta[]> {
|
|
153
|
-
return await this.spanAsync('getPendingTransactions', async () => {
|
|
154
|
-
// Acquires an exclusive mutex to ensure no race conditions while accessing pending transactions.
|
|
155
|
-
return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
|
|
156
|
-
// Find the supplied head
|
|
157
|
-
let lastHead = (filterAs(await this.chainArchivist.next({ limit: 100 }), x => asBlockBoundWitnessWithHashMeta(x))).at(-1)
|
|
158
|
-
if (isUndefined(lastHead)) return []
|
|
159
|
-
|
|
160
|
-
await this.pruneCuratedPendingTransactionsArchivist(lastHead._hash)
|
|
161
|
-
|
|
162
|
-
const foundPendingTransactions: SignedHydratedTransactionWithStorageMeta[] = []
|
|
163
|
-
let cursor: Sequence | undefined
|
|
164
|
-
|
|
165
|
-
// Continue fetching until the desired number of transactions is reached.
|
|
166
|
-
while (foundPendingTransactions.length < limit) {
|
|
167
|
-
// Fetch the next batch of payloads
|
|
168
|
-
const pendingBundledTransactions = await this.pendingBundledTransactionsLocalArchivist.next({
|
|
169
|
-
limit: 100,
|
|
170
|
-
order: 'asc',
|
|
171
|
-
cursor,
|
|
172
|
-
}) as WithStorageMeta<PayloadBundle>[]
|
|
173
|
-
|
|
174
|
-
// Exit if no more payloads are available.
|
|
175
|
-
if (pendingBundledTransactions.length === 0) break
|
|
176
|
-
|
|
177
|
-
// Update the cursor for the next iteration to fetch subsequent payloads.
|
|
178
|
-
cursor = pendingBundledTransactions.at(-1)?._sequence
|
|
179
|
-
|
|
180
|
-
// Keep only those payloads that are not marked for deletion.
|
|
181
|
-
const undeletedTransactionBundles = pendingBundledTransactions.filter(tx =>
|
|
182
|
-
!this._removablePendingTransactionHashes.has(tx.root))
|
|
183
|
-
|
|
184
|
-
// Convert each undeleted payload bundle into a hydrated transaction.
|
|
185
|
-
const transactions = (await Promise.all(
|
|
186
|
-
undeletedTransactionBundles.map(p => bundledPayloadToHydratedTransaction(p)),
|
|
187
|
-
)).filter(exists)
|
|
188
|
-
|
|
189
|
-
// Filter transactions to only include those that are active for the next
|
|
190
|
-
// potential block based on the last supplied head.
|
|
191
|
-
const activeTransactions = transactions.filter(isTransactionActive(asXL1BlockNumber(lastHead.block + 1, true)))
|
|
192
|
-
|
|
193
|
-
const txValidationResults = await Promise.all(activeTransactions.map(async tx => ([tx, await validateTransaction(
|
|
194
|
-
{ ...this.context, chainId: this.params.chainId },
|
|
195
|
-
tx,
|
|
196
|
-
this.additionalPendingTransactionValidators,
|
|
197
|
-
)])))
|
|
198
|
-
|
|
199
|
-
const validTransactions = txValidationResults.filter((
|
|
200
|
-
[, errors],
|
|
201
|
-
) => errors.length === 0).map(([tx]) => tx) as SignedHydratedTransactionWithStorageMeta[]
|
|
202
|
-
|
|
203
|
-
const invalidTransactions = txValidationResults.filter((
|
|
204
|
-
[, errors],
|
|
205
|
-
) => errors.length > 0).map(([tx]) => tx) as SignedHydratedTransactionWithStorageMeta[]
|
|
206
|
-
|
|
207
|
-
if (invalidTransactions.length > 0) {
|
|
208
|
-
this.logger?.warn(`getPendingTransactions: Found ${invalidTransactions.length} invalid pending transactions`)
|
|
209
|
-
for (const tx of invalidTransactions) {
|
|
210
|
-
this.logger?.warn(tx[0]._hash)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Add the valid hydrated transactions to the result set.
|
|
215
|
-
foundPendingTransactions.push(...validTransactions)
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (foundPendingTransactions.length > 0) {
|
|
219
|
-
this.logger?.log(`getPendingTransactions: Found ${foundPendingTransactions.length} pending transactions`)
|
|
220
|
-
for (const tx of foundPendingTransactions) {
|
|
221
|
-
this.logger?.log(tx[0]._hash)
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return foundPendingTransactions
|
|
226
|
-
}, BasePendingTransactionsService.MutexPriority.ReadTransactions)
|
|
227
|
-
}, this.context)
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
private async cleanupWorker() {
|
|
231
|
-
return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
|
|
232
|
-
const lastHead = await findMostRecentBlock(this.chainArchivist)
|
|
233
|
-
if (isDefined(lastHead)) await this.pruneCuratedPendingTransactionsArchivist(lastHead._hash)
|
|
234
|
-
}, BasePendingTransactionsService.MutexPriority.PurgeTransactions)
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
private async countPendingTransactions() {
|
|
238
|
-
if (this._countPendingTransactionsMutex.isLocked()) return
|
|
239
|
-
await this._countPendingTransactionsMutex.runExclusive(async () => {
|
|
240
|
-
const payloads = (await this._curatedPendingBundledTransactionsArchivist?.all()) ?? []
|
|
241
|
-
this._pendingTransactionsCount = payloads.length
|
|
242
|
-
})
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
private async filterAlreadyFinalizedTransactions(
|
|
246
|
-
incomingTransactions: WithStorageMeta<PayloadBundle>[],
|
|
247
|
-
): Promise<WithStorageMeta<PayloadBundle>[]> {
|
|
248
|
-
const incomingTransactionHashes = incomingTransactions.map(payload => payload.root)
|
|
249
|
-
const finalizedTransactions = await this.chainArchivist.get(incomingTransactionHashes)
|
|
250
|
-
const finalizedTransactionHashes = new Set(finalizedTransactions.map(item => item._hash))
|
|
251
|
-
const nonFinalizedTransactions = incomingTransactions.filter(item => !finalizedTransactionHashes.has(item._hash))
|
|
252
|
-
return nonFinalizedTransactions
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
private async insertNewTransactions(payloads: WithStorageMeta<PayloadBundle>[]) {
|
|
256
|
-
if (payloads.length === 0) return
|
|
257
|
-
return await this.spanAsync('InsertNewTransactions', async () => {
|
|
258
|
-
return await this._updateCuratedPendingTransactionsArchivistMutex.runExclusive(async () => {
|
|
259
|
-
// Check incoming transactions against finalized transactions
|
|
260
|
-
const unprocessedTransactions = await this.filterAlreadyFinalizedTransactions(payloads)
|
|
261
|
-
// Hydrate all unprocessed transactions
|
|
262
|
-
const hydratedUnprocessedTransactions = (await Promise.all(unprocessedTransactions.map(async (tx) => {
|
|
263
|
-
return await bundledPayloadToHydratedTransaction(tx)
|
|
264
|
-
}))).filter(exists)
|
|
265
|
-
// Filter to only valid transactions
|
|
266
|
-
const validTransactions = await filterAsync(hydratedUnprocessedTransactions, async (tx) => {
|
|
267
|
-
const errors = await validateTransaction({ ...this.context, chainId: this.params.chainId }, tx, [TransactionJsonSchemaValidator])
|
|
268
|
-
if (errors.length > 0) {
|
|
269
|
-
this.logger?.warn('validateTransaction', errors)
|
|
270
|
-
}
|
|
271
|
-
return errors.length > 0 ? false : true
|
|
272
|
-
})
|
|
273
|
-
if (validTransactions.length > 0) {
|
|
274
|
-
const bundledTransactions = validTransactions.map(tx => hydratedTransactionToPayloadBundle(tx))
|
|
275
|
-
await this.pendingBundledTransactionsLocalArchivist.insert(bundledTransactions)
|
|
276
|
-
}
|
|
277
|
-
}, BasePendingTransactionsService.MutexPriority.InsertNewTransactions)
|
|
278
|
-
}, this.context)
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Marks any included transactions in the provided payloads for removal preventing them
|
|
283
|
-
* from being included in the curated pending transactions archivist and from being offered
|
|
284
|
-
* during the next retrieval of pending transactions.
|
|
285
|
-
* @param payloads An array of payloads that may contain transactions.
|
|
286
|
-
*/
|
|
287
|
-
private markAnyIncludedTransactionsForRemoval(payloads: WithStorageMeta<Payload>[]) {
|
|
288
|
-
const hashes = payloads.filter(isTransactionBoundWitnessWithStorageMeta).map(p => p._hash)
|
|
289
|
-
for (const hash of hashes) {
|
|
290
|
-
this._removablePendingTransactionHashes.add(hash)
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
private async pruneCuratedPendingTransactionsArchivist(head: Hash) {
|
|
295
|
-
return await this.spanAsync('pruneCuratedPendingTransactionsArchivist', async () => {
|
|
296
|
-
const foundPendingTransactionsToDeleteHashes: Hash[] = []
|
|
297
|
-
|
|
298
|
-
let cursor: Sequence | undefined
|
|
299
|
-
let [lastHead] = filterAs(await this.chainArchivist.get([head]), x => asBlockBoundWitnessWithHashMeta(x))
|
|
300
|
-
|
|
301
|
-
// Continue fetching until the desired number of transactions is reached.
|
|
302
|
-
while (isDefined(lastHead)) {
|
|
303
|
-
// Fetch the next batch of payloads
|
|
304
|
-
const pendingBundledTransactions = await this.pendingBundledTransactionsLocalArchivist.next({
|
|
305
|
-
limit: 100,
|
|
306
|
-
order: 'asc',
|
|
307
|
-
cursor,
|
|
308
|
-
}) as WithStorageMeta<PayloadBundle>[]
|
|
309
|
-
|
|
310
|
-
// Exit if no more payloads are available.
|
|
311
|
-
if (pendingBundledTransactions.length === 0) {
|
|
312
|
-
break
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Update the cursor for the next iteration to fetch subsequent payloads.
|
|
316
|
-
cursor = pendingBundledTransactions.at(-1)?._sequence
|
|
317
|
-
|
|
318
|
-
// Filter out bundles that are marked as removable.
|
|
319
|
-
const deletedTransactionBundles = pendingBundledTransactions.filter(tx =>
|
|
320
|
-
this._removablePendingTransactionHashes.has(tx.root))
|
|
321
|
-
|
|
322
|
-
// Queue the hashes of deletable transactions for deletion and cleanup.
|
|
323
|
-
foundPendingTransactionsToDeleteHashes.push(
|
|
324
|
-
...deletedTransactionBundles.map(tx => tx._hash).filter(exists),
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
// Keep only those payloads that are not marked for deletion.
|
|
328
|
-
const undeletedTransactionBundles = pendingBundledTransactions.filter(tx =>
|
|
329
|
-
!this._removablePendingTransactionHashes.has(tx.root))
|
|
330
|
-
|
|
331
|
-
// Convert each undeleted payload bundle into a hydrated transaction.
|
|
332
|
-
const transactions = (await Promise.all(
|
|
333
|
-
undeletedTransactionBundles.map(p => bundledPayloadToHydratedTransaction(p)),
|
|
334
|
-
)).filter(exists)
|
|
335
|
-
|
|
336
|
-
// Find expired transactions based on the last supplied head
|
|
337
|
-
const expiredTransactions = transactions.filter(isTransactionExpired(asXL1BlockNumber(lastHead.block + 1, true)))
|
|
338
|
-
// Find the corresponding bundle hashes for the expired transactions
|
|
339
|
-
const expiredBundleHashes = expiredTransactions
|
|
340
|
-
.map(expiredHydratedTx =>
|
|
341
|
-
// Find the corresponding payload bundle hash for the expired transaction
|
|
342
|
-
pendingBundledTransactions.find(bundledTx => bundledTx.root === expiredHydratedTx[0]._hash)?._hash)
|
|
343
|
-
.filter(exists)
|
|
344
|
-
// Mark all expired bundled transactions for deletion.
|
|
345
|
-
foundPendingTransactionsToDeleteHashes.push(...expiredBundleHashes)
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Actually delete the marked payload bundles from the archivist
|
|
349
|
-
const deletedHashes = await this.pendingBundledTransactionsLocalArchivist.delete(foundPendingTransactionsToDeleteHashes)
|
|
350
|
-
|
|
351
|
-
// Remove all deleted hashes from the "pending delete" set now that they are deleted
|
|
352
|
-
for (const payload of deletedHashes) {
|
|
353
|
-
this._removablePendingTransactionHashes.delete(payload._hash)
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
if (deletedHashes.length > 0) {
|
|
357
|
-
this.logger?.log(`foundPendingTransactionsToDeleteHashes: Found ${deletedHashes.length} deletable transactions`)
|
|
358
|
-
for (const payload of deletedHashes) {
|
|
359
|
-
this.logger?.log(payload._hash)
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}, this.context)
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* Checks if a transaction is expired for a given block.
|
|
368
|
-
* @param block The block number to check against the transaction's validity period.
|
|
369
|
-
* @returns True if the transaction is expired for the given block, false otherwise.
|
|
370
|
-
*/
|
|
371
|
-
const isTransactionExpired = (block: XL1BlockNumber) =>
|
|
372
|
-
([txBw]: SignedHydratedTransactionWithHashMeta): boolean =>
|
|
373
|
-
txBw.exp < block
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Checks if a transaction is active for a given block.
|
|
377
|
-
* @param block The block number to check against the transaction's validity period.
|
|
378
|
-
* @returns True if the transaction is active for the given block, false otherwise.
|
|
379
|
-
*/
|
|
380
|
-
const isTransactionActive = (block: XL1BlockNumber) =>
|
|
381
|
-
([txBw]: SignedHydratedTransactionWithHashMeta): boolean =>
|
|
382
|
-
txBw.nbf <= block && txBw.exp >= block
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { PayloadBundle, WithStorageMeta } from '@xyo-network/payload-model'
|
|
2
|
-
import { PayloadBuilder } from '@xyo-network/sdk-js'
|
|
3
|
-
import type { SignedHydratedTransactionWithHashMeta } from '@xyo-network/xl1-sdk'
|
|
4
|
-
import { asSignedTransactionBoundWitnessWithHashMeta } from '@xyo-network/xl1-sdk'
|
|
5
|
-
|
|
6
|
-
export const bundledPayloadToHydratedTransaction = async (
|
|
7
|
-
payload: WithStorageMeta<PayloadBundle>,
|
|
8
|
-
): Promise<SignedHydratedTransactionWithHashMeta | undefined> => {
|
|
9
|
-
const withHashMeta = await PayloadBuilder.addHashMeta(payload.payloads)
|
|
10
|
-
const tx = asSignedTransactionBoundWitnessWithHashMeta(withHashMeta.find(p => p._hash === payload.root))
|
|
11
|
-
if (tx) {
|
|
12
|
-
return [tx, withHashMeta.filter(p => p._hash !== payload.root)]
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Hash } from '@xylabs/sdk-js'
|
|
2
|
-
import type { PayloadBundle } from '@xyo-network/payload-model'
|
|
3
|
-
import { PayloadBundleSchema } from '@xyo-network/payload-model'
|
|
4
|
-
import { PayloadBuilder } from '@xyo-network/sdk-js'
|
|
5
|
-
import type { SignedHydratedTransactionWithHashMeta } from '@xyo-network/xl1-sdk'
|
|
6
|
-
import { flattenHydratedTransaction } from '@xyo-network/xl1-sdk'
|
|
7
|
-
|
|
8
|
-
export const hydratedTransactionToPayloadBundle = (transaction: SignedHydratedTransactionWithHashMeta): PayloadBundle => {
|
|
9
|
-
const root = transaction[0]._hash
|
|
10
|
-
return bundle(root, transaction)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const bundle = (root: Hash, transaction: SignedHydratedTransactionWithHashMeta) => {
|
|
14
|
-
const payloads = flattenHydratedTransaction(transaction).flatMap(p => PayloadBuilder.omitStorageMeta(p))
|
|
15
|
-
return new PayloadBuilder<PayloadBundle>({ schema: PayloadBundleSchema })
|
|
16
|
-
.fields({ payloads, root })
|
|
17
|
-
.build()
|
|
18
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './BasePendingTransactions.ts'
|