@black-market/sdk 0.15.0 → 0.15.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/README.md +9 -8
- package/dist/lifecycle/auto-compound.d.ts +21 -0
- package/dist/lifecycle/auto-compound.d.ts.map +1 -0
- package/dist/lifecycle/auto-compound.js +34 -0
- package/dist/lifecycle/auto-compound.js.map +1 -0
- package/dist/lifecycle/calibration.d.ts +2 -4
- package/dist/lifecycle/calibration.d.ts.map +1 -1
- package/dist/lifecycle/calibration.js +1 -26
- package/dist/lifecycle/calibration.js.map +1 -1
- package/dist/lifecycle/deployments/auto-compound-dynamic-pool-v1-20261028.d.ts +73 -0
- package/dist/lifecycle/deployments/auto-compound-dynamic-pool-v1-20261028.d.ts.map +1 -0
- package/dist/lifecycle/deployments/auto-compound-dynamic-pool-v1-20261028.js +75 -0
- package/dist/lifecycle/deployments/auto-compound-dynamic-pool-v1-20261028.js.map +1 -0
- package/dist/lifecycle/deployments/auto-compound-static-pool-v1-20261028.d.ts +73 -0
- package/dist/lifecycle/deployments/auto-compound-static-pool-v1-20261028.d.ts.map +1 -0
- package/dist/lifecycle/deployments/auto-compound-static-pool-v1-20261028.js +75 -0
- package/dist/lifecycle/deployments/auto-compound-static-pool-v1-20261028.js.map +1 -0
- package/dist/lifecycle/gas-profile.d.ts +17 -13
- package/dist/lifecycle/gas-profile.d.ts.map +1 -1
- package/dist/lifecycle/gas-profile.js +125 -115
- package/dist/lifecycle/gas-profile.js.map +1 -1
- package/dist/lifecycle/index.d.ts +4 -4
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/index.js +4 -4
- package/dist/lifecycle/index.js.map +1 -1
- package/dist/lifecycle/markets.d.ts +2 -0
- package/dist/lifecycle/markets.d.ts.map +1 -1
- package/dist/lifecycle/markets.js +30 -3
- package/dist/lifecycle/markets.js.map +1 -1
- package/dist/lifecycle/opening-buys.js +1 -1
- package/dist/lifecycle/opening-buys.js.map +1 -1
- package/dist/lifecycle/planner.d.ts +6 -9
- package/dist/lifecycle/planner.d.ts.map +1 -1
- package/dist/lifecycle/planner.js +102 -207
- package/dist/lifecycle/planner.js.map +1 -1
- package/dist/lifecycle/presets.d.ts +7 -3
- package/dist/lifecycle/presets.d.ts.map +1 -1
- package/dist/lifecycle/presets.js +10 -1
- package/dist/lifecycle/presets.js.map +1 -1
- package/dist/lifecycle/rpc.d.ts +3 -13
- package/dist/lifecycle/rpc.d.ts.map +1 -1
- package/dist/lifecycle/rpc.js +11 -37
- package/dist/lifecycle/rpc.js.map +1 -1
- package/dist/lifecycle/snapshot.d.ts.map +1 -1
- package/dist/lifecycle/snapshot.js +1 -2
- package/dist/lifecycle/snapshot.js.map +1 -1
- package/dist/lifecycle/transactions.d.ts +10 -3
- package/dist/lifecycle/transactions.d.ts.map +1 -1
- package/dist/lifecycle/transactions.js +40 -10
- package/dist/lifecycle/transactions.js.map +1 -1
- package/dist/lifecycle/types.d.ts +32 -107
- package/dist/lifecycle/types.d.ts.map +1 -1
- package/dist/lifecycle/types.js +3 -3
- package/dist/lifecycle/types.js.map +1 -1
- package/dist/lifecycle/ufg.d.ts +1 -1
- package/dist/lifecycle/ufg.d.ts.map +1 -1
- package/dist/lifecycle/ufg.js +1 -1
- package/dist/lifecycle/ufg.js.map +1 -1
- package/docs/launch-lifecycle.md +43 -0
- package/docs/lifecycle-gas-profiles.md +1 -1
- package/docs/reference.md +56 -2
- package/examples/.env.example +0 -3
- package/examples/README.md +10 -10
- package/examples/launch-example-support.ts +4 -9
- package/examples/launch-example.ts +12 -28
- package/examples/launch-lifecycle-smoke.ts +10 -22
- package/examples/launch.ts +8 -11
- package/package.json +1 -1
- package/src/lifecycle/auto-compound.ts +38 -0
- package/src/lifecycle/calibration.ts +3 -23
- package/src/lifecycle/deployments/auto-compound-dynamic-pool-v1-20261028.ts +77 -0
- package/src/lifecycle/deployments/auto-compound-static-pool-v1-20261028.ts +77 -0
- package/src/lifecycle/gas-profile.ts +117 -106
- package/src/lifecycle/index.ts +4 -4
- package/src/lifecycle/markets.ts +25 -3
- package/src/lifecycle/opening-buys.ts +1 -1
- package/src/lifecycle/planner.ts +98 -190
- package/src/lifecycle/presets.ts +10 -1
- package/src/lifecycle/rpc.ts +10 -32
- package/src/lifecycle/snapshot.ts +1 -2
- package/src/lifecycle/transactions.ts +39 -9
- package/src/lifecycle/types.ts +38 -87
- package/src/lifecycle/ufg.ts +1 -1
- package/dist/lifecycle/fork.d.ts +0 -15
- package/dist/lifecycle/fork.d.ts.map +0 -1
- package/dist/lifecycle/fork.js +0 -36
- package/dist/lifecycle/fork.js.map +0 -1
- package/dist/lifecycle/simulation.d.ts +0 -17
- package/dist/lifecycle/simulation.d.ts.map +0 -1
- package/dist/lifecycle/simulation.js +0 -605
- package/dist/lifecycle/simulation.js.map +0 -1
- package/src/lifecycle/fork.ts +0 -36
- package/src/lifecycle/simulation.ts +0 -543
package/src/lifecycle/presets.ts
CHANGED
|
@@ -11,6 +11,9 @@ import { HMM_FIXED_PROFILE_ID, HMM_DYNAMIC_PROFILE_ID, isHmmProfile } from "./hm
|
|
|
11
11
|
import { ufgFixedEnvelope, ufgFixedAdapter, ufgFixedRegistration } from "./deployments/ufg-fixed-pool-20261021.js";
|
|
12
12
|
import { ufgDynamicEnvelope, ufgDynamicAdapter, ufgDynamicRegistration } from "./deployments/ufg-dynamic-pool-20261021.js";
|
|
13
13
|
import { UFG_FIXED_PROFILE_ID, UFG_DYNAMIC_PROFILE_ID } from "./ufg-config.js";
|
|
14
|
+
import { autoCompoundStaticEnvelope, autoCompoundStaticAdapter, autoCompoundStaticRegistration, autoCompoundStaticCreationCode } from "./deployments/auto-compound-static-pool-v1-20261028.js";
|
|
15
|
+
import { autoCompoundDynamicEnvelope, autoCompoundDynamicAdapter, autoCompoundDynamicRegistration, autoCompoundDynamicCreationCode } from "./deployments/auto-compound-dynamic-pool-v1-20261028.js";
|
|
16
|
+
import { AUTO_COMPOUND_STATIC_V1_PROFILE_ID, AUTO_COMPOUND_DYNAMIC_V1_PROFILE_ID } from "./auto-compound.js";
|
|
14
17
|
|
|
15
18
|
export enum KnownLifecycleProfile {
|
|
16
19
|
Abyss0 = "abyss-0",
|
|
@@ -23,6 +26,8 @@ export enum KnownLifecycleProfile {
|
|
|
23
26
|
V4HmmDynamicPool = "v4-hmm-dynamic-pool",
|
|
24
27
|
V4UfgFixedPool = "v4-ufg-fixed-pool",
|
|
25
28
|
V4UfgDynamicPool = "v4-ufg-dynamic-pool",
|
|
29
|
+
V4AutoCompoundStaticPool = "v4-auto-compound-static-pool",
|
|
30
|
+
V4AutoCompoundDynamicPool = "v4-auto-compound-dynamic-pool",
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
export enum KnownLifecycleHook {
|
|
@@ -30,6 +35,8 @@ export enum KnownLifecycleHook {
|
|
|
30
35
|
DynamicFeePoolV1 = "dynamic-fee-pool-v1",
|
|
31
36
|
HmmFixedPoolV2 = "hmm-fixed-pool-v2",
|
|
32
37
|
HmmDynamicPoolV2 = "hmm-dynamic-pool-v2",
|
|
38
|
+
AutoCompoundStaticV1 = "auto-compound-static-v1",
|
|
39
|
+
AutoCompoundDynamicV1 = "auto-compound-dynamic-v1",
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
Object.freeze(KnownLifecycleProfile);
|
|
@@ -351,6 +358,8 @@ const knownDeployment: LifecycleDeploymentPreset = Object.freeze({
|
|
|
351
358
|
poolBoundPreset(KnownLifecycleProfile.V4HmmDynamicPool, HMM_DYNAMIC_PROFILE_ID, hmmDynamicEnvelope, hmmDynamicAdapter, hmmDynamicRegistration, hmmDynamicCreationCode),
|
|
352
359
|
poolBoundPreset(KnownLifecycleProfile.V4UfgFixedPool, UFG_FIXED_PROFILE_ID, ufgFixedEnvelope, ufgFixedAdapter, ufgFixedRegistration, fixedFeePoolHookV1CreationCode),
|
|
353
360
|
poolBoundPreset(KnownLifecycleProfile.V4UfgDynamicPool, UFG_DYNAMIC_PROFILE_ID, ufgDynamicEnvelope, ufgDynamicAdapter, ufgDynamicRegistration, dynamicFeePoolHookV1CreationCode),
|
|
361
|
+
poolBoundPreset(KnownLifecycleProfile.V4AutoCompoundStaticPool, AUTO_COMPOUND_STATIC_V1_PROFILE_ID, autoCompoundStaticEnvelope, autoCompoundStaticAdapter, autoCompoundStaticRegistration, autoCompoundStaticCreationCode),
|
|
362
|
+
poolBoundPreset(KnownLifecycleProfile.V4AutoCompoundDynamicPool, AUTO_COMPOUND_DYNAMIC_V1_PROFILE_ID, autoCompoundDynamicEnvelope, autoCompoundDynamicAdapter, autoCompoundDynamicRegistration, autoCompoundDynamicCreationCode),
|
|
354
363
|
]),
|
|
355
364
|
provenance: Object.freeze({ sourceCommit: "e174ce695c7010f50ca9211b07b9f178c990beac", deploymentBlock: 82880546n }),
|
|
356
365
|
});
|
|
@@ -380,7 +389,7 @@ export function getKnownLifecycleProfile(options: KnownLifecycleDeploymentIdenti
|
|
|
380
389
|
return undefined;
|
|
381
390
|
}
|
|
382
391
|
|
|
383
|
-
/** Stable, frozen order: Abyss
|
|
392
|
+
/** Stable, frozen order: Abyss, fixed/dynamic V4, HMM, UFG, then auto-compounding. */
|
|
384
393
|
export function listKnownLifecycleProfiles(options: KnownLifecycleDeploymentIdentity): readonly LifecycleProfilePreset[] {
|
|
385
394
|
return getKnownLifecycleDeployment(options)?.profiles ?? noProfiles;
|
|
386
395
|
}
|
package/src/lifecycle/rpc.ts
CHANGED
|
@@ -22,8 +22,8 @@ type IndependentRead = { params: readonly unknown[]; resolve: (value: unknown) =
|
|
|
22
22
|
const lifecycleReadConcurrency = 8;
|
|
23
23
|
const diagnosticRpcMethods: Record<string, true> = {
|
|
24
24
|
eth_chainId: true, eth_getBlockByNumber: true, eth_getBlockByHash: true, eth_getCode: true,
|
|
25
|
-
eth_getBalance: true, eth_call: true,
|
|
26
|
-
|
|
25
|
+
eth_getBalance: true, eth_call: true, eth_gasPrice: true,
|
|
26
|
+
eth_getTransactionReceipt: true, eth_getTransactionByHash: true,
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
type SessionReadGroup = {
|
|
@@ -70,7 +70,7 @@ class SessionLifecycleCache implements LifecycleSessionCache {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
/** Opt-in pinned read reuse; client-bound identity/
|
|
73
|
+
/** Opt-in pinned read reuse; client-bound identity/deployment facts are separate. */
|
|
74
74
|
export function createLifecycleSessionCache(): LifecycleSessionCache {
|
|
75
75
|
return new SessionLifecycleCache();
|
|
76
76
|
}
|
|
@@ -410,7 +410,7 @@ export function readLifecycleImmutable<T>(client: LifecycleRpcClient, key: strin
|
|
|
410
410
|
return (client instanceof InvocationLifecycleClient ? client.immutableRead(key, work) : work()) as Promise<T>;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
/** Successful deployment
|
|
413
|
+
/** Successful deployment observations live for the caller's session, not one block. */
|
|
414
414
|
export function lifecycleSessionRead<T>(client: LifecycleRpcClient, key: string, work: () => Promise<T>): Promise<T> {
|
|
415
415
|
const source = lifecycleSourceClient(client);
|
|
416
416
|
const owner = source.sessionCache ?? source;
|
|
@@ -524,9 +524,7 @@ export async function readLifecycleProfileTopology(client: LifecycleRpcClient, r
|
|
|
524
524
|
if (topology.hookTopology !== 0 && topology.hookTopology !== 1 && topology.hookTopology !== 2) throw new LifecyclePlanningError("INVALID_RPC_RESPONSE", "Registry returned an unsupported hook topology");
|
|
525
525
|
return { ...topology, hookTopology: topology.hookTopology };
|
|
526
526
|
}
|
|
527
|
-
export const nitroArbSys = "0x0000000000000000000000000000000000000064";
|
|
528
527
|
export const nitroGasInfo = "0x000000000000000000000000000000000000006c";
|
|
529
|
-
export const nitroArbSysAbi = parseAbi(["function arbOSVersion() view returns (uint256)"]);
|
|
530
528
|
export const nitroGasInfoAbi = parseAbi([
|
|
531
529
|
// Transaction ceilings are release preset metadata, not guard-only getter reads.
|
|
532
530
|
"function getPricesInWei() view returns (uint256,uint256,uint256,uint256,uint256,uint256)",
|
|
@@ -534,7 +532,7 @@ export const nitroGasInfoAbi = parseAbi([
|
|
|
534
532
|
export type LifecycleNitroPrices = readonly [bigint, bigint, bigint, bigint, bigint, bigint];
|
|
535
533
|
const maxUint64 = (1n << 64n) - 1n;
|
|
536
534
|
|
|
537
|
-
/** Seeded by the planning aggregate
|
|
535
|
+
/** Seeded by the explicitly pinned planning aggregate. */
|
|
538
536
|
export function readNitroPrices(client: LifecycleRpcClient, block: LifecycleBlock): Promise<LifecycleNitroPrices> {
|
|
539
537
|
return readLifecycleContract(client, nitroGasInfo, nitroGasInfoAbi, "getPricesInWei", [], block, undefined, true, true);
|
|
540
538
|
}
|
|
@@ -551,12 +549,6 @@ export function nitroPosterGasBound(transaction: Pick<LifecycleTransaction, "dat
|
|
|
551
549
|
return { posterGas: 2n * ((feeBound + prices[5] - 1n) / prices[5]), feeBound };
|
|
552
550
|
}
|
|
553
551
|
|
|
554
|
-
async function readNitroScalar(context: LifecycleLimitContext, to: Address, abi: Abi, functionName: string): Promise<bigint> {
|
|
555
|
-
const data = encodeFunctionData({ abi, functionName });
|
|
556
|
-
const result = rpcHex(await lifecycleIndependentRpc(context.client, [{ to, data }, toHex(context.block.number)], context.block, true), functionName);
|
|
557
|
-
if (result.length !== 66) throw new LifecyclePlanningError("INVALID_RPC_RESPONSE", `${functionName} must return exactly one ABI word`);
|
|
558
|
-
return decodeFunctionResult({ abi, functionName, data: result }) as bigint;
|
|
559
|
-
}
|
|
560
552
|
|
|
561
553
|
export type LifecycleLimitObservation = {
|
|
562
554
|
limits: ResolvedLifecycleLimits;
|
|
@@ -591,7 +583,7 @@ async function resolveLifecycleLimitsFresh(context: LifecycleLimitContext, sourc
|
|
|
591
583
|
};
|
|
592
584
|
const headroomBps = configuration.headroomBps === undefined ? 1500 : configuration.headroomBps;
|
|
593
585
|
if (!Number.isSafeInteger(headroomBps) || headroomBps < 0 || headroomBps > 10000) throw new LifecyclePlanningError("INVALID_LIMITS", "Headroom must be between zero and 10000 basis points");
|
|
594
|
-
for (const limit of [context.block.gasLimit, configuration.chainGasLimit, configuration.rpcGasLimit, configuration.accountGasLimit
|
|
586
|
+
for (const limit of [context.block.gasLimit, configuration.chainGasLimit, configuration.rpcGasLimit, configuration.accountGasLimit]) {
|
|
595
587
|
if (limit !== undefined && (typeof limit !== "bigint" || limit <= 0n || limit > maxUint64)) throw new LifecyclePlanningError("INVALID_LIMITS", "Gas caps must be positive exact uint64 bigint values");
|
|
596
588
|
}
|
|
597
589
|
if (configuration.maxCalldataBytes !== undefined && (!Number.isSafeInteger(configuration.maxCalldataBytes) || configuration.maxCalldataBytes <= 0)) throw new LifecyclePlanningError("INVALID_LIMITS", "Calldata cap must be a positive byte count");
|
|
@@ -604,37 +596,23 @@ async function resolveLifecycleLimitsFresh(context: LifecycleLimitContext, sourc
|
|
|
604
596
|
throw new LifecyclePlanningError("LIMIT_CONTEXT_MISMATCH", "Supplied execution policy provenance differs from the canonical chain/account/core/block context");
|
|
605
597
|
}
|
|
606
598
|
const protocol = context.chainId === 4663n ? "nitro" : "evm";
|
|
607
|
-
|
|
608
|
-
let arbOSVersion: bigint | undefined;
|
|
609
|
-
if (protocol === "nitro") {
|
|
610
|
-
try {
|
|
611
|
-
const rawVersion = await readNitroScalar(context, nitroArbSys, nitroArbSysAbi, "arbOSVersion");
|
|
612
|
-
// ArbSys alone adds 55 to the logical Nitro ArbOS version.
|
|
613
|
-
if (typeof rawVersion !== "bigint" || rawVersion < 105n) throw new Error("ArbOS version 50 or newer is required (ArbSys raw version >= 105)");
|
|
614
|
-
arbOSVersion = rawVersion - 55n;
|
|
615
|
-
} catch (failure) {
|
|
616
|
-
if (failure instanceof Error && failure.name === "AbortError") throw failure;
|
|
617
|
-
throw new LifecyclePlanningError("NITRO_LIMITS_UNAVAILABLE", `Pinned Nitro version could not be established: ${lifecycleFailureReason(failure)}`);
|
|
618
|
-
}
|
|
619
|
-
if (configuration.estimateDataFee !== undefined) throw new LifecyclePlanningError("INVALID_LIMITS", "Nitro poster fees are already included in gas; an external data-fee estimator would double-charge them");
|
|
620
|
-
}
|
|
599
|
+
if (protocol === "nitro" && configuration.estimateDataFee !== undefined) throw new LifecyclePlanningError("INVALID_LIMITS", "Nitro poster fees are already included in gas; an external data-fee estimator would double-charge them");
|
|
621
600
|
const envelopeCaps = [configuration.chainGasLimit, configuration.rpcGasLimit, configuration.accountGasLimit].filter((limit): limit is bigint => limit !== undefined);
|
|
622
601
|
if (protocol === "evm") envelopeCaps.push(context.block.gasLimit);
|
|
623
602
|
const transactionGasCeiling = envelopeCaps.length === 0 ? undefined : envelopeCaps.reduce((minimum, limit) => limit < minimum ? limit : minimum);
|
|
624
603
|
const executionGasCeiling = protocol === "nitro" ? ROBINHOOD_NATIVE_TRANSACTION_GAS_LIMIT : transactionGasCeiling ?? context.block.gasLimit;
|
|
625
604
|
const unknownExecutionConstraints = [
|
|
626
|
-
...(protocol === "evm" && configuration.chainGasLimit === undefined ? ["Independent chain per-transaction
|
|
605
|
+
...(protocol === "evm" && configuration.chainGasLimit === undefined ? ["Independent chain per-transaction cap is unknown; the budget is bounded by the pinned header"] : []),
|
|
627
606
|
...(configuration.rpcGasLimit === undefined ? ["RPC transaction gas-envelope cap is unknown"] : []),
|
|
628
607
|
...(configuration.accountGasLimit === undefined ? ["Current account/wallet transaction gas-envelope cap is unknown"] : []),
|
|
629
608
|
...(configuration.maxCalldataBytes === undefined ? ["Applicable chain/account/RPC calldata byte cap is unknown"] : []),
|
|
630
|
-
...(maxSimulationGas === undefined ? ["RPC aggregate simulation gas cap is unknown"] : []),
|
|
631
609
|
];
|
|
632
610
|
assertCurrent();
|
|
633
611
|
return {
|
|
634
612
|
configuration, assertCurrent,
|
|
635
613
|
limits: Object.freeze({
|
|
636
|
-
protocol, executionGasCeiling, transactionGasCeiling,
|
|
637
|
-
maxCalldataBytes: configuration.maxCalldataBytes,
|
|
614
|
+
protocol, executionGasCeiling, transactionGasCeiling, headroomBps,
|
|
615
|
+
maxCalldataBytes: configuration.maxCalldataBytes,
|
|
638
616
|
blockGasLimit: context.block.gasLimit, chainGasLimit: configuration.chainGasLimit,
|
|
639
617
|
rpcGasLimit: configuration.rpcGasLimit, accountGasLimit: configuration.accountGasLimit,
|
|
640
618
|
unknownExecutionConstraints: Object.freeze(unknownExecutionConstraints),
|
|
@@ -5,7 +5,7 @@ import { getKnownLifecycleDeployment, type LifecycleDeploymentPreset } from "./p
|
|
|
5
5
|
import { lifecycleTokenPredictionAbi } from "./progress.js";
|
|
6
6
|
import { launchLensAbi, observeLifecycleLens, type LifecycleLensSnapshot } from "./lens.js";
|
|
7
7
|
import { hashLaunchIdentity, LifecycleFundingKind, type LaunchPlanV1 } from "./schema.js";
|
|
8
|
-
import { attestLifecycleMulticall, lifecycleRpc,
|
|
8
|
+
import { attestLifecycleMulticall, lifecycleRpc, nitroGasInfo, nitroGasInfoAbi, readLifecycleBlock, readLifecycleChainId, rpcHex, seedLifecycleRead } from "./rpc.js";
|
|
9
9
|
import { LifecyclePlanningError, type LifecycleBlock, type LifecycleRpcClient } from "./types.js";
|
|
10
10
|
import { UFG_LAUNCH_PROXY_ADDRESS } from "./ufg-config.js";
|
|
11
11
|
|
|
@@ -36,7 +36,6 @@ export async function readLifecyclePlanningBlock(client: LifecycleRpcClient, pla
|
|
|
36
36
|
if (escrow !== undefined) add(asset, lifecycleErc20Abi, "allowance", [account, escrow]);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
add(nitroArbSys, nitroArbSysAbi, "arbOSVersion", []);
|
|
40
39
|
add(nitroGasInfo, nitroGasInfoAbi, "getPricesInWei", []);
|
|
41
40
|
await attestLifecycleMulticall(client, block);
|
|
42
41
|
const calls = reads.map((read) => ({ target: read.to, allowFailure: true, callData: encodeFunctionData({ abi: read.abi, functionName: read.functionName, args: read.args }) }));
|
|
@@ -3,27 +3,57 @@ import { launchLifecycleAbi } from "./abi.js";
|
|
|
3
3
|
import { LifecycleFundingKind, LifecycleMode, type LaunchPlanV1 } from "./schema.js";
|
|
4
4
|
import { LifecyclePlanningError, type BuildLaunchTransactionsOptions, type LifecycleTransaction } from "./types.js";
|
|
5
5
|
import { assertLifecycleTokenAllocation } from "./allocations.js";
|
|
6
|
-
import { HMM_V2_PREPARE_GAS } from "./presets.js";
|
|
7
|
-
import { isHmmProfile } from "./hmm.js";
|
|
8
6
|
import { ufgLaunchProxyV1Abi } from "./ufg-abi.js";
|
|
9
|
-
import { UFG_LAUNCH_PROXY_ADDRESS } from "./ufg-config.js";
|
|
7
|
+
import { UFG_LAUNCH_PROXY_ADDRESS, isUfgProfile } from "./ufg-config.js";
|
|
8
|
+
import { decodeAbyssLifecycleMarketConfig, decodePoolBoundV4LifecycleMarketConfig, decodeV4LifecycleMarketConfig, isPoolBoundV4ConfigVersion } from "./markets.js";
|
|
9
|
+
import { isHmmProfile } from "./hmm.js";
|
|
10
10
|
import type { UfgLaunchConfig } from "./ufg-config.js";
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
// Native9,723,187 Abyss3 (0x679d…e77), fork32-position10,900,786;
|
|
13
|
+
// fork V4 fixed/dynamic8-position8,804,466; UFG9,896,176; native HMM8-position14,676,638 (0x459c…5b7).
|
|
14
|
+
const preparationCosts = {
|
|
15
|
+
abyss: { market: 9_800_000n, position: 70_000n },
|
|
16
|
+
v4: { market: 9_000_000n, position: 40_000n },
|
|
17
|
+
ufg: { market: 10_000_000n, position: 70_000n },
|
|
18
|
+
hmm: { market: 15_000_000n, position: 50_000n },
|
|
19
|
+
} as const;
|
|
20
|
+
export const LIFECYCLE_CAPACITY_PADDING_BPS = 2500;
|
|
21
|
+
/** Full single-market observations include call overhead. Add conservative full
|
|
22
|
+
* calldata/hash processing (16 intrinsic gas per nonzero byte plus8 for copying). */
|
|
23
|
+
export function preparationCalldataGas(data: `0x${string}`): bigint { return 24n * BigInt((data.length - 2) / 2); }
|
|
13
24
|
|
|
14
25
|
export function preparationGasEstimate(plan: LaunchPlanV1, first: number, count: number): bigint {
|
|
15
26
|
let gas = 0n;
|
|
16
|
-
for (let index = first; index < first + count; index += 1)
|
|
27
|
+
for (let index = first; index < first + count; index += 1) {
|
|
28
|
+
const market = plan.markets[index]!;
|
|
29
|
+
const positions = market.configVersion === 1 ? decodeAbyssLifecycleMarketConfig(market.config).positions.length
|
|
30
|
+
: isPoolBoundV4ConfigVersion(market.configVersion) ? decodePoolBoundV4LifecycleMarketConfig(market.config, market.configVersion).positions.length
|
|
31
|
+
: decodeV4LifecycleMarketConfig(market.config).positions.length;
|
|
32
|
+
const cost = market.configVersion === 1 ? preparationCosts.abyss : isHmmProfile(market.profileId) ? preparationCosts.hmm
|
|
33
|
+
: isUfgProfile(market.profileId) ? preparationCosts.ufg : preparationCosts.v4;
|
|
34
|
+
gas += cost.market + cost.position * BigInt(positions - 1);
|
|
35
|
+
}
|
|
17
36
|
return gas;
|
|
18
37
|
}
|
|
19
38
|
|
|
20
|
-
/** Contiguous
|
|
21
|
-
|
|
39
|
+
/** Contiguous deterministic packing with compute headroom. The caller reserves
|
|
40
|
+
* poster allocation separately from computeCap; neither resizes transaction gas. */
|
|
41
|
+
export function packPreparationBatches(plan: LaunchPlanV1, prepared: number, computeCap: bigint, headroomBps = 1500): number[] {
|
|
42
|
+
const data = buildLifecycleCommand(plan, { kind: "prepare", first: prepared, count: 1 }).data;
|
|
43
|
+
return packLifecyclePreparationBatches(plan, prepared, computeCap, headroomBps, preparationCalldataGas(data));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Internal path reuses the command already encoded for poster allocation. */
|
|
47
|
+
export function packLifecyclePreparationBatches(plan: LaunchPlanV1, prepared: number, computeCap: bigint, headroomBps: number, calldataGas: bigint): number[] {
|
|
48
|
+
if (!Number.isSafeInteger(headroomBps) || headroomBps < 0 || headroomBps > 10000) throw new LifecyclePlanningError("INVALID_LIMITS", "Headroom must be between zero and10000 basis points");
|
|
49
|
+
const padding = BigInt(10000 + Math.max(LIFECYCLE_CAPACITY_PADDING_BPS, headroomBps));
|
|
50
|
+
const fits = (gas: bigint) => ((gas + calldataGas) * padding + 9999n) / 10000n <= computeCap;
|
|
22
51
|
const batches = prepared > 0 ? [prepared] : [];
|
|
23
52
|
let count = 0, gas = 0n;
|
|
24
53
|
for (let index = prepared; index < plan.markets.length; index += 1) {
|
|
25
54
|
const estimate = preparationGasEstimate(plan, index, 1);
|
|
26
|
-
if (
|
|
55
|
+
if (!fits(estimate)) throw new LifecyclePlanningError("PREPARATION_GAS_LIMIT", "A market exceeds the preparation gas budget. Reduce its positions before launching.");
|
|
56
|
+
if (count > 0 && !fits(gas + estimate)) { batches.push(count); count = 0; gas = 0n; }
|
|
27
57
|
count += 1;
|
|
28
58
|
gas += estimate;
|
|
29
59
|
}
|
|
@@ -53,7 +83,7 @@ export function buildLifecycleCommand(plan: LaunchPlanV1, command: LifecycleComm
|
|
|
53
83
|
|
|
54
84
|
/** Pure unsigned launch commands. Every command carries the complete commitment;
|
|
55
85
|
* preparation splits only empty markets, never positions, buys or public opening.
|
|
56
|
-
* Allowance discovery, recovery and
|
|
86
|
+
* Allowance discovery, recovery and gas-budget checks belong to the planner. */
|
|
57
87
|
export function buildLifecycleCommands({ plan, mode, preparationBatches }: BuildLaunchTransactionsOptions, ufg?: LifecycleUfgRoute): LifecycleTransaction[] {
|
|
58
88
|
if (mode !== "atomic" && mode !== "staged") throw new LifecyclePlanningError("EXPLICIT_MODE_REQUIRED", "Choose atomic or staged explicitly; staged is never silently substituted");
|
|
59
89
|
if (plan.chainId <= 0n || plan.chainId > BigInt(Number.MAX_SAFE_INTEGER)) throw new LifecyclePlanningError("CHAIN_MISMATCH", "Chain ID must be a positive exact JavaScript integer");
|
package/src/lifecycle/types.ts
CHANGED
|
@@ -5,13 +5,10 @@ import type {
|
|
|
5
5
|
MarketLiveStateV1, PreparedMarketV1, ProfileRegistrationV1, ProfileTopologyV1, LaunchEnvelopeV2, LifecycleDeveloperTerms,
|
|
6
6
|
} from "./schema.js";
|
|
7
7
|
|
|
8
|
-
/** Local opt-in timing only: never contains request arguments, addresses, results or errors.
|
|
9
|
-
* Since 0.14.0, removed replay/envelope stages are represented by simulation.measure,
|
|
10
|
-
* which includes the final validated execution at the returned gas envelope. */
|
|
8
|
+
/** Local opt-in timing only: never contains request arguments, addresses, results or errors. */
|
|
11
9
|
export type LifecycleDiagnosticStage =
|
|
12
10
|
| "plan" | "plan.context" | "plan.domain" | "plan.progress" | "plan.inputs" | "rpc"
|
|
13
|
-
| "profile.certification" | "
|
|
14
|
-
| "simulation.poster" | "simulation.measure" | "session-cache";
|
|
11
|
+
| "profile.certification" | "session-cache";
|
|
15
12
|
export type LifecycleDiagnosticEvent = {
|
|
16
13
|
stage: LifecycleDiagnosticStage;
|
|
17
14
|
phase: "queued" | "start" | "success" | "failure" | "reuse";
|
|
@@ -31,13 +28,13 @@ export type LifecycleRpcClient = {
|
|
|
31
28
|
request(args: { method: string; params?: readonly unknown[] }): Promise<unknown>;
|
|
32
29
|
/** Opt in to bounded parallel reads only when the supplied transport batches concurrent requests. */
|
|
33
30
|
supportsReadBatching?: boolean;
|
|
34
|
-
/** Optional local observer. Listener failures cannot change
|
|
31
|
+
/** Optional local observer. Listener failures cannot change planning or sending. */
|
|
35
32
|
onDiagnostic?: LifecycleDiagnosticListener;
|
|
36
33
|
/** Caller-owned, opt-in static observations; create with createLifecycleSessionCache(). */
|
|
37
34
|
sessionCache?: LifecycleSessionCache;
|
|
38
35
|
};
|
|
39
36
|
export type LifecycleBlock = { number: bigint; hash: Hash; timestamp: bigint; gasLimit: bigint; baseFeePerGas?: bigint };
|
|
40
|
-
/** A session retains pinned static reads and deployment
|
|
37
|
+
/** A session retains pinned static reads and deployment metadata observations. */
|
|
41
38
|
export type LifecycleSessionCache = {
|
|
42
39
|
readonly block: Readonly<Pick<LifecycleBlock, "number" | "hash">> | undefined;
|
|
43
40
|
/** Call on wallet/chain changes and after every confirmed transaction. */
|
|
@@ -48,8 +45,6 @@ export type LifecycleLimits = {
|
|
|
48
45
|
/** Optional tightening caps on the complete transaction gas envelope, including Nitro poster gas. */
|
|
49
46
|
headroomBps?: number; chainGasLimit?: bigint; rpcGasLimit?: bigint; accountGasLimit?: bigint;
|
|
50
47
|
maxCalldataBytes?: number;
|
|
51
|
-
/** Optional aggregate gas-used policy ceiling for one simulation request; no SDK-invented default window. */
|
|
52
|
-
maxSimulationGas?: bigint;
|
|
53
48
|
chainId?: bigint; orchestrator?: Address; account?: Address; observedBlockNumber?: bigint; observedBlockHash?: Hash;
|
|
54
49
|
/** External data fee not already charged in gas, called with exact calldata and the pinned block.
|
|
55
50
|
* Nitro poster fees are already included in gas, bounded locally from same-review ArbGasInfo prices. */
|
|
@@ -59,18 +54,10 @@ export type LifecycleLimitSource = LifecycleLimits | ((context: LifecycleLimitCo
|
|
|
59
54
|
export type ResolvedLifecycleLimits = {
|
|
60
55
|
/** Fixed native transaction ceiling, including poster gas; caller caps may refuse but never resize it. */
|
|
61
56
|
executionGasCeiling: bigint; transactionGasCeiling?: bigint; protocol: "evm" | "nitro";
|
|
62
|
-
|
|
63
|
-
headroomBps: number; maxCalldataBytes?: number; maxSimulationGas?: bigint;
|
|
57
|
+
headroomBps: number; maxCalldataBytes?: number;
|
|
64
58
|
blockGasLimit: bigint; chainGasLimit?: bigint; rpcGasLimit?: bigint; accountGasLimit?: bigint;
|
|
65
59
|
unknownExecutionConstraints: readonly string[]; unknownConstraints: readonly string[];
|
|
66
60
|
};
|
|
67
|
-
/** Only explicitly disposable RPCs may execute snapshot-isolated simulation transactions. */
|
|
68
|
-
export type ControlledLifecycleFork = {
|
|
69
|
-
client: LifecycleRpcClient; isolation: "disposable"; allowTransactions: true;
|
|
70
|
-
expectedChainId?: bigint; expectedBlockHash?: Hash; impersonation?: "anvil" | "hardhat" | "none";
|
|
71
|
-
receiptTimeoutMs?: number;
|
|
72
|
-
sourceRpcUrl: string; forkRpcUrl: string; resetMethod?: "anvil_reset" | "hardhat_reset";
|
|
73
|
-
};
|
|
74
61
|
export type LifecycleTransactionKind = "approve-reset" | "approve" | "atomic" | "begin" | "prepare" | "activate" | "cancel";
|
|
75
62
|
export type LifecyclePostcondition =
|
|
76
63
|
| { kind: "allowance"; asset: Address; spender: Address; minimum: bigint; exact?: bigint }
|
|
@@ -81,70 +68,42 @@ export type LifecycleTransaction = {
|
|
|
81
68
|
marketStart?: number; marketCount?: number; gas?: bigint; gasPrice?: bigint;
|
|
82
69
|
/** Exact encoded byte count; populated on SDK-built commands, including approvals. */
|
|
83
70
|
calldataBytes?: number;
|
|
84
|
-
/** Only the immediate command receives
|
|
85
|
-
*
|
|
86
|
-
|
|
71
|
+
/** Only the immediate command receives current planning checks and fees.
|
|
72
|
+
* Launch gas is the native ceiling; approvals leave gas to the wallet. */
|
|
73
|
+
assessment?: LifecyclePlanningAssessment;
|
|
87
74
|
estimate?: LifecycleTransactionEstimate;
|
|
88
75
|
};
|
|
89
76
|
export type LifecycleTransactionEstimate = {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
/** Estimated poster allocation within gasLimit, never an exact compute measurement or an extra fee. */
|
|
77
|
+
gasLimit: bigint; gasPrice: bigint; executionFee: bigint; dataFee?: bigint; totalFee?: bigint;
|
|
78
|
+
/** Estimated poster allocation within gasLimit, never a measured or additional fee. */
|
|
93
79
|
posterGas?: bigint; posterFee?: bigint; dataFeeIncludedInGas: boolean;
|
|
94
|
-
feeConfidence: "
|
|
95
|
-
};
|
|
96
|
-
/** Proof scopes are independent: current execution is not guaranteed wallet submission. */
|
|
97
|
-
export type LifecycleProofOutcomes = {
|
|
98
|
-
executionProof: "proved" | "failed" | "unavailable" | "not-run";
|
|
99
|
-
protocolFit: "proved" | "failed" | "unknown" | "profiled";
|
|
100
|
-
};
|
|
101
|
-
export type LifecycleAdmission = LifecycleProofOutcomes & {
|
|
102
|
-
admitted: boolean; confidence: "stateful" | "provisional" | "profiled";
|
|
103
|
-
blockNumber: bigint; blockHash: Hash; account: Address; chainId: bigint;
|
|
104
|
-
reason?: string; limits: ResolvedLifecycleLimits;
|
|
105
|
-
};
|
|
106
|
-
export type LifecycleFailureCategory = "semantic" | "capacity" | "opaque" | "source" | "postcondition" | "affordability";
|
|
107
|
-
export type LifecycleCapacityConstraint = "compute" | "gas-envelope" | "calldata" | "simulation-gas" | "activation";
|
|
108
|
-
export type LifecycleSimulationStep = {
|
|
109
|
-
transactionId: string; success: boolean; gasUsed?: bigint; gasLimit?: bigint; gasRequired?: bigint;
|
|
110
|
-
returnData?: Hex; error?: string; estimate?: LifecycleTransactionEstimate;
|
|
111
|
-
/** Suffix proof is historical and provisional; only a fresh build admits
|
|
112
|
-
* its immediate transaction, still at the native ceiling and current fee. */
|
|
113
|
-
provisional?: boolean;
|
|
114
|
-
failureCategory?: LifecycleFailureCategory; decodedError?: string;
|
|
115
|
-
/** Safe failed-call facts only; native messages and error-data bytes are never copied here. */
|
|
116
|
-
nativeErrorCode?: number;
|
|
117
|
-
nativeErrorKind?: "out-of-gas" | "execution-reverted" | "vm-error" | "other" | "missing";
|
|
118
|
-
nativeErrorDataBytes?: number;
|
|
119
|
-
/** Explicit native simulator report, not inferred from gas consumption or the requested limit. */
|
|
120
|
-
nativeGasCapped?: boolean;
|
|
80
|
+
feeConfidence: "native-ceiling-and-data" | "native-ceiling-only";
|
|
121
81
|
};
|
|
82
|
+
export type LifecycleFailureCategory = "semantic" | "capacity" | "affordability";
|
|
83
|
+
export type LifecycleCapacityConstraint = "gas-envelope" | "calldata" | "activation" | "preparation";
|
|
122
84
|
export type LifecycleOpeningBuyQuote = {
|
|
123
85
|
buyIndex: number; marketIndex: number; quoteAmountIn: bigint; quoteSpent: bigint;
|
|
124
86
|
tokenOut: bigint; sqrtPriceAfterX96: bigint;
|
|
125
87
|
};
|
|
126
|
-
/**
|
|
127
|
-
*
|
|
88
|
+
/** Versioned compute budgets with headroom, never transaction gas-limit sizing.
|
|
89
|
+
* Atomic budget is absent when conversion work is outside the template model. */
|
|
128
90
|
export type LifecycleLaunchGasBounds = {
|
|
129
|
-
atomicComputeGasUpperBound
|
|
91
|
+
atomicComputeGasUpperBound?: bigint; activationComputeGasUpperBound: bigint;
|
|
130
92
|
};
|
|
131
|
-
export type
|
|
93
|
+
export type LifecycleGasProfile = {
|
|
132
94
|
version: string; bounds: LifecycleLaunchGasBounds;
|
|
133
95
|
initialBuys: readonly LifecycleOpeningBuyQuote[];
|
|
134
96
|
};
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
confidence: "stateful" | "provisional" | "profiled"; admitted: boolean;
|
|
97
|
+
/** Pinned input and gas-budget checks only. No transaction is simulated or proved. */
|
|
98
|
+
export type LifecyclePlanningAssessment = {
|
|
99
|
+
ready: boolean;
|
|
139
100
|
blockNumber: bigint; blockHash: Hash; account: Address; chainId: bigint;
|
|
140
|
-
|
|
141
|
-
/** Immediate
|
|
101
|
+
limits: ResolvedLifecycleLimits;
|
|
102
|
+
/** Immediate native-ceiling fee budget; absent for wallet-prepared approvals. */
|
|
142
103
|
estimate?: LifecycleTransactionEstimate;
|
|
143
|
-
gasProfile?:
|
|
144
|
-
/**
|
|
145
|
-
|
|
146
|
-
reason?: string; failedTransactionId?: string;
|
|
147
|
-
/** A payer must reserve the native ceiling up front even if actual gas usage is lower. */
|
|
104
|
+
gasProfile?: LifecycleGasProfile;
|
|
105
|
+
/** Controlled SDK code and user-safe actionable reason, never raw provider errors. */
|
|
106
|
+
code?: string; reason?: string; failedTransactionId?: string;
|
|
148
107
|
failureCategory?: LifecycleFailureCategory; capacityConstraint?: LifecycleCapacityConstraint;
|
|
149
108
|
};
|
|
150
109
|
export type LifecycleFundingPrerequisite = {
|
|
@@ -190,24 +149,24 @@ export type PlannedLaunch = {
|
|
|
190
149
|
account: Address; chainId: bigint; mode: LaunchExecutionMode; confirmations: number;
|
|
191
150
|
/** Opt-in proxy routing; the committed creator remains the proxy, account is its principal. */
|
|
192
151
|
ufg?: { config: UfgLaunchConfig; configHash: Hash };
|
|
193
|
-
/** Only transactions[0] has fresh immediate
|
|
194
|
-
*
|
|
152
|
+
/** Only transactions[0] has fresh immediate planning checks/fees. Launch gas is
|
|
153
|
+
* the native ceiling; wallet-assigned nonce and approval gas are omitted. */
|
|
195
154
|
transactions: readonly LifecycleTransaction[]; prerequisites: readonly LifecycleFundingPrerequisite[];
|
|
196
155
|
/** Sum of exact calldata bytes across the returned remaining commands, including approvals. */
|
|
197
156
|
totalCalldataBytes: number;
|
|
198
|
-
profiles: readonly (LifecycleProfile | LifecycleConstructionProfile)[];
|
|
157
|
+
profiles: readonly (LifecycleProfile | LifecycleConstructionProfile)[]; assessment: LifecyclePlanningAssessment;
|
|
199
158
|
/** Exact CREATE2 metadata captured from the final committed bound markets. */
|
|
200
159
|
hookDeployments: readonly LifecyclePoolBoundHookDeployment[];
|
|
201
160
|
progress: CanonicalLaunchProgress;
|
|
202
161
|
limits?: LifecycleLimitSource;
|
|
203
|
-
/** Unstarted-launch
|
|
162
|
+
/** Unstarted-launch construction choices; never part of committed calldata. */
|
|
204
163
|
allowTopologyGaps?: boolean; allowMissingPermanentTail?: boolean;
|
|
205
164
|
};
|
|
206
165
|
export type PlanLaunchOptions = {
|
|
207
166
|
client: LifecycleRpcClient; account: Address; plan: LaunchPlanV1;
|
|
208
|
-
/** Atomic
|
|
209
|
-
*
|
|
210
|
-
mode: LaunchExecutionMode; limits?: LifecycleLimitSource;
|
|
167
|
+
/** Atomic requires one market, no conversion and a known budget fitting with headroom.
|
|
168
|
+
* All other unstarted launches are staged; started launches retain canonical mode. */
|
|
169
|
+
mode: LaunchExecutionMode; limits?: LifecycleLimitSource; receipts?: readonly LifecycleReceiptReference[];
|
|
211
170
|
confirmations?: number; signal?: AbortSignal;
|
|
212
171
|
/** Opt in to the pinned UFG proxy; sender must match the nonce's principal namespace. */
|
|
213
172
|
ufg?: { config: UfgLaunchConfig };
|
|
@@ -218,8 +177,8 @@ export type PlanLaunchOptions = {
|
|
|
218
177
|
};
|
|
219
178
|
export type PrepareAndPlanLifecycleLaunchOptions = PlanLaunchOptions & {
|
|
220
179
|
onProgress?: (progress: PoolBoundLifecyclePreparationProgress) => void;
|
|
221
|
-
/** Protect ordered buys from exact local curve outputs
|
|
222
|
-
*
|
|
180
|
+
/** Protect ordered buys from exact local curve outputs, rounded down.
|
|
181
|
+
* Omitted preserves committed minima; unstarted launches only. */
|
|
223
182
|
buySlippageBps?: number;
|
|
224
183
|
};
|
|
225
184
|
export type BuildLaunchTransactionsOptions = {
|
|
@@ -227,29 +186,21 @@ export type BuildLaunchTransactionsOptions = {
|
|
|
227
186
|
/** Positive ordered preparation counts covering every market exactly. Staged only. */
|
|
228
187
|
preparationBatches?: readonly number[];
|
|
229
188
|
};
|
|
230
|
-
export type SimulateLaunchPlanOptions = {
|
|
231
|
-
client: LifecycleRpcClient; planned: PlannedLaunch; limits?: LifecycleLimitSource; fork?: ControlledLifecycleFork;
|
|
232
|
-
/** Submitted receipt evidence and confirmation depth are inherited from the
|
|
233
|
-
* stored plan when omitted, exactly as build-next consumes them; resimulation
|
|
234
|
-
* never silently drops submitted-transaction context. */
|
|
235
|
-
receipts?: readonly LifecycleReceiptReference[]; confirmations?: number;
|
|
236
|
-
signal?: AbortSignal;
|
|
237
|
-
};
|
|
238
189
|
export type ReadLaunchProgressOptions = {
|
|
239
190
|
client: LifecycleRpcClient; planned: Pick<PlannedLaunch, "plan" | "planHash" | "launchId" | "predictedToken" | "account" | "mode" | "confirmations" | "ufg">;
|
|
240
191
|
receipts?: readonly LifecycleReceiptReference[]; confirmations?: number;
|
|
241
192
|
signal?: AbortSignal;
|
|
242
193
|
};
|
|
243
194
|
export type BuildNextTransactionOptions = ReadLaunchProgressOptions & {
|
|
244
|
-
planned: PlannedLaunch; action?: "continue" | "cancel"; limits?: LifecycleLimitSource;
|
|
195
|
+
planned: PlannedLaunch; action?: "continue" | "cancel"; limits?: LifecycleLimitSource;
|
|
245
196
|
/** Untrusted reviewed intent/fee. Gas differing from the native ceiling is stale;
|
|
246
197
|
* never resize it, bump a held fee or assign a wallet nonce. */
|
|
247
198
|
reviewedTransaction?: LifecycleTransaction;
|
|
248
199
|
};
|
|
249
200
|
export class LifecyclePlanningError extends Error {
|
|
250
201
|
readonly code: string;
|
|
251
|
-
readonly
|
|
252
|
-
constructor(code: string, message: string,
|
|
253
|
-
super(message); this.name = "LifecyclePlanningError"; this.code = code; this.
|
|
202
|
+
readonly assessment?: LifecyclePlanningAssessment;
|
|
203
|
+
constructor(code: string, message: string, assessment?: LifecyclePlanningAssessment) {
|
|
204
|
+
super(message); this.name = "LifecyclePlanningError"; this.code = code; this.assessment = assessment;
|
|
254
205
|
}
|
|
255
206
|
}
|
package/src/lifecycle/ufg.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { buildUfgFeeAssetPolicies, encodeUfgLaunchConfig, hashUfgLaunchConfig, i
|
|
|
10
10
|
|
|
11
11
|
export { UFG_LAUNCH_PROXY_ADDRESS, UFG_TREASURY_FACTORY_ADDRESS, UFG_UPSTREAM_FACTORY_ADDRESS, UFG_ORCHESTRATOR_ADDRESS, UFG_FIXED_PROFILE_ID, UFG_DYNAMIC_PROFILE_ID, UFG_FIXED_ADAPTER_ID, UFG_DYNAMIC_ADAPTER_ID, isUfgProfile, ufgLaunchConfigComponents, encodeUfgLaunchConfig, decodeUfgLaunchConfig, hashUfgLaunchConfig, validateUfgLaunchConfig, ufgLaunchNonce, buildUfgFeeAssetPolicies, type UfgLaunchConfig } from "./ufg-config.js";
|
|
12
12
|
|
|
13
|
-
/** Offline proxy-specific
|
|
13
|
+
/** Offline proxy-specific intent checks. Registry, transfers and reserve behavior are enforced on-chain. */
|
|
14
14
|
export function validateUfgLaunchPlan(plan: LaunchPlanV1, config: UfgLaunchConfig, predictedToken: Address): void {
|
|
15
15
|
try {
|
|
16
16
|
ufgPlanPrincipal(plan);
|
package/dist/lifecycle/fork.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { type ControlledLifecycleFork } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Connects an explicitly disposable loopback fork. Only the fork receives resets/transactions;
|
|
4
|
-
* sourceRpcUrl is used by the fork node for read-only canonical state synchronization.
|
|
5
|
-
*/
|
|
6
|
-
export declare function createControlledLifecycleFork(options: {
|
|
7
|
-
sourceRpcUrl: string;
|
|
8
|
-
forkRpcUrl: string;
|
|
9
|
-
allowTransactions: true;
|
|
10
|
-
fetch?: typeof globalThis.fetch;
|
|
11
|
-
impersonation?: "anvil" | "hardhat" | "none";
|
|
12
|
-
resetMethod?: "anvil_reset" | "hardhat_reset";
|
|
13
|
-
receiptTimeoutMs?: number;
|
|
14
|
-
}): ControlledLifecycleFork;
|
|
15
|
-
//# sourceMappingURL=fork.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fork.d.ts","sourceRoot":"","sources":["../../src/lifecycle/fork.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,uBAAuB,EAA2B,MAAM,YAAY,CAAC;AAG3G;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE;IACrD,YAAY,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,IAAI,CAAC;IAClE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAC9E,WAAW,CAAC,EAAE,aAAa,GAAG,eAAe,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1E,GAAG,uBAAuB,CAwB1B"}
|
package/dist/lifecycle/fork.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { LifecyclePlanningError } from "./types.js";
|
|
2
|
-
import { rpcObject } from "./rpc.js";
|
|
3
|
-
/**
|
|
4
|
-
* Connects an explicitly disposable loopback fork. Only the fork receives resets/transactions;
|
|
5
|
-
* sourceRpcUrl is used by the fork node for read-only canonical state synchronization.
|
|
6
|
-
*/
|
|
7
|
-
export function createControlledLifecycleFork(options) {
|
|
8
|
-
const source = new URL(options.sourceRpcUrl);
|
|
9
|
-
const fork = new URL(options.forkRpcUrl);
|
|
10
|
-
if (!["http:", "https:"].includes(source.protocol) || !["http:", "https:"].includes(fork.protocol))
|
|
11
|
-
throw new LifecyclePlanningError("UNSAFE_FORK", "Controlled fork RPCs must use HTTP(S)");
|
|
12
|
-
const loopback = ["localhost", "127.0.0.1", "[::1]", "::1"];
|
|
13
|
-
const sourcePort = source.port || (source.protocol === "https:" ? "443" : "80");
|
|
14
|
-
const forkPort = fork.port || (fork.protocol === "https:" ? "443" : "80");
|
|
15
|
-
if (!loopback.includes(fork.hostname) || (loopback.includes(source.hostname) && sourcePort === forkPort) || source.href === fork.href || options.allowTransactions !== true)
|
|
16
|
-
throw new LifecyclePlanningError("UNSAFE_FORK", "Controlled fork must be an explicit, distinct disposable loopback RPC, not a localhost/IP alias of the source");
|
|
17
|
-
const fetch = options.fetch ?? globalThis.fetch;
|
|
18
|
-
let id = 0;
|
|
19
|
-
const client = {
|
|
20
|
-
async request({ method, params }) {
|
|
21
|
-
const response = await fetch(fork.href, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: ++id, method, params: params ?? [] }) });
|
|
22
|
-
if (!response.ok)
|
|
23
|
-
throw new LifecyclePlanningError("FORK_RPC_ERROR", `Disposable fork RPC returned HTTP ${response.status}`);
|
|
24
|
-
const result = rpcObject(await response.json(), "fork JSON-RPC envelope");
|
|
25
|
-
if (result.error !== undefined) {
|
|
26
|
-
const error = rpcObject(result.error, "fork JSON-RPC error");
|
|
27
|
-
throw new LifecyclePlanningError("FORK_RPC_ERROR", typeof error.message === "string" ? error.message : "Disposable fork RPC returned an error");
|
|
28
|
-
}
|
|
29
|
-
if (!("result" in result))
|
|
30
|
-
throw new LifecyclePlanningError("INVALID_RPC_RESPONSE", "Disposable fork RPC omitted its result");
|
|
31
|
-
return result.result;
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
return { client, isolation: "disposable", allowTransactions: true, sourceRpcUrl: source.href, forkRpcUrl: fork.href, resetMethod: options.resetMethod ?? "anvil_reset", impersonation: options.impersonation ?? "anvil", receiptTimeoutMs: options.receiptTimeoutMs };
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=fork.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fork.js","sourceRoot":"","sources":["../../src/lifecycle/fork.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type LifecycleBlock, type LifecycleSimulation, type LifecycleTransaction, type SimulateLaunchPlanOptions } from "./types.js";
|
|
2
|
-
/** Internal, operation-local fee envelope for the already matched immediate step. */
|
|
3
|
-
export type NextTransactionEnvelope = Readonly<{
|
|
4
|
-
gas: bigint;
|
|
5
|
-
gasPrice: bigint;
|
|
6
|
-
}>;
|
|
7
|
-
export type PreparedLaunchSimulation = ((transactions: readonly LifecycleTransaction[], nextEnvelope?: NextTransactionEnvelope) => Promise<LifecycleSimulation>) & {
|
|
8
|
-
/** Unadmitted diagnostic results only; final measurement validates exact calldata. */
|
|
9
|
-
measure(transactions: readonly LifecycleTransaction[]): Promise<LifecycleSimulation>;
|
|
10
|
-
close(): void;
|
|
11
|
-
};
|
|
12
|
-
export declare function observedFields<T extends object>(value: T): () => boolean;
|
|
13
|
-
/** Internal continuation owned by one SDK read invocation. Only its positive
|
|
14
|
-
* capability proof is reused; every candidate executes its entire economic sequence. */
|
|
15
|
-
export declare function prepareLaunchSimulation(options: SimulateLaunchPlanOptions, block: LifecycleBlock, hasTransactions?: boolean, immediate?: boolean): PreparedLaunchSimulation;
|
|
16
|
-
export declare function simulateLaunchTransactions(options: SimulateLaunchPlanOptions, transactions: readonly LifecycleTransaction[], pinnedBlock?: LifecycleBlock, nextEnvelope?: NextTransactionEnvelope): Promise<LifecycleSimulation>;
|
|
17
|
-
//# sourceMappingURL=simulation.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"simulation.d.ts","sourceRoot":"","sources":["../../src/lifecycle/simulation.ts"],"names":[],"mappings":"AAIA,OAAO,EAAwD,KAAK,cAAc,EAAoF,KAAK,mBAAmB,EAAgC,KAAK,oBAAoB,EAAoD,KAAK,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAoS9V,qFAAqF;AACrF,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAClF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,YAAY,EAAE,SAAS,oBAAoB,EAAE,EAAE,YAAY,CAAC,EAAE,uBAAuB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC,GAAG;IACjK,sFAAsF;IACtF,OAAO,CAAC,YAAY,EAAE,SAAS,oBAAoB,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACrF,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAEF,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,OAAO,CAIxE;AAED;wFACwF;AACxF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,yBAAyB,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,UAAO,EAAE,SAAS,UAAQ,GAAG,wBAAwB,CAgHtK;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,SAAS,oBAAoB,EAAE,EAAE,WAAW,CAAC,EAAE,cAAc,EAAE,YAAY,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAStO"}
|