@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.
- package/dist/neutral/CreatableProvider/AbstractCreatableProvider.d.ts +7 -0
- package/dist/neutral/CreatableProvider/AbstractCreatableProvider.d.ts.map +1 -1
- package/dist/neutral/config/Actor.d.ts +42 -0
- package/dist/neutral/config/Actor.d.ts.map +1 -1
- package/dist/neutral/config/Actors.d.ts +7 -0
- package/dist/neutral/config/Actors.d.ts.map +1 -1
- package/dist/neutral/config/Base.d.ts +7 -0
- package/dist/neutral/config/Base.d.ts.map +1 -1
- package/dist/neutral/config/Config.d.ts +28 -0
- package/dist/neutral/config/Config.d.ts.map +1 -1
- package/dist/neutral/config/HostActor.d.ts +42 -0
- package/dist/neutral/config/HostActor.d.ts.map +1 -1
- package/dist/neutral/config/index.d.ts +1 -1
- package/dist/neutral/config/index.d.ts.map +1 -1
- package/dist/neutral/config/storage/Storage.d.ts +7 -0
- package/dist/neutral/config/storage/Storage.d.ts.map +1 -1
- package/dist/neutral/config/storage/driver/R2.d.ts +25 -0
- package/dist/neutral/config/storage/driver/R2.d.ts.map +1 -0
- package/dist/neutral/config/storage/driver/index.d.ts +1 -0
- package/dist/neutral/config/storage/driver/index.d.ts.map +1 -1
- package/dist/neutral/context/Actor.d.ts +42 -0
- package/dist/neutral/context/Actor.d.ts.map +1 -1
- package/dist/neutral/context/HostActor.d.ts +42 -0
- package/dist/neutral/context/HostActor.d.ts.map +1 -1
- package/dist/neutral/getFileConfig.d.ts +14 -0
- package/dist/neutral/getFileConfig.d.ts.map +1 -1
- package/dist/neutral/getFileConfig.mjs +76 -44
- package/dist/neutral/getFileConfig.mjs.map +4 -4
- package/dist/neutral/index.d.ts +1 -0
- package/dist/neutral/index.d.ts.map +1 -1
- package/dist/neutral/index.mjs +560 -156
- package/dist/neutral/index.mjs.map +4 -4
- package/dist/neutral/model/CreatableProviderContext.zod.d.ts +42 -0
- package/dist/neutral/model/CreatableProviderContext.zod.d.ts.map +1 -1
- package/dist/neutral/test/index.d.ts +1 -0
- package/dist/neutral/test/index.d.ts.map +1 -1
- package/dist/neutral/test/index.mjs +1056 -1019
- package/dist/neutral/test/index.mjs.map +4 -4
- 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/
|
|
15
|
-
import {
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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 {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
|
|
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/
|
|
85
|
-
|
|
40
|
+
// src/block/hydrate/flattenHydratedBlocks.ts
|
|
41
|
+
var flattenHydratedBlocks = (hydratedBlocks) => hydratedBlocks.flatMap((blk) => flattenHydratedBlock(blk));
|
|
86
42
|
|
|
87
|
-
// src/
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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/
|
|
95
|
-
import {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
130
|
-
|
|
99
|
+
if (isUndefined(context.caches[name])) {
|
|
100
|
+
context.caches[name] = create?.() ?? new MemoryMap();
|
|
131
101
|
}
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
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
|
-
|
|
191
|
-
|
|
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
|
-
|
|
194
|
-
|
|
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
|
-
|
|
197
|
-
|
|
315
|
+
const typedValue = value;
|
|
316
|
+
if (!isArray(typedValue.blockPayloads) || !isAddress(typedValue.chainId) || !isArray(typedValue.signers) || !isArray(typedValue.txs)) {
|
|
317
|
+
return false;
|
|
198
318
|
}
|
|
199
|
-
|
|
200
|
-
|
|
319
|
+
return true;
|
|
320
|
+
};
|
|
321
|
+
var isBuildGenesisBlockOptions = (value) => {
|
|
322
|
+
if (!isBaseBuildBlockOptions(value)) {
|
|
323
|
+
return false;
|
|
201
324
|
}
|
|
202
|
-
|
|
203
|
-
|
|
325
|
+
const typedValue = value;
|
|
326
|
+
if (typedValue.previousBlockHash !== null) {
|
|
327
|
+
return false;
|
|
204
328
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
return factory;
|
|
329
|
+
if (typedValue.previousBlockNumber !== void 0) {
|
|
330
|
+
return false;
|
|
208
331
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
return
|
|
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
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
235
|
-
return
|
|
342
|
+
if (!isNumber(typedValue.previousBlockNumber)) {
|
|
343
|
+
return false;
|
|
236
344
|
}
|
|
237
|
-
|
|
238
|
-
return
|
|
345
|
+
if (!isArray(typedValue.previousStepHashes)) {
|
|
346
|
+
return false;
|
|
239
347
|
}
|
|
348
|
+
return true;
|
|
240
349
|
};
|
|
241
350
|
|
|
242
|
-
// src/
|
|
243
|
-
function
|
|
244
|
-
return (
|
|
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
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
993
|
+
import { globalRegistry as globalRegistry13, z as z17 } from "zod/mini";
|
|
454
994
|
|
|
455
995
|
// src/config/Base.ts
|
|
456
|
-
import { z as
|
|
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/
|
|
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
|
|
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
|
-
|
|
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
|
|
670
|
-
var MetricsScrapeConfigZod =
|
|
671
|
-
path:
|
|
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:
|
|
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 =
|
|
684
|
-
var OpenTelemetryConfigZod =
|
|
1255
|
+
var MetricsConfigZod = z14.object({ scrape: MetricsScrapeConfigZod }).describe("Metrics configuration options");
|
|
1256
|
+
var OpenTelemetryConfigZod = z14.object({
|
|
685
1257
|
// OpenTelemetry options
|
|
686
|
-
otlpEndpoint:
|
|
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 =
|
|
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
|
|
1273
|
+
import { globalRegistry as globalRegistry12, z as z15 } from "zod";
|
|
702
1274
|
|
|
703
1275
|
// src/primitives/block/rate/blockRate.ts
|
|
704
|
-
import { isDefined as
|
|
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
|
|
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 =
|
|
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 =
|
|
766
|
-
const returnedTimeDifference =
|
|
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:
|
|
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
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
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
|
|
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/
|
|
1370
|
+
// src/primitives/block/rate/stepRate.ts
|
|
1371
|
+
import { assertEx as assertEx11 } from "@xylabs/sdk-js";
|
|
1081
1372
|
import {
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
} from "@
|
|
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
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
1177
|
-
allowedRewardRedeemers:
|
|
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:
|
|
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:
|
|
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:
|
|
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 =
|
|
1203
|
-
chain:
|
|
1204
|
-
dataLake:
|
|
1205
|
-
evm:
|
|
1206
|
-
log:
|
|
1207
|
-
providers:
|
|
1208
|
-
remote:
|
|
1209
|
-
storage:
|
|
1210
|
-
telemetry:
|
|
1211
|
-
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 =
|
|
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 =
|
|
1220
|
-
name:
|
|
1221
|
-
accountPath:
|
|
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
|
|
1233
|
-
var ActorsConfigZod =
|
|
1234
|
-
|
|
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
|
|
1240
|
-
var ConfigZod =
|
|
1575
|
+
import { globalRegistry as globalRegistry14, z as z19 } from "zod/mini";
|
|
1576
|
+
var ConfigZod = z19.extend(BaseConfigZod, {
|
|
1241
1577
|
actors: ActorsConfigZod,
|
|
1242
|
-
healthCheckPort:
|
|
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(
|
|
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 =
|
|
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
|
|
1604
|
+
import { assertEx as assertEx14, spanRootAsync } from "@xylabs/sdk-js";
|
|
1269
1605
|
import { isAnyPayload } from "@xyo-network/sdk-js";
|
|
1270
|
-
import { asXL1BlockNumber as
|
|
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 =
|
|
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 =
|
|
1294
|
-
|
|
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
|
|
1666
|
+
assertEx as assertEx15,
|
|
1331
1667
|
exists,
|
|
1332
|
-
isUndefined as
|
|
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
|
|
1674
|
+
asXL1BlockNumber as asXL1BlockNumber9,
|
|
1339
1675
|
asXL1BlockRange as asXL1BlockRange4,
|
|
1340
1676
|
BlockViewerMoniker,
|
|
1341
1677
|
FinalizationViewerMoniker,
|
|
1342
1678
|
stepSize as stepSize2,
|
|
1343
|
-
StepSizes as
|
|
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 =
|
|
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
|
-
|
|
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:
|
|
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 (
|
|
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
|
-
|
|
1444
|
-
|
|
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
|
-
|
|
1459
|
-
|
|
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 (
|
|
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 =
|
|
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
|
-
|
|
1813
|
+
assertEx15(Number.isInteger(stepIndex) && stepIndex >= 0, () => "stepIndex must be a non-negative integer");
|
|
1478
1814
|
const size = stepSize2(stepLevel);
|
|
1479
|
-
|
|
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 (
|
|
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 :
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
1818
|
-
|
|
1819
|
-
return false;
|
|
2030
|
+
get store() {
|
|
2031
|
+
return this._store;
|
|
1820
2032
|
}
|
|
1821
|
-
|
|
1822
|
-
return
|
|
2033
|
+
static async paramsHandler(params) {
|
|
2034
|
+
return {
|
|
2035
|
+
...await super.paramsHandler(params),
|
|
2036
|
+
finalizedArchivist: assertEx17(params.finalizedArchivist, () => "finalizedArchivist is required")
|
|
2037
|
+
};
|
|
1823
2038
|
}
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
var isBuildNextBlockOptions = (value) => {
|
|
1827
|
-
if (!isBaseBuildBlockOptions(value)) {
|
|
1828
|
-
return false;
|
|
2039
|
+
chainId() {
|
|
2040
|
+
return this._chainId;
|
|
1829
2041
|
}
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
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
|
-
|
|
1835
|
-
return
|
|
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
|
-
|
|
1838
|
-
return
|
|
2058
|
+
async headBlock() {
|
|
2059
|
+
return (await this.head())[0];
|
|
1839
2060
|
}
|
|
1840
|
-
|
|
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
|
-
|
|
1871
|
-
|
|
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
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
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
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
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
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
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
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
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
|