@xyo-network/xl1-protocol-sdk 2.0.11 → 2.0.13

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 (39) hide show
  1. package/dist/neutral/CreatableProvider/AbstractCreatableProvider.d.ts +7 -0
  2. package/dist/neutral/CreatableProvider/AbstractCreatableProvider.d.ts.map +1 -1
  3. package/dist/neutral/config/Actor.d.ts +42 -0
  4. package/dist/neutral/config/Actor.d.ts.map +1 -1
  5. package/dist/neutral/config/Actors.d.ts +7 -0
  6. package/dist/neutral/config/Actors.d.ts.map +1 -1
  7. package/dist/neutral/config/Base.d.ts +7 -0
  8. package/dist/neutral/config/Base.d.ts.map +1 -1
  9. package/dist/neutral/config/Config.d.ts +28 -0
  10. package/dist/neutral/config/Config.d.ts.map +1 -1
  11. package/dist/neutral/config/HostActor.d.ts +42 -0
  12. package/dist/neutral/config/HostActor.d.ts.map +1 -1
  13. package/dist/neutral/config/index.d.ts +1 -1
  14. package/dist/neutral/config/index.d.ts.map +1 -1
  15. package/dist/neutral/config/storage/Storage.d.ts +7 -0
  16. package/dist/neutral/config/storage/Storage.d.ts.map +1 -1
  17. package/dist/neutral/config/storage/driver/R2.d.ts +25 -0
  18. package/dist/neutral/config/storage/driver/R2.d.ts.map +1 -0
  19. package/dist/neutral/config/storage/driver/index.d.ts +1 -0
  20. package/dist/neutral/config/storage/driver/index.d.ts.map +1 -1
  21. package/dist/neutral/context/Actor.d.ts +42 -0
  22. package/dist/neutral/context/Actor.d.ts.map +1 -1
  23. package/dist/neutral/context/HostActor.d.ts +42 -0
  24. package/dist/neutral/context/HostActor.d.ts.map +1 -1
  25. package/dist/neutral/getFileConfig.d.ts +14 -0
  26. package/dist/neutral/getFileConfig.d.ts.map +1 -1
  27. package/dist/neutral/getFileConfig.mjs +76 -44
  28. package/dist/neutral/getFileConfig.mjs.map +4 -4
  29. package/dist/neutral/index.d.ts +1 -0
  30. package/dist/neutral/index.d.ts.map +1 -1
  31. package/dist/neutral/index.mjs +560 -156
  32. package/dist/neutral/index.mjs.map +4 -4
  33. package/dist/neutral/model/CreatableProviderContext.zod.d.ts +42 -0
  34. package/dist/neutral/model/CreatableProviderContext.zod.d.ts.map +1 -1
  35. package/dist/neutral/test/index.d.ts +1 -0
  36. package/dist/neutral/test/index.d.ts.map +1 -1
  37. package/dist/neutral/test/index.mjs +1056 -1019
  38. package/dist/neutral/test/index.mjs.map +4 -4
  39. package/package.json +6 -6
@@ -11,285 +11,825 @@ var __decorateClass = (decorators, target, key, kind) => {
11
11
  };
12
12
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
13
13
 
14
- // src/test/buildRandomTransaction.ts
15
- import { Account } from "@xyo-network/sdk-js";
16
- import { asXL1BlockNumber, isAllowedBlockPayload } from "@xyo-network/xl1-protocol-lib";
17
-
18
- // src/createTransferPayload.ts
19
- import { toHex } from "@xylabs/sdk-js";
20
- import { PayloadBuilder } from "@xyo-network/sdk-js";
21
- import { TransferSchema } from "@xyo-network/xl1-protocol-lib";
22
- function createTransferPayload(from, transfers, context) {
23
- return new PayloadBuilder({ schema: TransferSchema }).fields({
24
- epoch: Date.now(),
25
- from,
26
- transfers: Object.fromEntries(Object.entries(transfers).map(([k, v]) => [k, toHex(v)])),
27
- context
28
- }).build();
29
- }
30
-
31
- // src/transaction/buildTransaction.ts
32
- import { assertEx, toHex as toHex2 } from "@xylabs/sdk-js";
14
+ // src/test/buildRandomChain.ts
15
+ import { asAddress as asAddress2, assertEx as assertEx6 } from "@xylabs/sdk-js";
33
16
  import {
34
- asAnyPayload,
35
- BoundWitnessBuilder,
36
- PayloadBuilder as PayloadBuilder2
17
+ Account as Account3,
18
+ asSchema as asSchema2,
19
+ IdSchema as IdSchema2,
20
+ MemoryArchivist,
21
+ PayloadBuilder as PayloadBuilder8
37
22
  } from "@xyo-network/sdk-js";
38
- import { defaultTransactionFees } from "@xyo-network/xl1-protocol-lib";
39
- async function buildTransaction(chain, onChainPayloads, offChainPayloads, signer, nbf, exp, from, fees = defaultTransactionFees) {
40
- if (from === void 0 && Array.isArray(signer)) {
41
- throw new Error("from is required when signer is an array");
42
- }
43
- const txBoundWitnessFields = {
44
- chain,
45
- fees: {
46
- base: toHex2(fees.base),
47
- gasLimit: toHex2(fees.gasLimit),
48
- gasPrice: toHex2(fees.gasPrice),
49
- priority: toHex2(fees.priority)
50
- },
51
- nbf,
52
- exp
53
- };
54
- const elevatedHashes = await PayloadBuilder2.hashes(onChainPayloads);
55
- const script = [];
56
- for (const elevatedHash of elevatedHashes) {
57
- script.push(`elevate|${elevatedHash}`);
58
- }
59
- const fields = {
60
- ...txBoundWitnessFields,
61
- from: from ?? (Array.isArray(signer) ? assertEx(signer.at(0)?.address) : signer.address)
62
- };
63
- if (script.length > 0) {
64
- fields.script = script;
65
- }
66
- const [tx, txPayloads] = await new BoundWitnessBuilder().fields(fields).meta({ $signatures: [] }).payloads([...onChainPayloads, ...offChainPayloads]).signers(Array.isArray(signer) ? signer : [signer]).build();
67
- return [await PayloadBuilder2.addHashMeta(tx), await PayloadBuilder2.addHashMeta(txPayloads.map((p) => asAnyPayload(p, true)))];
23
+ import {
24
+ asXL1BlockNumber as asXL1BlockNumber6
25
+ } from "@xyo-network/xl1-protocol-lib";
26
+
27
+ // src/block/hydrate/allHashesPresent.ts
28
+ function allHashesPresent(hashes, payloads) {
29
+ const payloadHashes = new Set(payloads.map((p) => p._hash));
30
+ return hashes.every((hash) => payloadHashes.has(hash));
68
31
  }
69
32
 
70
- // src/test/buildRandomTransaction.ts
71
- var buildRandomTransaction = async (chain, payloads, account, nbf = asXL1BlockNumber(0, true), exp = asXL1BlockNumber(nbf + 1e3, true), privatePayloadSchemas = [], receiverAddress) => {
72
- const elevatedPayloads = (payloads ?? []).filter(isAllowedBlockPayload);
73
- const additionalPayloads = (payloads ?? []).filter((payload) => !isAllowedBlockPayload(payload));
74
- const sender = account ?? await Account.random();
75
- if (elevatedPayloads.length === 0) {
76
- const receiver = receiverAddress ?? (await Account.random()).address;
77
- const transferPayload = createTransferPayload(sender.address, { [receiver]: 1n });
78
- elevatedPayloads.push(transferPayload);
79
- }
80
- const hydratedTransaction = await buildTransaction(chain, elevatedPayloads, additionalPayloads, sender, nbf, exp);
81
- return [hydratedTransaction[0], hydratedTransaction[1].filter((payload) => !privatePayloadSchemas.includes(payload.schema))];
33
+ // src/block/hydrate/flattenHydratedBlock.ts
34
+ import { toHydratedBlock } from "@xyo-network/xl1-protocol-lib";
35
+ var flattenHydratedBlock = (hydratedBlock) => {
36
+ const [blk, blkPayloads] = hydratedBlock;
37
+ return [...blkPayloads, blk];
82
38
  };
83
39
 
84
- // src/test/getSimpleBlockViewerLocator.ts
85
- import { XYO_ZERO_ADDRESS as XYO_ZERO_ADDRESS3 } from "@xyo-network/xl1-protocol-lib";
40
+ // src/block/hydrate/flattenHydratedBlocks.ts
41
+ var flattenHydratedBlocks = (hydratedBlocks) => hydratedBlocks.flatMap((blk) => flattenHydratedBlock(blk));
86
42
 
87
- // src/CreatableProvider/AbstractCreatableProvider.ts
43
+ // src/block/hydrate/hydrateBlock.ts
44
+ import { assertEx } from "@xylabs/sdk-js";
45
+ import { asAnyPayload } from "@xyo-network/sdk-js";
46
+ import { asBlockBoundWitnessWithStorageMeta, isTransactionBoundWitnessWithStorageMeta } from "@xyo-network/xl1-protocol-lib";
47
+ var hydrateBlock = async (context, hash, maxDepth = 1, minDepth = maxDepth) => {
48
+ assertEx(maxDepth >= 0, () => "maxDepth must be greater than or equal to 0");
49
+ assertEx(minDepth >= 0, () => "minDepth must be greater than or equal to 0");
50
+ assertEx(maxDepth >= minDepth, () => "maxDepth must be greater than or equal to minDepth");
51
+ const { chainMap } = context;
52
+ const [block] = await chainMap.get([hash]);
53
+ const bw = assertEx(asBlockBoundWitnessWithStorageMeta(
54
+ assertEx(block, () => `block ${hash} not found`)
55
+ ), () => `hash ${hash} is not a BlockBoundWitness`);
56
+ if (maxDepth === 0) return [bw, []];
57
+ const blkPayloads = (await chainMap.get(bw.payload_hashes)).map((p) => asAnyPayload(p, true));
58
+ if (minDepth === 1) assertEx(allHashesPresent(bw.payload_hashes, blkPayloads), () => `Unable to find all payloads for block ${hash}`);
59
+ if (maxDepth === 1) return [bw, blkPayloads];
60
+ const transactions = blkPayloads.filter(isTransactionBoundWitnessWithStorageMeta);
61
+ const transactionsPayloadHashes = transactions.flatMap((tx) => tx.payload_hashes);
62
+ const transactionsPayloads = (await chainMap.get(transactionsPayloadHashes)).map((p) => asAnyPayload(p, true));
63
+ assertEx(allHashesPresent(transactionsPayloadHashes, transactionsPayloads), () => `Unable to find all payloads for transactions in block ${hash}`);
64
+ const allPayloadsHashes = new Set([...blkPayloads, ...transactionsPayloads].flatMap((p) => p._hash));
65
+ const allPayloads = (await chainMap.get([...allPayloadsHashes])).map((p) => asAnyPayload(p, true));
66
+ const allPayloadsFiltered = allPayloads.filter((p) => allPayloadsHashes.has(p._hash));
67
+ if (maxDepth === 2) assertEx(allHashesPresent(
68
+ [...allPayloadsHashes],
69
+ allPayloadsFiltered
70
+ ), () => `Unable to find all payloads for transactions in block ${hash}`);
71
+ return [bw, allPayloadsFiltered];
72
+ };
73
+
74
+ // src/block/primitives/blockFromBlockNumber.ts
88
75
  import {
89
- AbstractCreatable,
90
- assertEx as assertEx3,
91
- IdLogger
76
+ asHash,
77
+ isDefined as isDefined2,
78
+ spanAsync
92
79
  } from "@xylabs/sdk-js";
80
+ import { toSafeJsonString } from "@xylabs/sdk-js";
81
+ import {
82
+ asSignedBlockBoundWitnessWithStorageMeta,
83
+ SignedBlockBoundWitnessWithHashMetaZod,
84
+ StepSizes
85
+ } from "@xyo-network/xl1-protocol-lib";
93
86
 
94
- // src/CreatableProvider/ProviderFactory.ts
95
- import { assertEx as assertEx2 } from "@xylabs/sdk-js";
96
- function providerFactoryDescription(factory, labels) {
97
- return `${factory.providerName}:${factory.defaultMoniker}:${JSON.stringify(labels ?? factory.labels ?? {})}`;
98
- }
99
- var ProviderFactory = class _ProviderFactory {
100
- creatableProvider;
101
- defaultMoniker;
102
- defaultParams;
103
- dependencies;
104
- labels;
105
- monikers;
106
- providerName;
107
- scope;
108
- _uniqueId;
109
- constructor(creatableProvider2, dependencies, params, labels = {}, scope = "context") {
110
- this.creatableProvider = creatableProvider2;
111
- this.defaultParams = params;
112
- this.defaultMoniker = creatableProvider2.defaultMoniker;
113
- this.dependencies = dependencies;
114
- this.monikers = creatableProvider2.monikers;
115
- this.scope = scope;
116
- assertEx2(this.monikers.includes(this.defaultMoniker), () => "defaultMoniker must be in monikers");
117
- this.labels = Object.assign({}, creatableProvider2.labels ?? {}, labels ?? {});
118
- this.providerName = creatableProvider2.name;
119
- this._uniqueId = Symbol(providerFactoryDescription(this));
120
- }
121
- get resolvedMoniker() {
122
- const labels = this.labels ?? {};
123
- const labelString = Object.entries(labels).map(([key, value]) => `${key}=${value}`).join(",");
124
- return labelString.length === 0 ? `${this.defaultMoniker}` : `${this.defaultMoniker}|${labelString}`;
125
- }
126
- get uniqueId() {
127
- return this._uniqueId;
87
+ // src/ChainContextHelpers.ts
88
+ import {
89
+ isDefined,
90
+ isObject,
91
+ isUndefined,
92
+ timeBudget
93
+ } from "@xylabs/sdk-js";
94
+ import { LruCacheMap, MemoryMap } from "@xyo-network/xl1-driver-memory";
95
+ function contextCache(context, name, create) {
96
+ if (!isObject(context.caches)) {
97
+ throw new Error("Context does not have an appropriate caches property");
128
98
  }
129
- static withParams(creatableProvider2, dependencies, params, labels = {}) {
130
- return new _ProviderFactory(creatableProvider2, dependencies, params, labels);
99
+ if (isUndefined(context.caches[name])) {
100
+ context.caches[name] = create?.() ?? new MemoryMap();
131
101
  }
132
- factory(dependencies, params, labels = {}) {
133
- return new _ProviderFactory(this.creatableProvider, dependencies, params, labels);
102
+ return context.caches[name];
103
+ }
104
+ async function withContextCacheResponse(context, name, key, func, { max = 1e4 } = {}) {
105
+ const cache = contextCache(
106
+ context,
107
+ name,
108
+ () => new LruCacheMap({ max })
109
+ );
110
+ const { timeBudgetLimit = 0 } = context;
111
+ const cacheResult = await cache.get(key);
112
+ if (isDefined(cacheResult)) {
113
+ return cacheResult;
134
114
  }
135
- async getInstance(params, { start = true }) {
136
- let scopeObject;
137
- switch (this.scope) {
138
- case "global": {
139
- globalThis.xyoServiceSingletons ??= {};
140
- scopeObject = globalThis.xyoServiceSingletons;
141
- break;
115
+ const result = timeBudgetLimit > 0 ? timeBudget(name, context.logger, func, timeBudgetLimit) : func();
116
+ await cache.set(key, result);
117
+ return result;
118
+ }
119
+
120
+ // src/block/primitives/blockFromBlockNumber.ts
121
+ async function blockFromBlockNumber(context, blockNumber) {
122
+ return await spanAsync("blockFromBlockNumber", async () => {
123
+ const cacheKey = `${blockNumber}`;
124
+ const { chainMap, head } = context;
125
+ return await withContextCacheResponse(context, "blockFromBlockNumber", cacheKey, async () => {
126
+ const [result] = await chainMap.get([head._hash]);
127
+ if (!isDefined2(result)) {
128
+ throw new Error(`Head block not found for hash: ${head._hash}`);
142
129
  }
143
- case "context": {
144
- const context = assertEx2(
145
- params?.context,
146
- () => "Context is required for context-scoped providers"
147
- );
148
- context.singletons ??= {};
149
- scopeObject = context.singletons;
150
- break;
130
+ let currentBlock = asSignedBlockBoundWitnessWithStorageMeta(
131
+ result,
132
+ () => `Found Payload is not a Signed<BlockBoundWitness>: ${JSON.stringify(result, null, 2)}`
133
+ );
134
+ if (currentBlock.block < blockNumber) {
135
+ throw new Error(`Block number ${blockNumber} is greater than head ${currentBlock.block}.`);
151
136
  }
152
- default: {
153
- scopeObject = {};
154
- break;
137
+ while (currentBlock.block > blockNumber) {
138
+ let jumpHash = currentBlock.previous;
139
+ let jumpBlockNumber = currentBlock.block - 1;
140
+ for (const [step, stepSize3] of StepSizes.entries()) {
141
+ const possibleJumpBlockNumber = currentBlock.block - currentBlock.block % stepSize3 - 1;
142
+ if (possibleJumpBlockNumber >= blockNumber && possibleJumpBlockNumber <= jumpBlockNumber) {
143
+ jumpBlockNumber = possibleJumpBlockNumber;
144
+ jumpHash = asHash(currentBlock.step_hashes?.at(step), () => `Step hash not found for step ${step} in block ${currentBlock.block}`);
145
+ }
146
+ }
147
+ const [newBlock] = await chainMap.get([
148
+ asHash(jumpHash, () => `Jump hash not found for block number [${blockNumber}]: ${jumpBlockNumber} ${toSafeJsonString(currentBlock, 10)}`)
149
+ ]);
150
+ if (!isDefined2(newBlock)) {
151
+ throw new Error(`Block not found for jump hash: ${jumpHash}`);
152
+ }
153
+ currentBlock = asSignedBlockBoundWitnessWithStorageMeta(
154
+ newBlock,
155
+ () => {
156
+ const result2 = SignedBlockBoundWitnessWithHashMetaZod.safeParse(newBlock);
157
+ return `Found Payload [jump hash] is not a Signed<BlockBoundWitness>: ${result2.error}`;
158
+ }
159
+ );
160
+ if (currentBlock.block === blockNumber) {
161
+ break;
162
+ }
163
+ if (currentBlock.block < blockNumber) {
164
+ throw new Error(`Block number ${blockNumber} is not a valid step block number for block ${head._hash}.`);
165
+ }
155
166
  }
167
+ return currentBlock;
168
+ });
169
+ }, { ...context, timeBudgetLimit: 500 });
170
+ }
171
+
172
+ // src/block/primitives/frames/calculateFramesFromRange.ts
173
+ import { asXL1BlockNumber, stepSize } from "@xyo-network/xl1-protocol-lib";
174
+ function calculateFramesFromRange(range, step) {
175
+ const size = stepSize(step);
176
+ let start = Math.trunc(range[0] / size) * size;
177
+ const fitted = [];
178
+ const remaining = [];
179
+ if (start !== range[0]) {
180
+ start += size;
181
+ remaining.push([range[0], asXL1BlockNumber(Math.min(start - 1, range[1]), true)]);
182
+ }
183
+ for (let i = start; i <= range[1]; i += size) {
184
+ if (i + size - 1 <= range[1]) {
185
+ fitted.push([
186
+ asXL1BlockNumber(i, { name: "calculateFramesFromRange A" }),
187
+ asXL1BlockNumber(Math.min(i + size - 1, range[1]), { name: "calculateFramesFromRange B" })
188
+ ]);
189
+ } else {
190
+ remaining.push([asXL1BlockNumber(i, { name: "calculateFramesFromRange C" }), range[1]]);
156
191
  }
157
- const mergedParams = {
158
- ...this.defaultParams,
159
- ...params
160
- };
161
- const resultPromise = scopeObject[this.resolvedMoniker] ?? this.creatableProvider.create(mergedParams);
162
- scopeObject[this.resolvedMoniker] = resultPromise;
163
- const result = await resultPromise;
164
- if (start) {
165
- assertEx2(await result.start(), () => `Failed to start provider instance [${this.resolvedMoniker}]`);
166
- }
167
- return result;
168
192
  }
169
- async tryGetInstance(params, options) {
170
- try {
171
- return await this.getInstance(params, options);
172
- } catch {
173
- return;
193
+ return [fitted, remaining];
194
+ }
195
+
196
+ // src/block/primitives/frames/deepCalculateFramesFromRange.ts
197
+ import { StepSizes as StepSizes2 } from "@xyo-network/xl1-protocol-lib";
198
+ function deepCalculateFramesFromRange(range, startingStep = StepSizes2.length - 1) {
199
+ const fitted = [];
200
+ let remaining = [range];
201
+ const actualStartingStep = Math.min(startingStep, StepSizes2.length - 1);
202
+ for (let step = actualStartingStep; step >= 0; step--) {
203
+ const newRemaining = [];
204
+ for (const range2 of remaining) {
205
+ const [newFittedFrames, newRemainingFrames] = calculateFramesFromRange(range2, step);
206
+ fitted.push(...newFittedFrames);
207
+ newRemaining.push(...newRemainingFrames);
174
208
  }
209
+ remaining = newRemaining;
175
210
  }
176
- };
177
-
178
- // src/CreatableProvider/AbstractCreatableProvider.ts
179
- var AbstractCreatableProvider = class extends AbstractCreatable {
180
- dependencies = {};
181
- _contextCache;
182
- _logger;
183
- get logger() {
184
- if (this._logger === void 0) {
185
- const providedLogger = this.params.logger ?? this.context.logger;
186
- this._logger = providedLogger ? new IdLogger(providedLogger, () => `${this.moniker} [${this.constructor.name}]`) : null;
211
+ for (const range2 of remaining) {
212
+ for (let i = range2[0]; i <= range2[1]; i++) {
213
+ fitted.push([i, i]);
187
214
  }
188
- return this._logger ?? void 0;
189
215
  }
190
- get meter() {
191
- return this.context.meterProvider?.getMeter(this.name) ?? super.meter;
216
+ return fitted.toSorted((a, b) => a[0] - b[0]);
217
+ }
218
+
219
+ // src/block/primitives/validateTransactionOpcodes.ts
220
+ import {
221
+ assertEx as assertEx2,
222
+ isHash,
223
+ toSafeJsonString as toSafeJsonString2
224
+ } from "@xylabs/sdk-js";
225
+ import {
226
+ PayloadBuilder
227
+ } from "@xyo-network/sdk-js";
228
+ import { isExecutable } from "@xyo-network/xl1-protocol-lib";
229
+ async function validateTransactionsOpcodes(txs) {
230
+ const txElevatedPayloads = [];
231
+ for (const [txBw, txPayloads] of txs) {
232
+ if (isExecutable(txBw)) {
233
+ const operations = txBw.script.map((op) => op.split("|"));
234
+ for (const [opCode, ...args] of operations) {
235
+ switch (opCode) {
236
+ case "elevate": {
237
+ const [hash, ...rest] = args;
238
+ const txPayloadsWithStorageMeta = await PayloadBuilder.addStorageMeta(txPayloads);
239
+ assertEx2(rest.length === 0, () => `Invalid elevate operation ${opCode} ${args.join(", ")} - Too many Arguments`);
240
+ if (isHash(hash)) {
241
+ assertEx2(
242
+ txBw.payload_hashes.includes(hash),
243
+ () => `Invalid elevate operation ${opCode} ${args.join(", ")} - Hash not in payload hashes => ${toSafeJsonString2(txBw, 20)}`
244
+ );
245
+ const txPayload = assertEx2(
246
+ txPayloadsWithStorageMeta.find((p) => p._hash === hash),
247
+ () => `Invalid elevate operation ${opCode} ${args.join(", ")} - Payload not found`
248
+ );
249
+ txElevatedPayloads.push(txPayload);
250
+ } else {
251
+ throw new Error(`Invalid elevate operation ${opCode} ${args.join(", ")} - Invalid hash`);
252
+ }
253
+ break;
254
+ }
255
+ default: {
256
+ throw new Error(`Invalid opCode ${opCode}`);
257
+ }
258
+ }
259
+ }
260
+ }
192
261
  }
193
- get tracer() {
194
- return this.context.traceProvider?.getTracer(this.name) ?? super.tracer;
262
+ return txElevatedPayloads;
263
+ }
264
+
265
+ // src/test/buildNextBlock.ts
266
+ import {
267
+ AttoXL1 as AttoXL12,
268
+ XYO_STEP_REWARD_ADDRESS as XYO_STEP_REWARD_ADDRESS2
269
+ } from "@xyo-network/xl1-protocol-lib";
270
+
271
+ // src/test/buildBlock.ts
272
+ import { assertEx as assertEx3, isDefined as isDefined3 } from "@xylabs/sdk-js";
273
+ import {
274
+ asAnyPayload as asAnyPayload2,
275
+ BoundWitnessBuilder,
276
+ PayloadBuilder as PayloadBuilder3
277
+ } from "@xyo-network/sdk-js";
278
+ import {
279
+ asXL1BlockNumber as asXL1BlockNumber2,
280
+ AttoXL1,
281
+ isBlockBoundWitness,
282
+ rewardAddressFromStepIdentity,
283
+ StepRewardFractions,
284
+ StepSizes as StepSizes3,
285
+ XL1_PROTOCOL_VERSION,
286
+ XYO_STEP_REWARD_ADDRESS,
287
+ XYO_ZERO_ADDRESS
288
+ } from "@xyo-network/xl1-protocol-lib";
289
+
290
+ // src/createTransferPayload.ts
291
+ import { toHex } from "@xylabs/sdk-js";
292
+ import { PayloadBuilder as PayloadBuilder2 } from "@xyo-network/sdk-js";
293
+ import { TransferSchema } from "@xyo-network/xl1-protocol-lib";
294
+ function createTransferPayload(from, transfers, context) {
295
+ return new PayloadBuilder2({ schema: TransferSchema }).fields({
296
+ epoch: Date.now(),
297
+ from,
298
+ transfers: Object.fromEntries(Object.entries(transfers).map(([k, v]) => [k, toHex(v)])),
299
+ context
300
+ }).build();
301
+ }
302
+
303
+ // src/test/BuildBlockOptions.ts
304
+ import {
305
+ isAddress,
306
+ isArray,
307
+ isHash as isHash2,
308
+ isNumber,
309
+ isObject as isObject2
310
+ } from "@xylabs/sdk-js";
311
+ var isBaseBuildBlockOptions = (value) => {
312
+ if (!isObject2(value)) {
313
+ return false;
195
314
  }
196
- get config() {
197
- return this.context.config;
315
+ const typedValue = value;
316
+ if (!isArray(typedValue.blockPayloads) || !isAddress(typedValue.chainId) || !isArray(typedValue.signers) || !isArray(typedValue.txs)) {
317
+ return false;
198
318
  }
199
- get context() {
200
- return this.params.context;
319
+ return true;
320
+ };
321
+ var isBuildGenesisBlockOptions = (value) => {
322
+ if (!isBaseBuildBlockOptions(value)) {
323
+ return false;
201
324
  }
202
- get locator() {
203
- return this.context.locator;
325
+ const typedValue = value;
326
+ if (typedValue.previousBlockHash !== null) {
327
+ return false;
204
328
  }
205
- static factory(dependencies, params) {
206
- const factory = ProviderFactory.withParams(this, dependencies, params);
207
- return factory;
329
+ if (typedValue.previousBlockNumber !== void 0) {
330
+ return false;
208
331
  }
209
- static async paramsHandler(params = {}) {
210
- const context = assertEx3(params.context, () => new Error("Context is required"));
211
- const config = assertEx3(context.config, () => new Error("Context config is required"));
212
- const locator = assertEx3(context.locator, () => new Error("Context locator is required"));
213
- return await super.paramsHandler({
214
- ...params,
215
- statusReporter: params.statusReporter ?? context.statusReporter,
216
- context: {
217
- ...context,
218
- config,
219
- locator
220
- },
221
- name: params.name ?? this.defaultMoniker,
222
- logger: params.logger ?? context.logger
223
- });
332
+ return true;
333
+ };
334
+ var isBuildNextBlockOptions = (value) => {
335
+ if (!isBaseBuildBlockOptions(value)) {
336
+ return false;
224
337
  }
225
- async createHandler() {
226
- await super.createHandler();
227
- if (this.tracer === void 0) {
228
- this.logger?.warn("No tracer available in context");
229
- }
230
- if (this.meter === void 0) {
231
- this.logger?.warn("No meter available in context");
232
- }
338
+ const typedValue = value;
339
+ if (!isHash2(typedValue.previousBlockHash)) {
340
+ return false;
233
341
  }
234
- async locateAndCreate(moniker) {
235
- return await this.locator.getInstance(moniker);
342
+ if (!isNumber(typedValue.previousBlockNumber)) {
343
+ return false;
236
344
  }
237
- async tryLocateAndCreate(moniker) {
238
- return await this.locator.tryGetInstance(moniker);
345
+ if (!isArray(typedValue.previousStepHashes)) {
346
+ return false;
239
347
  }
348
+ return true;
240
349
  };
241
350
 
242
- // src/CreatableProvider/CreatableProvider.ts
243
- function creatableProvider() {
244
- return (constructor) => {
245
- constructor;
246
- };
351
+ // src/test/buildBlock.ts
352
+ function calculateCompletedStepReward(step, balance) {
353
+ return AttoXL1(StepRewardFractions[step][0] * balance / StepRewardFractions[step][1]);
247
354
  }
248
-
249
- // src/CreatableProvider/CreatableProviderRegistry.ts
250
- import { isTruthy } from "@xylabs/sdk-js";
251
- var buildProviderFactory = (provider, defaultParams, labels) => {
252
- const factory = {
253
- monikers: provider.monikers,
254
- uniqueId: Symbol(providerFactoryDescription(provider, labels)),
255
- // Merge module & supplied labels
256
- labels: { ...provider.labels, ...labels },
257
- creatableProvider: provider.creatableProvider,
258
- dependencies: provider.dependencies,
259
- resolvedMoniker: provider.resolvedMoniker,
260
- providerName: provider.providerName,
261
- scope: provider.scope,
262
- defaultParams,
263
- getInstance: provider.getInstance.bind(provider),
264
- tryGetInstance: provider.tryGetInstance?.bind(provider),
265
- defaultMoniker: provider.defaultMoniker,
266
- factory: provider.factory.bind(provider)
267
- };
268
- return factory;
269
- };
270
- var registerCreatableProviderFactory = (registry, factory, labels, primary = false) => {
271
- const primaryMonikers = primary !== true && isTruthy(primary) ? Array.isArray(primary) ? primary : [primary] : [];
272
- for (const primaryMoniker of primaryMonikers) {
273
- if (!factory.monikers.includes(primaryMoniker)) {
274
- throw new Error(`Primary moniker ${String(primaryMoniker)} not found in factory monikers`);
355
+ async function buildBlock(options) {
356
+ const previousBlockNumber = isBuildGenesisBlockOptions(options) ? -1 : options.previousBlockNumber;
357
+ const blockNumber = asXL1BlockNumber2(previousBlockNumber + 1, true);
358
+ const inStepHashes = isBuildNextBlockOptions(options) ? options.previousStepHashes : [];
359
+ const previousBlockHash = isBuildNextBlockOptions(options) ? options.previousBlockHash : void 0;
360
+ const stepRewardPoolBalance = isBuildNextBlockOptions(options) ? options.stepRewardPoolBalance : AttoXL1(0n);
361
+ const {
362
+ chainId,
363
+ txs,
364
+ chainStepRewardAddress = XYO_STEP_REWARD_ADDRESS,
365
+ blockPayloads,
366
+ protocol = XL1_PROTOCOL_VERSION,
367
+ signers
368
+ } = options;
369
+ const step_hashes = [];
370
+ for (const [tx] of txs) {
371
+ if (tx.nbf > blockNumber) {
372
+ throw new Error(`Transaction ${await PayloadBuilder3.hash(tx)} not valid for block ${blockNumber} - NBF is ${tx.nbf}`);
373
+ }
374
+ if (tx.exp < blockNumber) {
375
+ throw new Error(`Transaction ${await PayloadBuilder3.hash(tx)} not valid for block ${blockNumber} - EXP is ${tx.exp}`);
275
376
  }
276
377
  }
277
- const isPrimaryForMoniker = (moniker) => {
278
- switch (typeof primary) {
279
- case "boolean": {
280
- return primary;
281
- }
282
- case "string": {
283
- return moniker === primary;
378
+ const completedStepRewardTransfers = [];
379
+ for (const [i, step] of StepSizes3.entries()) {
380
+ if (blockNumber < step) {
381
+ break;
382
+ }
383
+ if (blockNumber % step === 0) {
384
+ if (StepRewardFractions[i][0] > 0 && chainStepRewardAddress !== XYO_ZERO_ADDRESS) {
385
+ const completedStepRewardHolderAddress = rewardAddressFromStepIdentity({ block: blockNumber, step });
386
+ const completedStepReward = calculateCompletedStepReward(i, stepRewardPoolBalance);
387
+ completedStepRewardTransfers.push(createTransferPayload(chainStepRewardAddress, { [completedStepRewardHolderAddress]: completedStepReward }));
284
388
  }
285
- case "object": {
286
- if (Array.isArray(primary)) {
287
- return primary.includes(moniker);
288
- }
389
+ step_hashes.push(assertEx3(previousBlockHash, () => `Previous block hash is required for step ${step} at block ${blockNumber}`));
390
+ } else {
391
+ if (isDefined3(inStepHashes.at(i))) {
392
+ step_hashes.push(inStepHashes[i]);
289
393
  }
290
394
  }
291
- throw new Error(`Invalid primary value: ${String(primary)}`);
292
- };
395
+ }
396
+ const previous = previousBlockHash ?? null;
397
+ const block = blockNumber;
398
+ const txElevatedPayloads = await validateTransactionsOpcodes(txs);
399
+ const payloads = [
400
+ ...txs.map(([tx]) => tx),
401
+ ...blockPayloads,
402
+ ...txElevatedPayloads,
403
+ ...completedStepRewardTransfers
404
+ ];
405
+ const [bw, txPayloads] = await new BoundWitnessBuilder().fields({
406
+ block,
407
+ chain: chainId,
408
+ previous,
409
+ step_hashes,
410
+ protocol
411
+ }).meta({ $epoch: Date.now(), $signatures: [] }).signers(signers).payloads(await PayloadBuilder3.addStorageMeta(payloads)).build();
412
+ assertEx3(isBlockBoundWitness(bw), () => "Build of BlockBoundWitness failed");
413
+ return [await PayloadBuilder3.addStorageMeta(bw), txPayloads.map((p) => asAnyPayload2(p, true))];
414
+ }
415
+
416
+ // src/test/buildNextBlock.ts
417
+ async function buildNextBlock(previousBlock, txs, blockPayloads, signers, chainStepRewardAddress = XYO_STEP_REWARD_ADDRESS2, stepRewardPoolBalance = AttoXL12(0n), protocol, chainId) {
418
+ return await buildBlock({
419
+ chainId: chainId ?? previousBlock.chain,
420
+ previousBlockNumber: previousBlock.block,
421
+ previousStepHashes: previousBlock.step_hashes ?? [],
422
+ previousBlockHash: previousBlock._hash,
423
+ txs,
424
+ blockPayloads,
425
+ signers,
426
+ protocol,
427
+ chainStepRewardAddress,
428
+ stepRewardPoolBalance
429
+ });
430
+ }
431
+
432
+ // src/test/buildRandomGenesisBlock.ts
433
+ import { asAddress, assertEx as assertEx5 } from "@xylabs/sdk-js";
434
+ import {
435
+ Account as Account2,
436
+ asAnyPayload as asAnyPayload4,
437
+ asSchema,
438
+ IdSchema,
439
+ PayloadBuilder as PayloadBuilder5
440
+ } from "@xyo-network/sdk-js";
441
+ import {
442
+ asXL1BlockNumber as asXL1BlockNumber4
443
+ } from "@xyo-network/xl1-protocol-lib";
444
+
445
+ // src/test/buildGenesisBlock.ts
446
+ import { XYO_ZERO_ADDRESS as XYO_ZERO_ADDRESS2 } from "@xyo-network/xl1-protocol-lib";
447
+ async function buildGenesisBlock(chainId, txs, blockPayloads, signers, chainStepRewardAddress = XYO_ZERO_ADDRESS2, protocol) {
448
+ return await buildBlock({
449
+ previousBlockHash: null,
450
+ chainId,
451
+ txs,
452
+ blockPayloads,
453
+ signers,
454
+ chainStepRewardAddress,
455
+ protocol
456
+ });
457
+ }
458
+
459
+ // src/test/buildRandomTransaction.ts
460
+ import { Account } from "@xyo-network/sdk-js";
461
+ import { asXL1BlockNumber as asXL1BlockNumber3, isAllowedBlockPayload } from "@xyo-network/xl1-protocol-lib";
462
+
463
+ // src/transaction/buildTransaction.ts
464
+ import { assertEx as assertEx4, toHex as toHex2 } from "@xylabs/sdk-js";
465
+ import {
466
+ asAnyPayload as asAnyPayload3,
467
+ BoundWitnessBuilder as BoundWitnessBuilder2,
468
+ PayloadBuilder as PayloadBuilder4
469
+ } from "@xyo-network/sdk-js";
470
+ import { defaultTransactionFees } from "@xyo-network/xl1-protocol-lib";
471
+ async function buildTransaction(chain, onChainPayloads, offChainPayloads, signer, nbf, exp, from, fees = defaultTransactionFees) {
472
+ if (from === void 0 && Array.isArray(signer)) {
473
+ throw new Error("from is required when signer is an array");
474
+ }
475
+ const txBoundWitnessFields = {
476
+ chain,
477
+ fees: {
478
+ base: toHex2(fees.base),
479
+ gasLimit: toHex2(fees.gasLimit),
480
+ gasPrice: toHex2(fees.gasPrice),
481
+ priority: toHex2(fees.priority)
482
+ },
483
+ nbf,
484
+ exp
485
+ };
486
+ const elevatedHashes = await PayloadBuilder4.hashes(onChainPayloads);
487
+ const script = [];
488
+ for (const elevatedHash of elevatedHashes) {
489
+ script.push(`elevate|${elevatedHash}`);
490
+ }
491
+ const fields = {
492
+ ...txBoundWitnessFields,
493
+ from: from ?? (Array.isArray(signer) ? assertEx4(signer.at(0)?.address) : signer.address)
494
+ };
495
+ if (script.length > 0) {
496
+ fields.script = script;
497
+ }
498
+ const [tx, txPayloads] = await new BoundWitnessBuilder2().fields(fields).meta({ $signatures: [] }).payloads([...onChainPayloads, ...offChainPayloads]).signers(Array.isArray(signer) ? signer : [signer]).build();
499
+ return [await PayloadBuilder4.addHashMeta(tx), await PayloadBuilder4.addHashMeta(txPayloads.map((p) => asAnyPayload3(p, true)))];
500
+ }
501
+
502
+ // src/test/buildRandomTransaction.ts
503
+ var buildRandomTransaction = async (chain, payloads, account, nbf = asXL1BlockNumber3(0, true), exp = asXL1BlockNumber3(nbf + 1e3, true), privatePayloadSchemas = [], receiverAddress) => {
504
+ const elevatedPayloads = (payloads ?? []).filter(isAllowedBlockPayload);
505
+ const additionalPayloads = (payloads ?? []).filter((payload) => !isAllowedBlockPayload(payload));
506
+ const sender = account ?? await Account.random();
507
+ if (elevatedPayloads.length === 0) {
508
+ const receiver = receiverAddress ?? (await Account.random()).address;
509
+ const transferPayload = createTransferPayload(sender.address, { [receiver]: 1n });
510
+ elevatedPayloads.push(transferPayload);
511
+ }
512
+ const hydratedTransaction = await buildTransaction(chain, elevatedPayloads, additionalPayloads, sender, nbf, exp);
513
+ return [hydratedTransaction[0], hydratedTransaction[1].filter((payload) => !privatePayloadSchemas.includes(payload.schema))];
514
+ };
515
+
516
+ // src/test/buildRandomGenesisBlock.ts
517
+ var TestChainId = assertEx5(asAddress("c5fe2e6F6841Cbab12d8C0618Be2DF8C6156cC44"));
518
+
519
+ // src/test/createGenesisBlock.ts
520
+ import { PayloadBuilder as PayloadBuilder7 } from "@xyo-network/sdk-js";
521
+ import {
522
+ BlockBoundWitnessSchemaPayload,
523
+ BlockBoundWitnessWithStorageMetaSchemaPayload,
524
+ ChainStakeIntentPayloadJsonSchemaPayload,
525
+ HashPayloadJsonSchemaPayload,
526
+ TransactionBoundWitnessSchemaPayload,
527
+ TransactionBoundWitnessWithStorageMetaSchemaPayload,
528
+ TransferPayloadJsonSchemaPayload
529
+ } from "@xyo-network/xl1-schema";
530
+
531
+ // src/test/createProducerChainStakeIntentTransaction.ts
532
+ import { PayloadBuilder as PayloadBuilder6 } from "@xyo-network/sdk-js";
533
+ import {
534
+ asXL1BlockNumber as asXL1BlockNumber5,
535
+ ChainStakeIntentSchema,
536
+ defaultTransactionFees as defaultTransactionFees2
537
+ } from "@xyo-network/xl1-protocol-lib";
538
+ async function createProducerChainStakeIntent(from, exp, nbf = 0) {
539
+ return await PayloadBuilder6.addHashMeta(new PayloadBuilder6({ schema: ChainStakeIntentSchema }).fields({
540
+ from,
541
+ exp,
542
+ nbf,
543
+ intent: "producer"
544
+ }).build());
545
+ }
546
+
547
+ // src/test/createGenesisBlock.ts
548
+ var createGenesisBlock = async (initialBlockProducer, nextContractAddress, genesisBlockRewardAmount, genesisBlockRewardAddress) => {
549
+ const blockPayloads = await PayloadBuilder7.addHashMeta([
550
+ TransferPayloadJsonSchemaPayload,
551
+ BlockBoundWitnessSchemaPayload,
552
+ BlockBoundWitnessWithStorageMetaSchemaPayload,
553
+ TransactionBoundWitnessSchemaPayload,
554
+ TransactionBoundWitnessWithStorageMetaSchemaPayload,
555
+ ChainStakeIntentPayloadJsonSchemaPayload,
556
+ HashPayloadJsonSchemaPayload
557
+ ]);
558
+ const intentPayload = await createProducerChainStakeIntent(initialBlockProducer.address, 1, 0);
559
+ blockPayloads.push(intentPayload);
560
+ if (genesisBlockRewardAmount > 0n) {
561
+ blockPayloads.push(await PayloadBuilder7.addHashMeta(createTransferPayload(
562
+ nextContractAddress,
563
+ { [genesisBlockRewardAddress]: genesisBlockRewardAmount }
564
+ )));
565
+ }
566
+ return await buildGenesisBlock(nextContractAddress, [], blockPayloads, [initialBlockProducer]);
567
+ };
568
+
569
+ // src/test/buildRandomChain.ts
570
+ var TestGenesisBlockRewardAddress = assertEx6(asAddress2("fa7f0bb865a4bfff3d5e2c726d3e063297014da9"));
571
+ var buildRandomChain = async (blockProducer, count = 10, previousBlock, chainId, transactionAccount, receiverAddresses) => {
572
+ const chainIdToUse = chainId ?? TestChainId;
573
+ const blocks = [];
574
+ let remaining = count;
575
+ let lastBlock = previousBlock;
576
+ const transactionAccountToUse = transactionAccount ?? await Account3.random();
577
+ if (!lastBlock) {
578
+ const block = await createGenesisBlock(
579
+ blockProducer,
580
+ chainIdToUse,
581
+ 1000000000n * 10n ** 18n,
582
+ transactionAccountToUse.address
583
+ );
584
+ blocks.push(block);
585
+ remaining = remaining - 1;
586
+ lastBlock = block;
587
+ }
588
+ const resolvedReceiverAddresses = receiverAddresses ?? [(await Account3.random()).address];
589
+ let saltCounter = 0;
590
+ while (remaining > 0) {
591
+ saltCounter += 1;
592
+ const payloads = [new PayloadBuilder8({ schema: IdSchema2 }).fields({ salt: `${Date.now()}-${saltCounter}` }).build()];
593
+ saltCounter += 1;
594
+ const additionalPrivatePayloads = remaining % 2 === 0 ? [new PayloadBuilder8({ schema: asSchema2("network.xyo.private", true) }).fields({ salt: `${Date.now()}-${saltCounter}` }).build()] : [];
595
+ const txs = [];
596
+ for (const receiverAddress of resolvedReceiverAddresses) {
597
+ txs.push(await buildRandomTransaction(
598
+ chainIdToUse,
599
+ [...payloads, ...additionalPrivatePayloads],
600
+ transactionAccountToUse,
601
+ asXL1BlockNumber6(Math.max(count - remaining - 1e3, 0), true),
602
+ asXL1BlockNumber6(count - remaining + 1e3, true),
603
+ [asSchema2("network.xyo.private", true)],
604
+ receiverAddress
605
+ ));
606
+ }
607
+ const previousBlock2 = assertEx6(lastBlock?.[0], () => new Error("No last block"));
608
+ const block = await buildNextBlock(previousBlock2, txs, [], [blockProducer], transactionAccountToUse.address);
609
+ blocks.push(block);
610
+ remaining = remaining - 1;
611
+ lastBlock = block;
612
+ }
613
+ return blocks;
614
+ };
615
+ async function buildRandomChainArchivist(count = 20) {
616
+ const producerAccount = await Account3.random();
617
+ const blocks = await buildRandomChain(producerAccount, count);
618
+ const archivist = await MemoryArchivist.create();
619
+ const payloads = flattenHydratedBlocks(blocks);
620
+ await archivist.insert(payloads);
621
+ return archivist;
622
+ }
623
+
624
+ // src/test/getSimpleBlockViewerLocator.ts
625
+ import { XYO_ZERO_ADDRESS as XYO_ZERO_ADDRESS3 } from "@xyo-network/xl1-protocol-lib";
626
+
627
+ // src/CreatableProvider/AbstractCreatableProvider.ts
628
+ import {
629
+ AbstractCreatable,
630
+ assertEx as assertEx8,
631
+ IdLogger
632
+ } from "@xylabs/sdk-js";
633
+
634
+ // src/CreatableProvider/ProviderFactory.ts
635
+ import { assertEx as assertEx7 } from "@xylabs/sdk-js";
636
+ function providerFactoryDescription(factory, labels) {
637
+ return `${factory.providerName}:${factory.defaultMoniker}:${JSON.stringify(labels ?? factory.labels ?? {})}`;
638
+ }
639
+ var ProviderFactory = class _ProviderFactory {
640
+ creatableProvider;
641
+ defaultMoniker;
642
+ defaultParams;
643
+ dependencies;
644
+ labels;
645
+ monikers;
646
+ providerName;
647
+ scope;
648
+ _uniqueId;
649
+ constructor(creatableProvider2, dependencies, params, labels = {}, scope = "context") {
650
+ this.creatableProvider = creatableProvider2;
651
+ this.defaultParams = params;
652
+ this.defaultMoniker = creatableProvider2.defaultMoniker;
653
+ this.dependencies = dependencies;
654
+ this.monikers = creatableProvider2.monikers;
655
+ this.scope = scope;
656
+ assertEx7(this.monikers.includes(this.defaultMoniker), () => "defaultMoniker must be in monikers");
657
+ this.labels = Object.assign({}, creatableProvider2.labels ?? {}, labels ?? {});
658
+ this.providerName = creatableProvider2.name;
659
+ this._uniqueId = Symbol(providerFactoryDescription(this));
660
+ }
661
+ get resolvedMoniker() {
662
+ const labels = this.labels ?? {};
663
+ const labelString = Object.entries(labels).map(([key, value]) => `${key}=${value}`).join(",");
664
+ return labelString.length === 0 ? `${this.defaultMoniker}` : `${this.defaultMoniker}|${labelString}`;
665
+ }
666
+ get uniqueId() {
667
+ return this._uniqueId;
668
+ }
669
+ static withParams(creatableProvider2, dependencies, params, labels = {}) {
670
+ return new _ProviderFactory(creatableProvider2, dependencies, params, labels);
671
+ }
672
+ factory(dependencies, params, labels = {}) {
673
+ return new _ProviderFactory(this.creatableProvider, dependencies, params, labels);
674
+ }
675
+ async getInstance(params, { start = true }) {
676
+ let scopeObject;
677
+ switch (this.scope) {
678
+ case "global": {
679
+ globalThis.xyoServiceSingletons ??= {};
680
+ scopeObject = globalThis.xyoServiceSingletons;
681
+ break;
682
+ }
683
+ case "context": {
684
+ const context = assertEx7(
685
+ params?.context,
686
+ () => "Context is required for context-scoped providers"
687
+ );
688
+ context.singletons ??= {};
689
+ scopeObject = context.singletons;
690
+ break;
691
+ }
692
+ default: {
693
+ scopeObject = {};
694
+ break;
695
+ }
696
+ }
697
+ const mergedParams = {
698
+ ...this.defaultParams,
699
+ ...params
700
+ };
701
+ const resultPromise = scopeObject[this.resolvedMoniker] ?? this.creatableProvider.create(mergedParams);
702
+ scopeObject[this.resolvedMoniker] = resultPromise;
703
+ const result = await resultPromise;
704
+ if (start) {
705
+ assertEx7(await result.start(), () => `Failed to start provider instance [${this.resolvedMoniker}]`);
706
+ }
707
+ return result;
708
+ }
709
+ async tryGetInstance(params, options) {
710
+ try {
711
+ return await this.getInstance(params, options);
712
+ } catch {
713
+ return;
714
+ }
715
+ }
716
+ };
717
+
718
+ // src/CreatableProvider/AbstractCreatableProvider.ts
719
+ var AbstractCreatableProvider = class extends AbstractCreatable {
720
+ dependencies = {};
721
+ _contextCache;
722
+ _logger;
723
+ get logger() {
724
+ if (this._logger === void 0) {
725
+ const providedLogger = this.params.logger ?? this.context.logger;
726
+ this._logger = providedLogger ? new IdLogger(providedLogger, () => `${this.moniker} [${this.constructor.name}]`) : null;
727
+ }
728
+ return this._logger ?? void 0;
729
+ }
730
+ get meter() {
731
+ return this.context.meterProvider?.getMeter(this.name) ?? super.meter;
732
+ }
733
+ get tracer() {
734
+ return this.context.traceProvider?.getTracer(this.name) ?? super.tracer;
735
+ }
736
+ get config() {
737
+ return this.context.config;
738
+ }
739
+ get context() {
740
+ return this.params.context;
741
+ }
742
+ get locator() {
743
+ return this.context.locator;
744
+ }
745
+ static factory(dependencies, params) {
746
+ const factory = ProviderFactory.withParams(this, dependencies, params);
747
+ return factory;
748
+ }
749
+ static async paramsHandler(params = {}) {
750
+ const context = assertEx8(params.context, () => new Error("Context is required"));
751
+ const config = assertEx8(context.config, () => new Error("Context config is required"));
752
+ const locator = assertEx8(context.locator, () => new Error("Context locator is required"));
753
+ return await super.paramsHandler({
754
+ ...params,
755
+ statusReporter: params.statusReporter ?? context.statusReporter,
756
+ context: {
757
+ ...context,
758
+ config,
759
+ locator
760
+ },
761
+ name: params.name ?? this.defaultMoniker,
762
+ logger: params.logger ?? context.logger
763
+ });
764
+ }
765
+ async createHandler() {
766
+ await super.createHandler();
767
+ if (this.tracer === void 0) {
768
+ this.logger?.warn("No tracer available in context");
769
+ }
770
+ if (this.meter === void 0) {
771
+ this.logger?.warn("No meter available in context");
772
+ }
773
+ }
774
+ async locateAndCreate(moniker) {
775
+ return await this.locator.getInstance(moniker);
776
+ }
777
+ async tryLocateAndCreate(moniker) {
778
+ return await this.locator.tryGetInstance(moniker);
779
+ }
780
+ };
781
+
782
+ // src/CreatableProvider/CreatableProvider.ts
783
+ function creatableProvider() {
784
+ return (constructor) => {
785
+ constructor;
786
+ };
787
+ }
788
+
789
+ // src/CreatableProvider/CreatableProviderRegistry.ts
790
+ import { isTruthy } from "@xylabs/sdk-js";
791
+ var buildProviderFactory = (provider, defaultParams, labels) => {
792
+ const factory = {
793
+ monikers: provider.monikers,
794
+ uniqueId: Symbol(providerFactoryDescription(provider, labels)),
795
+ // Merge module & supplied labels
796
+ labels: { ...provider.labels, ...labels },
797
+ creatableProvider: provider.creatableProvider,
798
+ dependencies: provider.dependencies,
799
+ resolvedMoniker: provider.resolvedMoniker,
800
+ providerName: provider.providerName,
801
+ scope: provider.scope,
802
+ defaultParams,
803
+ getInstance: provider.getInstance.bind(provider),
804
+ tryGetInstance: provider.tryGetInstance?.bind(provider),
805
+ defaultMoniker: provider.defaultMoniker,
806
+ factory: provider.factory.bind(provider)
807
+ };
808
+ return factory;
809
+ };
810
+ var registerCreatableProviderFactory = (registry, factory, labels, primary = false) => {
811
+ const primaryMonikers = primary !== true && isTruthy(primary) ? Array.isArray(primary) ? primary : [primary] : [];
812
+ for (const primaryMoniker of primaryMonikers) {
813
+ if (!factory.monikers.includes(primaryMoniker)) {
814
+ throw new Error(`Primary moniker ${String(primaryMoniker)} not found in factory monikers`);
815
+ }
816
+ }
817
+ const isPrimaryForMoniker = (moniker) => {
818
+ switch (typeof primary) {
819
+ case "boolean": {
820
+ return primary;
821
+ }
822
+ case "string": {
823
+ return moniker === primary;
824
+ }
825
+ case "object": {
826
+ if (Array.isArray(primary)) {
827
+ return primary.includes(moniker);
828
+ }
829
+ }
830
+ }
831
+ throw new Error(`Invalid primary value: ${String(primary)}`);
832
+ };
293
833
  const factoryClone = buildProviderFactory(factory, factory.defaultParams, labels);
294
834
  registry[factoryClone.defaultMoniker] = [factoryClone, ...registry[factoryClone.defaultMoniker] ?? []];
295
835
  for (const moniker of factoryClone.monikers) {
@@ -305,7 +845,7 @@ var hasLabels = (factory) => {
305
845
 
306
846
  // src/CreatableProvider/ProviderFactoryLocator.ts
307
847
  import { hasAllLabels } from "@xylabs/sdk-js";
308
- import { assertEx as assertEx4 } from "@xylabs/sdk-js";
848
+ import { assertEx as assertEx9 } from "@xylabs/sdk-js";
309
849
  var ProviderFactoryLocator = class _ProviderFactoryLocator {
310
850
  _context;
311
851
  _registry;
@@ -337,7 +877,7 @@ var ProviderFactoryLocator = class _ProviderFactoryLocator {
337
877
  this._frozen = true;
338
878
  }
339
879
  async getInstance(moniker, { start = true, labels } = {}) {
340
- return assertEx4(
880
+ return assertEx9(
341
881
  await this.tryGetInstance(moniker, { start, labels }),
342
882
  () => `No provider instance for the supplied config moniker [${moniker}]${labels ? ` & labels [${JSON.stringify(labels)}]` : ""} could be created`
343
883
  );
@@ -352,7 +892,7 @@ var ProviderFactoryLocator = class _ProviderFactoryLocator {
352
892
  * @returns A provider factory that matches the supplied moniker and labels or throws if one is not found
353
893
  */
354
894
  locate(moniker, labels) {
355
- return assertEx4(
895
+ return assertEx9(
356
896
  this.tryLocate(moniker, labels),
357
897
  () => `No module factory for the supplied config moniker [${moniker}]${labels ? ` & labels [${JSON.stringify(labels)}]` : ""} registered`
358
898
  );
@@ -374,10 +914,10 @@ var ProviderFactoryLocator = class _ProviderFactoryLocator {
374
914
  * @param labels The labels for the module factory
375
915
  */
376
916
  register(factory, labels, primary = false) {
377
- assertEx4(!this._frozen, () => "Cannot register a module factory after the locator has been frozen");
917
+ assertEx9(!this._frozen, () => "Cannot register a module factory after the locator has been frozen");
378
918
  if (this.validateDepsOnRegister) {
379
919
  const missingDeps = factory.dependencies.filter((dep) => !this.registered(dep));
380
- assertEx4(missingDeps.length === 0, () => `Cannot register module factory [${factory.uniqueId.description}] due to missing dependencies: ${missingDeps.join(", ")}`);
920
+ assertEx9(missingDeps.length === 0, () => `Cannot register module factory [${factory.uniqueId.description}] due to missing dependencies: ${missingDeps.join(", ")}`);
381
921
  }
382
922
  registerCreatableProviderFactory(this._registry, factory, labels, primary);
383
923
  return this;
@@ -425,7 +965,7 @@ var ProviderFactoryLocator = class _ProviderFactoryLocator {
425
965
  for (const moniker in this.registry) {
426
966
  for (const factory of this.registry[moniker] ?? []) {
427
967
  const missingDeps = factory.dependencies.filter((dep) => !this.registered(dep));
428
- assertEx4(missingDeps.length === 0, () => `Module factory [${factory.uniqueId.description}] is missing dependencies: ${missingDeps.join(", ")}`);
968
+ assertEx9(missingDeps.length === 0, () => `Module factory [${factory.uniqueId.description}] is missing dependencies: ${missingDeps.join(", ")}`);
429
969
  }
430
970
  }
431
971
  }
@@ -450,10 +990,10 @@ import {
450
990
  zodIsFactory as zodIsFactory2,
451
991
  zodToFactory as zodToFactory2
452
992
  } from "@xylabs/sdk-js";
453
- import { globalRegistry as globalRegistry12, z as z16 } from "zod/mini";
993
+ import { globalRegistry as globalRegistry13, z as z17 } from "zod/mini";
454
994
 
455
995
  // src/config/Base.ts
456
- import { z as z15 } from "zod/mini";
996
+ import { z as z16 } from "zod/mini";
457
997
 
458
998
  // src/config/Chain.ts
459
999
  import { HexZod } from "@xylabs/sdk-js";
@@ -623,7 +1163,7 @@ var RpcRemoteConfigZod = z10.union([HttpRpcRemoteConfigZod, PostMessageRpcRemote
623
1163
  var RemoteConfigZod = z10.object({ rpc: RpcRemoteConfigZod.optional() }).describe("Configuration for remote connections, including RPC");
624
1164
 
625
1165
  // src/config/storage/driver/Mongo.ts
626
- import { isDefined, isUndefined } from "@xylabs/sdk-js";
1166
+ import { isDefined as isDefined4, isUndefined as isUndefined2 } from "@xylabs/sdk-js";
627
1167
  import { globalRegistry as globalRegistry8, z as z11 } from "zod";
628
1168
  var MongoConfigZod = z11.object({
629
1169
  // TODO: Create from other arguments
@@ -654,11 +1194,43 @@ var MongoConfigZod = z11.object({
654
1194
  })
655
1195
  });
656
1196
 
657
- // src/config/storage/Storage.ts
1197
+ // src/config/storage/driver/R2.ts
1198
+ import { isDefined as isDefined5, isUndefined as isUndefined3 } from "@xylabs/sdk-js";
658
1199
  import { globalRegistry as globalRegistry9, z as z12 } from "zod";
659
- var StorageConfigZod = z12.object({
1200
+ var R2ConfigZod = z12.object({
1201
+ accessKeyId: z12.string().nonempty().optional().register(globalRegistry9, {
1202
+ description: "Cloudflare R2 access key id (from an R2 API token)",
1203
+ title: "storage.r2.accessKeyId",
1204
+ type: "string"
1205
+ }),
1206
+ accountId: z12.string().nonempty().optional().register(globalRegistry9, {
1207
+ description: "Cloudflare account id; determines the R2 endpoint https://<accountId>.r2.cloudflarestorage.com",
1208
+ title: "storage.r2.accountId",
1209
+ type: "string"
1210
+ }),
1211
+ bucket: z12.string().nonempty().optional().register(globalRegistry9, {
1212
+ description: "Cloudflare R2 bucket name",
1213
+ title: "storage.r2.bucket",
1214
+ type: "string"
1215
+ }),
1216
+ prefix: z12.string().nonempty().optional().register(globalRegistry9, {
1217
+ description: "Optional key prefix namespacing this store within the bucket",
1218
+ title: "storage.r2.prefix",
1219
+ type: "string"
1220
+ }),
1221
+ secretAccessKey: z12.string().nonempty().optional().register(globalRegistry9, {
1222
+ description: "Cloudflare R2 secret access key (from an R2 API token)",
1223
+ title: "storage.r2.secretAccessKey",
1224
+ type: "string"
1225
+ })
1226
+ });
1227
+
1228
+ // src/config/storage/Storage.ts
1229
+ import { globalRegistry as globalRegistry10, z as z13 } from "zod";
1230
+ var StorageConfigZod = z13.object({
660
1231
  mongo: MongoConfigZod.optional().describe("Configuration for the MongoD storage driver"),
661
- root: z12.string().optional().register(globalRegistry9, {
1232
+ r2: R2ConfigZod.optional().describe("Configuration for the Cloudflare R2 storage driver"),
1233
+ root: z13.string().optional().register(globalRegistry10, {
662
1234
  description: "Root directory for local storage",
663
1235
  title: "storage.root",
664
1236
  type: "string"
@@ -666,30 +1238,30 @@ var StorageConfigZod = z12.object({
666
1238
  }).describe("Storage configuration options");
667
1239
 
668
1240
  // src/config/Telemetry.ts
669
- import { globalRegistry as globalRegistry10, z as z13 } from "zod";
670
- var MetricsScrapeConfigZod = z13.object({
671
- path: z13.string().default("/metrics").register(globalRegistry10, {
1241
+ import { globalRegistry as globalRegistry11, z as z14 } from "zod";
1242
+ var MetricsScrapeConfigZod = z14.object({
1243
+ path: z14.string().default("/metrics").register(globalRegistry11, {
672
1244
  default: "/metrics",
673
1245
  description: "Path for the metrics scrape endpoint",
674
1246
  title: "telemetry.metrics.scrape.path",
675
1247
  type: "string"
676
1248
  }),
677
- port: z13.coerce.number().int().positive().optional().register(globalRegistry10, {
1249
+ port: z14.coerce.number().int().positive().optional().register(globalRegistry11, {
678
1250
  description: "Port for the metrics scrape endpoint",
679
1251
  title: "telemetry.metrics.scrape.port",
680
1252
  type: "number"
681
1253
  })
682
1254
  }).describe("Metrics scrape configuration");
683
- var MetricsConfigZod = z13.object({ scrape: MetricsScrapeConfigZod }).describe("Metrics configuration options");
684
- var OpenTelemetryConfigZod = z13.object({
1255
+ var MetricsConfigZod = z14.object({ scrape: MetricsScrapeConfigZod }).describe("Metrics configuration options");
1256
+ var OpenTelemetryConfigZod = z14.object({
685
1257
  // OpenTelemetry options
686
- otlpEndpoint: z13.url().optional().register(globalRegistry10, {
1258
+ otlpEndpoint: z14.url().optional().register(globalRegistry11, {
687
1259
  description: "OTLP endpoint for exporting telemetry data",
688
1260
  title: "telemetry.otel.otlpEndpoint",
689
1261
  type: "string"
690
1262
  })
691
1263
  });
692
- var TelemetryConfigZod = z13.object({
1264
+ var TelemetryConfigZod = z14.object({
693
1265
  // Metrics configuration
694
1266
  metrics: MetricsConfigZod.optional().describe("Metrics configuration"),
695
1267
  // OpenTelemetry configuration
@@ -698,14 +1270,14 @@ var TelemetryConfigZod = z13.object({
698
1270
 
699
1271
  // src/config/Validation.ts
700
1272
  import { XyoAddressZod as XyoAddressZod2 } from "@xyo-network/address";
701
- import { globalRegistry as globalRegistry11, z as z14 } from "zod";
1273
+ import { globalRegistry as globalRegistry12, z as z15 } from "zod";
702
1274
 
703
1275
  // src/primitives/block/rate/blockRate.ts
704
- import { isDefined as isDefined3, isFalsy } from "@xylabs/sdk-js";
1276
+ import { isDefined as isDefined7, isFalsy } from "@xylabs/sdk-js";
705
1277
  import { asXL1BlockRange } from "@xyo-network/xl1-protocol-lib";
706
1278
 
707
1279
  // src/primitives/block/rate/timeHelpers.ts
708
- import { assertEx as assertEx5, isDefined as isDefined2 } from "@xylabs/sdk-js";
1280
+ import { assertEx as assertEx10, isDefined as isDefined6 } from "@xylabs/sdk-js";
709
1281
  var rateMultipliers = {
710
1282
  millis: 1,
711
1283
  seconds: 1e3,
@@ -723,7 +1295,7 @@ var timeDurations = (timeInMs) => ({
723
1295
  weeks: timeInMs / (1e3 * 60 * 60 * 24 * 7)
724
1296
  });
725
1297
  var getTimeConfigInMilliseconds = (timeConfig) => {
726
- const assertedTimeConfig = assertEx5(isDefined2(timeConfig) ? timeConfig : void 0, () => "Time configuration must be provided");
1298
+ const assertedTimeConfig = assertEx10(isDefined6(timeConfig) ? timeConfig : void 0, () => "Time configuration must be provided");
727
1299
  let totalMilliseconds = 0;
728
1300
  if ("years" in assertedTimeConfig) {
729
1301
  totalMilliseconds += assertedTimeConfig.years * 31536e6;
@@ -762,366 +1334,130 @@ var blockRate = (startBlock, endBlock, timeUnit) => {
762
1334
  throw new Error("Time difference must be greater than 0");
763
1335
  }
764
1336
  const rate = heightDifference / timeDifference;
765
- const timeUnitValue = isDefined3(timeUnit) ? timeUnit : "millis";
766
- const returnedTimeDifference = isDefined3(timeUnit) ? timeDurations(timeDifference)[timeUnit] : timeDifference;
1337
+ const timeUnitValue = isDefined7(timeUnit) ? timeUnit : "millis";
1338
+ const returnedTimeDifference = isDefined7(timeUnit) ? timeDurations(timeDifference)[timeUnit] : timeDifference;
767
1339
  const timePerBlock = returnedTimeDifference / heightDifference;
768
1340
  return {
769
1341
  range: asXL1BlockRange([startingBlock.block, endingBlock.block], true),
770
1342
  span: heightDifference,
771
- rate: isDefined3(timeUnit) ? rate * rateMultipliers[timeUnit] : rate,
1343
+ rate: isDefined7(timeUnit) ? rate * rateMultipliers[timeUnit] : rate,
772
1344
  timeUnit: timeUnitValue,
773
1345
  timeDifference: returnedTimeDifference,
774
1346
  timePerBlock
775
1347
  };
776
1348
  };
777
- var getBlockRateBlocks = async (viewer, startBlockHeight, endBlockHeight) => {
778
- if (endBlockHeight <= startBlockHeight) {
779
- throw new Error(`End block height must be greater than start block height [start=${startBlockHeight}, end=${endBlockHeight}]`);
780
- }
781
- const startingBlock = await viewer.blockByNumber(startBlockHeight);
782
- const endingBlock = await viewer.blockByNumber(endBlockHeight);
783
- if (isFalsy(startingBlock) || isFalsy(endingBlock)) {
784
- throw new Error("Could not retrieve blocks for speed calculation");
785
- }
786
- return { startingBlock, endingBlock };
787
- };
788
- var calculateBlockRate = async (viewer, range, timeUnit) => {
789
- const [startBlockHeight, endBlockHeight] = range;
790
- const { startingBlock, endingBlock } = await getBlockRateBlocks(
791
- viewer,
792
- startBlockHeight,
793
- endBlockHeight
794
- );
795
- return blockRate(startingBlock, endingBlock, timeUnit);
796
- };
797
-
798
- // src/primitives/block/rate/stepRate.ts
799
- import { assertEx as assertEx6 } from "@xylabs/sdk-js";
800
- import {
801
- asXL1BlockRange as asXL1BlockRange2,
802
- isValidStep,
803
- StepSizes
804
- } from "@xyo-network/xl1-protocol-lib";
805
- var stepRate = async (viewer, start, step, count = 1, timeUnit) => {
806
- const end = start + step * count;
807
- const range = asXL1BlockRange2([start, end], true);
808
- return await calculateBlockRate(viewer, range, timeUnit);
809
- };
810
- var calculateStepSizeRate = async (viewer, start, stepIndex, count = 1, timeUnit) => {
811
- assertEx6(isValidStep(stepIndex), () => `Invalid step index: ${stepIndex}`);
812
- const step = StepSizes[stepIndex];
813
- return await stepRate(viewer, start, step, count, timeUnit);
814
- };
815
-
816
- // src/primitives/block/rate/timeRate.ts
817
- import {
818
- assertEx as assertEx7,
819
- isDefined as isDefined4,
820
- isDefinedNotNull
821
- } from "@xylabs/sdk-js";
822
- import { asXL1BlockNumber as asXL1BlockNumber2, asXL1BlockRange as asXL1BlockRange3 } from "@xyo-network/xl1-protocol-lib";
823
- var DEFAULT_TOLERANCE_MS = 3e4;
824
- var DEFAULT_MAX_ATTEMPTS = 10;
825
- var calculateTimeRate = async (viewer, timeConfig, startBlockNumber, timeUnit, toleranceMs = DEFAULT_TOLERANCE_MS, maxAttempts = DEFAULT_MAX_ATTEMPTS) => {
826
- assertEx7(Object.keys(timeConfig ?? {}).length === 1, () => "Only one time unit should be specified in timeConfig");
827
- const startBlock = isDefinedNotNull(startBlockNumber) ? await viewer.blockByNumber(startBlockNumber) : null;
828
- const resolvedStartBlock = isDefinedNotNull(startBlock) ? startBlock[0] : (await viewer.currentBlock())[0];
829
- const timeInMilliseconds = getTimeConfigInMilliseconds(timeConfig);
830
- assertEx7(timeInMilliseconds > 0, () => "Time duration must be greater than zero");
831
- const blocksPerMillisecondRate = 1 / (12 * 1e3);
832
- const initialBlocksInDuration = Math.floor(blocksPerMillisecondRate * timeInMilliseconds);
833
- const endBlockNumber = await findEndBlockRecursive(
834
- viewer,
835
- resolvedStartBlock,
836
- timeInMilliseconds,
837
- initialBlocksInDuration,
838
- toleranceMs,
839
- maxAttempts
840
- );
841
- return await calculateBlockRate(
842
- viewer,
843
- asXL1BlockRange3([endBlockNumber, resolvedStartBlock.block], true),
844
- timeUnit
845
- );
846
- };
847
- var findEndBlockRecursive = async (viewer, startBlock, targetTimeMs, estimatedBlocksBack, toleranceMs, attemptsRemaining) => {
848
- assertEx7(attemptsRemaining >= 0, () => "Maximum attempts reached while searching for end block");
849
- const startBlockEpoch = startBlock.$epoch;
850
- const estimatedEndBlockNumber = asXL1BlockNumber2(startBlock.block - estimatedBlocksBack, true);
851
- if (estimatedEndBlockNumber < 0) {
852
- throw new Error("Estimated end block number is less than zero");
853
- }
854
- const endBlock = await viewer.blockByNumber(estimatedEndBlockNumber);
855
- const resolvedEndBlock = assertEx7(
856
- isDefined4(endBlock?.[0]) ? endBlock[0] : void 0,
857
- () => `Could not retrieve block ${estimatedEndBlockNumber} for time rate calculation`
858
- );
859
- const endBlockEpoch = resolvedEndBlock.$epoch;
860
- if (!Number.isFinite(startBlockEpoch) || !Number.isFinite(endBlockEpoch)) {
861
- throw new TypeError("Block has missing or invalid $epoch");
862
- }
863
- const actualTimeDifference = startBlockEpoch - endBlockEpoch;
864
- if (actualTimeDifference === 0) {
865
- throw new Error("Start and end blocks have identical timestamps");
866
- }
867
- const timeDelta = Math.abs(actualTimeDifference - targetTimeMs);
868
- if (timeDelta <= toleranceMs) {
869
- return resolvedEndBlock.block;
870
- }
871
- let adjustedBlocksBack;
872
- if (actualTimeDifference < targetTimeMs) {
873
- const adjustmentFactor = targetTimeMs / actualTimeDifference;
874
- adjustedBlocksBack = Math.floor(estimatedBlocksBack * adjustmentFactor);
875
- } else {
876
- const adjustmentFactor = actualTimeDifference / targetTimeMs;
877
- adjustedBlocksBack = Math.floor(estimatedBlocksBack / adjustmentFactor);
878
- }
879
- adjustedBlocksBack = Number.isFinite(adjustedBlocksBack) && adjustedBlocksBack >= 1 ? adjustedBlocksBack : 1;
880
- return await findEndBlockRecursive(
881
- viewer,
882
- startBlock,
883
- targetTimeMs,
884
- adjustedBlocksBack,
885
- toleranceMs,
886
- attemptsRemaining - 1
887
- );
888
- };
889
-
890
- // src/ChainContextHelpers.ts
891
- import {
892
- isDefined as isDefined5,
893
- isObject,
894
- isUndefined as isUndefined2,
895
- timeBudget
896
- } from "@xylabs/sdk-js";
897
- import { LruCacheMap, MemoryMap } from "@xyo-network/xl1-driver-memory";
898
- function contextCache(context, name, create) {
899
- if (!isObject(context.caches)) {
900
- throw new Error("Context does not have an appropriate caches property");
901
- }
902
- if (isUndefined2(context.caches[name])) {
903
- context.caches[name] = create?.() ?? new MemoryMap();
904
- }
905
- return context.caches[name];
906
- }
907
- async function withContextCacheResponse(context, name, key, func, { max = 1e4 } = {}) {
908
- const cache = contextCache(
909
- context,
910
- name,
911
- () => new LruCacheMap({ max })
912
- );
913
- const { timeBudgetLimit = 0 } = context;
914
- const cacheResult = await cache.get(key);
915
- if (isDefined5(cacheResult)) {
916
- return cacheResult;
917
- }
918
- const result = timeBudgetLimit > 0 ? timeBudget(name, context.logger, func, timeBudgetLimit) : func();
919
- await cache.set(key, result);
920
- return result;
921
- }
922
-
923
- // src/block/hydrate/allHashesPresent.ts
924
- function allHashesPresent(hashes, payloads) {
925
- const payloadHashes = new Set(payloads.map((p) => p._hash));
926
- return hashes.every((hash) => payloadHashes.has(hash));
927
- }
928
-
929
- // src/block/hydrate/flattenHydratedBlock.ts
930
- import { toHydratedBlock } from "@xyo-network/xl1-protocol-lib";
931
- var flattenHydratedBlock = (hydratedBlock) => {
932
- const [blk, blkPayloads] = hydratedBlock;
933
- return [...blkPayloads, blk];
934
- };
935
-
936
- // src/block/hydrate/flattenHydratedBlocks.ts
937
- var flattenHydratedBlocks = (hydratedBlocks) => hydratedBlocks.flatMap((blk) => flattenHydratedBlock(blk));
938
-
939
- // src/block/hydrate/hydrateBlock.ts
940
- import { assertEx as assertEx8 } from "@xylabs/sdk-js";
941
- import { asAnyPayload as asAnyPayload2 } from "@xyo-network/sdk-js";
942
- import { asBlockBoundWitnessWithStorageMeta, isTransactionBoundWitnessWithStorageMeta } from "@xyo-network/xl1-protocol-lib";
943
- var hydrateBlock = async (context, hash, maxDepth = 1, minDepth = maxDepth) => {
944
- assertEx8(maxDepth >= 0, () => "maxDepth must be greater than or equal to 0");
945
- assertEx8(minDepth >= 0, () => "minDepth must be greater than or equal to 0");
946
- assertEx8(maxDepth >= minDepth, () => "maxDepth must be greater than or equal to minDepth");
947
- const { chainMap } = context;
948
- const [block] = await chainMap.get([hash]);
949
- const bw = assertEx8(asBlockBoundWitnessWithStorageMeta(
950
- assertEx8(block, () => `block ${hash} not found`)
951
- ), () => `hash ${hash} is not a BlockBoundWitness`);
952
- if (maxDepth === 0) return [bw, []];
953
- const blkPayloads = (await chainMap.get(bw.payload_hashes)).map((p) => asAnyPayload2(p, true));
954
- if (minDepth === 1) assertEx8(allHashesPresent(bw.payload_hashes, blkPayloads), () => `Unable to find all payloads for block ${hash}`);
955
- if (maxDepth === 1) return [bw, blkPayloads];
956
- const transactions = blkPayloads.filter(isTransactionBoundWitnessWithStorageMeta);
957
- const transactionsPayloadHashes = transactions.flatMap((tx) => tx.payload_hashes);
958
- const transactionsPayloads = (await chainMap.get(transactionsPayloadHashes)).map((p) => asAnyPayload2(p, true));
959
- assertEx8(allHashesPresent(transactionsPayloadHashes, transactionsPayloads), () => `Unable to find all payloads for transactions in block ${hash}`);
960
- const allPayloadsHashes = new Set([...blkPayloads, ...transactionsPayloads].flatMap((p) => p._hash));
961
- const allPayloads = (await chainMap.get([...allPayloadsHashes])).map((p) => asAnyPayload2(p, true));
962
- const allPayloadsFiltered = allPayloads.filter((p) => allPayloadsHashes.has(p._hash));
963
- if (maxDepth === 2) assertEx8(allHashesPresent(
964
- [...allPayloadsHashes],
965
- allPayloadsFiltered
966
- ), () => `Unable to find all payloads for transactions in block ${hash}`);
967
- return [bw, allPayloadsFiltered];
968
- };
969
-
970
- // src/block/primitives/blockFromBlockNumber.ts
971
- import {
972
- asHash,
973
- isDefined as isDefined6,
974
- spanAsync
975
- } from "@xylabs/sdk-js";
976
- import { toSafeJsonString } from "@xylabs/sdk-js";
977
- import {
978
- asSignedBlockBoundWitnessWithStorageMeta,
979
- SignedBlockBoundWitnessWithHashMetaZod,
980
- StepSizes as StepSizes2
981
- } from "@xyo-network/xl1-protocol-lib";
982
- async function blockFromBlockNumber(context, blockNumber) {
983
- return await spanAsync("blockFromBlockNumber", async () => {
984
- const cacheKey = `${blockNumber}`;
985
- const { chainMap, head } = context;
986
- return await withContextCacheResponse(context, "blockFromBlockNumber", cacheKey, async () => {
987
- const [result] = await chainMap.get([head._hash]);
988
- if (!isDefined6(result)) {
989
- throw new Error(`Head block not found for hash: ${head._hash}`);
990
- }
991
- let currentBlock = asSignedBlockBoundWitnessWithStorageMeta(
992
- result,
993
- () => `Found Payload is not a Signed<BlockBoundWitness>: ${JSON.stringify(result, null, 2)}`
994
- );
995
- if (currentBlock.block < blockNumber) {
996
- throw new Error(`Block number ${blockNumber} is greater than head ${currentBlock.block}.`);
997
- }
998
- while (currentBlock.block > blockNumber) {
999
- let jumpHash = currentBlock.previous;
1000
- let jumpBlockNumber = currentBlock.block - 1;
1001
- for (const [step, stepSize3] of StepSizes2.entries()) {
1002
- const possibleJumpBlockNumber = currentBlock.block - currentBlock.block % stepSize3 - 1;
1003
- if (possibleJumpBlockNumber >= blockNumber && possibleJumpBlockNumber <= jumpBlockNumber) {
1004
- jumpBlockNumber = possibleJumpBlockNumber;
1005
- jumpHash = asHash(currentBlock.step_hashes?.at(step), () => `Step hash not found for step ${step} in block ${currentBlock.block}`);
1006
- }
1007
- }
1008
- const [newBlock] = await chainMap.get([
1009
- asHash(jumpHash, () => `Jump hash not found for block number [${blockNumber}]: ${jumpBlockNumber} ${toSafeJsonString(currentBlock, 10)}`)
1010
- ]);
1011
- if (!isDefined6(newBlock)) {
1012
- throw new Error(`Block not found for jump hash: ${jumpHash}`);
1013
- }
1014
- currentBlock = asSignedBlockBoundWitnessWithStorageMeta(
1015
- newBlock,
1016
- () => {
1017
- const result2 = SignedBlockBoundWitnessWithHashMetaZod.safeParse(newBlock);
1018
- return `Found Payload [jump hash] is not a Signed<BlockBoundWitness>: ${result2.error}`;
1019
- }
1020
- );
1021
- if (currentBlock.block === blockNumber) {
1022
- break;
1023
- }
1024
- if (currentBlock.block < blockNumber) {
1025
- throw new Error(`Block number ${blockNumber} is not a valid step block number for block ${head._hash}.`);
1026
- }
1027
- }
1028
- return currentBlock;
1029
- });
1030
- }, { ...context, timeBudgetLimit: 500 });
1031
- }
1032
-
1033
- // src/block/primitives/frames/calculateFramesFromRange.ts
1034
- import { asXL1BlockNumber as asXL1BlockNumber3, stepSize } from "@xyo-network/xl1-protocol-lib";
1035
- function calculateFramesFromRange(range, step) {
1036
- const size = stepSize(step);
1037
- let start = Math.trunc(range[0] / size) * size;
1038
- const fitted = [];
1039
- const remaining = [];
1040
- if (start !== range[0]) {
1041
- start += size;
1042
- remaining.push([range[0], asXL1BlockNumber3(Math.min(start - 1, range[1]), true)]);
1043
- }
1044
- for (let i = start; i <= range[1]; i += size) {
1045
- if (i + size - 1 <= range[1]) {
1046
- fitted.push([
1047
- asXL1BlockNumber3(i, { name: "calculateFramesFromRange A" }),
1048
- asXL1BlockNumber3(Math.min(i + size - 1, range[1]), { name: "calculateFramesFromRange B" })
1049
- ]);
1050
- } else {
1051
- remaining.push([asXL1BlockNumber3(i, { name: "calculateFramesFromRange C" }), range[1]]);
1052
- }
1053
- }
1054
- return [fitted, remaining];
1055
- }
1056
-
1057
- // src/block/primitives/frames/deepCalculateFramesFromRange.ts
1058
- import { StepSizes as StepSizes3 } from "@xyo-network/xl1-protocol-lib";
1059
- function deepCalculateFramesFromRange(range, startingStep = StepSizes3.length - 1) {
1060
- const fitted = [];
1061
- let remaining = [range];
1062
- const actualStartingStep = Math.min(startingStep, StepSizes3.length - 1);
1063
- for (let step = actualStartingStep; step >= 0; step--) {
1064
- const newRemaining = [];
1065
- for (const range2 of remaining) {
1066
- const [newFittedFrames, newRemainingFrames] = calculateFramesFromRange(range2, step);
1067
- fitted.push(...newFittedFrames);
1068
- newRemaining.push(...newRemainingFrames);
1069
- }
1070
- remaining = newRemaining;
1349
+ var getBlockRateBlocks = async (viewer, startBlockHeight, endBlockHeight) => {
1350
+ if (endBlockHeight <= startBlockHeight) {
1351
+ throw new Error(`End block height must be greater than start block height [start=${startBlockHeight}, end=${endBlockHeight}]`);
1071
1352
  }
1072
- for (const range2 of remaining) {
1073
- for (let i = range2[0]; i <= range2[1]; i++) {
1074
- fitted.push([i, i]);
1075
- }
1353
+ const startingBlock = await viewer.blockByNumber(startBlockHeight);
1354
+ const endingBlock = await viewer.blockByNumber(endBlockHeight);
1355
+ if (isFalsy(startingBlock) || isFalsy(endingBlock)) {
1356
+ throw new Error("Could not retrieve blocks for speed calculation");
1076
1357
  }
1077
- return fitted.toSorted((a, b) => a[0] - b[0]);
1078
- }
1358
+ return { startingBlock, endingBlock };
1359
+ };
1360
+ var calculateBlockRate = async (viewer, range, timeUnit) => {
1361
+ const [startBlockHeight, endBlockHeight] = range;
1362
+ const { startingBlock, endingBlock } = await getBlockRateBlocks(
1363
+ viewer,
1364
+ startBlockHeight,
1365
+ endBlockHeight
1366
+ );
1367
+ return blockRate(startingBlock, endingBlock, timeUnit);
1368
+ };
1079
1369
 
1080
- // src/block/primitives/validateTransactionOpcodes.ts
1370
+ // src/primitives/block/rate/stepRate.ts
1371
+ import { assertEx as assertEx11 } from "@xylabs/sdk-js";
1081
1372
  import {
1082
- assertEx as assertEx9,
1083
- isHash,
1084
- toSafeJsonString as toSafeJsonString2
1085
- } from "@xylabs/sdk-js";
1373
+ asXL1BlockRange as asXL1BlockRange2,
1374
+ isValidStep,
1375
+ StepSizes as StepSizes4
1376
+ } from "@xyo-network/xl1-protocol-lib";
1377
+ var stepRate = async (viewer, start, step, count = 1, timeUnit) => {
1378
+ const end = start + step * count;
1379
+ const range = asXL1BlockRange2([start, end], true);
1380
+ return await calculateBlockRate(viewer, range, timeUnit);
1381
+ };
1382
+ var calculateStepSizeRate = async (viewer, start, stepIndex, count = 1, timeUnit) => {
1383
+ assertEx11(isValidStep(stepIndex), () => `Invalid step index: ${stepIndex}`);
1384
+ const step = StepSizes4[stepIndex];
1385
+ return await stepRate(viewer, start, step, count, timeUnit);
1386
+ };
1387
+
1388
+ // src/primitives/block/rate/timeRate.ts
1086
1389
  import {
1087
- PayloadBuilder as PayloadBuilder3
1088
- } from "@xyo-network/sdk-js";
1089
- import { isExecutable } from "@xyo-network/xl1-protocol-lib";
1090
- async function validateTransactionsOpcodes(txs) {
1091
- const txElevatedPayloads = [];
1092
- for (const [txBw, txPayloads] of txs) {
1093
- if (isExecutable(txBw)) {
1094
- const operations = txBw.script.map((op) => op.split("|"));
1095
- for (const [opCode, ...args] of operations) {
1096
- switch (opCode) {
1097
- case "elevate": {
1098
- const [hash, ...rest] = args;
1099
- const txPayloadsWithStorageMeta = await PayloadBuilder3.addStorageMeta(txPayloads);
1100
- assertEx9(rest.length === 0, () => `Invalid elevate operation ${opCode} ${args.join(", ")} - Too many Arguments`);
1101
- if (isHash(hash)) {
1102
- assertEx9(
1103
- txBw.payload_hashes.includes(hash),
1104
- () => `Invalid elevate operation ${opCode} ${args.join(", ")} - Hash not in payload hashes => ${toSafeJsonString2(txBw, 20)}`
1105
- );
1106
- const txPayload = assertEx9(
1107
- txPayloadsWithStorageMeta.find((p) => p._hash === hash),
1108
- () => `Invalid elevate operation ${opCode} ${args.join(", ")} - Payload not found`
1109
- );
1110
- txElevatedPayloads.push(txPayload);
1111
- } else {
1112
- throw new Error(`Invalid elevate operation ${opCode} ${args.join(", ")} - Invalid hash`);
1113
- }
1114
- break;
1115
- }
1116
- default: {
1117
- throw new Error(`Invalid opCode ${opCode}`);
1118
- }
1119
- }
1120
- }
1121
- }
1390
+ assertEx as assertEx12,
1391
+ isDefined as isDefined8,
1392
+ isDefinedNotNull
1393
+ } from "@xylabs/sdk-js";
1394
+ import { asXL1BlockNumber as asXL1BlockNumber7, asXL1BlockRange as asXL1BlockRange3 } from "@xyo-network/xl1-protocol-lib";
1395
+ var DEFAULT_TOLERANCE_MS = 3e4;
1396
+ var DEFAULT_MAX_ATTEMPTS = 10;
1397
+ var calculateTimeRate = async (viewer, timeConfig, startBlockNumber, timeUnit, toleranceMs = DEFAULT_TOLERANCE_MS, maxAttempts = DEFAULT_MAX_ATTEMPTS) => {
1398
+ assertEx12(Object.keys(timeConfig ?? {}).length === 1, () => "Only one time unit should be specified in timeConfig");
1399
+ const startBlock = isDefinedNotNull(startBlockNumber) ? await viewer.blockByNumber(startBlockNumber) : null;
1400
+ const resolvedStartBlock = isDefinedNotNull(startBlock) ? startBlock[0] : (await viewer.currentBlock())[0];
1401
+ const timeInMilliseconds = getTimeConfigInMilliseconds(timeConfig);
1402
+ assertEx12(timeInMilliseconds > 0, () => "Time duration must be greater than zero");
1403
+ const blocksPerMillisecondRate = 1 / (12 * 1e3);
1404
+ const initialBlocksInDuration = Math.floor(blocksPerMillisecondRate * timeInMilliseconds);
1405
+ const endBlockNumber = await findEndBlockRecursive(
1406
+ viewer,
1407
+ resolvedStartBlock,
1408
+ timeInMilliseconds,
1409
+ initialBlocksInDuration,
1410
+ toleranceMs,
1411
+ maxAttempts
1412
+ );
1413
+ return await calculateBlockRate(
1414
+ viewer,
1415
+ asXL1BlockRange3([endBlockNumber, resolvedStartBlock.block], true),
1416
+ timeUnit
1417
+ );
1418
+ };
1419
+ var findEndBlockRecursive = async (viewer, startBlock, targetTimeMs, estimatedBlocksBack, toleranceMs, attemptsRemaining) => {
1420
+ assertEx12(attemptsRemaining >= 0, () => "Maximum attempts reached while searching for end block");
1421
+ const startBlockEpoch = startBlock.$epoch;
1422
+ const estimatedEndBlockNumber = asXL1BlockNumber7(startBlock.block - estimatedBlocksBack, true);
1423
+ if (estimatedEndBlockNumber < 0) {
1424
+ throw new Error("Estimated end block number is less than zero");
1122
1425
  }
1123
- return txElevatedPayloads;
1124
- }
1426
+ const endBlock = await viewer.blockByNumber(estimatedEndBlockNumber);
1427
+ const resolvedEndBlock = assertEx12(
1428
+ isDefined8(endBlock?.[0]) ? endBlock[0] : void 0,
1429
+ () => `Could not retrieve block ${estimatedEndBlockNumber} for time rate calculation`
1430
+ );
1431
+ const endBlockEpoch = resolvedEndBlock.$epoch;
1432
+ if (!Number.isFinite(startBlockEpoch) || !Number.isFinite(endBlockEpoch)) {
1433
+ throw new TypeError("Block has missing or invalid $epoch");
1434
+ }
1435
+ const actualTimeDifference = startBlockEpoch - endBlockEpoch;
1436
+ if (actualTimeDifference === 0) {
1437
+ throw new Error("Start and end blocks have identical timestamps");
1438
+ }
1439
+ const timeDelta = Math.abs(actualTimeDifference - targetTimeMs);
1440
+ if (timeDelta <= toleranceMs) {
1441
+ return resolvedEndBlock.block;
1442
+ }
1443
+ let adjustedBlocksBack;
1444
+ if (actualTimeDifference < targetTimeMs) {
1445
+ const adjustmentFactor = targetTimeMs / actualTimeDifference;
1446
+ adjustedBlocksBack = Math.floor(estimatedBlocksBack * adjustmentFactor);
1447
+ } else {
1448
+ const adjustmentFactor = actualTimeDifference / targetTimeMs;
1449
+ adjustedBlocksBack = Math.floor(estimatedBlocksBack / adjustmentFactor);
1450
+ }
1451
+ adjustedBlocksBack = Number.isFinite(adjustedBlocksBack) && adjustedBlocksBack >= 1 ? adjustedBlocksBack : 1;
1452
+ return await findEndBlockRecursive(
1453
+ viewer,
1454
+ startBlock,
1455
+ targetTimeMs,
1456
+ adjustedBlocksBack,
1457
+ toleranceMs,
1458
+ attemptsRemaining - 1
1459
+ );
1460
+ };
1125
1461
 
1126
1462
  // src/primitives/state/findMostRecentBlock.ts
1127
1463
  import { isSignedBlockBoundWitnessWithStorageMeta } from "@xyo-network/xl1-protocol-lib";
@@ -1151,7 +1487,7 @@ var findMostRecentBlock = async (chainArchivist, nextOptions = DEFAULT_NEXT_OPTI
1151
1487
  };
1152
1488
 
1153
1489
  // src/primitives/state/hydratedBlockByNumber.ts
1154
- import { assertEx as assertEx10, spanAsync as spanAsync2 } from "@xylabs/sdk-js";
1490
+ import { assertEx as assertEx13, spanAsync as spanAsync2 } from "@xylabs/sdk-js";
1155
1491
  async function hydratedBlockByNumber(context, blockNumber) {
1156
1492
  return await spanAsync2("hydratedBlockByNumber", async () => {
1157
1493
  if (blockNumber < 0) throw new Error(`Block number ${blockNumber} is less than 0`);
@@ -1159,7 +1495,7 @@ async function hydratedBlockByNumber(context, blockNumber) {
1159
1495
  if (blockNumber % 1 !== 0) throw new Error(`Block number ${blockNumber} is not an integer`);
1160
1496
  const cacheKey = `${blockNumber}`;
1161
1497
  return await withContextCacheResponse(context, "hydratedBlockByNumber", cacheKey, async () => {
1162
- const block = assertEx10(
1498
+ const block = assertEx13(
1163
1499
  await blockFromBlockNumber(context, blockNumber),
1164
1500
  () => `Could not find block for block number ${blockNumber}`
1165
1501
  );
@@ -1173,24 +1509,24 @@ var DEFAULT_MIN_CANDIDATES = 1;
1173
1509
  var DEFAULT_BACKOFF_MS = 12e4;
1174
1510
 
1175
1511
  // src/config/Validation.ts
1176
- var ValidationConfigZod = z14.object({
1177
- allowedRewardRedeemers: z14.array(XyoAddressZod2).optional().register(globalRegistry11, {
1512
+ var ValidationConfigZod = z15.object({
1513
+ allowedRewardRedeemers: z15.array(XyoAddressZod2).optional().register(globalRegistry12, {
1178
1514
  description: "List of allowed reward redeemer addresses, if undefined anyone can participate",
1179
1515
  title: "allowedRewardRedeemers",
1180
1516
  type: "array"
1181
1517
  }),
1182
- allowedRewardEscrowAccountSigners: z14.array(XyoAddressZod2).optional().register(globalRegistry11, {
1518
+ allowedRewardEscrowAccountSigners: z15.array(XyoAddressZod2).optional().register(globalRegistry12, {
1183
1519
  description: "List of allowed reward escrow account signer addresses, if undefined anyone can participate",
1184
1520
  title: "allowedRewardEscrowAccountSigners",
1185
1521
  type: "array"
1186
1522
  }),
1187
- minCandidates: z14.coerce.number().default(DEFAULT_MIN_CANDIDATES).register(globalRegistry11, {
1523
+ minCandidates: z15.coerce.number().default(DEFAULT_MIN_CANDIDATES).register(globalRegistry12, {
1188
1524
  default: DEFAULT_MIN_CANDIDATES,
1189
1525
  description: "Minimum number of uncle candidates before selecting the best uncle",
1190
1526
  title: "validation.minCandidates",
1191
1527
  type: "number"
1192
1528
  }),
1193
- backoffMs: z14.coerce.number().default(DEFAULT_BACKOFF_MS).register(globalRegistry11, {
1529
+ backoffMs: z15.coerce.number().default(DEFAULT_BACKOFF_MS).register(globalRegistry12, {
1194
1530
  default: DEFAULT_BACKOFF_MS,
1195
1531
  description: "Back-off timeout in ms. If head age exceeds this, minCandidates is ignored",
1196
1532
  title: "validation.backoffMs",
@@ -1199,26 +1535,26 @@ var ValidationConfigZod = z14.object({
1199
1535
  });
1200
1536
 
1201
1537
  // src/config/Base.ts
1202
- var BaseConfigZod = z15.object({
1203
- chain: z15._default(ChainConfigZod, ChainConfigZod.parse({})).check(z15.describe("Configuration for the chain")),
1204
- dataLake: z15.optional(DataLakeConfigZod).check(z15.describe("Configuration for data lakes")),
1205
- evm: z15._default(EvmConfigZod, EvmConfigZod.parse({})).check(z15.describe("Configuration for EVM-backed services")),
1206
- log: z15._default(LogConfigZod, LogConfigZod.parse({})).check(z15.describe("Configuration for logging")),
1207
- providers: z15._default(ProvidersConfigZod, ProvidersConfigZod.parse([])).check(z15.describe("Configuration for providers")),
1208
- remote: z15._default(RemoteConfigZod, RemoteConfigZod.parse({})).check(z15.describe("Configuration for remote services")),
1209
- storage: z15._default(StorageConfigZod, StorageConfigZod.parse({})).check(z15.describe("Configuration for the storage")),
1210
- telemetry: z15._default(TelemetryConfigZod, TelemetryConfigZod.parse({})).check(z15.describe("Configuration for telemetry")),
1211
- validation: z15._default(ValidationConfigZod, ValidationConfigZod.parse({})).check(z15.describe("Configuration for validation"))
1538
+ var BaseConfigZod = z16.object({
1539
+ chain: z16._default(ChainConfigZod, ChainConfigZod.parse({})).check(z16.describe("Configuration for the chain")),
1540
+ dataLake: z16.optional(DataLakeConfigZod).check(z16.describe("Configuration for data lakes")),
1541
+ evm: z16._default(EvmConfigZod, EvmConfigZod.parse({})).check(z16.describe("Configuration for EVM-backed services")),
1542
+ log: z16._default(LogConfigZod, LogConfigZod.parse({})).check(z16.describe("Configuration for logging")),
1543
+ providers: z16._default(ProvidersConfigZod, ProvidersConfigZod.parse([])).check(z16.describe("Configuration for providers")),
1544
+ remote: z16._default(RemoteConfigZod, RemoteConfigZod.parse({})).check(z16.describe("Configuration for remote services")),
1545
+ storage: z16._default(StorageConfigZod, StorageConfigZod.parse({})).check(z16.describe("Configuration for the storage")),
1546
+ telemetry: z16._default(TelemetryConfigZod, TelemetryConfigZod.parse({})).check(z16.describe("Configuration for telemetry")),
1547
+ validation: z16._default(ValidationConfigZod, ValidationConfigZod.parse({})).check(z16.describe("Configuration for validation"))
1212
1548
  });
1213
1549
 
1214
1550
  // src/config/Actor.ts
1215
- var AccountPathZod = z16.string().check(z16.regex(
1551
+ var AccountPathZod = z17.string().check(z17.regex(
1216
1552
  /^(m(\/\d+'?)+|\d+'?(\/\d+'?)*)$/,
1217
1553
  `Invalid BIP-32 derivation path. Use either an absolute path like "m/44'/60'/0'/0/0" or a relative path like "0", "0/1", or "44'/60'/0'/0/0".`
1218
1554
  ));
1219
- var ActorConfigZod = z16.extend(BaseConfigZod, {
1220
- name: z16.string(),
1221
- accountPath: z16.optional(AccountPathZod).register(globalRegistry12, {
1555
+ var ActorConfigZod = z17.extend(BaseConfigZod, {
1556
+ name: z17.string(),
1557
+ accountPath: z17.optional(AccountPathZod).register(globalRegistry13, {
1222
1558
  description: 'BIP-32 derivation path for the actor wallet. Absolute when it starts with "m/"; otherwise relative to the root wallet base path. Each actor must derive to a distinct path.',
1223
1559
  title: "accountPath",
1224
1560
  type: "string"
@@ -1229,31 +1565,31 @@ var asActorConfig = zodAsFactory2(ActorConfigZod, "asActorConfig");
1229
1565
  var toActorConfig = zodToFactory2(ActorConfigZod, "toActorConfig");
1230
1566
 
1231
1567
  // src/config/Actors.ts
1232
- import { z as z17 } from "zod/mini";
1233
- var ActorsConfigZod = z17._default(
1234
- z17.array(z17.looseObject(ActorConfigZod.shape)).check(z17.describe("Actor-specific configurations that override the base configuration when the actor is running")),
1568
+ import { z as z18 } from "zod/mini";
1569
+ var ActorsConfigZod = z18._default(
1570
+ z18.array(z18.looseObject(ActorConfigZod.shape)).check(z18.describe("Actor-specific configurations that override the base configuration when the actor is running")),
1235
1571
  []
1236
1572
  );
1237
1573
 
1238
1574
  // src/config/Config.ts
1239
- import { globalRegistry as globalRegistry13, z as z18 } from "zod/mini";
1240
- var ConfigZod = z18.extend(BaseConfigZod, {
1575
+ import { globalRegistry as globalRegistry14, z as z19 } from "zod/mini";
1576
+ var ConfigZod = z19.extend(BaseConfigZod, {
1241
1577
  actors: ActorsConfigZod,
1242
- healthCheckPort: z18.optional(z18.coerce.number()).register(globalRegistry13, {
1578
+ healthCheckPort: z19.optional(z19.coerce.number()).register(globalRegistry14, {
1243
1579
  description: "Port for the system-wide health, readiness, and liveness endpoints (/healthz, /livez, /readyz). Set to 0 to disable.",
1244
1580
  title: "healthCheckPort",
1245
1581
  type: "number"
1246
1582
  })
1247
- }).check(z18.describe("The complete configuration for the protocol, including global settings and actor-specific overrides"));
1583
+ }).check(z19.describe("The complete configuration for the protocol, including global settings and actor-specific overrides"));
1248
1584
 
1249
1585
  // src/summary/model/BlocksStepSummary.ts
1250
1586
  import { AsObjectFactory } from "@xylabs/sdk-js";
1251
1587
  import {
1252
- asSchema,
1588
+ asSchema as asSchema3,
1253
1589
  isPayloadOfSchemaType,
1254
1590
  isStorageMeta
1255
1591
  } from "@xyo-network/sdk-js";
1256
- var BlocksStepSummarySchema = asSchema("network.xyo.step.summary.blocks", true);
1592
+ var BlocksStepSummarySchema = asSchema3("network.xyo.step.summary.blocks", true);
1257
1593
  var isBlocksStepSummary = isPayloadOfSchemaType(BlocksStepSummarySchema);
1258
1594
  var asBlocksStepSummary = AsObjectFactory.create(isBlocksStepSummary);
1259
1595
  var isBlocksStepSummaryWithStorageMeta = (value) => {
@@ -1265,9 +1601,9 @@ var asBlocksStepSummaryWithStorageMeta = AsObjectFactory.create(isBlocksStepSumm
1265
1601
  var blocksMaxStep = 3;
1266
1602
 
1267
1603
  // src/summary/primitives/blocks/blocksStepSummaryFromRange.ts
1268
- import { assertEx as assertEx11, spanRootAsync } from "@xylabs/sdk-js";
1604
+ import { assertEx as assertEx14, spanRootAsync } from "@xylabs/sdk-js";
1269
1605
  import { isAnyPayload } from "@xyo-network/sdk-js";
1270
- import { asXL1BlockNumber as asXL1BlockNumber4, StepSizes as StepSizes4 } from "@xyo-network/xl1-protocol-lib";
1606
+ import { asXL1BlockNumber as asXL1BlockNumber8, StepSizes as StepSizes5 } from "@xyo-network/xl1-protocol-lib";
1271
1607
  function blocksStepSummaryKey(frameHeadHash, frameSize) {
1272
1608
  return `${frameHeadHash}|${frameSize}`;
1273
1609
  }
@@ -1275,7 +1611,7 @@ async function blocksStepSummaryFromRange(context, semaphores, blockViewer, summ
1275
1611
  const cacheKey = `${range[0]}|${range[1]}`;
1276
1612
  return await withContextCacheResponse(context, "blocksStepSummaryFromRange", cacheKey, async () => {
1277
1613
  return await spanRootAsync("blocksStepSummaryFromRange", async () => {
1278
- const frameHead = assertEx11(
1614
+ const frameHead = assertEx14(
1279
1615
  await blockViewer.blockByNumber(range[1]),
1280
1616
  () => `Block not found for number: ${range[1]}`
1281
1617
  );
@@ -1290,8 +1626,8 @@ async function blocksStepSummaryFromRange(context, semaphores, blockViewer, summ
1290
1626
  blocks: [frameHead]
1291
1627
  };
1292
1628
  } else {
1293
- const step = StepSizes4.indexOf(asXL1BlockNumber4(frameSize, true));
1294
- assertEx11(step !== -1, () => `Invalid step size: ${frameSize}. Must be one of ${StepSizes4.join(", ")}`);
1629
+ const step = StepSizes5.indexOf(asXL1BlockNumber8(frameSize, true));
1630
+ assertEx14(step !== -1, () => `Invalid step size: ${frameSize}. Must be one of ${StepSizes5.join(", ")}`);
1295
1631
  const key = blocksStepSummaryKey(frameHeadHash, frameSize);
1296
1632
  const summaryResult = await summaryMap.get(key);
1297
1633
  if (isAnyPayload(summaryResult)) {
@@ -1327,20 +1663,20 @@ async function blocksStepSummaryFromRange(context, semaphores, blockViewer, summ
1327
1663
 
1328
1664
  // src/simple/block/SimpleBlockViewer.ts
1329
1665
  import {
1330
- assertEx as assertEx12,
1666
+ assertEx as assertEx15,
1331
1667
  exists,
1332
- isUndefined as isUndefined3
1668
+ isUndefined as isUndefined4
1333
1669
  } from "@xylabs/sdk-js";
1334
1670
  import { LruCacheMap as LruCacheMap2 } from "@xyo-network/xl1-driver-memory";
1335
1671
  import {
1336
1672
  asSignedHydratedBlockWithHashMeta,
1337
1673
  asSignedHydratedBlockWithStorageMeta,
1338
- asXL1BlockNumber as asXL1BlockNumber5,
1674
+ asXL1BlockNumber as asXL1BlockNumber9,
1339
1675
  asXL1BlockRange as asXL1BlockRange4,
1340
1676
  BlockViewerMoniker,
1341
1677
  FinalizationViewerMoniker,
1342
1678
  stepSize as stepSize2,
1343
- StepSizes as StepSizes5
1679
+ StepSizes as StepSizes6
1344
1680
  } from "@xyo-network/xl1-protocol-lib";
1345
1681
  import { Semaphore } from "async-mutex";
1346
1682
 
@@ -1375,7 +1711,7 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1375
1711
  finalizationViewer;
1376
1712
  payloadCache = new LruCacheMap2({ max: 1e4 });
1377
1713
  signedHydratedBlockWithHashMetaCache = new LruCacheMap2({ max: 2e3, ttl: 1e3 * 60 * 60 });
1378
- _blockStepSemaphores = StepSizes5.map(() => new Semaphore(20));
1714
+ _blockStepSemaphores = StepSizes6.map(() => new Semaphore(20));
1379
1715
  _blocksSummaryMap;
1380
1716
  _headPollHash;
1381
1717
  _headPollInProgress = false;
@@ -1406,12 +1742,12 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1406
1742
  static async paramsHandler(params) {
1407
1743
  const headPollIntervalMs = params.headPollIntervalMs;
1408
1744
  if (headPollIntervalMs !== void 0) {
1409
- assertEx12(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS}ms`);
1745
+ assertEx15(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS}ms`);
1410
1746
  }
1411
1747
  return {
1412
1748
  ...await super.paramsHandler(params),
1413
1749
  blocksSummaryMap: params.blocksSummaryMap,
1414
- finalizedArchivist: assertEx12(params.finalizedArchivist, () => "finalizedArchivist is required"),
1750
+ finalizedArchivist: assertEx15(params.finalizedArchivist, () => "finalizedArchivist is required"),
1415
1751
  headPollIntervalMs
1416
1752
  };
1417
1753
  }
@@ -1432,7 +1768,7 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1432
1768
  async blockByNumber(blockNumber) {
1433
1769
  return await this.spanAsync("blockByNumber", async () => {
1434
1770
  const chainContext = await this.getChainContextRead();
1435
- if (isUndefined3(chainContext.head)) {
1771
+ if (isUndefined4(chainContext.head)) {
1436
1772
  return null;
1437
1773
  }
1438
1774
  return await this.blockByNumberWithContext(chainContext, blockNumber);
@@ -1440,8 +1776,8 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1440
1776
  }
1441
1777
  async blocksByHash(hash, limit = 50) {
1442
1778
  return await this.spanAsync("blocksByHash", async () => {
1443
- assertEx12(limit > 0, () => "limit must be greater than 0");
1444
- assertEx12(limit <= 100, () => "limit must be less than 100");
1779
+ assertEx15(limit > 0, () => "limit must be greater than 0");
1780
+ assertEx15(limit <= 100, () => "limit must be less than 100");
1445
1781
  const blocks = [];
1446
1782
  let current = await this.blockByHash(hash);
1447
1783
  while (current && blocks.length < limit) {
@@ -1455,10 +1791,10 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1455
1791
  }
1456
1792
  async blocksByNumber(blockNumber, limit = 50) {
1457
1793
  return await this.spanAsync("blocksByNumber", async () => {
1458
- assertEx12(limit > 0, () => "limit must be greater than 0");
1459
- assertEx12(limit <= 100, () => "limit must be less than 100");
1794
+ assertEx15(limit > 0, () => "limit must be greater than 0");
1795
+ assertEx15(limit <= 100, () => "limit must be less than 100");
1460
1796
  const chainContext = await this.getChainContextRead();
1461
- if (isUndefined3(chainContext.head)) {
1797
+ if (isUndefined4(chainContext.head)) {
1462
1798
  return [];
1463
1799
  }
1464
1800
  const blocks = [];
@@ -1466,7 +1802,7 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1466
1802
  while (current && blocks.length < limit) {
1467
1803
  blocks.push(current);
1468
1804
  if (current[0].block === 0) break;
1469
- const previousNumber = asXL1BlockNumber5(current[0].block - 1, true);
1805
+ const previousNumber = asXL1BlockNumber9(current[0].block - 1, true);
1470
1806
  current = await this.blockByNumberWithContext(chainContext, previousNumber);
1471
1807
  }
1472
1808
  return blocks.map((b) => asSignedHydratedBlockWithHashMeta(b, true));
@@ -1474,14 +1810,14 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1474
1810
  }
1475
1811
  async blocksByStep(stepLevel, stepIndex) {
1476
1812
  return await this.spanAsync("blocksByStep", async () => {
1477
- assertEx12(Number.isInteger(stepIndex) && stepIndex >= 0, () => "stepIndex must be a non-negative integer");
1813
+ assertEx15(Number.isInteger(stepIndex) && stepIndex >= 0, () => "stepIndex must be a non-negative integer");
1478
1814
  const size = stepSize2(stepLevel);
1479
- assertEx12(
1815
+ assertEx15(
1480
1816
  stepLevel <= blocksMaxStep,
1481
1817
  () => `blocksByStep does not support step levels above ${blocksMaxStep} (requested ${stepLevel})`
1482
1818
  );
1483
1819
  const chainContext = await this.getChainContextRead();
1484
- if (isUndefined3(chainContext.head)) {
1820
+ if (isUndefined4(chainContext.head)) {
1485
1821
  return [];
1486
1822
  }
1487
1823
  const start = stepIndex * size;
@@ -1498,7 +1834,7 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1498
1834
  }
1499
1835
  async chainId(blockNumber = "latest") {
1500
1836
  return await this.spanAsync("chainId", async () => {
1501
- return blockNumber === "latest" ? (await this.finalizationViewer.headBlock()).chain : assertEx12(await this.blockByNumber(blockNumber), () => `Block not found [${blockNumber}]`)[0].chain;
1837
+ return blockNumber === "latest" ? (await this.finalizationViewer.headBlock()).chain : assertEx15(await this.blockByNumber(blockNumber), () => `Block not found [${blockNumber}]`)[0].chain;
1502
1838
  }, this.context);
1503
1839
  }
1504
1840
  async createHandler() {
@@ -1610,7 +1946,7 @@ SimpleBlockViewer = __decorateClass([
1610
1946
  ], SimpleBlockViewer);
1611
1947
 
1612
1948
  // src/simple/chainContractViewer/SimpleChainContractViewer.ts
1613
- import { assertEx as assertEx13 } from "@xylabs/sdk-js";
1949
+ import { assertEx as assertEx16 } from "@xylabs/sdk-js";
1614
1950
  import { ChainContractViewerMoniker, FinalizationViewerMoniker as FinalizationViewerMoniker2 } from "@xyo-network/xl1-protocol-lib";
1615
1951
  var SimpleChainContractViewer = class extends AbstractCreatableProvider {
1616
1952
  moniker = SimpleChainContractViewer.defaultMoniker;
@@ -1627,7 +1963,7 @@ var SimpleChainContractViewer = class extends AbstractCreatableProvider {
1627
1963
  let contractViewer = this;
1628
1964
  let forkedAtBlockNumber = await contractViewer.forkedAtBlockNumber();
1629
1965
  while (forkedAtBlockNumber !== null && blockNumber <= forkedAtBlockNumber) {
1630
- contractViewer = assertEx13(await contractViewer.forkedChainContractViewer());
1966
+ contractViewer = assertEx16(await contractViewer.forkedChainContractViewer());
1631
1967
  forkedAtBlockNumber = await contractViewer.forkedAtBlockNumber();
1632
1968
  chainId = await contractViewer.chainId();
1633
1969
  }
@@ -1668,7 +2004,7 @@ SimpleChainContractViewer = __decorateClass([
1668
2004
  ], SimpleChainContractViewer);
1669
2005
 
1670
2006
  // src/simple/finalization/SimpleFinalizationViewer.ts
1671
- import { assertEx as assertEx14 } from "@xylabs/sdk-js";
2007
+ import { assertEx as assertEx17 } from "@xylabs/sdk-js";
1672
2008
  import {
1673
2009
  asSignedHydratedBlockWithStorageMeta as asSignedHydratedBlockWithStorageMeta2,
1674
2010
  ChainContractViewerMoniker as ChainContractViewerMoniker2,
@@ -1687,374 +2023,72 @@ var SimpleFinalizationViewer = class extends AbstractCreatableProvider {
1687
2023
  const context = this.getBlockContextRead();
1688
2024
  this._signedHydratedBlockCache = new HydratedCache(context, async (store, hash, maxDepth, minDepth) => {
1689
2025
  const result = await hydrateBlock(context, hash, maxDepth, minDepth);
1690
- return asSignedHydratedBlockWithStorageMeta2(result, true);
1691
- }, 200);
1692
- return this._signedHydratedBlockCache;
1693
- }
1694
- get store() {
1695
- return this._store;
1696
- }
1697
- static async paramsHandler(params) {
1698
- return {
1699
- ...await super.paramsHandler(params),
1700
- finalizedArchivist: assertEx14(params.finalizedArchivist, () => "finalizedArchivist is required")
1701
- };
1702
- }
1703
- chainId() {
1704
- return this._chainId;
1705
- }
1706
- async createHandler() {
1707
- await super.createHandler();
1708
- this._chainId = assertEx14(this.config.chain.id ?? (await findMostRecentBlock(this.params.finalizedArchivist))?.chain, () => "chain.id is required if empty archivist");
1709
- this._store = { chainMap: this.params.finalizedArchivist };
1710
- }
1711
- async head() {
1712
- return await this.spanAsync("head", async () => {
1713
- const currentHead = assertEx14(await this.getCurrentHead(), () => "Could not find most recent block [currentBlock]");
1714
- const cache = this.hydratedBlockCache;
1715
- const block = await cache.get(currentHead._hash);
1716
- if (!block) {
1717
- this.logger?.error(`Could not find current block with hash ${currentHead._hash}`);
1718
- }
1719
- return assertEx14(block, () => "Could not find current block");
1720
- }, this.context);
1721
- }
1722
- async headBlock() {
1723
- return (await this.head())[0];
1724
- }
1725
- async headHash() {
1726
- return (await this.headBlock())._hash;
1727
- }
1728
- async headNumber() {
1729
- return (await this.headBlock()).block;
1730
- }
1731
- getBlockContextRead() {
1732
- return {
1733
- ...this.context,
1734
- chainMap: this.store.chainMap
1735
- };
1736
- }
1737
- async getChainContextRead() {
1738
- return {
1739
- ...this.getBlockContextRead(),
1740
- head: (await this.head())[0]
1741
- };
1742
- }
1743
- async getCurrentHead() {
1744
- const chainArchivist = this.finalizedArchivist;
1745
- const result = assertEx14(await findMostRecentBlock(chainArchivist), () => "Could not find most recent block [getCurrentHead]");
1746
- assertEx14(result?.chain === this._chainId, () => "Chain ID does not match head block chain ID");
1747
- return result;
1748
- }
1749
- };
1750
- __publicField(SimpleFinalizationViewer, "defaultMoniker", FinalizationViewerMoniker3);
1751
- __publicField(SimpleFinalizationViewer, "dependencies", [ChainContractViewerMoniker2]);
1752
- __publicField(SimpleFinalizationViewer, "monikers", [FinalizationViewerMoniker3]);
1753
- SimpleFinalizationViewer = __decorateClass([
1754
- creatableProvider()
1755
- ], SimpleFinalizationViewer);
1756
-
1757
- // src/test/buildRandomChain.ts
1758
- import { asAddress as asAddress2, assertEx as assertEx17 } from "@xylabs/sdk-js";
1759
- import {
1760
- Account as Account3,
1761
- asSchema as asSchema3,
1762
- IdSchema as IdSchema2,
1763
- MemoryArchivist,
1764
- PayloadBuilder as PayloadBuilder8
1765
- } from "@xyo-network/sdk-js";
1766
- import {
1767
- asXL1BlockNumber as asXL1BlockNumber9
1768
- } from "@xyo-network/xl1-protocol-lib";
1769
-
1770
- // src/test/buildNextBlock.ts
1771
- import {
1772
- AttoXL1 as AttoXL12,
1773
- XYO_STEP_REWARD_ADDRESS as XYO_STEP_REWARD_ADDRESS2
1774
- } from "@xyo-network/xl1-protocol-lib";
1775
-
1776
- // src/test/buildBlock.ts
1777
- import { assertEx as assertEx15, isDefined as isDefined7 } from "@xylabs/sdk-js";
1778
- import {
1779
- asAnyPayload as asAnyPayload3,
1780
- BoundWitnessBuilder as BoundWitnessBuilder2,
1781
- PayloadBuilder as PayloadBuilder4
1782
- } from "@xyo-network/sdk-js";
1783
- import {
1784
- asXL1BlockNumber as asXL1BlockNumber6,
1785
- AttoXL1,
1786
- isBlockBoundWitness,
1787
- rewardAddressFromStepIdentity,
1788
- StepRewardFractions,
1789
- StepSizes as StepSizes6,
1790
- XL1_PROTOCOL_VERSION,
1791
- XYO_STEP_REWARD_ADDRESS,
1792
- XYO_ZERO_ADDRESS
1793
- } from "@xyo-network/xl1-protocol-lib";
1794
-
1795
- // src/test/BuildBlockOptions.ts
1796
- import {
1797
- isAddress,
1798
- isArray,
1799
- isHash as isHash2,
1800
- isNumber,
1801
- isObject as isObject2
1802
- } from "@xylabs/sdk-js";
1803
- var isBaseBuildBlockOptions = (value) => {
1804
- if (!isObject2(value)) {
1805
- return false;
1806
- }
1807
- const typedValue = value;
1808
- if (!isArray(typedValue.blockPayloads) || !isAddress(typedValue.chainId) || !isArray(typedValue.signers) || !isArray(typedValue.txs)) {
1809
- return false;
1810
- }
1811
- return true;
1812
- };
1813
- var isBuildGenesisBlockOptions = (value) => {
1814
- if (!isBaseBuildBlockOptions(value)) {
1815
- return false;
2026
+ return asSignedHydratedBlockWithStorageMeta2(result, true);
2027
+ }, 200);
2028
+ return this._signedHydratedBlockCache;
1816
2029
  }
1817
- const typedValue = value;
1818
- if (typedValue.previousBlockHash !== null) {
1819
- return false;
2030
+ get store() {
2031
+ return this._store;
1820
2032
  }
1821
- if (typedValue.previousBlockNumber !== void 0) {
1822
- return false;
2033
+ static async paramsHandler(params) {
2034
+ return {
2035
+ ...await super.paramsHandler(params),
2036
+ finalizedArchivist: assertEx17(params.finalizedArchivist, () => "finalizedArchivist is required")
2037
+ };
1823
2038
  }
1824
- return true;
1825
- };
1826
- var isBuildNextBlockOptions = (value) => {
1827
- if (!isBaseBuildBlockOptions(value)) {
1828
- return false;
2039
+ chainId() {
2040
+ return this._chainId;
1829
2041
  }
1830
- const typedValue = value;
1831
- if (!isHash2(typedValue.previousBlockHash)) {
1832
- return false;
2042
+ async createHandler() {
2043
+ await super.createHandler();
2044
+ this._chainId = assertEx17(this.config.chain.id ?? (await findMostRecentBlock(this.params.finalizedArchivist))?.chain, () => "chain.id is required if empty archivist");
2045
+ this._store = { chainMap: this.params.finalizedArchivist };
1833
2046
  }
1834
- if (!isNumber(typedValue.previousBlockNumber)) {
1835
- return false;
2047
+ async head() {
2048
+ return await this.spanAsync("head", async () => {
2049
+ const currentHead = assertEx17(await this.getCurrentHead(), () => "Could not find most recent block [currentBlock]");
2050
+ const cache = this.hydratedBlockCache;
2051
+ const block = await cache.get(currentHead._hash);
2052
+ if (!block) {
2053
+ this.logger?.error(`Could not find current block with hash ${currentHead._hash}`);
2054
+ }
2055
+ return assertEx17(block, () => "Could not find current block");
2056
+ }, this.context);
1836
2057
  }
1837
- if (!isArray(typedValue.previousStepHashes)) {
1838
- return false;
2058
+ async headBlock() {
2059
+ return (await this.head())[0];
1839
2060
  }
1840
- return true;
1841
- };
1842
-
1843
- // src/test/buildBlock.ts
1844
- function calculateCompletedStepReward(step, balance) {
1845
- return AttoXL1(StepRewardFractions[step][0] * balance / StepRewardFractions[step][1]);
1846
- }
1847
- async function buildBlock(options) {
1848
- const previousBlockNumber = isBuildGenesisBlockOptions(options) ? -1 : options.previousBlockNumber;
1849
- const blockNumber = asXL1BlockNumber6(previousBlockNumber + 1, true);
1850
- const inStepHashes = isBuildNextBlockOptions(options) ? options.previousStepHashes : [];
1851
- const previousBlockHash = isBuildNextBlockOptions(options) ? options.previousBlockHash : void 0;
1852
- const stepRewardPoolBalance = isBuildNextBlockOptions(options) ? options.stepRewardPoolBalance : AttoXL1(0n);
1853
- const {
1854
- chainId,
1855
- txs,
1856
- chainStepRewardAddress = XYO_STEP_REWARD_ADDRESS,
1857
- blockPayloads,
1858
- protocol = XL1_PROTOCOL_VERSION,
1859
- signers
1860
- } = options;
1861
- const step_hashes = [];
1862
- for (const [tx] of txs) {
1863
- if (tx.nbf > blockNumber) {
1864
- throw new Error(`Transaction ${await PayloadBuilder4.hash(tx)} not valid for block ${blockNumber} - NBF is ${tx.nbf}`);
1865
- }
1866
- if (tx.exp < blockNumber) {
1867
- throw new Error(`Transaction ${await PayloadBuilder4.hash(tx)} not valid for block ${blockNumber} - EXP is ${tx.exp}`);
1868
- }
2061
+ async headHash() {
2062
+ return (await this.headBlock())._hash;
1869
2063
  }
1870
- const completedStepRewardTransfers = [];
1871
- for (const [i, step] of StepSizes6.entries()) {
1872
- if (blockNumber < step) {
1873
- break;
1874
- }
1875
- if (blockNumber % step === 0) {
1876
- if (StepRewardFractions[i][0] > 0 && chainStepRewardAddress !== XYO_ZERO_ADDRESS) {
1877
- const completedStepRewardHolderAddress = rewardAddressFromStepIdentity({ block: blockNumber, step });
1878
- const completedStepReward = calculateCompletedStepReward(i, stepRewardPoolBalance);
1879
- completedStepRewardTransfers.push(createTransferPayload(chainStepRewardAddress, { [completedStepRewardHolderAddress]: completedStepReward }));
1880
- }
1881
- step_hashes.push(assertEx15(previousBlockHash, () => `Previous block hash is required for step ${step} at block ${blockNumber}`));
1882
- } else {
1883
- if (isDefined7(inStepHashes.at(i))) {
1884
- step_hashes.push(inStepHashes[i]);
1885
- }
1886
- }
2064
+ async headNumber() {
2065
+ return (await this.headBlock()).block;
1887
2066
  }
1888
- const previous = previousBlockHash ?? null;
1889
- const block = blockNumber;
1890
- const txElevatedPayloads = await validateTransactionsOpcodes(txs);
1891
- const payloads = [
1892
- ...txs.map(([tx]) => tx),
1893
- ...blockPayloads,
1894
- ...txElevatedPayloads,
1895
- ...completedStepRewardTransfers
1896
- ];
1897
- const [bw, txPayloads] = await new BoundWitnessBuilder2().fields({
1898
- block,
1899
- chain: chainId,
1900
- previous,
1901
- step_hashes,
1902
- protocol
1903
- }).meta({ $epoch: Date.now(), $signatures: [] }).signers(signers).payloads(await PayloadBuilder4.addStorageMeta(payloads)).build();
1904
- assertEx15(isBlockBoundWitness(bw), () => "Build of BlockBoundWitness failed");
1905
- return [await PayloadBuilder4.addStorageMeta(bw), txPayloads.map((p) => asAnyPayload3(p, true))];
1906
- }
1907
-
1908
- // src/test/buildNextBlock.ts
1909
- async function buildNextBlock(previousBlock, txs, blockPayloads, signers, chainStepRewardAddress = XYO_STEP_REWARD_ADDRESS2, stepRewardPoolBalance = AttoXL12(0n), protocol, chainId) {
1910
- return await buildBlock({
1911
- chainId: chainId ?? previousBlock.chain,
1912
- previousBlockNumber: previousBlock.block,
1913
- previousStepHashes: previousBlock.step_hashes ?? [],
1914
- previousBlockHash: previousBlock._hash,
1915
- txs,
1916
- blockPayloads,
1917
- signers,
1918
- protocol,
1919
- chainStepRewardAddress,
1920
- stepRewardPoolBalance
1921
- });
1922
- }
1923
-
1924
- // src/test/buildRandomGenesisBlock.ts
1925
- import { asAddress, assertEx as assertEx16 } from "@xylabs/sdk-js";
1926
- import {
1927
- Account as Account2,
1928
- asAnyPayload as asAnyPayload4,
1929
- asSchema as asSchema2,
1930
- IdSchema,
1931
- PayloadBuilder as PayloadBuilder5
1932
- } from "@xyo-network/sdk-js";
1933
- import {
1934
- asXL1BlockNumber as asXL1BlockNumber7
1935
- } from "@xyo-network/xl1-protocol-lib";
1936
-
1937
- // src/test/buildGenesisBlock.ts
1938
- import { XYO_ZERO_ADDRESS as XYO_ZERO_ADDRESS2 } from "@xyo-network/xl1-protocol-lib";
1939
- async function buildGenesisBlock(chainId, txs, blockPayloads, signers, chainStepRewardAddress = XYO_ZERO_ADDRESS2, protocol) {
1940
- return await buildBlock({
1941
- previousBlockHash: null,
1942
- chainId,
1943
- txs,
1944
- blockPayloads,
1945
- signers,
1946
- chainStepRewardAddress,
1947
- protocol
1948
- });
1949
- }
1950
-
1951
- // src/test/buildRandomGenesisBlock.ts
1952
- var TestChainId = assertEx16(asAddress("c5fe2e6F6841Cbab12d8C0618Be2DF8C6156cC44"));
1953
-
1954
- // src/test/createGenesisBlock.ts
1955
- import { PayloadBuilder as PayloadBuilder7 } from "@xyo-network/sdk-js";
1956
- import {
1957
- BlockBoundWitnessSchemaPayload,
1958
- BlockBoundWitnessWithStorageMetaSchemaPayload,
1959
- ChainStakeIntentPayloadJsonSchemaPayload,
1960
- HashPayloadJsonSchemaPayload,
1961
- TransactionBoundWitnessSchemaPayload,
1962
- TransactionBoundWitnessWithStorageMetaSchemaPayload,
1963
- TransferPayloadJsonSchemaPayload
1964
- } from "@xyo-network/xl1-schema";
1965
-
1966
- // src/test/createProducerChainStakeIntentTransaction.ts
1967
- import { PayloadBuilder as PayloadBuilder6 } from "@xyo-network/sdk-js";
1968
- import {
1969
- asXL1BlockNumber as asXL1BlockNumber8,
1970
- ChainStakeIntentSchema,
1971
- defaultTransactionFees as defaultTransactionFees2
1972
- } from "@xyo-network/xl1-protocol-lib";
1973
- async function createProducerChainStakeIntent(from, exp, nbf = 0) {
1974
- return await PayloadBuilder6.addHashMeta(new PayloadBuilder6({ schema: ChainStakeIntentSchema }).fields({
1975
- from,
1976
- exp,
1977
- nbf,
1978
- intent: "producer"
1979
- }).build());
1980
- }
1981
-
1982
- // src/test/createGenesisBlock.ts
1983
- var createGenesisBlock = async (initialBlockProducer, nextContractAddress, genesisBlockRewardAmount, genesisBlockRewardAddress) => {
1984
- const blockPayloads = await PayloadBuilder7.addHashMeta([
1985
- TransferPayloadJsonSchemaPayload,
1986
- BlockBoundWitnessSchemaPayload,
1987
- BlockBoundWitnessWithStorageMetaSchemaPayload,
1988
- TransactionBoundWitnessSchemaPayload,
1989
- TransactionBoundWitnessWithStorageMetaSchemaPayload,
1990
- ChainStakeIntentPayloadJsonSchemaPayload,
1991
- HashPayloadJsonSchemaPayload
1992
- ]);
1993
- const intentPayload = await createProducerChainStakeIntent(initialBlockProducer.address, 1, 0);
1994
- blockPayloads.push(intentPayload);
1995
- if (genesisBlockRewardAmount > 0n) {
1996
- blockPayloads.push(await PayloadBuilder7.addHashMeta(createTransferPayload(
1997
- nextContractAddress,
1998
- { [genesisBlockRewardAddress]: genesisBlockRewardAmount }
1999
- )));
2067
+ getBlockContextRead() {
2068
+ return {
2069
+ ...this.context,
2070
+ chainMap: this.store.chainMap
2071
+ };
2000
2072
  }
2001
- return await buildGenesisBlock(nextContractAddress, [], blockPayloads, [initialBlockProducer]);
2002
- };
2003
-
2004
- // src/test/buildRandomChain.ts
2005
- var TestGenesisBlockRewardAddress = assertEx17(asAddress2("fa7f0bb865a4bfff3d5e2c726d3e063297014da9"));
2006
- var buildRandomChain = async (blockProducer, count = 10, previousBlock, chainId, transactionAccount, receiverAddresses) => {
2007
- const chainIdToUse = chainId ?? TestChainId;
2008
- const blocks = [];
2009
- let remaining = count;
2010
- let lastBlock = previousBlock;
2011
- const transactionAccountToUse = transactionAccount ?? await Account3.random();
2012
- if (!lastBlock) {
2013
- const block = await createGenesisBlock(
2014
- blockProducer,
2015
- chainIdToUse,
2016
- 1000000000n * 10n ** 18n,
2017
- transactionAccountToUse.address
2018
- );
2019
- blocks.push(block);
2020
- remaining = remaining - 1;
2021
- lastBlock = block;
2073
+ async getChainContextRead() {
2074
+ return {
2075
+ ...this.getBlockContextRead(),
2076
+ head: (await this.head())[0]
2077
+ };
2022
2078
  }
2023
- const resolvedReceiverAddresses = receiverAddresses ?? [(await Account3.random()).address];
2024
- let saltCounter = 0;
2025
- while (remaining > 0) {
2026
- saltCounter += 1;
2027
- const payloads = [new PayloadBuilder8({ schema: IdSchema2 }).fields({ salt: `${Date.now()}-${saltCounter}` }).build()];
2028
- saltCounter += 1;
2029
- const additionalPrivatePayloads = remaining % 2 === 0 ? [new PayloadBuilder8({ schema: asSchema3("network.xyo.private", true) }).fields({ salt: `${Date.now()}-${saltCounter}` }).build()] : [];
2030
- const txs = [];
2031
- for (const receiverAddress of resolvedReceiverAddresses) {
2032
- txs.push(await buildRandomTransaction(
2033
- chainIdToUse,
2034
- [...payloads, ...additionalPrivatePayloads],
2035
- transactionAccountToUse,
2036
- asXL1BlockNumber9(Math.max(count - remaining - 1e3, 0), true),
2037
- asXL1BlockNumber9(count - remaining + 1e3, true),
2038
- [asSchema3("network.xyo.private", true)],
2039
- receiverAddress
2040
- ));
2041
- }
2042
- const previousBlock2 = assertEx17(lastBlock?.[0], () => new Error("No last block"));
2043
- const block = await buildNextBlock(previousBlock2, txs, [], [blockProducer], transactionAccountToUse.address);
2044
- blocks.push(block);
2045
- remaining = remaining - 1;
2046
- lastBlock = block;
2079
+ async getCurrentHead() {
2080
+ const chainArchivist = this.finalizedArchivist;
2081
+ const result = assertEx17(await findMostRecentBlock(chainArchivist), () => "Could not find most recent block [getCurrentHead]");
2082
+ assertEx17(result?.chain === this._chainId, () => "Chain ID does not match head block chain ID");
2083
+ return result;
2047
2084
  }
2048
- return blocks;
2049
2085
  };
2050
- async function buildRandomChainArchivist(count = 20) {
2051
- const producerAccount = await Account3.random();
2052
- const blocks = await buildRandomChain(producerAccount, count);
2053
- const archivist = await MemoryArchivist.create();
2054
- const payloads = flattenHydratedBlocks(blocks);
2055
- await archivist.insert(payloads);
2056
- return archivist;
2057
- }
2086
+ __publicField(SimpleFinalizationViewer, "defaultMoniker", FinalizationViewerMoniker3);
2087
+ __publicField(SimpleFinalizationViewer, "dependencies", [ChainContractViewerMoniker2]);
2088
+ __publicField(SimpleFinalizationViewer, "monikers", [FinalizationViewerMoniker3]);
2089
+ SimpleFinalizationViewer = __decorateClass([
2090
+ creatableProvider()
2091
+ ], SimpleFinalizationViewer);
2058
2092
 
2059
2093
  // src/test/getSimpleBlockViewerLocator.ts
2060
2094
  async function getTestSimpleBlockViewerLocator({
@@ -2083,6 +2117,9 @@ function getTestProviderContext2(config) {
2083
2117
  return getTestProviderContext(config);
2084
2118
  }
2085
2119
  export {
2120
+ TestGenesisBlockRewardAddress,
2121
+ buildRandomChain,
2122
+ buildRandomChainArchivist,
2086
2123
  buildRandomTransaction,
2087
2124
  getTestProviderContext2 as getTestProviderContext,
2088
2125
  getTestSimpleBlockViewerLocator