@black-market/sdk 0.6.4 → 0.7.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.
Files changed (82) hide show
  1. package/README.md +28 -4
  2. package/dist/addresses.d.ts +1 -1
  3. package/dist/addresses.js +4 -4
  4. package/dist/launch.d.ts +61 -0
  5. package/dist/launch.d.ts.map +1 -1
  6. package/dist/launch.js +171 -6
  7. package/dist/launch.js.map +1 -1
  8. package/dist/lifecycle/abi.d.ts +1999 -253
  9. package/dist/lifecycle/abi.d.ts.map +1 -1
  10. package/dist/lifecycle/abi.js +43 -14
  11. package/dist/lifecycle/abi.js.map +1 -1
  12. package/dist/lifecycle/allocations.d.ts +11 -0
  13. package/dist/lifecycle/allocations.d.ts.map +1 -0
  14. package/dist/lifecycle/allocations.js +36 -0
  15. package/dist/lifecycle/allocations.js.map +1 -0
  16. package/dist/lifecycle/calibration.d.ts +19 -0
  17. package/dist/lifecycle/calibration.d.ts.map +1 -0
  18. package/dist/lifecycle/calibration.js +65 -0
  19. package/dist/lifecycle/calibration.js.map +1 -0
  20. package/dist/lifecycle/deployments/fixed-fee-pool-hook-v1-20261008.d.ts +11 -0
  21. package/dist/lifecycle/deployments/fixed-fee-pool-hook-v1-20261008.d.ts.map +1 -0
  22. package/dist/lifecycle/deployments/fixed-fee-pool-hook-v1-20261008.js +10 -0
  23. package/dist/lifecycle/deployments/fixed-fee-pool-hook-v1-20261008.js.map +1 -0
  24. package/dist/lifecycle/index.d.ts +4 -2
  25. package/dist/lifecycle/index.d.ts.map +1 -1
  26. package/dist/lifecycle/index.js +4 -2
  27. package/dist/lifecycle/index.js.map +1 -1
  28. package/dist/lifecycle/markets.d.ts +170 -6
  29. package/dist/lifecycle/markets.d.ts.map +1 -1
  30. package/dist/lifecycle/markets.js +164 -37
  31. package/dist/lifecycle/markets.js.map +1 -1
  32. package/dist/lifecycle/planner.d.ts +7 -14
  33. package/dist/lifecycle/planner.d.ts.map +1 -1
  34. package/dist/lifecycle/planner.js +354 -400
  35. package/dist/lifecycle/planner.js.map +1 -1
  36. package/dist/lifecycle/presets.d.ts +62 -0
  37. package/dist/lifecycle/presets.d.ts.map +1 -0
  38. package/dist/lifecycle/presets.js +195 -0
  39. package/dist/lifecycle/presets.js.map +1 -0
  40. package/dist/lifecycle/progress.d.ts +5 -1
  41. package/dist/lifecycle/progress.d.ts.map +1 -1
  42. package/dist/lifecycle/progress.js +212 -53
  43. package/dist/lifecycle/progress.js.map +1 -1
  44. package/dist/lifecycle/rpc.d.ts +13 -2
  45. package/dist/lifecycle/rpc.d.ts.map +1 -1
  46. package/dist/lifecycle/rpc.js +92 -8
  47. package/dist/lifecycle/rpc.js.map +1 -1
  48. package/dist/lifecycle/simulation.d.ts +14 -4
  49. package/dist/lifecycle/simulation.d.ts.map +1 -1
  50. package/dist/lifecycle/simulation.js +381 -118
  51. package/dist/lifecycle/simulation.js.map +1 -1
  52. package/dist/lifecycle/transactions.d.ts +6 -0
  53. package/dist/lifecycle/transactions.d.ts.map +1 -0
  54. package/dist/lifecycle/transactions.js +40 -0
  55. package/dist/lifecycle/transactions.js.map +1 -0
  56. package/dist/lifecycle/types.d.ts +39 -2
  57. package/dist/lifecycle/types.d.ts.map +1 -1
  58. package/dist/lifecycle/types.js.map +1 -1
  59. package/docs/launch-lifecycle.md +228 -54
  60. package/examples/README.md +108 -18
  61. package/examples/generate-lifecycle-commitment-fixture.mjs +3 -1
  62. package/examples/launch-example-support.mjs +1 -1
  63. package/examples/launch-example.mjs +73 -26
  64. package/examples/launch-lifecycle-smoke.mjs +13 -11
  65. package/examples/launch.mjs +12 -11
  66. package/examples/quickstart.mjs +1 -1
  67. package/package.json +1 -1
  68. package/src/addresses.ts +4 -4
  69. package/src/launch.ts +213 -6
  70. package/src/lifecycle/abi.ts +43 -14
  71. package/src/lifecycle/allocations.ts +35 -0
  72. package/src/lifecycle/calibration.ts +59 -0
  73. package/src/lifecycle/deployments/fixed-fee-pool-hook-v1-20261008.ts +11 -0
  74. package/src/lifecycle/index.ts +4 -2
  75. package/src/lifecycle/markets.ts +169 -35
  76. package/src/lifecycle/planner.ts +326 -330
  77. package/src/lifecycle/presets.ts +243 -0
  78. package/src/lifecycle/progress.ts +193 -50
  79. package/src/lifecycle/rpc.ts +97 -9
  80. package/src/lifecycle/simulation.ts +369 -111
  81. package/src/lifecycle/transactions.ts +34 -0
  82. package/src/lifecycle/types.ts +35 -3
@@ -1,15 +1,69 @@
1
1
  import { concatHex, decodeFunctionData, encodeAbiParameters, encodeFunctionData, keccak256, stringToHex, toHex, zeroAddress, zeroHash } from "viem";
2
- import { launchLifecycleAbi, lifecycleAdapterAbi, lifecycleDirectoryAbi, lifecycleErc20Abi, lifecycleOracleFactoryAbi, lifecycleRegistryAbi, poolFeeCollectorFactoryV1Abi, lifecycleV4HookAbi, lifecycleV4LockerAbi, poolHookDeployerV1Abi, sharedHookDeployerV1Abi, fixedFeePoolHookV1Abi, poolMarketAdapterV1Abi, sharedMarketAdapterV1Abi } from "./abi.js";
3
- import { decodePoolBoundV4LifecycleMarketConfig, encodePoolBoundHookParameters, hasLifecycleV4HookPermissions, hashPoolBoundV4MarketCommitment, poolBoundHookInitCodeHash, predictPoolBoundHookAddress, validateV4LifecycleMarket, V4_LIFECYCLE_CONFIG_SCHEMA, V4_POOL_BOUND_LIFECYCLE_CONFIG_SCHEMA } from "./markets.js";
4
- import { hashLaunchIdentity, hashLaunchPlan, hashLaunchBounds, hashLaunchDependencies, hashLifecycleProfile, launchProgressV1Components, LifecycleMode, LifecyclePhase, LifecycleVenue, LIFECYCLE_REQUIRED_CAPABILITIES, LIFECYCLE_ERC404_CAPABILITY, LIFECYCLE_MULTI_POSITION_CAPABILITY } from "./schema.js";
5
- import { assertLifecycleBlock, lifecyclePinnedRpc, lifecycleRpc, lifecycleStage, readLifecycleBlock, readLifecycleContract, readLifecycleProfileTopology, rpcHex, rpcObject, rpcQuantity, withLifecycleReadClient } from "./rpc.js";
2
+ import { launchLifecycleAbi, lifecycleAdapterAbi, lifecycleDirectoryAbi, lifecycleErc20Abi, lifecycleOracleFactoryAbi, lifecycleRegistryAbi, poolFeeCollectorFactoryV1Abi, poolFeeCollectorFactoryConfigV6Abi, lifecycleV4HookAbi, lifecycleV4LockerAbi, poolHookDeployerV1Abi, poolHookDeployerConfigV6Abi, sharedHookDeployerV1Abi, fixedFeePoolHookV1Abi, fixedFeePoolHookConfigV6Abi, poolMarketAdapterV1Abi, sharedMarketAdapterV1Abi } from "./abi.js";
3
+ import { buildPoolBoundHookParameters, decodePoolBoundV4LifecycleMarketConfig, encodePoolBoundHookParameters, hasLifecycleV4HookPermissions, isPoolBoundV4ConfigVersion, poolBoundHookInitCodeHash, predictPoolBoundHookAddress, validateV4LifecycleMarket, V4_LIFECYCLE_CONFIG_SCHEMA, V4_POOL_BOUND_LIFECYCLE_CONFIG_SCHEMA_V5, V4_POOL_BOUND_LIFECYCLE_CONFIG_SCHEMA_V6 } from "./markets.js";
4
+ import { hashLaunchIdentity, hashLaunchPlan, hashLaunchBounds, hashLaunchDependencies, hashLifecycleProfile, lifecycleTokenComponents, launchProgressV1Components, LifecycleMode, LifecyclePhase, LifecycleVenue, LIFECYCLE_REQUIRED_CAPABILITIES, LIFECYCLE_ERC404_CAPABILITY, LIFECYCLE_MULTI_POSITION_CAPABILITY } from "./schema.js";
5
+ import { assertLifecycleBlock, assertLifecycleReadClientOpen, lifecycleFailureReason, lifecyclePinnedRpc, lifecycleRpc, lifecycleStage, readLifecycleBlock, readLifecycleChainId, readLifecycleContract, readLifecycleProfileTopology, rpcHex, rpcObject, rpcQuantity, withLifecycleReadClient } from "./rpc.js";
6
6
  import { LifecyclePlanningError } from "./types.js";
7
+ import { deriveKnownPoolBoundHookDeployment } from "./calibration.js";
8
+ import { getKnownLifecycleDeployment, getKnownLifecycleProfile } from "./presets.js";
7
9
  export const ABYSS_LIFECYCLE_CONFIG_SCHEMA = keccak256(stringToHex("(uint8,uint24,bytes32,uint160,(int24,int24,uint128,uint256)[])"));
10
+ const lifecycleTokenPredictionAbi = [{
11
+ type: "function", name: "predictToken", stateMutability: "view",
12
+ inputs: [{ name: "launchId", type: "bytes32" }, { name: "config", type: "tuple", components: lifecycleTokenComponents }],
13
+ outputs: [{ type: "address" }],
14
+ }];
15
+ /** The known immutable factory accepts only launch identity and token config,
16
+ * avoiding full-plan prediction reads after salts or buy minima change. */
17
+ export async function readLifecycleTokenAtBlock(client, plan, block) {
18
+ const deployment = getKnownLifecycleDeployment({ chainId: plan.chainId, orchestrator: plan.orchestrator });
19
+ return deployment === undefined
20
+ ? readLifecycleContract(client, plan.orchestrator, launchLifecycleAbi, "predictToken", [plan], block)
21
+ : readLifecycleContract(client, deployment.tokenFactory, lifecycleTokenPredictionAbi, "predictToken", [hashLaunchIdentity(plan), plan.token], block);
22
+ }
8
23
  export async function predictLifecycleToken(options) {
9
- const block = await readLifecycleBlock(options.client);
10
- const token = await readLifecycleContract(options.client, options.plan.orchestrator, launchLifecycleAbi, "predictToken", [options.plan], block);
11
- await assertLifecycleBlock(options.client, block);
12
- return token;
24
+ return withLifecycleReadClient(options.client, async (client) => {
25
+ const block = await readLifecycleBlock(client);
26
+ const token = await readLifecycleTokenAtBlock(client, options.plan, block);
27
+ await assertLifecycleBlock(client, block, options.plan.chainId);
28
+ return token;
29
+ });
30
+ }
31
+ const certifiedProfilesByInvocation = new WeakMap();
32
+ const boundDeploymentsByInvocation = new WeakMap();
33
+ function assertDerivedReadClientOpen(client) {
34
+ try {
35
+ return assertLifecycleReadClientOpen(client);
36
+ }
37
+ catch (failure) {
38
+ certifiedProfilesByInvocation.delete(client);
39
+ boundDeploymentsByInvocation.delete(client);
40
+ throw failure;
41
+ }
42
+ }
43
+ function lifecycleProfileCertificateKey(orchestrator, registry, id, registration, adapter, topology, envelope, block, chainId) {
44
+ const g = envelope?.graph;
45
+ const b = envelope?.bounds;
46
+ // Fixed ABI field order preserves every scalar, including flags delegated to
47
+ // registry eligibility. Keys never rehash runtime, chunk or creation bytes.
48
+ return JSON.stringify([
49
+ block.number.toString(), block.hash.toLowerCase(), chainId.toString(), orchestrator.toLowerCase(), registry.toLowerCase(), id.toLowerCase(),
50
+ [registration.adapterId.toLowerCase(), registration.configSchema.toLowerCase(), registration.dependencyDigest.toLowerCase(),
51
+ registration.venue.toLowerCase(), registration.factory.toLowerCase(), registration.hook.toLowerCase(), registration.capabilities.toString(), registration.enabled],
52
+ [adapter.implementation.toLowerCase(), adapter.codeHash.toLowerCase(), adapter.capabilities.toString(), adapter.configVersion, adapter.enabled],
53
+ [topology.hookTopology, topology.configVersion, topology.hookDeployer.toLowerCase(), topology.hookCreationCodeHash.toLowerCase()],
54
+ envelope === undefined ? null : [
55
+ envelope.artifactDigest.toLowerCase(), envelope.reviewManifestDigest.toLowerCase(), envelope.configBoundsDigest.toLowerCase(), envelope.termsDigest.toLowerCase(),
56
+ envelope.topology, envelope.configVersion, envelope.economicVersion, envelope.capabilities.toString(), envelope.flags.toString(),
57
+ envelope.callbackFlags, envelope.callbackMask, envelope.protocolTreasury.toLowerCase(), envelope.protocolFeeDenominator,
58
+ envelope.beneficiary.toLowerCase(), envelope.maximumDeveloperFeeBps,
59
+ [b.minimumTickSpacing, b.maximumTickSpacing, b.maximumPositions, b.maximumOracleCardinality, b.feeModeFlags],
60
+ [g.manager.toLowerCase(), g.hookRoot.toLowerCase(), g.oracleFactory.toLowerCase(), g.locker.toLowerCase(), g.collectorFactory.toLowerCase(),
61
+ g.collectorDeployer.toLowerCase(), g.hookDeployer.toLowerCase(), g.coreCodeHash.toLowerCase(), g.managerCodeHash.toLowerCase(),
62
+ g.hookRuntimeCodeHash.toLowerCase(), g.oracleFactoryCodeHash.toLowerCase(), g.lockerCodeHash.toLowerCase(), g.collectorFactoryCodeHash.toLowerCase(),
63
+ g.collectorDeployerCodeHash.toLowerCase(), g.hookDeployerCodeHash.toLowerCase(), g.hookCreationCodeHash.toLowerCase(),
64
+ g.codeChunk0.toLowerCase(), g.codeChunk0Hash.toLowerCase(), g.codeChunk1.toLowerCase(), g.codeChunk1Hash.toLowerCase(), g.sharedHookSalt.toLowerCase()],
65
+ ],
66
+ ]);
13
67
  }
14
68
  async function readDependencyCode(client, address, block) {
15
69
  const code = rpcHex(await lifecyclePinnedRpc(client, "eth_getCode", [address, toHex(block.number)], block), "lifecycle dependency code");
@@ -17,13 +71,39 @@ async function readDependencyCode(client, address, block) {
17
71
  throw new LifecyclePlanningError("PROFILE_DEPENDENCY", `Lifecycle dependency ${address} has no deployed code`);
18
72
  return code;
19
73
  }
20
- async function certifyLifecycleProfile(client, orchestrator, registry, id, registration, adapter, topology, envelope, block, chainId) {
74
+ async function certifyLifecycleProfile(client, orchestrator, registry, id, registration, adapter, topology, envelope, block, chainId, eligibility) {
75
+ if (!assertDerivedReadClientOpen(client))
76
+ return certifyLifecycleProfileFresh(client, orchestrator, registry, id, registration, adapter, topology, envelope, block, chainId, eligibility);
77
+ const key = lifecycleProfileCertificateKey(orchestrator, registry, id, registration, adapter, topology, envelope, block, chainId);
78
+ let certificates = certifiedProfilesByInvocation.get(client);
79
+ if (certificates === undefined) {
80
+ certificates = new Map();
81
+ certifiedProfilesByInvocation.set(client, certificates);
82
+ }
83
+ let pending = certificates.get(key);
84
+ if (pending === undefined) {
85
+ pending = certifyLifecycleProfileFresh(client, orchestrator, registry, id, registration, adapter, topology, envelope, block, chainId, eligibility);
86
+ certificates.set(key, pending);
87
+ const owned = pending;
88
+ void pending.catch(() => { if (certificates.get(key) === owned)
89
+ certificates.delete(key); });
90
+ }
91
+ try {
92
+ return await pending;
93
+ }
94
+ finally {
95
+ assertDerivedReadClientOpen(client);
96
+ }
97
+ }
98
+ async function certifyLifecycleProfileFresh(client, orchestrator, registry, id, registration, adapter, topology, envelope, block, chainId, eligibility) {
21
99
  const shared = registration.configSchema.toLowerCase() === V4_LIFECYCLE_CONFIG_SCHEMA.toLowerCase();
22
- const bound = registration.configSchema.toLowerCase() === V4_POOL_BOUND_LIFECYCLE_CONFIG_SCHEMA.toLowerCase();
100
+ const boundVersion = registration.configSchema.toLowerCase() === V4_POOL_BOUND_LIFECYCLE_CONFIG_SCHEMA_V5.toLowerCase() ? 5
101
+ : registration.configSchema.toLowerCase() === V4_POOL_BOUND_LIFECYCLE_CONFIG_SCHEMA_V6.toLowerCase() ? 6 : undefined;
102
+ const bound = boundVersion !== undefined;
23
103
  const abyss = registration.configSchema.toLowerCase() === ABYSS_LIFECYCLE_CONFIG_SCHEMA.toLowerCase();
24
104
  if (!shared && !bound && !abyss)
25
105
  throw new LifecyclePlanningError("UNSUPPORTED_SCHEMA", `Unsupported lifecycle config schema ${registration.configSchema}`);
26
- const version = shared ? 4 : bound ? 5 : 1;
106
+ const version = shared ? 4 : boundVersion ?? 1;
27
107
  if (adapter.configVersion !== version || topology.configVersion !== version || topology.hookTopology !== (shared ? 1 : bound ? 2 : 0))
28
108
  throw new LifecyclePlanningError("UNCERTIFIED_TOPOLOGY", "Registry topology/version differs from the supported config schema");
29
109
  if (abyss) {
@@ -36,10 +116,12 @@ async function certifyLifecycleProfile(client, orchestrator, registry, id, regis
36
116
  const known = [0, 1, 2, 3].some((variant) => keccak256(encodeAbiParameters([{ type: "bytes32" }, { type: "uint256" }, { type: "address" }, { type: "uint8" }], [domain, chainId, factory, variant])).toLowerCase() === id.toLowerCase());
37
117
  if (!known || registration.venue.toLowerCase() !== factory.toLowerCase() || registration.hook !== zeroAddress)
38
118
  throw new LifecyclePlanningError("PROFILE_DEPENDENCY", "Abyss profile is not the exact canonical factory/variant/schema binding");
39
- const eligible = await readLifecycleContract(client, registry, lifecycleRegistryAbi, "requireEligible", [registration.adapterId, id, version, LIFECYCLE_REQUIRED_CAPABILITIES], block);
119
+ if (eligibility !== undefined && "failure" in eligibility)
120
+ throw eligibility.failure;
121
+ const eligible = eligibility?.eligible ?? await readLifecycleContract(client, registry, lifecycleRegistryAbi, "requireEligible", [registration.adapterId, id, version, LIFECYCLE_REQUIRED_CAPABILITIES], block);
40
122
  if (eligible.toLowerCase() !== adapter.implementation.toLowerCase())
41
123
  throw new LifecyclePlanningError("INELIGIBLE_PROFILE", "Registry refuses this profile for pending source admission");
42
- return { topology };
124
+ return Object.freeze({ topology: Object.freeze({ ...topology }) });
43
125
  }
44
126
  if (envelope === undefined || envelope.topology !== topology.hookTopology || envelope.configVersion !== version || envelope.economicVersion !== 3 ||
45
127
  envelope.flags !== 0n || envelope.callbackFlags !== 0x1afc || envelope.callbackMask !== 0x3fff ||
@@ -61,7 +143,7 @@ async function certifyLifecycleProfile(client, orchestrator, registry, id, regis
61
143
  if (registration.factory !== zeroAddress || registration.venue.toLowerCase() !== g.manager.toLowerCase() || registration.hook.toLowerCase() !== g.hookRoot.toLowerCase() ||
62
144
  topology.hookDeployer.toLowerCase() !== g.hookDeployer.toLowerCase() || topology.hookCreationCodeHash.toLowerCase() !== g.hookCreationCodeHash.toLowerCase())
63
145
  throw new LifecyclePlanningError("PROFILE_DEPENDENCY", "Reviewed venue/topology differs from the frozen envelope graph");
64
- const deployerAbi = shared ? sharedHookDeployerV1Abi : poolHookDeployerV1Abi;
146
+ const deployerAbi = shared ? sharedHookDeployerV1Abi : boundVersion === 5 ? poolHookDeployerV1Abi : poolHookDeployerConfigV6Abi;
65
147
  const codeBindings = [[orchestrator, g.coreCodeHash], [g.manager, g.managerCodeHash], [g.oracleFactory, g.oracleFactoryCodeHash],
66
148
  [g.locker, g.lockerCodeHash], [g.collectorFactory, g.collectorFactoryCodeHash], [g.collectorDeployer, g.collectorDeployerCodeHash],
67
149
  [g.hookDeployer, g.hookDeployerCodeHash]];
@@ -118,7 +200,7 @@ async function certifyLifecycleProfile(client, orchestrator, registry, id, regis
118
200
  keccak256(chunk0Code).toLowerCase() !== g.codeChunk0Hash.toLowerCase() || (chunk1 === zeroAddress ? zeroHash : keccak256(chunk1Code)).toLowerCase() !== g.codeChunk1Hash.toLowerCase())
119
201
  throw new LifecyclePlanningError("PROFILE_DEPENDENCY", "Reviewed deployer chunks differ from exact immutable STOP-prefixed bytecode evidence");
120
202
  const creationCode = concatHex([`0x${chunk0Code.slice(4)}`, chunk1 === zeroAddress ? "0x" : `0x${chunk1Code.slice(4)}`]);
121
- if ((creationCode.length - 2) / 2 + (shared ? 96 : 576) > 49152 || creationCodeHash === zeroHash ||
203
+ if ((creationCode.length - 2) / 2 + (shared ? 96 : boundVersion === 5 ? 576 : 640) > 49152 || creationCodeHash === zeroHash ||
122
204
  creationCodeHash.toLowerCase() !== g.hookCreationCodeHash.toLowerCase() || keccak256(creationCode).toLowerCase() !== creationCodeHash.toLowerCase() ||
123
205
  hashLaunchDependencies({ chainId, core: orchestrator, registry, registrar: adapter.implementation, graph: g }).toLowerCase() !== registration.dependencyDigest.toLowerCase())
124
206
  throw new LifecyclePlanningError("PROFILE_DEPENDENCY", "Reviewed creation artifact, constructor bound or graph digest differs from admission");
@@ -140,7 +222,7 @@ async function certifyLifecycleProfile(client, orchestrator, registry, id, regis
140
222
  throw new LifecyclePlanningError("PROFILE_DEPENDENCY", "Bound topology cannot reuse a shared root");
141
223
  if ([zeroAddress, orchestrator, registry, adapter.implementation, g.manager, g.hookRoot, g.locker, g.collectorFactory, g.collectorDeployer, g.hookDeployer].some((address) => address.toLowerCase() === envelope.beneficiary.toLowerCase()))
142
224
  throw new LifecyclePlanningError("PROFILE_TERMS", "Stable author identity is an excluded reviewed graph destination");
143
- return { topology, boundGraph: bound ? { manager: g.manager, oracleFactory: g.oracleFactory, locker: g.locker, collectorFactory: g.collectorFactory, deployer: g.hookDeployer, creationCode } : undefined };
225
+ return Object.freeze({ topology: Object.freeze({ ...topology }), boundGraph: bound ? Object.freeze({ manager: g.manager, oracleFactory: g.oracleFactory, locker: g.locker, collectorFactory: g.collectorFactory, deployer: g.hookDeployer, creationCode }) : undefined });
144
226
  }
145
227
  /** Validate the market-selected registered oracle against the certified factory at the pinned block. */
146
228
  export async function validateV4LifecycleOracle(options) {
@@ -172,7 +254,7 @@ export async function readLifecycleProfiles(options, pinnedBlock) {
172
254
  const readProfile = async (id) => {
173
255
  const registration = await readLifecycleContract(client, registry, lifecycleRegistryAbi, "profile", [id], block);
174
256
  const schema = registration.configSchema.toLowerCase();
175
- const venueKind = schema === V4_LIFECYCLE_CONFIG_SCHEMA.toLowerCase() || schema === V4_POOL_BOUND_LIFECYCLE_CONFIG_SCHEMA.toLowerCase() ? "uniswap-v4" : schema === ABYSS_LIFECYCLE_CONFIG_SCHEMA.toLowerCase() ? "abyss" : "unknown";
257
+ const venueKind = schema === V4_LIFECYCLE_CONFIG_SCHEMA.toLowerCase() || schema === V4_POOL_BOUND_LIFECYCLE_CONFIG_SCHEMA_V5.toLowerCase() || schema === V4_POOL_BOUND_LIFECYCLE_CONFIG_SCHEMA_V6.toLowerCase() ? "uniswap-v4" : schema === ABYSS_LIFECYCLE_CONFIG_SCHEMA.toLowerCase() ? "abyss" : "unknown";
176
258
  const [adapter, certification] = await Promise.all([
177
259
  readLifecycleContract(client, registry, lifecycleRegistryAbi, "adapter", [registration.adapterId], block),
178
260
  venueKind === "unknown" ? undefined : Promise.all([
@@ -182,6 +264,10 @@ export async function readLifecycleProfiles(options, pinnedBlock) {
182
264
  readLifecycleContract(client, registry, lifecycleRegistryAbi, "developerTerms", [id], block),
183
265
  readProtocolMaximumDeveloperFeeBps(),
184
266
  ]) : undefined,
267
+ // The exact Abyss arguments follow from registration, independently
268
+ // of adapter/topology responses. Handle refusal immediately, but
269
+ // keep its original place after canonical/schema/topology checks.
270
+ venueKind === "abyss" ? chainIdPromise.then(() => readLifecycleContract(client, registry, lifecycleRegistryAbi, "requireEligible", [registration.adapterId, id, 1, LIFECYCLE_REQUIRED_CAPABILITIES], block)).then((eligible) => ({ eligible }), (failure) => ({ failure })) : undefined,
185
271
  ]).then((values) => ({ values }), (failure) => ({ failure })),
186
272
  ]);
187
273
  const chainId = await chainIdPromise;
@@ -196,7 +282,7 @@ export async function readLifecycleProfiles(options, pinnedBlock) {
196
282
  throw new LifecyclePlanningError("UNSUPPORTED_SCHEMA", `Unsupported lifecycle config schema ${registration.configSchema}`);
197
283
  if ("failure" in certification)
198
284
  throw certification.failure;
199
- const [recordedTopology, reviewed] = certification.values;
285
+ const [recordedTopology, reviewed, eligibility] = certification.values;
200
286
  topology = recordedTopology;
201
287
  if (reviewed !== undefined) {
202
288
  envelope = reviewed[0];
@@ -208,13 +294,13 @@ export async function readLifecycleProfiles(options, pinnedBlock) {
208
294
  maximumDeveloperFeeBps > reviewed[2])
209
295
  throw new LifecyclePlanningError("PROFILE_TERMS", "Registry developer terms differ from the frozen reviewed envelope");
210
296
  }
211
- await certifyLifecycleProfile(client, options.orchestrator, registry, id, registration, adapter, topology, envelope, block, chainId);
297
+ await certifyLifecycleProfile(client, options.orchestrator, registry, id, registration, adapter, topology, envelope, block, chainId, eligibility);
212
298
  if (developerTerms !== undefined && !developerTerms.enabled)
213
299
  throw new LifecyclePlanningError("INELIGIBLE_PROFILE", "Registry refuses this profile for pending source admission");
214
300
  admitted = true;
215
301
  }
216
302
  catch (failure) {
217
- reason = failure instanceof Error ? failure.message : String(failure);
303
+ reason = lifecycleFailureReason(failure);
218
304
  }
219
305
  return { id, registration, adapter, topology, envelope, developerTerms, protocolMaximumDeveloperFeeBps: venueKind === "uniswap-v4" ? protocolMaximumDeveloperFeeBps : undefined, admitted, reason, venueKind };
220
306
  };
@@ -235,14 +321,67 @@ export async function readLifecycleProfiles(options, pinnedBlock) {
235
321
  return profiles;
236
322
  }));
237
323
  }
238
- async function readPoolBoundHookDeploymentDetails(options, block) {
324
+ async function readPoolBoundHookDeploymentDetails(options, block, commitment) {
239
325
  const { client, plan, marketIndex } = options;
240
326
  const market = plan.markets[marketIndex];
241
- if (market === undefined || market.configVersion !== 5)
242
- throw new LifecyclePlanningError("INVALID_BOUND_MARKET", "Market index must select reviewed pool-bound config version 5");
243
- const chainId = rpcQuantity(await lifecycleRpc(client, "eth_chainId"), "chain ID");
327
+ if (market === undefined || !isPoolBoundV4ConfigVersion(market.configVersion))
328
+ throw new LifecyclePlanningError("INVALID_BOUND_MARKET", "Market index must select explicit pool-bound config version 5 or 6");
329
+ let chainId;
330
+ try {
331
+ chainId = rpcQuantity(await lifecycleRpc(client, "eth_chainId"), "chain ID");
332
+ }
333
+ finally {
334
+ assertDerivedReadClientOpen(client);
335
+ }
336
+ if (hashLaunchPlan(plan) !== commitment)
337
+ throw new LifecyclePlanningError("PLAN_MUTATED", "Economic plan changed while observing the hook deployment chain");
244
338
  if (chainId !== plan.chainId)
245
339
  throw new LifecyclePlanningError("CHAIN_MISMATCH", "RPC chain differs from the committed plan");
340
+ if (getKnownLifecycleProfile({ chainId, orchestrator: plan.orchestrator, profileId: market.profileId }) !== undefined) {
341
+ const token = await readLifecycleTokenAtBlock(client, plan, block);
342
+ const details = deriveKnownPoolBoundHookDeployment({ plan, marketIndex, token });
343
+ if (details === undefined)
344
+ throw new LifecyclePlanningError("INVALID_BOUND_MARKET", "Known profile has no bound-hook construction metadata");
345
+ if (hashLaunchPlan(plan) !== commitment)
346
+ throw new LifecyclePlanningError("PLAN_MUTATED", "Economic plan changed while deriving hook deployment metadata");
347
+ assertDerivedReadClientOpen(client);
348
+ return Object.freeze({ deployment: Object.freeze(details.deployment), parameters: Object.freeze(details.parameters), configVersion: details.configVersion });
349
+ }
350
+ if (!assertDerivedReadClientOpen(client)) {
351
+ const details = await readPoolBoundHookDeploymentDetailsFresh(options, block, chainId);
352
+ if (hashLaunchPlan(plan) !== commitment)
353
+ throw new LifecyclePlanningError("PLAN_MUTATED", "Economic plan changed while reading hook deployment metadata");
354
+ return details;
355
+ }
356
+ const key = JSON.stringify([block.number.toString(), block.hash.toLowerCase(), chainId.toString(), commitment.toLowerCase(), marketIndex]);
357
+ let deployments = boundDeploymentsByInvocation.get(client);
358
+ if (deployments === undefined) {
359
+ deployments = new Map();
360
+ boundDeploymentsByInvocation.set(client, deployments);
361
+ }
362
+ let pending = deployments.get(key);
363
+ if (pending === undefined) {
364
+ pending = readPoolBoundHookDeploymentDetailsFresh(options, block, chainId).then((details) => {
365
+ if (hashLaunchPlan(plan) !== commitment)
366
+ throw new LifecyclePlanningError("PLAN_MUTATED", "Economic plan changed while reading hook deployment metadata");
367
+ assertDerivedReadClientOpen(client);
368
+ return details;
369
+ });
370
+ deployments.set(key, pending);
371
+ const owned = pending;
372
+ void pending.catch(() => { if (deployments.get(key) === owned)
373
+ deployments.delete(key); });
374
+ }
375
+ try {
376
+ return await pending;
377
+ }
378
+ finally {
379
+ assertDerivedReadClientOpen(client);
380
+ }
381
+ }
382
+ async function readPoolBoundHookDeploymentDetailsFresh(options, block, chainId) {
383
+ const { client, plan, marketIndex } = options;
384
+ const market = plan.markets[marketIndex];
246
385
  const registry = await readLifecycleContract(client, plan.orchestrator, launchLifecycleAbi, "registry", [], block);
247
386
  const [authority, registration] = await Promise.all([
248
387
  readLifecycleContract(client, registry, lifecycleRegistryAbi, "core", [], block),
@@ -263,35 +402,35 @@ async function readPoolBoundHookDeploymentDetails(options, block) {
263
402
  const { boundGraph } = await certifyLifecycleProfile(client, plan.orchestrator, registry, market.profileId, registration, adapter, recorded, envelope, block, chainId);
264
403
  if (boundGraph === undefined)
265
404
  throw new LifecyclePlanningError("UNCERTIFIED_TOPOLOGY", "Market does not have a certified pool-bound deployer graph");
266
- const config = decodePoolBoundV4LifecycleMarketConfig(market.config);
405
+ if (!isPoolBoundV4ConfigVersion(market.configVersion))
406
+ throw new LifecyclePlanningError("INVALID_BOUND_MARKET", "Market must select an explicit pool-bound version");
407
+ const config = decodePoolBoundV4LifecycleMarketConfig(market.config, market.configVersion);
267
408
  validateV4LifecycleMarket({ market, config, token, profile: {
268
409
  id: market.profileId, registration, adapter, topology: recorded, envelope,
269
410
  developerTerms: { adapter: implementation, beneficiary, maximumDeveloperFeeBps, termsDigest, enabled },
270
411
  protocolMaximumDeveloperFeeBps, venueKind: "uniswap-v4", admitted: enabled,
271
412
  } });
272
413
  await validateV4LifecycleOracle({ client, envelope, oracleConfigId: config.oracleConfigId, block });
273
- const expected = {
274
- poolManager: boundGraph.manager, registrar: adapter.implementation, oracleFactory: boundGraph.oracleFactory, core: plan.orchestrator,
275
- liquidityLocker: boundGraph.locker, token, quoteCurrency: market.quoteAsset, lpFeePips: config.lpFeePips, tickSpacing: config.tickSpacing,
276
- sqrtPriceX96: config.sqrtPriceX96, hookFeePips: config.hookFeePips, feeMode: config.feeMode, protocolFeeDenominator: config.protocolFeeDenominator,
277
- treasury: config.treasury, externalLiquidityDisabled: config.externalLiquidityDisabled, oracleConfigId: config.oracleConfigId,
278
- marketCommitment: hashPoolBoundV4MarketCommitment({ chainId, core: plan.orchestrator, registrar: adapter.implementation, token, market }),
279
- expectedPositionCount: config.positions.length,
280
- };
414
+ const expected = buildPoolBoundHookParameters({
415
+ chainId, core: plan.orchestrator, poolManager: boundGraph.manager, registrar: adapter.implementation,
416
+ oracleFactory: boundGraph.oracleFactory, liquidityLocker: boundGraph.locker, token, market, config,
417
+ });
418
+ const deployerAbi = config.version === 5 ? poolHookDeployerV1Abi : poolHookDeployerConfigV6Abi;
419
+ const collectorAbi = config.version === 5 ? poolFeeCollectorFactoryV1Abi : poolFeeCollectorFactoryConfigV6Abi;
281
420
  const [[parameters, parameterSalt], [deployer, initCodeHash, salt, predictedHook], remoteInitCodeHash, remotePrediction] = await Promise.all([
282
- readLifecycleContract(client, boundGraph.collectorFactory, poolFeeCollectorFactoryV1Abi, "poolBoundHookParameters", [adapter.implementation, token, market], block),
421
+ readLifecycleContract(client, boundGraph.collectorFactory, collectorAbi, "poolBoundHookParameters", [adapter.implementation, token, market], block),
283
422
  readLifecycleContract(client, adapter.implementation, poolMarketAdapterV1Abi, "hookDeploymentMetadata", [token, market], block),
284
- readLifecycleContract(client, boundGraph.deployer, poolHookDeployerV1Abi, "initCodeHash", [expected], block),
285
- readLifecycleContract(client, boundGraph.deployer, poolHookDeployerV1Abi, "predict", [expected, config.hookSalt], block),
423
+ readLifecycleContract(client, boundGraph.deployer, deployerAbi, "initCodeHash", [expected], block),
424
+ readLifecycleContract(client, boundGraph.deployer, deployerAbi, "predict", [expected, config.hookSalt], block),
286
425
  ]);
287
- const localInitCodeHash = poolBoundHookInitCodeHash(boundGraph.creationCode, expected);
426
+ const localInitCodeHash = poolBoundHookInitCodeHash(boundGraph.creationCode, expected, config.version);
288
427
  const localPrediction = predictPoolBoundHookAddress({ deployer: boundGraph.deployer, initCodeHash: localInitCodeHash, salt: config.hookSalt });
289
- if (encodePoolBoundHookParameters(parameters).toLowerCase() !== encodePoolBoundHookParameters(expected).toLowerCase() || parameterSalt.toLowerCase() !== config.hookSalt.toLowerCase() || salt.toLowerCase() !== config.hookSalt.toLowerCase() || deployer.toLowerCase() !== boundGraph.deployer.toLowerCase() || initCodeHash.toLowerCase() !== localInitCodeHash.toLowerCase() || remoteInitCodeHash.toLowerCase() !== localInitCodeHash.toLowerCase() || predictedHook.toLowerCase() !== localPrediction.toLowerCase() || remotePrediction.toLowerCase() !== localPrediction.toLowerCase())
290
- throw new LifecyclePlanningError("HOOK_DEPLOYMENT_CHANGED", "Bound hook metadata differs from the exact certified constructor economics, factory, initcode, salt or CREATE2 prediction");
428
+ if (encodePoolBoundHookParameters(parameters, config.version).toLowerCase() !== encodePoolBoundHookParameters(expected, config.version).toLowerCase() || parameterSalt.toLowerCase() !== config.hookSalt.toLowerCase() || salt.toLowerCase() !== config.hookSalt.toLowerCase() || deployer.toLowerCase() !== boundGraph.deployer.toLowerCase() || initCodeHash.toLowerCase() !== localInitCodeHash.toLowerCase() || remoteInitCodeHash.toLowerCase() !== localInitCodeHash.toLowerCase() || predictedHook.toLowerCase() !== localPrediction.toLowerCase() || remotePrediction.toLowerCase() !== localPrediction.toLowerCase())
429
+ throw new LifecyclePlanningError("HOOK_DEPLOYMENT_CHANGED", "Bound hook metadata differs from the exact certified version, constructor economics, factory, initcode, salt or CREATE2 prediction");
291
430
  const hookCode = rpcHex(await lifecyclePinnedRpc(client, "eth_getCode", [predictedHook, toHex(block.number)], block), "bound hook code");
292
431
  if (hookCode !== "0x") {
293
- const [deployedCodeHash, dependencies, requiredFlags, allFlags, actualPoolId, deploymentConfigHash, marketCommitment, opening, positions] = await Promise.all([
294
- readLifecycleContract(client, deployer, poolHookDeployerV1Abi, "deployedCodeHash", [predictedHook], block),
432
+ const [deployedCodeHash, dependencies, requiredFlags, allFlags, actualPoolId, deploymentConfigHash, marketCommitment, opening, positions, feePolicy] = await Promise.all([
433
+ readLifecycleContract(client, deployer, deployerAbi, "deployedCodeHash", [predictedHook], block),
295
434
  Promise.all(["poolManager", "registrar", "oracleFactory", "core", "liquidityLocker", "token"].map((getter) => readLifecycleContract(client, predictedHook, fixedFeePoolHookV1Abi, getter, [], block))),
296
435
  readLifecycleContract(client, predictedHook, fixedFeePoolHookV1Abi, "REQUIRED_HOOK_FLAGS", [], block),
297
436
  readLifecycleContract(client, predictedHook, fixedFeePoolHookV1Abi, "ALL_HOOK_MASK", [], block),
@@ -300,6 +439,10 @@ async function readPoolBoundHookDeploymentDetails(options, block) {
300
439
  readLifecycleContract(client, predictedHook, fixedFeePoolHookV1Abi, "marketCommitment", [], block),
301
440
  readLifecycleContract(client, predictedHook, fixedFeePoolHookV1Abi, "openingSqrtPriceX96", [], block),
302
441
  readLifecycleContract(client, predictedHook, fixedFeePoolHookV1Abi, "expectedPositionCount", [], block),
442
+ config.version === 6 ? Promise.all([
443
+ readLifecycleContract(client, predictedHook, fixedFeePoolHookConfigV6Abi, "minimumHookFeePips", [], block),
444
+ readLifecycleContract(client, predictedHook, fixedFeePoolHookConfigV6Abi, "feeSensitivityPipsSecondsPerTick", [], block),
445
+ ]) : undefined,
303
446
  ]);
304
447
  if ((hookCode.length - 2) / 2 > 24576 || deployedCodeHash === zeroHash || deployedCodeHash.toLowerCase() !== keccak256(hookCode).toLowerCase())
305
448
  throw new LifecyclePlanningError("HOOK_DEPLOYMENT_CHANGED", "Existing hook lacks this exact typed deployer's bounded runtime-code provenance");
@@ -311,22 +454,24 @@ async function readPoolBoundHookDeploymentDetails(options, block) {
311
454
  throw new LifecyclePlanningError("HOOK_DEPLOYMENT_CHANGED", "Existing bound hook callback declarations differ from the reviewed envelope");
312
455
  const [currency0, currency1] = BigInt(token) < BigInt(market.quoteAsset) ? [token, market.quoteAsset] : [market.quoteAsset, token];
313
456
  const expectedPoolId = keccak256(encodeAbiParameters([{ type: "address" }, { type: "address" }, { type: "uint24" }, { type: "int24" }, { type: "address" }], [currency0, currency1, config.lpFeePips, config.tickSpacing, predictedHook]));
314
- if (actualPoolId.toLowerCase() !== expectedPoolId.toLowerCase() || deploymentConfigHash.toLowerCase() !== keccak256(encodePoolBoundHookParameters(expected)).toLowerCase() || marketCommitment.toLowerCase() !== expected.marketCommitment.toLowerCase() || opening !== expected.sqrtPriceX96 || positions !== expected.expectedPositionCount)
315
- throw new LifecyclePlanningError("HOOK_DEPLOYMENT_CHANGED", "Existing hook key, economic commitment or immutable opening geometry changed");
457
+ if (actualPoolId.toLowerCase() !== expectedPoolId.toLowerCase() || deploymentConfigHash.toLowerCase() !== keccak256(encodePoolBoundHookParameters(expected, config.version)).toLowerCase() || marketCommitment.toLowerCase() !== expected.marketCommitment.toLowerCase() || opening !== expected.sqrtPriceX96 || positions !== expected.expectedPositionCount ||
458
+ (config.version === 6 && (feePolicy?.[0] !== config.minimumHookFeePips || feePolicy?.[1] !== config.feeSensitivityPipsSecondsPerTick)))
459
+ throw new LifecyclePlanningError("HOOK_DEPLOYMENT_CHANGED", "Existing hook key, economic commitment, versioned fee policy or immutable opening geometry changed");
316
460
  }
317
- return { deployment: { deployer, initCodeHash, salt, predictedHook }, parameters: expected };
461
+ return Object.freeze({ deployment: Object.freeze({ deployer, initCodeHash, salt, predictedHook }), parameters: Object.freeze(expected), configVersion: config.version });
318
462
  }
319
- /** Works with an unmined candidate salt and after preparation; never accepts a caller-selected root. */
463
+ /** Known identities use frozen local construction data; unlisted identities use
464
+ * explicit live certification. Exact launch execution, not either DTO, authorizes. */
320
465
  export async function readPoolBoundHookDeployment(options, pinnedBlock) {
321
466
  const commitment = hashLaunchPlan(options.plan);
322
467
  const block = pinnedBlock ?? await readLifecycleBlock(options.client);
323
468
  return withLifecycleReadClient(options.client, async (client) => {
324
- const { deployment } = await readPoolBoundHookDeploymentDetails({ ...options, client }, block);
469
+ const { deployment } = await readPoolBoundHookDeploymentDetails({ ...options, client }, block, commitment);
325
470
  if (hashLaunchPlan(options.plan) !== commitment)
326
471
  throw new LifecyclePlanningError("PLAN_MUTATED", "Economic plan changed while reading hook deployment metadata");
327
472
  if (pinnedBlock === undefined)
328
473
  await assertLifecycleBlock(client, block, options.plan.chainId);
329
- return deployment;
474
+ return { ...deployment };
330
475
  });
331
476
  }
332
477
  /** Optional permissionless predeployment calldata; no token deployment, pool registration or wallet broadcast. */
@@ -334,13 +479,14 @@ export async function buildPoolBoundHookDeploymentTransaction(options) {
334
479
  const commitment = hashLaunchPlan(options.plan);
335
480
  const block = await readLifecycleBlock(options.client);
336
481
  return withLifecycleReadClient(options.client, async (client) => {
337
- const { deployment, parameters } = await readPoolBoundHookDeploymentDetails({ ...options, client }, block);
482
+ const { deployment, parameters, configVersion } = await readPoolBoundHookDeploymentDetails({ ...options, client }, block, commitment);
338
483
  if (!hasLifecycleV4HookPermissions(deployment.predictedHook))
339
484
  throw new LifecyclePlanningError("INVALID_HOOK_BITS", "Finalize a salt with the exact lifecycle hook permissions before predeployment");
340
485
  if (hashLaunchPlan(options.plan) !== commitment)
341
486
  throw new LifecyclePlanningError("PLAN_MUTATED", "Economic plan changed while constructing hook deployment calldata");
342
487
  await assertLifecycleBlock(client, block, options.plan.chainId);
343
- return { to: deployment.deployer, data: encodeFunctionData({ abi: poolHookDeployerV1Abi, functionName: "deploy", args: [parameters, deployment.salt] }), value: 0n, deployment };
488
+ const abi = configVersion === 5 ? poolHookDeployerV1Abi : poolHookDeployerConfigV6Abi;
489
+ return { to: deployment.deployer, data: encodeFunctionData({ abi, functionName: "deploy", args: [parameters, deployment.salt] }), value: 0n, deployment: { ...deployment } };
344
490
  });
345
491
  }
346
492
  export function validateLifecycleMarketIdentity(identity, plan, token, marketIndex) {
@@ -447,20 +593,28 @@ async function readReceipt(reference, options, block) {
447
593
  }
448
594
  /** Reads confirmation-bound canonical state and receipt provenance; local step counters are never used. */
449
595
  export async function readLaunchProgress(options, pinnedBlock) {
596
+ if (options.signal?.aborted)
597
+ throw Object.assign(new Error("Lifecycle progress read cancelled"), { name: "AbortError" });
450
598
  const block = pinnedBlock ?? await readLifecycleBlock(options.client);
451
599
  return withLifecycleReadClient(options.client, (client) => readLaunchProgressAtBlock(options, client, block, pinnedBlock === undefined));
452
600
  }
453
601
  async function readLaunchProgressAtBlock(options, client, block, checkBlock) {
454
602
  const { planned } = options;
603
+ const assertActive = () => {
604
+ if (options.signal?.aborted)
605
+ throw Object.assign(new Error("Lifecycle progress read cancelled"), { name: "AbortError" });
606
+ };
607
+ assertActive();
455
608
  const confirmationDepth = options.confirmations ?? planned.confirmations;
456
609
  if (!Number.isSafeInteger(confirmationDepth) || confirmationDepth < 1)
457
610
  throw new LifecyclePlanningError("INVALID_CONFIRMATIONS", "Confirmation depth must be a positive integer");
458
611
  const confirmedNumber = block.number >= BigInt(confirmationDepth - 1) ? block.number - BigInt(confirmationDepth - 1) : 0n;
459
612
  const [confirmedBlock, chainIdValue] = await Promise.all([
460
613
  confirmedNumber === block.number ? block : readLifecycleBlock(client, toHex(confirmedNumber)),
461
- lifecycleRpc(client, "eth_chainId"),
614
+ readLifecycleChainId(client),
462
615
  ]);
463
- const chainId = rpcQuantity(chainIdValue, "chain ID");
616
+ assertActive();
617
+ const chainId = chainIdValue;
464
618
  if (chainId !== planned.plan.chainId)
465
619
  throw new LifecyclePlanningError("CHAIN_MISMATCH", "RPC chain differs from the committed launch");
466
620
  if (planned.account.toLowerCase() !== planned.plan.creator.toLowerCase())
@@ -470,11 +624,12 @@ async function readLaunchProgressAtBlock(options, client, block, checkBlock) {
470
624
  const [head, confirmedProgress, token, confirmedNonce, headNonce, pendingNonce] = await Promise.all([
471
625
  readLifecycleContract(client, planned.plan.orchestrator, launchLifecycleAbi, "readLaunchProgress", [planned.launchId], block, planned.account),
472
626
  confirmedNumber === block.number ? undefined : readLifecycleContract(client, planned.plan.orchestrator, launchLifecycleAbi, "readLaunchProgress", [planned.launchId], confirmedBlock, planned.account),
473
- readLifecycleContract(client, planned.plan.orchestrator, launchLifecycleAbi, "predictToken", [planned.plan], block),
627
+ readLifecycleTokenAtBlock(client, planned.plan, block),
474
628
  lifecycleRpc(client, "eth_getTransactionCount", [planned.account, toHex(confirmedBlock.number)]),
475
629
  confirmedNumber === block.number ? undefined : lifecycleRpc(client, "eth_getTransactionCount", [planned.account, toHex(block.number)]),
476
630
  lifecycleRpc(client, "eth_getTransactionCount", [planned.account, "pending"]),
477
631
  ]);
632
+ assertActive();
478
633
  const canonical = confirmedProgress ?? head;
479
634
  if (token.toLowerCase() !== planned.predictedToken.toLowerCase())
480
635
  throw new LifecyclePlanningError("TOKEN_IDENTITY", "Predicted token changed for the committed token configuration");
@@ -493,6 +648,7 @@ async function readLaunchProgressAtBlock(options, client, block, checkBlock) {
493
648
  const progressParameters = [{ type: "tuple", components: launchProgressV1Components }];
494
649
  const confirmationSafe = confirmedAccountNonce === headAccountNonce && pendingAccountNonce === headAccountNonce && keccak256(encodeAbiParameters(progressParameters, [canonical])) === keccak256(encodeAbiParameters(progressParameters, [head]));
495
650
  const receipts = await Promise.all((options.receipts ?? []).map((reference) => readReceipt({ ...reference, confirmations: Math.max(reference.confirmations ?? 1, confirmationDepth) }, { ...options, client }, block)));
651
+ assertActive();
496
652
  let markets = [];
497
653
  if (canonical.preparedMarkets > 0) {
498
654
  const directory = await readLifecycleContract(client, planned.plan.orchestrator, launchLifecycleAbi, "directory", [], confirmedBlock);
@@ -504,7 +660,9 @@ async function readLaunchProgressAtBlock(options, client, block, checkBlock) {
504
660
  return { index, prepared, live };
505
661
  }
506
662
  catch (failure) {
507
- return { index, prepared, error: failure instanceof Error ? failure.message : String(failure) };
663
+ if (failure instanceof Error && failure.name === "AbortError")
664
+ throw failure;
665
+ return { index, prepared, error: lifecycleFailureReason(failure) };
508
666
  }
509
667
  }));
510
668
  }
@@ -514,6 +672,7 @@ async function readLaunchProgressAtBlock(options, client, block, checkBlock) {
514
672
  await assertLifecycleBlock(client, confirmedBlock, chainId);
515
673
  if (hashLaunchPlan(planned.plan).toLowerCase() !== planned.planHash.toLowerCase() || hashLaunchIdentity(planned.plan).toLowerCase() !== planned.launchId.toLowerCase())
516
674
  throw new LifecyclePlanningError("PLAN_MUTATED", "Stored economic plan changed during asynchronous progress reads");
675
+ assertActive();
517
676
  return { canonical, head, confirmationDepth, confirmedBlockNumber: confirmedBlock.number, confirmedBlockHash: confirmedBlock.hash, confirmedAccountNonce, headAccountNonce, pendingAccountNonce, confirmationSafe, token, planHash: planned.planHash, launchId: planned.launchId, chainId, blockNumber: block.number, blockHash: block.hash, markets, receipts };
518
677
  }
519
678
  //# sourceMappingURL=progress.js.map