@recoillink/cli 0.0.0-stage → 45.0.1
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/LICENSE.md +193 -0
- package/README.md +149 -2
- package/bundle/154.index.js +462 -0
- package/bundle/230.index.js +569 -0
- package/bundle/25.index.js +9569 -0
- package/bundle/267.index.js +1386 -0
- package/bundle/308.index.js +5121 -0
- package/bundle/367.index.js +4 -0
- package/bundle/369.index.js +3443 -0
- package/bundle/529.index.js +3596 -0
- package/bundle/576.index.js +36 -0
- package/bundle/610.index.js +86 -0
- package/bundle/617.index.js +1612 -0
- package/bundle/628.index.js +152 -0
- package/bundle/633.index.js +86 -0
- package/bundle/697.index.js +410 -0
- package/bundle/7183ea1c1bf0a5da980d.js +214 -0
- package/bundle/748.index.js +672 -0
- package/bundle/78.index.js +372 -0
- package/bundle/841.index.js +2093 -0
- package/bundle/868.index.js +290 -0
- package/bundle/902.index.js +173 -0
- package/bundle/956.index.js +9901 -0
- package/bundle/aleo_wasm.wasm +0 -0
- package/bundle/aleo_wasm1.wasm +0 -0
- package/bundle/build/Release/bigint_buffer.node +0 -0
- package/bundle/file.js +12 -0
- package/bundle/index.js +4 -0
- package/bundle/package.json +3 -0
- package/bundle/worker-pipeline.js +38 -0
- package/bundle/worker.js +54 -0
- package/bundle/worker1.js +171 -0
- package/bundle/worker2.js +19834 -0
- package/bundle/worker3.js +19834 -0
- package/examples/aleo/core-config.yaml +19 -0
- package/examples/ccip/ccip-warp-route.yaml +26 -0
- package/examples/ccip/multi-chain-ccip-warp-route.yaml +81 -0
- package/examples/chain-config.yaml +42 -0
- package/examples/contract-artifacts.yaml +20 -0
- package/examples/core-config.yaml +19 -0
- package/examples/cosmosnative/core-config.yaml +20 -0
- package/examples/cosmosnative/warp-route-deployment.yaml +21 -0
- package/examples/crosschain/README.md +31 -0
- package/examples/crosschain/cosmosnative/core-config.yaml +69 -0
- package/examples/crosschain/ethereum/core-config.yaml +70 -0
- package/examples/crosschain/radix/core-config.yaml +96 -0
- package/examples/fork/file-transactions.yaml +5 -0
- package/examples/fork/timelock-testing.yaml +36 -0
- package/examples/fork/warp-route-update.yaml +100 -0
- package/examples/hooks.yaml +70 -0
- package/examples/ism-advanced.yaml +33 -0
- package/examples/ism.yaml +13 -0
- package/examples/radix/core-config.yaml +29 -0
- package/examples/sealevel/core-config-apply.yaml +7 -0
- package/examples/sealevel/core-config-composite-ism.yaml +21 -0
- package/examples/sealevel/core-config.yaml +12 -0
- package/examples/sealevel/igp-hook-config.yaml +13 -0
- package/examples/sealevel/warp-config-routing-message-id-multisig-ism.yaml +21 -0
- package/examples/starknet/core-config.yaml +20 -0
- package/examples/submit/strategy/file-strategy.yaml +8 -0
- package/examples/submit/strategy/gnosis-chain-strategy.yaml +10 -0
- package/examples/submit/strategy/gnosis-chain-tx-builder-strategy.yaml +6 -0
- package/examples/submit/strategy/gnosis-strategy-avalanche.yaml +4 -0
- package/examples/submit/strategy/gnosis-tx-builder-ica-strategy.yaml +20 -0
- package/examples/submit/strategy/ica-timelock-strategy.yaml +15 -0
- package/examples/submit/strategy/impersonated-account-strategy.yaml +4 -0
- package/examples/submit/strategy/json-rpc-chain-strategy.yaml +8 -0
- package/examples/submit/strategy/json-rpc-ica-strategy.yaml +13 -0
- package/examples/submit/strategy/json-rpc-strategy.yaml +3 -0
- package/examples/submit/strategy/json-rpc-timelock-strategy.yaml +17 -0
- package/examples/submit/strategy/starknet-json-rpc-chain-strategy.yaml +11 -0
- package/examples/submit/transactions/anvil-transactions.yaml +10 -0
- package/examples/submit/transactions/avalanche-transactions.json +8 -0
- package/examples/submit/transactions/sepolia-transactions.json +8 -0
- package/examples/tron-core-config.yaml +18 -0
- package/examples/warp-base.yaml +24 -0
- package/examples/warp-config-predicate-mainnet.yaml +14 -0
- package/examples/warp-deployed-predicate-mainnet.yaml +19 -0
- package/examples/warp-ethereum.yaml +19 -0
- package/examples/warp-route-deployment.yaml +21 -0
- package/package.json +117 -3
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
export const id = 748;
|
|
2
|
+
export const ids = [748];
|
|
3
|
+
export const modules = {
|
|
4
|
+
|
|
5
|
+
/***/ 60367:
|
|
6
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
// EXPORTS
|
|
10
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
11
|
+
createSvmForkManager: () => (/* reexport */ createSvmForkManager),
|
|
12
|
+
parseSvmForkConfig: () => (/* reexport */ parseSvmForkConfig)
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// UNUSED EXPORTS: PrintableSvmTransactionSchema, SURFPOOL_MIN_VERSION, SolanaCluster, SurfpoolDatasourceMode, SvmForkManager, SvmRawForkConfigSchema, runSurfpoolNode
|
|
16
|
+
|
|
17
|
+
// EXTERNAL MODULE: external "child_process"
|
|
18
|
+
var external_child_process_ = __webpack_require__(35317);
|
|
19
|
+
// EXTERNAL MODULE: external "node:fs"
|
|
20
|
+
var external_node_fs_ = __webpack_require__(73024);
|
|
21
|
+
// EXTERNAL MODULE: external "node:net"
|
|
22
|
+
var external_node_net_ = __webpack_require__(77030);
|
|
23
|
+
// EXTERNAL MODULE: external "node:os"
|
|
24
|
+
var external_node_os_ = __webpack_require__(48161);
|
|
25
|
+
// EXTERNAL MODULE: external "node:path"
|
|
26
|
+
var external_node_path_ = __webpack_require__(76760);
|
|
27
|
+
// EXTERNAL MODULE: ../forking-sdk/dist/index.js + 3 modules
|
|
28
|
+
var dist = __webpack_require__(65310);
|
|
29
|
+
// EXTERNAL MODULE: ../utils/dist/logging.js
|
|
30
|
+
var logging = __webpack_require__(94523);
|
|
31
|
+
// EXTERNAL MODULE: ../utils/dist/typeof.js
|
|
32
|
+
var dist_typeof = __webpack_require__(73689);
|
|
33
|
+
// EXTERNAL MODULE: ../utils/dist/validation.js
|
|
34
|
+
var validation = __webpack_require__(21387);
|
|
35
|
+
// EXTERNAL MODULE: ../svm-sdk/dist/rpc.js + 9 modules
|
|
36
|
+
var dist_rpc = __webpack_require__(48080);
|
|
37
|
+
;// CONCATENATED MODULE: ../svm-sdk/dist/fork/surfpool-node.js
|
|
38
|
+
// eslint-disable-next-line import/no-nodejs-modules
|
|
39
|
+
|
|
40
|
+
// eslint-disable-next-line import/no-nodejs-modules
|
|
41
|
+
|
|
42
|
+
// eslint-disable-next-line import/no-nodejs-modules
|
|
43
|
+
|
|
44
|
+
// eslint-disable-next-line import/no-nodejs-modules
|
|
45
|
+
|
|
46
|
+
// eslint-disable-next-line import/no-nodejs-modules
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
const logger = logging/* rootLogger */.Jk.child({ module: 'surfpool-node' });
|
|
52
|
+
// Minimum acceptable local `surfpool` version; aligned with the docker image
|
|
53
|
+
// `surfpool/surfpool:1.5.0` used by the container runner in test infra.
|
|
54
|
+
const SURFPOOL_MIN_VERSION = '1.5.0';
|
|
55
|
+
// Install guidance surfaced whenever a compatible `surfpool` binary is missing.
|
|
56
|
+
// Points at the pinned, checksum-verified release rather than the mutable
|
|
57
|
+
// `run.surfpool.run` installer, so an operator (or agent) never pipes remote
|
|
58
|
+
// code to a shell.
|
|
59
|
+
const SURFPOOL_INSTALL_GUIDANCE = `Install a pinned surfpool ${SURFPOOL_MIN_VERSION}+ release from ` +
|
|
60
|
+
'https://github.com/txtx/surfpool/releases and verify its SHA-256 checksum; ' +
|
|
61
|
+
'do not pipe the mutable run.surfpool.run installer to a shell.';
|
|
62
|
+
// Env var surfpool reads for its fork datasource. Passing the (possibly
|
|
63
|
+
// credential-bearing) upstream URL this way keeps it out of the process argv.
|
|
64
|
+
const SURFPOOL_DATASOURCE_RPC_URL_ENV = 'SURFPOOL_DATASOURCE_RPC_URL';
|
|
65
|
+
// Per-probe RPC timeout so a single hung request fails fast and the bounded
|
|
66
|
+
// readiness loop can continue.
|
|
67
|
+
const RPC_PROBE_TIMEOUT_MS = 5000;
|
|
68
|
+
// Cap on the retained tail of surfpool stderr, surfaced in exit errors.
|
|
69
|
+
const STDERR_TAIL_MAX = 8192;
|
|
70
|
+
const REDACTED_DATASOURCE_URL = '<redacted-datasource-url>';
|
|
71
|
+
// URL userinfo credentials (scheme://user:pass@host). A defense-in-depth
|
|
72
|
+
// backstop that scrubs a reformatted/percent-encoded credential the exact
|
|
73
|
+
// datasource-URL match would miss.
|
|
74
|
+
const URL_USERINFO_CREDENTIALS_RE = /\/\/[^/@\s]+:[^/@\s]+@/g;
|
|
75
|
+
/**
|
|
76
|
+
* Scrubs secrets from surfpool stderr before it is embedded in a surfaced error.
|
|
77
|
+
* surfpool prints stderr verbatim (not shell-escaped), so the known
|
|
78
|
+
* credential-bearing datasource URL is removed by exact-string replacement;
|
|
79
|
+
* stripping URL userinfo credentials is a backstop for any other credential URL.
|
|
80
|
+
*/
|
|
81
|
+
function redactSurfpoolStderr(detail, datasourceUrl) {
|
|
82
|
+
const withoutDatasource = (0,dist_typeof/* isNullish */.u)(datasourceUrl)
|
|
83
|
+
? detail
|
|
84
|
+
: detail.split(datasourceUrl).join(REDACTED_DATASOURCE_URL);
|
|
85
|
+
return withoutDatasource.replace(URL_USERINFO_CREDENTIALS_RE, '//<redacted>@');
|
|
86
|
+
}
|
|
87
|
+
const SurfpoolDatasourceMode = {
|
|
88
|
+
Fork: 'fork',
|
|
89
|
+
Network: 'network',
|
|
90
|
+
Offline: 'offline',
|
|
91
|
+
};
|
|
92
|
+
const SolanaCluster = {
|
|
93
|
+
Mainnet: 'mainnet',
|
|
94
|
+
Devnet: 'devnet',
|
|
95
|
+
Testnet: 'testnet',
|
|
96
|
+
};
|
|
97
|
+
const SURFPOOL_BINARY_PATHS = [
|
|
98
|
+
(0,external_node_path_.join)((0,external_node_os_.homedir)(), '.cargo/bin'),
|
|
99
|
+
'/opt/homebrew/bin',
|
|
100
|
+
'/usr/local/bin',
|
|
101
|
+
];
|
|
102
|
+
function parseVersion(version) {
|
|
103
|
+
const match = version.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
104
|
+
if (!match)
|
|
105
|
+
return null;
|
|
106
|
+
const [, major, minor, patch] = match;
|
|
107
|
+
(0,validation/* assert */.v)(major && minor && patch, `Invalid surfpool version: ${version}`);
|
|
108
|
+
return {
|
|
109
|
+
major: parseInt(major, 10),
|
|
110
|
+
minor: parseInt(minor, 10),
|
|
111
|
+
patch: parseInt(patch, 10),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function meetsMinVersion(version, min) {
|
|
115
|
+
if (version.major !== min.major)
|
|
116
|
+
return version.major > min.major;
|
|
117
|
+
if (version.minor !== min.minor)
|
|
118
|
+
return version.minor > min.minor;
|
|
119
|
+
return version.patch >= min.patch;
|
|
120
|
+
}
|
|
121
|
+
function getSurfpoolVersion(binaryPath) {
|
|
122
|
+
try {
|
|
123
|
+
const output = (0,external_child_process_.execFileSync)(binaryPath, ['--version'], {
|
|
124
|
+
encoding: 'utf-8',
|
|
125
|
+
});
|
|
126
|
+
const match = output.match(/surfpool\s+(\d+\.\d+\.\d+)/);
|
|
127
|
+
return match?.[1] ?? null;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
logger.debug({ err: error }, `failed to get surfpool version at ${binaryPath}`);
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function findSurfpoolCandidates() {
|
|
135
|
+
const candidates = [];
|
|
136
|
+
for (const basePath of SURFPOOL_BINARY_PATHS) {
|
|
137
|
+
const binaryPath = (0,external_node_path_.join)(basePath, 'surfpool');
|
|
138
|
+
if ((0,external_node_fs_.existsSync)(binaryPath)) {
|
|
139
|
+
const version = getSurfpoolVersion(binaryPath);
|
|
140
|
+
if (version) {
|
|
141
|
+
candidates.push({ path: binaryPath, version });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const result = (0,external_child_process_.execSync)('which surfpool', { encoding: 'utf-8' }).trim();
|
|
147
|
+
if (result && (0,external_node_fs_.existsSync)(result)) {
|
|
148
|
+
const version = getSurfpoolVersion(result);
|
|
149
|
+
if (version && !candidates.some((c) => c.path === result)) {
|
|
150
|
+
candidates.push({ path: result, version });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
logger.debug({ err: error }, 'surfpool not found in PATH');
|
|
156
|
+
}
|
|
157
|
+
return candidates;
|
|
158
|
+
}
|
|
159
|
+
function buildSurfpoolArgs(config, datasource, bindHost) {
|
|
160
|
+
const args = [
|
|
161
|
+
'start',
|
|
162
|
+
'--no-tui',
|
|
163
|
+
'--no-studio',
|
|
164
|
+
'--no-deploy',
|
|
165
|
+
'--host',
|
|
166
|
+
bindHost,
|
|
167
|
+
'--port',
|
|
168
|
+
String(config.rpcPort),
|
|
169
|
+
];
|
|
170
|
+
if (!(0,dist_typeof/* isNullish */.u)(config.wsPort)) {
|
|
171
|
+
args.push('--ws-port', String(config.wsPort));
|
|
172
|
+
}
|
|
173
|
+
if (datasource.mode === SurfpoolDatasourceMode.Network) {
|
|
174
|
+
args.push('--network', datasource.network);
|
|
175
|
+
}
|
|
176
|
+
else if (datasource.mode === SurfpoolDatasourceMode.Offline) {
|
|
177
|
+
args.push('--offline');
|
|
178
|
+
}
|
|
179
|
+
// Fork mode: the datasource URL is passed via the SURFPOOL_DATASOURCE_RPC_URL
|
|
180
|
+
// env (see buildSurfpoolDatasourceEnv) rather than argv.
|
|
181
|
+
if (config.skipSignatureVerification) {
|
|
182
|
+
args.push('--skip-signature-verification');
|
|
183
|
+
}
|
|
184
|
+
if (config.skipBlockhashCheck) {
|
|
185
|
+
args.push('--skip-blockhash-check');
|
|
186
|
+
}
|
|
187
|
+
if (config.airdrops && config.airdrops.addresses.length > 0) {
|
|
188
|
+
for (const address of config.airdrops.addresses) {
|
|
189
|
+
args.push('--airdrop', address);
|
|
190
|
+
}
|
|
191
|
+
args.push('--airdrop-amount', config.airdrops.lamports.toString());
|
|
192
|
+
}
|
|
193
|
+
return args;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Spawn env carrying surfpool's fork datasource URL. Empty for network/offline
|
|
197
|
+
* datasources, which take no credentials and are expressed via argv flags.
|
|
198
|
+
*/
|
|
199
|
+
function buildSurfpoolDatasourceEnv(datasource) {
|
|
200
|
+
if (datasource.mode !== SurfpoolDatasourceMode.Fork) {
|
|
201
|
+
return {};
|
|
202
|
+
}
|
|
203
|
+
return { [SURFPOOL_DATASOURCE_RPC_URL_ENV]: datasource.rpcUrl };
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Per-attempt abort signal that fires after `timeoutMs`, or immediately when
|
|
207
|
+
* `parent` aborts (so a caller cancelling the readiness loop also cancels the
|
|
208
|
+
* in-flight probe request). Composed manually to stay usable on Node <17, which
|
|
209
|
+
* lacks `AbortSignal.timeout`/`AbortSignal.any`. `dispose` clears the timer and
|
|
210
|
+
* detaches the parent listener so nothing lingers between attempts.
|
|
211
|
+
*/
|
|
212
|
+
function probeTimeoutSignal(timeoutMs, parent) {
|
|
213
|
+
const controller = new AbortController();
|
|
214
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
215
|
+
const onParentAbort = () => controller.abort();
|
|
216
|
+
if (parent) {
|
|
217
|
+
if (parent.aborted) {
|
|
218
|
+
controller.abort();
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
parent.addEventListener('abort', onParentAbort, { once: true });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const dispose = () => {
|
|
225
|
+
clearTimeout(timer);
|
|
226
|
+
parent?.removeEventListener('abort', onParentAbort);
|
|
227
|
+
};
|
|
228
|
+
return { signal: controller.signal, dispose };
|
|
229
|
+
}
|
|
230
|
+
async function waitForSolanaRpcReady(rpcUrl, signal) {
|
|
231
|
+
const rpc = (0,dist_rpc/* createRpc */.C8)(rpcUrl);
|
|
232
|
+
await (0,dist/* waitUntilReady */.bs)(async () => {
|
|
233
|
+
const { signal: probeSignal, dispose } = probeTimeoutSignal(RPC_PROBE_TIMEOUT_MS, signal);
|
|
234
|
+
try {
|
|
235
|
+
const health = await rpc.getHealth().send({ abortSignal: probeSignal });
|
|
236
|
+
(0,validation/* assert */.v)(health === 'ok', `surfpool RPC not healthy: ${health}`);
|
|
237
|
+
}
|
|
238
|
+
finally {
|
|
239
|
+
dispose();
|
|
240
|
+
}
|
|
241
|
+
}, { attempts: 60, baseRetryMs: 1000, signal });
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Rejects if `port` on 127.0.0.1 is already bound. A bind-test up front closes
|
|
245
|
+
* the port-collision race: proving RPC health after spawn can otherwise pass
|
|
246
|
+
* against an unrelated node already listening on the port, before our freshly
|
|
247
|
+
* spawned child fails with EADDRINUSE.
|
|
248
|
+
*/
|
|
249
|
+
async function assertPortAvailable(port) {
|
|
250
|
+
await new Promise((resolve, reject) => {
|
|
251
|
+
const server = (0,external_node_net_.createServer)();
|
|
252
|
+
server.once('error', (error) => {
|
|
253
|
+
const code = 'code' in error ? error.code : undefined;
|
|
254
|
+
reject(code === 'EADDRINUSE'
|
|
255
|
+
? new Error(`port ${port} is already in use`)
|
|
256
|
+
: error);
|
|
257
|
+
});
|
|
258
|
+
server.once('listening', () => {
|
|
259
|
+
server.close(() => resolve());
|
|
260
|
+
});
|
|
261
|
+
server.listen(port, '127.0.0.1');
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
// A single process-level `exit` hook kills every still-running fork, rather than
|
|
265
|
+
// one listener per fork — which would trip MaxListenersExceededWarning past ten
|
|
266
|
+
// forks and retain each child's closure until process exit. A fork joins the
|
|
267
|
+
// registry on start and leaves when it is killed or its child exits.
|
|
268
|
+
const runningForkKills = new Set();
|
|
269
|
+
let forkExitHookInstalled = false;
|
|
270
|
+
function trackForkExit(killFork) {
|
|
271
|
+
runningForkKills.add(killFork);
|
|
272
|
+
if (!forkExitHookInstalled) {
|
|
273
|
+
forkExitHookInstalled = true;
|
|
274
|
+
process.once('exit', () => {
|
|
275
|
+
for (const kill of Array.from(runningForkKills)) {
|
|
276
|
+
kill();
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
return () => {
|
|
281
|
+
runningForkKills.delete(killFork);
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
async function startLocalSurfpool(config, binaryPath, waitForRpcReady = waitForSolanaRpcReady) {
|
|
285
|
+
// Fail fast if any bind port is taken, before spawning, so we never treat
|
|
286
|
+
// another process's RPC as our fork and never spawn a doomed child that would
|
|
287
|
+
// fail to bind an occupied ws port.
|
|
288
|
+
await assertPortAvailable(config.rpcPort);
|
|
289
|
+
if (!(0,dist_typeof/* isNullish */.u)(config.wsPort)) {
|
|
290
|
+
await assertPortAvailable(config.wsPort);
|
|
291
|
+
}
|
|
292
|
+
const args = buildSurfpoolArgs(config, config.datasource, '127.0.0.1');
|
|
293
|
+
// Suppress surfpool's own logs (its default ./.surfpool/logs dir would clutter
|
|
294
|
+
// the working dir); startup/bind failures still surface on stderr, drained below.
|
|
295
|
+
args.push('--log-level', 'none');
|
|
296
|
+
const proc = (0,external_child_process_.spawn)(binaryPath, args, {
|
|
297
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
298
|
+
detached: false,
|
|
299
|
+
env: { ...process.env, ...buildSurfpoolDatasourceEnv(config.datasource) },
|
|
300
|
+
});
|
|
301
|
+
// Drain stderr into a bounded tail; reading it also keeps the pipe from
|
|
302
|
+
// filling and blocking the child.
|
|
303
|
+
let stderrTail = '';
|
|
304
|
+
proc.stderr?.on('data', (chunk) => {
|
|
305
|
+
stderrTail = (stderrTail + chunk.toString()).slice(-STDERR_TAIL_MAX);
|
|
306
|
+
});
|
|
307
|
+
const rpcUrl = `http://127.0.0.1:${config.rpcPort}`;
|
|
308
|
+
const datasourceUrl = config.datasource.mode === SurfpoolDatasourceMode.Fork
|
|
309
|
+
? config.datasource.rpcUrl
|
|
310
|
+
: undefined;
|
|
311
|
+
const kill = () => {
|
|
312
|
+
// Leave the process-exit registry whenever the child is gone (killed here,
|
|
313
|
+
// or exited/errored below) so a dead fork never keeps being tracked.
|
|
314
|
+
untrackFork();
|
|
315
|
+
if (config.keepRunning) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if ((0,dist_typeof/* isNullish */.u)(proc.exitCode)) {
|
|
319
|
+
proc.kill('SIGTERM');
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
const untrackFork = trackForkExit(kill);
|
|
323
|
+
// A failed spawn (e.g. ENOENT) emits `error` with no guaranteed `exit`, so the
|
|
324
|
+
// readiness race must reject on it — otherwise readiness burns the full probe
|
|
325
|
+
// timeout and reports a misleading RPC error instead of the real spawn failure.
|
|
326
|
+
// Attach synchronously here so no `error` can fire before a listener exists.
|
|
327
|
+
const errored = new Promise((_, reject) => {
|
|
328
|
+
proc.once('error', (error) => {
|
|
329
|
+
untrackFork();
|
|
330
|
+
logger.debug({ err: error }, 'surfpool process error');
|
|
331
|
+
reject(error);
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
// A spawn error arriving after readiness (or exit) has already settled the race
|
|
335
|
+
// must not surface as an unhandled rejection.
|
|
336
|
+
errored.catch(() => { });
|
|
337
|
+
// Capture the child's exit synchronously after spawn rather than lazily inside
|
|
338
|
+
// `waitForReady`: `exit` is not replayed, so a caller that waits after the
|
|
339
|
+
// child has already exited must still observe it instead of polling to the
|
|
340
|
+
// readiness bound. Rejecting here also drops the fork from the exit registry.
|
|
341
|
+
const exited = new Promise((_, reject) => {
|
|
342
|
+
proc.once('exit', (code, signal) => {
|
|
343
|
+
untrackFork();
|
|
344
|
+
const detail = redactSurfpoolStderr(stderrTail.trim(), datasourceUrl);
|
|
345
|
+
reject(new Error(`surfpool exited before its RPC was ready (code=${code}, signal=${signal})` +
|
|
346
|
+
(detail ? `: ${detail}` : '')));
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
// A later exit (e.g. on kill once readiness has won) must not surface as an
|
|
350
|
+
// unhandled rejection after the race settles.
|
|
351
|
+
exited.catch(() => { });
|
|
352
|
+
const waitForReady = async () => {
|
|
353
|
+
// Abort the readiness probe the instant the race settles so no retry timer
|
|
354
|
+
// keeps polling a dead port after an early exit or spawn error wins.
|
|
355
|
+
const controller = new AbortController();
|
|
356
|
+
try {
|
|
357
|
+
await Promise.race([
|
|
358
|
+
waitForRpcReady(rpcUrl, controller.signal),
|
|
359
|
+
exited,
|
|
360
|
+
errored,
|
|
361
|
+
]);
|
|
362
|
+
}
|
|
363
|
+
finally {
|
|
364
|
+
controller.abort();
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
return { node: { rpcUrl, kill }, waitForReady };
|
|
368
|
+
}
|
|
369
|
+
// A caller-supplied binary is an explicit choice, so failures name the specific
|
|
370
|
+
// cause (missing / not executable / too old) instead of the generic auto-
|
|
371
|
+
// discovery "no compatible binary" message, which would otherwise report the
|
|
372
|
+
// substituted "unknown" version and hide the real problem.
|
|
373
|
+
function resolveExplicitBinary(binaryPath, min) {
|
|
374
|
+
(0,validation/* assert */.v)((0,external_node_fs_.existsSync)(binaryPath), `surfpool binary not found at ${binaryPath}`);
|
|
375
|
+
const version = getSurfpoolVersion(binaryPath);
|
|
376
|
+
(0,validation/* assert */.v)(version, `surfpool binary at ${binaryPath} could not be run (check it is executable and 'surfpool --version' works).`);
|
|
377
|
+
const parsed = parseVersion(version);
|
|
378
|
+
(0,validation/* assert */.v)(parsed && meetsMinVersion(parsed, min), `surfpool at ${binaryPath} is version ${version} but ${SURFPOOL_MIN_VERSION}+ is required. ` +
|
|
379
|
+
SURFPOOL_INSTALL_GUIDANCE);
|
|
380
|
+
return { path: binaryPath, version };
|
|
381
|
+
}
|
|
382
|
+
function resolveDiscoveredBinary(min) {
|
|
383
|
+
const candidates = findSurfpoolCandidates();
|
|
384
|
+
const match = candidates.find((candidate) => {
|
|
385
|
+
const parsed = parseVersion(candidate.version);
|
|
386
|
+
return parsed !== null && meetsMinVersion(parsed, min);
|
|
387
|
+
});
|
|
388
|
+
(0,validation/* assert */.v)(match, candidates.length === 0
|
|
389
|
+
? `surfpool ${SURFPOOL_MIN_VERSION}+ is required but no surfpool binary was found on PATH. ` +
|
|
390
|
+
SURFPOOL_INSTALL_GUIDANCE
|
|
391
|
+
: `surfpool ${SURFPOOL_MIN_VERSION}+ is required but only found version(s) ` +
|
|
392
|
+
`${candidates.map((c) => c.version).join(', ')}. ` +
|
|
393
|
+
SURFPOOL_INSTALL_GUIDANCE);
|
|
394
|
+
return match;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Starts a surfpool node from a locally-installed `surfpool` binary (version
|
|
398
|
+
* {@link SURFPOOL_MIN_VERSION} or newer) and waits for its RPC to be ready.
|
|
399
|
+
* An explicit `config.binaryPath` is validated up front with a specific error;
|
|
400
|
+
* otherwise the PATH is searched and an install-guidance error is thrown if no
|
|
401
|
+
* compatible binary is found.
|
|
402
|
+
*/
|
|
403
|
+
async function runSurfpoolNode(config) {
|
|
404
|
+
const min = parseVersion(SURFPOOL_MIN_VERSION);
|
|
405
|
+
(0,validation/* assert */.v)(min, `Invalid SURFPOOL_MIN_VERSION: ${SURFPOOL_MIN_VERSION}`);
|
|
406
|
+
const match = config.binaryPath
|
|
407
|
+
? resolveExplicitBinary(config.binaryPath, min)
|
|
408
|
+
: resolveDiscoveredBinary(min);
|
|
409
|
+
logger.debug(`Using local surfpool binary: ${match.path} (v${match.version})`);
|
|
410
|
+
const { node, waitForReady } = await startLocalSurfpool(config, match.path);
|
|
411
|
+
try {
|
|
412
|
+
await waitForReady();
|
|
413
|
+
}
|
|
414
|
+
catch (error) {
|
|
415
|
+
node.kill();
|
|
416
|
+
throw error;
|
|
417
|
+
}
|
|
418
|
+
return node;
|
|
419
|
+
}
|
|
420
|
+
//# sourceMappingURL=surfpool-node.js.map
|
|
421
|
+
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+codecs-strings@8.2.0_@typescript+typescript6@6.0.2_fastestsmallesttextencoderdecoder@1.0.22/node_modules/@solana/codecs-strings/dist/index.node.mjs
|
|
422
|
+
var index_node = __webpack_require__(48990);
|
|
423
|
+
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+transactions@8.2.0_@typescript+typescript6@6.0.2_fastestsmallesttextencoderdecoder@1.0.22/node_modules/@solana/transactions/dist/index.node.mjs
|
|
424
|
+
var dist_index_node = __webpack_require__(11508);
|
|
425
|
+
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+transaction-messages@8.2.0_@typescript+typescript6@6.0.2_fastestsmallesttextencoderdecoder@1.0.22/node_modules/@solana/transaction-messages/dist/index.node.mjs
|
|
426
|
+
var transaction_messages_dist_index_node = __webpack_require__(13464);
|
|
427
|
+
// EXTERNAL MODULE: ../utils/dist/async.js
|
|
428
|
+
var dist_async = __webpack_require__(14918);
|
|
429
|
+
// EXTERNAL MODULE: ../svm-sdk/dist/accounts/address-lookup-table.js
|
|
430
|
+
var address_lookup_table = __webpack_require__(96971);
|
|
431
|
+
// EXTERNAL MODULE: ../svm-sdk/dist/constants.js
|
|
432
|
+
var constants = __webpack_require__(94327);
|
|
433
|
+
// EXTERNAL MODULE: ../svm-sdk/dist/tx.js
|
|
434
|
+
var tx = __webpack_require__(55960);
|
|
435
|
+
// EXTERNAL MODULE: ../svm-sdk/dist/fork/impersonation.js
|
|
436
|
+
var impersonation = __webpack_require__(44391);
|
|
437
|
+
;// CONCATENATED MODULE: ../svm-sdk/dist/fork/svm-fork-manager.js
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
const svm_fork_manager_logger = logging/* rootLogger */.Jk.child({ module: 'svm-fork-manager' });
|
|
447
|
+
const RPC_COMMITMENT = 'confirmed';
|
|
448
|
+
const POLL_INTERVAL_MS = 500;
|
|
449
|
+
const POLL_MAX_ATTEMPTS = 60;
|
|
450
|
+
const RESOLVE_ALT_CONCURRENCY = 4;
|
|
451
|
+
const base58Encoder = (0,index_node/* getBase58Encoder */.nZ)();
|
|
452
|
+
const transactionDecoder = (0,dist_index_node/* getTransactionDecoder */.BX)();
|
|
453
|
+
const compiledMessageDecoder = (0,transaction_messages_dist_index_node/* getCompiledTransactionMessageDecoder */.fr)();
|
|
454
|
+
/**
|
|
455
|
+
* Fetches the addresses stored in each address-lookup table referenced by a
|
|
456
|
+
* compiled message, producing the map kit needs to decompile the message and
|
|
457
|
+
* re-compress it against the same tables. Returns `undefined` for a message
|
|
458
|
+
* that uses no lookup tables (so callers can skip compression entirely).
|
|
459
|
+
*/
|
|
460
|
+
async function resolveForkLookupTables(rpc, compiledMessage) {
|
|
461
|
+
const lookups = 'addressTableLookups' in compiledMessage
|
|
462
|
+
? compiledMessage.addressTableLookups
|
|
463
|
+
: undefined;
|
|
464
|
+
if ((0,dist_typeof/* isNullish */.u)(lookups) || lookups.length === 0) {
|
|
465
|
+
return undefined;
|
|
466
|
+
}
|
|
467
|
+
const entries = await (0,dist_async/* concurrentMap */.q1)(RESOLVE_ALT_CONCURRENCY, lookups, async (lookup) => {
|
|
468
|
+
const state = await (0,address_lookup_table/* fetchAddressLookupTableState */.a)(rpc, lookup.lookupTableAddress);
|
|
469
|
+
return [lookup.lookupTableAddress, state.addresses];
|
|
470
|
+
});
|
|
471
|
+
return Object.fromEntries(entries);
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Rebuilds the wire transaction to replay against a fork.
|
|
475
|
+
*
|
|
476
|
+
* `transaction_base58` is serialized without the compute-budget instruction
|
|
477
|
+
* (an external executor — Squads / file submitter — prepends it from
|
|
478
|
+
* `computeUnits`, defaulting to {@link DEFAULT_COMPUTE_UNITS}). Replaying it
|
|
479
|
+
* verbatim leaves the tx under the runtime per-instruction default, so a tx that
|
|
480
|
+
* consumes more than that (e.g. a program upgrade) fails on the fork even though
|
|
481
|
+
* real execution succeeds. To match live/Squads execution exactly, every replay
|
|
482
|
+
* tx is decoded and re-emitted with the same `SetComputeUnitLimit` an external
|
|
483
|
+
* executor would prepend — using `computeUnits` when set, `DEFAULT_COMPUTE_UNITS`
|
|
484
|
+
* otherwise (mirroring `buildTransactionMessage`/`transactionToInstructions`).
|
|
485
|
+
*
|
|
486
|
+
* Any address-lookup-table compression in the source tx is preserved: the
|
|
487
|
+
* message is re-compressed against the same tables before compiling, so an
|
|
488
|
+
* ALT-heavy tx (e.g. cross-collateral reconciliation) stays under the 1232-byte
|
|
489
|
+
* packet limit instead of being re-emitted with the accounts inlined. The zero
|
|
490
|
+
* DEFAULT_BLOCKHASH is preserved and accepted because the fork runs with
|
|
491
|
+
* `skipBlockhashCheck` and the send uses `skipPreflight`.
|
|
492
|
+
*/
|
|
493
|
+
async function buildForkReplayTransaction(rpc, transaction) {
|
|
494
|
+
const wireBytes = base58Encoder.encode(transaction.transaction_base58);
|
|
495
|
+
const decoded = transactionDecoder.decode(wireBytes);
|
|
496
|
+
const units = transaction.computeUnits ?? constants/* DEFAULT_COMPUTE_UNITS */.I1;
|
|
497
|
+
const compiledMessage = compiledMessageDecoder.decode(decoded.messageBytes);
|
|
498
|
+
(0,validation/* assert */.v)(compiledMessage.version !== 1, 'v1 fork replay requires header-based compute budget support');
|
|
499
|
+
const addressLookupTables = await resolveForkLookupTables(rpc, compiledMessage);
|
|
500
|
+
const message = (0,transaction_messages_dist_index_node/* decompileTransactionMessage */.mm)(compiledMessage, {
|
|
501
|
+
addressesByLookupTableAddress: addressLookupTables,
|
|
502
|
+
});
|
|
503
|
+
const withComputeBudget = (0,transaction_messages_dist_index_node/* prependTransactionMessageInstructions */.rR)((0,tx/* getComputeBudgetInstructions */.oR)(units), message);
|
|
504
|
+
if ((0,dist_typeof/* isNullish */.u)(addressLookupTables)) {
|
|
505
|
+
return (0,dist_index_node/* getBase64EncodedWireTransaction */.RO)((0,dist_index_node/* compileTransaction */.i5)(withComputeBudget));
|
|
506
|
+
}
|
|
507
|
+
// Only versioned (v0) messages reference lookup tables, so a defined ALT map
|
|
508
|
+
// implies a non-legacy message; narrow so kit's compressor accepts it.
|
|
509
|
+
(0,validation/* assert */.v)(withComputeBudget.version === 0, 'address-lookup tables require a v0 transaction');
|
|
510
|
+
const recompressed = (0,transaction_messages_dist_index_node/* compressTransactionMessageUsingAddressLookupTables */.Zg)(withComputeBudget, addressLookupTables);
|
|
511
|
+
return (0,dist_index_node/* getBase64EncodedWireTransaction */.RO)((0,dist_index_node/* compileTransaction */.i5)(recompressed));
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Ensures the fork airdrops SOL to the fixed fork-only impersonation fee payer
|
|
515
|
+
* at boot, so keyless impersonated applies can pay fees. surfpool airdrops a
|
|
516
|
+
* single amount to every address, so the fee payer is merged into the caller's
|
|
517
|
+
* address list and the amount is raised to at least the impersonation buffer.
|
|
518
|
+
*/
|
|
519
|
+
function withImpersonationAirdrop(airdrops) {
|
|
520
|
+
const feePayer = impersonation/* FORK_IMPERSONATION_FEE_PAYER */.P.address;
|
|
521
|
+
if (!airdrops) {
|
|
522
|
+
return {
|
|
523
|
+
addresses: [feePayer],
|
|
524
|
+
lamports: impersonation/* FORK_IMPERSONATION_AIRDROP_LAMPORTS */.X,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
const addresses = airdrops.addresses.includes(feePayer)
|
|
528
|
+
? airdrops.addresses
|
|
529
|
+
: [...airdrops.addresses, feePayer];
|
|
530
|
+
const lamports = airdrops.lamports > impersonation/* FORK_IMPERSONATION_AIRDROP_LAMPORTS */.X
|
|
531
|
+
? airdrops.lamports
|
|
532
|
+
: impersonation/* FORK_IMPERSONATION_AIRDROP_LAMPORTS */.X;
|
|
533
|
+
return { addresses, lamports };
|
|
534
|
+
}
|
|
535
|
+
class RunningSvmFork {
|
|
536
|
+
node;
|
|
537
|
+
rpc;
|
|
538
|
+
rpcUrl;
|
|
539
|
+
constructor(node, rpc, rpcUrl) {
|
|
540
|
+
this.node = node;
|
|
541
|
+
this.rpc = rpc;
|
|
542
|
+
this.rpcUrl = rpcUrl;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
async function startSvmFork(config) {
|
|
546
|
+
const runNode = config.runNode ?? runSurfpoolNode;
|
|
547
|
+
const node = await runNode({
|
|
548
|
+
datasource: {
|
|
549
|
+
mode: SurfpoolDatasourceMode.Fork,
|
|
550
|
+
rpcUrl: config.upstreamRpcUrl,
|
|
551
|
+
},
|
|
552
|
+
rpcPort: config.rpcPort,
|
|
553
|
+
wsPort: config.wsPort,
|
|
554
|
+
airdrops: withImpersonationAirdrop(config.airdrops),
|
|
555
|
+
skipSignatureVerification: true,
|
|
556
|
+
skipBlockhashCheck: true,
|
|
557
|
+
image: config.image,
|
|
558
|
+
binaryPath: config.binaryPath,
|
|
559
|
+
keepRunning: config.keepRunning,
|
|
560
|
+
});
|
|
561
|
+
return new RunningSvmFork(node, (0,dist_rpc/* createRpc */.C8)(node.rpcUrl), node.rpcUrl);
|
|
562
|
+
}
|
|
563
|
+
class SvmForkManager {
|
|
564
|
+
config;
|
|
565
|
+
running;
|
|
566
|
+
constructor(config) {
|
|
567
|
+
this.config = config;
|
|
568
|
+
}
|
|
569
|
+
get requireRunning() {
|
|
570
|
+
const running = this.running;
|
|
571
|
+
(0,validation/* assert */.v)(running, `Fork not started for chain ${this.config.chainName}`);
|
|
572
|
+
return running;
|
|
573
|
+
}
|
|
574
|
+
async start() {
|
|
575
|
+
this.running = await startSvmFork(this.config);
|
|
576
|
+
}
|
|
577
|
+
async applyForkConfig(config) {
|
|
578
|
+
const { rpc } = this.requireRunning;
|
|
579
|
+
for (const transaction of config.transactions) {
|
|
580
|
+
await this.submitTransaction(rpc, transaction);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
getForkedChainMetadata() {
|
|
584
|
+
return {
|
|
585
|
+
rpcUrls: [{ http: this.requireRunning.rpcUrl }],
|
|
586
|
+
blocks: { confirmations: 1 },
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
kill() {
|
|
590
|
+
this.running?.node.kill();
|
|
591
|
+
}
|
|
592
|
+
async submitTransaction(rpc, transaction) {
|
|
593
|
+
const wireTransaction = await buildForkReplayTransaction(rpc, transaction);
|
|
594
|
+
svm_fork_manager_logger.debug({ annotation: transaction.annotation }, 'replaying transaction against fork');
|
|
595
|
+
const signature = await rpc
|
|
596
|
+
.sendTransaction(wireTransaction, {
|
|
597
|
+
encoding: 'base64',
|
|
598
|
+
skipPreflight: true,
|
|
599
|
+
maxRetries: 0n,
|
|
600
|
+
preflightCommitment: RPC_COMMITMENT,
|
|
601
|
+
})
|
|
602
|
+
.send();
|
|
603
|
+
const status = await (0,dist_async/* pollAsync */.kp)(async () => {
|
|
604
|
+
const { value } = await rpc.getSignatureStatuses([signature]).send();
|
|
605
|
+
const result = value[0];
|
|
606
|
+
(0,validation/* assert */.v)(result, `transaction ${signature} not processed yet`);
|
|
607
|
+
// A failed tx is terminal: resolve immediately so the assert below
|
|
608
|
+
// surfaces the failure instead of polling until the attempts run out.
|
|
609
|
+
if (!(0,dist_typeof/* isNullish */.u)(result.err)) {
|
|
610
|
+
return result;
|
|
611
|
+
}
|
|
612
|
+
// kit 6.x can report `processed` before `confirmed`; wait for the
|
|
613
|
+
// configured commitment so a dependent next tx doesn't race an
|
|
614
|
+
// unconfirmed one.
|
|
615
|
+
const confirmation = result.confirmationStatus;
|
|
616
|
+
(0,validation/* assert */.v)(confirmation === RPC_COMMITMENT || confirmation === 'finalized', `transaction ${signature} not yet ${RPC_COMMITMENT} (status: ${confirmation})`);
|
|
617
|
+
return result;
|
|
618
|
+
}, POLL_INTERVAL_MS, POLL_MAX_ATTEMPTS);
|
|
619
|
+
(0,validation/* assert */.v)((0,dist_typeof/* isNullish */.u)(status.err), `fork replay transaction ${signature} failed: ${JSON.stringify(status.err, (_key, value) => (typeof value === 'bigint' ? value.toString() : value))}`);
|
|
620
|
+
if (transaction.waitForSlotAdvance) {
|
|
621
|
+
const confirmedSlot = status.slot;
|
|
622
|
+
await (0,dist_async/* pollAsync */.kp)(async () => {
|
|
623
|
+
const slot = await rpc.getSlot({ commitment: RPC_COMMITMENT }).send();
|
|
624
|
+
(0,validation/* assert */.v)(slot > confirmedSlot, `slot ${slot} has not advanced past ${confirmedSlot}`);
|
|
625
|
+
}, POLL_INTERVAL_MS, POLL_MAX_ATTEMPTS);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
function createSvmForkManager(config) {
|
|
630
|
+
return new SvmForkManager(config);
|
|
631
|
+
}
|
|
632
|
+
//# sourceMappingURL=svm-fork-manager.js.map
|
|
633
|
+
// EXTERNAL MODULE: ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/schemas.js + 7 modules
|
|
634
|
+
var schemas = __webpack_require__(58228);
|
|
635
|
+
;// CONCATENATED MODULE: ../svm-sdk/dist/fork/svm-fork-config.js
|
|
636
|
+
|
|
637
|
+
const PrintableSvmTransactionSchema = schemas/* object */.Ik({
|
|
638
|
+
annotation: schemas/* string */.Yj().optional(),
|
|
639
|
+
instructions: schemas/* array */.YO(schemas/* unknown */.L5()).optional(),
|
|
640
|
+
computeUnits: schemas/* number */.ai().optional(),
|
|
641
|
+
transaction_base58: schemas/* string */.Yj(),
|
|
642
|
+
message_base58: schemas/* string */.Yj().optional(),
|
|
643
|
+
waitForSlotAdvance: schemas/* boolean */.zM().optional(),
|
|
644
|
+
});
|
|
645
|
+
const SvmRawForkConfigSchema = schemas/* union */.KC([
|
|
646
|
+
schemas/* object */.Ik({ transactions: schemas/* array */.YO(PrintableSvmTransactionSchema) }),
|
|
647
|
+
schemas/* object */.Ik({ path: schemas/* string */.Yj() }),
|
|
648
|
+
]);
|
|
649
|
+
/**
|
|
650
|
+
* Parses a per-chain SVM fork-config slice. A `path` reference loads the
|
|
651
|
+
* `warp apply --submitter file` output (a `PrintableSvmTransaction[]`) via the
|
|
652
|
+
* injected file reader; inline `transactions` are used directly.
|
|
653
|
+
*/
|
|
654
|
+
function parseSvmForkConfig(raw, fileReader) {
|
|
655
|
+
const parsed = SvmRawForkConfigSchema.parse(raw);
|
|
656
|
+
if ('path' in parsed) {
|
|
657
|
+
const transactions = schemas/* array */.YO(PrintableSvmTransactionSchema)
|
|
658
|
+
.parse(fileReader(parsed.path));
|
|
659
|
+
return { transactions };
|
|
660
|
+
}
|
|
661
|
+
return { transactions: parsed.transactions };
|
|
662
|
+
}
|
|
663
|
+
//# sourceMappingURL=svm-fork-config.js.map
|
|
664
|
+
;// CONCATENATED MODULE: ../svm-sdk/dist/fork/index.js
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
//# sourceMappingURL=index.js.map
|
|
669
|
+
|
|
670
|
+
/***/ })
|
|
671
|
+
|
|
672
|
+
};
|