@black-market/sdk 0.14.0 → 0.15.0

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 (73) hide show
  1. package/README.md +4 -3
  2. package/dist/lifecycle/authors.js +2 -2
  3. package/dist/lifecycle/authors.js.map +1 -1
  4. package/dist/lifecycle/gas-profile.d.ts +35 -0
  5. package/dist/lifecycle/gas-profile.d.ts.map +1 -0
  6. package/dist/lifecycle/gas-profile.js +183 -0
  7. package/dist/lifecycle/gas-profile.js.map +1 -0
  8. package/dist/lifecycle/index.d.ts +3 -1
  9. package/dist/lifecycle/index.d.ts.map +1 -1
  10. package/dist/lifecycle/index.js +3 -1
  11. package/dist/lifecycle/index.js.map +1 -1
  12. package/dist/lifecycle/lens.d.ts +1 -1
  13. package/dist/lifecycle/lens.d.ts.map +1 -1
  14. package/dist/lifecycle/lens.js +1 -1
  15. package/dist/lifecycle/lens.js.map +1 -1
  16. package/dist/lifecycle/opening-buys.d.ts +13 -0
  17. package/dist/lifecycle/opening-buys.d.ts.map +1 -0
  18. package/dist/lifecycle/opening-buys.js +171 -0
  19. package/dist/lifecycle/opening-buys.js.map +1 -0
  20. package/dist/lifecycle/planner.d.ts +2 -2
  21. package/dist/lifecycle/planner.d.ts.map +1 -1
  22. package/dist/lifecycle/planner.js +178 -163
  23. package/dist/lifecycle/planner.js.map +1 -1
  24. package/dist/lifecycle/presets.d.ts +6 -1
  25. package/dist/lifecycle/presets.d.ts.map +1 -1
  26. package/dist/lifecycle/presets.js +7 -0
  27. package/dist/lifecycle/presets.js.map +1 -1
  28. package/dist/lifecycle/progress.d.ts +1 -1
  29. package/dist/lifecycle/progress.d.ts.map +1 -1
  30. package/dist/lifecycle/progress.js +21 -20
  31. package/dist/lifecycle/progress.js.map +1 -1
  32. package/dist/lifecycle/rpc.d.ts +24 -19
  33. package/dist/lifecycle/rpc.d.ts.map +1 -1
  34. package/dist/lifecycle/rpc.js +58 -50
  35. package/dist/lifecycle/rpc.js.map +1 -1
  36. package/dist/lifecycle/simulation.d.ts +3 -4
  37. package/dist/lifecycle/simulation.d.ts.map +1 -1
  38. package/dist/lifecycle/simulation.js +98 -247
  39. package/dist/lifecycle/simulation.js.map +1 -1
  40. package/dist/lifecycle/snapshot.d.ts.map +1 -1
  41. package/dist/lifecycle/snapshot.js +1 -2
  42. package/dist/lifecycle/snapshot.js.map +1 -1
  43. package/dist/lifecycle/transactions.d.ts +19 -3
  44. package/dist/lifecycle/transactions.d.ts.map +1 -1
  45. package/dist/lifecycle/transactions.js +25 -20
  46. package/dist/lifecycle/transactions.js.map +1 -1
  47. package/dist/lifecycle/types.d.ts +53 -45
  48. package/dist/lifecycle/types.d.ts.map +1 -1
  49. package/dist/lifecycle/types.js.map +1 -1
  50. package/dist/lifecycle/ufg.d.ts.map +1 -1
  51. package/dist/lifecycle/ufg.js +3 -7
  52. package/dist/lifecycle/ufg.js.map +1 -1
  53. package/docs/launch-lifecycle.md +71 -82
  54. package/docs/lifecycle-gas-profiles.md +90 -0
  55. package/docs/reference.md +53 -51
  56. package/examples/README.md +13 -10
  57. package/examples/launch-example.ts +35 -25
  58. package/examples/launch-lifecycle-smoke.ts +5 -3
  59. package/package.json +1 -1
  60. package/src/lifecycle/authors.ts +2 -2
  61. package/src/lifecycle/gas-profile.ts +175 -0
  62. package/src/lifecycle/index.ts +3 -1
  63. package/src/lifecycle/lens.ts +1 -1
  64. package/src/lifecycle/opening-buys.ts +157 -0
  65. package/src/lifecycle/planner.ts +164 -151
  66. package/src/lifecycle/presets.ts +12 -1
  67. package/src/lifecycle/progress.ts +19 -20
  68. package/src/lifecycle/rpc.ts +56 -44
  69. package/src/lifecycle/simulation.ts +85 -231
  70. package/src/lifecycle/snapshot.ts +1 -2
  71. package/src/lifecycle/transactions.ts +33 -21
  72. package/src/lifecycle/types.ts +52 -42
  73. package/src/lifecycle/ufg.ts +3 -7
@@ -1,6 +1,6 @@
1
1
  # Launch a token with the TypeScript SDK
2
2
 
3
- Use SDK **0.14.0** on Robinhood Chain mainnet (**4663**). For a first launch, run
3
+ Use SDK **0.14.1** on Robinhood Chain mainnet (**4663**). For a first launch, run
4
4
  [`launch-erc20-abyss.ts`](../examples/launch-erc20-abyss.ts): one market, one position,
5
5
  one buy. [Runner setup](../examples/README.md) covers its environment and commands.
6
6
  This guide explains the economics and the public APIs for your own integration.
@@ -188,15 +188,15 @@ examples; it does not predict the impact of a $100 or $1,000 buy.
188
188
  A larger buy traverses ranges and can acquire a large share of supply.
189
189
 
190
190
  `prepareAndPlanLifecycleLaunch({ buySlippageBps: 50 })` derives every ordered buy's
191
- minimum from stateful diagnostic output, then proves the final protected commitment:
191
+ minimum from the covered exact local curve model or native diagnostic output:
192
192
 
193
193
  ```text
194
- minTokenOut = floor(simulatedTokenOut × (10000 - buySlippageBps) / 10000)
195
- 50 bps: floor(simulatedTokenOut × 9950 / 10000)
194
+ minTokenOut = floor(tokenOut × (10000 - buySlippageBps) / 10000)
195
+ 50 bps: floor(tokenOut × 9950 / 10000)
196
196
  ```
197
197
 
198
- This requires activation inside the simulated prefix. The option accepts 0–9,999
199
- bps and applies only before begin; omitting it preserves your committed minima.
198
+ Native calibration requires activation in the complete executed sequence. The
199
+ option accepts 0–9,999 bps and applies only before begin; omission preserves minima.
200
200
  A 1-wei minimum is effectively unprotected. Never submit the diagnostic draft.
201
201
  A Kyber conversion minimum protects ETH→quote output, not quote→launch-token output.
202
202
 
@@ -204,7 +204,7 @@ A Kyber conversion minimum protects ETH→quote output, not quote→launch-token
204
204
  Its `slippageBps` accepts 1–9,999 (default 50). It may stop a buy early; check partial
205
205
  fills and refunds. It does not calculate minimum token output.
206
206
  `estimateLaunchInitialBuy` is a pure single-position estimate, not a model of
207
- multi-band traversal, prior buys, or hook execution. Use exact simulation for signing.
207
+ multi-band traversal, prior buys, or hook execution. Use the ordered model or native calibration.
208
208
  Final valuation uses the retained supply after burn and the observed post-buy price.
209
209
 
210
210
  ## Build the plan
@@ -319,97 +319,94 @@ saved deadline or replace committed conversion bytes after begin.
319
319
 
320
320
  Staging is not rollback. A begun plan remains begun after its deadline until cancelled.
321
321
  Activation cannot be split into separate position mints or buys.
322
- The SDK never switches your requested mode or removes markets to make it fit.
322
+ An atomic request is a preference: conservative capacity bounds or an actual atomic capacity failure may select staged. Explicit staged stays staged. No markets or buys are removed. Review and persist returned `planned.mode`.
323
323
 
324
324
  | Operation | Options type / purpose |
325
325
  | --- | --- |
326
- | `prepareAndPlanLifecycleLaunch` | `PrepareAndPlanLifecycleLaunchOptions`: `client`, `account`, `plan`, `mode`; optional `ufg: { config }`, `buySlippageBps`, `fixedFinalEnvelope`, `limits`, `fork`, `receipts`, `confirmations`, `signal`, `onProgress`, topology opt-outs. |
326
+ | `prepareAndPlanLifecycleLaunch` | `PrepareAndPlanLifecycleLaunchOptions`: `client`, `account`, `plan`, `mode`; optional `ufg: { config }`, `buySlippageBps`, `limits`, `fork`, `receipts`, `confirmations`, `signal`, `onProgress`, topology opt-outs. |
327
327
  | `planLaunch` | `PlanLaunchOptions`: same execution context, including optional `ufg: { config }` and `signal`; re-admits an already-finalized plan without changing salts/minima. |
328
328
  | `simulateLaunchPlan` | `client`, `planned`; optional `limits`, `fork`, `receipts`, `confirmations`, `signal`. |
329
329
  | `readLaunchProgress` | `client`, `planned`; optional `receipts`, `confirmations`, `signal`. |
330
- | `buildNextTransaction` | Progress options, plus optional `action`, `limits`, `fork`, `submissionClient`, `reviewedTransaction`. |
330
+ | `buildNextTransaction` | Progress options, plus optional `action`, `limits`, `fork`, `reviewedTransaction`. |
331
331
 
332
332
  `buildLaunchTransactions` compiles unsigned commands; it does not prove execution.
333
- Persist `serializeLaunchPlan(planned.plan)`, mode, confirmation policy, receipt
334
- references, and UFG config if applicable. `parseLaunchPlan` restores bigint values.
333
+ Persist `serializeLaunchPlan(planned.plan)`, returned `planned.mode`, confirmation policy,
334
+ receipt references, and UFG config if applicable. `parseLaunchPlan` restores bigint values.
335
335
  Do not serialize the entire `PlannedLaunch`, which can contain live limit callbacks.
336
336
 
337
- Robinhood proof requires native Nitro `eth_simulateV1`. A generic Anvil/Hardhat fork
338
- can exercise EVM behavior but cannot certify Nitro compute/poster accounting.
339
- The default aggregate proof window is **50M used gas**, not a per-transaction ceiling.
340
- Inspect `simulation.deferredTransactionIds` even when `simulation.admitted` is true:
341
- admission can cover only a prefix. Deferred steps have no gas, price, or admission.
342
- Buy-output calibration refuses a deferred activation. Start with one market; raise
343
- `limits.maxSimulationGas` only with a provider that supports the larger window.
344
-
345
- The full simulated prefix still checks whether later staged commands can execute.
346
- Only its immediate command receives a final gas/price/estimate/admission. Later
347
- `simulation.steps` have `provisional: true`: their conservative, affordable
348
- `gasLimit` is a feasibility budget, not a transaction estimate. Their unsigned
349
- commands have no gas/price/estimate/admission until `buildNextTransaction` obtains
350
- a fresh poster quote, sizes that command and validates its exact returned envelope.
351
- Calibration and separable prior compute observations size proposals, never admission.
352
- Without one, unvalidated sizing uses affordable per-call ceilings. Only an upfront
353
- funds refusal permits one second unvalidated attempt sharing the remaining budget.
354
- No semantic, HTTP or cancellation failure retries, and the final exact validated
355
- pass never retries or changes its returned gas.
337
+ Every launch step uses the native total transaction ceiling:32M on4663, including
338
+ poster gas. Approvals omit gas/fees for wallet preparation. Covered Robinhood
339
+ ArbOS61 templates use capacity bounds and exact local ordered-buy math, never
340
+ component-sized gas limits. Their evidence is `profiled` / `not-run`, not a receipt.
341
+ Conversion-carrying begin/atomic and consuming activation require exact native
342
+ execution. Unknown coverage or uncertain activation gets full-sequence execution
343
+ before begin. Explicit `simulateLaunchPlan` always executes; a generic fork is not Nitro proof.
344
+
345
+ Review checks the complete sequence, not just a successful prefix. There is no
346
+ SDK-invented 50M aggregate cap. A caller `maxSimulationGas` still tightens policy;
347
+ incomplete execution proof refuses admission. A refused full review cannot begin
348
+ a new launch. Only the immediate command receives final gas/price/estimate/admission.
349
+ Suffix metrics remain provisional; build-next admits only the canonical next command
350
+ at its fresh native-ceiling budget, never reusing a provisional estimate.
351
+
352
+ See [capacity, native/fork evidence and migration](lifecycle-gas-profiles.md)
353
+ for exact proof fields, upfront affordability and the public capacity-bound helper.
356
354
 
357
355
  Review the returned final plan/hash, aligned price, burn, retained supply, fees,
358
356
  ordered buy outputs/minima, funding, refunds, and complete gas envelope. A fresh
359
- `buildNextTransaction` proves the immediate next step as canonical progress advances.
360
- `submissionClient` adds read-only exact-envelope preflight on the sending RPC.
357
+ `buildNextTransaction` admits the immediate next step as canonical progress advances.
358
+ The wallet owns sending-RPC preparation; `submissionClient` has been removed.
361
359
 
362
- `planned.transactions[0]` already contains the immediate exact `from/to/data/value`,
363
- `nonce`, `gas` and `gasPrice` when that step has admitted execution proof. There is
364
- no need for another unreviewed build just to discover its envelope. The envelope
365
- is reviewable and reusable; its block-bound admission is historical, not permission
360
+ `planned.transactions[0]` contains exact immediate `from/to/data/value` and, for
361
+ launch commands, native-ceiling `gas` and current `gasPrice`. Approvals omit both.
362
+ There is no fixed wallet nonce; the wallet assigns it. The plan identity nonce is unchanged.
363
+ The envelope is reusable, but its block-bound admission is historical, not permission
366
364
  to sign later. Pass it as `reviewedTransaction` for fresh immediate admission after
367
- review or recovery. This is execution revalidation, not a second user review gate.
365
+ review or recovery. This is not a second user review gate.
368
366
  Reuse `planned.progress` for the same result's display instead of reading progress
369
367
  independently beside the plan.
370
368
 
371
- For an atomic caller with a chosen final gas envelope, prepare with
372
- `fixedFinalEnvelope: { gas: 31_000_000n }`. This is an explicit chosen gas amount,
373
- not a universal gas recommendation. `limits.accountGasLimit` remains only a ceiling.
374
- The option accepts exactly one immediate atomic command with no approval prefix;
375
- staged mode and approval-first shapes refuse it. Diagnostic and final protection
376
- share one frozen fee recommendation. Supplying `gasPrice` holds that fee exactly;
377
- it is never bumped to obtain admission. The final protected calldata still receives
378
- one natural-child-fee validated replay at the exact chosen envelope. Failure never
379
- enlarges it or switches mode.
369
+ `fixedFinalEnvelope` and `LifecycleFinalEnvelope` are removed. A reviewed launch gas
370
+ that differs from the native ceiling refuses with `STALE_REVIEWED_GAS`; re-review,
371
+ never silently rewrite it. A lower caller complete-envelope cap refuses rather than
372
+ shrinking gas. Held prices below the pinned fee floor also refuse without bumping.
373
+ On Nitro the floor is max(ArbGasInfo L2 price, header base fee); twice base fee is
374
+ fresh recommendation headroom only. Reserve value plus ceiling×price, without
375
+ adding poster fees again. Actual activation capacity refusal asks the user to
376
+ reduce positions/pools; a large conservative bound alone is not such a refusal.
380
377
 
381
378
  On chain4663, one RPC L2 header pins the invocation. Token prediction, native/token
382
- balances, allowances, launch progress and Nitro getters share one Multicall3 call
379
+ balances, allowances, launch progress, Nitro getters and prices share one Multicall3 call
383
380
  at that explicit L2 block. Further independent stages use one aggregate, even for
384
381
  one or two reads. Multicall3's block-number/hash getters expose L1 values on Nitro
385
382
  and must not select the L2 pin.
386
383
  The same pin survives salt mining and buy calibration; there are no final chain or
387
384
  canonical-header guard reads. Receipt confirmation/reorg checks remain.
388
385
 
389
- Final measurement validates the exact calldata once; there is no later exact-gas
390
- replay. Poster allocation is estimated only for the immediate final command.
391
- `buildNextTransaction` preserves the original staged batch spans and proves only
392
- the next command, rather than simulating the whole remaining launch.
386
+ Required native execution validates the exact calldata once; there is no later
387
+ exact-gas replay. Poster allocation comes from the same-review price tuple and a
388
+ local size bound, not a per-transaction oracle. Build-next encodes only its canonical
389
+ next command, preserving normal/UFG calldata and original/clipped batch spans.
393
390
 
394
391
  Multicall3 runtime, Nitro backend capability and account-code observations are
395
- retained for the caller's session. Financial state and execution proof are not.
392
+ retained for the caller's session. Chain identity is observed once per bound client;
393
+ recreate the client on chain changes. Financial state and required proof stay fresh.
396
394
  The 4663 preset uses the deployed `hookSaltMiner`; returned salts are verified
397
- locally. The optional `launchLens` preset is unset in this release. Once deployed,
398
- its address enables dependent progress, market, balance and hook-mining reads in
399
- the same initial aggregate. See [read caching](reference.md#cache-static-reads-and-inspect-timing).
395
+ locally. Its deployed `launchLens` supplies dependent progress, market, balance
396
+ and hook-mining reads in the same initial aggregate. Callers need no lens
397
+ configuration. See [read caching](reference.md#cache-static-reads-and-inspect-timing).
400
398
 
401
399
  ## Sign and confirm
402
400
 
403
401
  Call `buildNextTransaction` before **every signature**, including approvals and
404
- cancellation. For a reviewed command, pass `reviewedTransaction` so the SDK replays
405
- the same gas/fee/nonce rather than rediscovering it. Send the exact returned
406
- `from/to/data/value/nonce/gas/gasPrice` with a matching explicit viem chain.
402
+ cancellation. Pass `reviewedTransaction` to hold the same gas/fee and intent, not a
403
+ wallet nonce. Send the exact returned `from/to/data/value/gas/gasPrice`.
407
404
  `confirmations` defaults to 1; choose and retain your policy before begin.
408
- SDK affordability is observed at block B, not at the provider's pending state.
409
- Immediately before signing, the host must freshly compare pending nonce and
410
- balance with this exact envelope and verify the active provider account/chain
411
- after asynchronous work. Changed identity, nonce, intent or insufficient pending
412
- funds blocks the signature; never overwrite the reviewed nonce or replay a write.
405
+ The wallet owns its queue, nonce assignment and sending-RPC preparation. Unrelated
406
+ pending transactions are not an SDK confirmation-safety refusal. Retain the actual
407
+ submitted nonce and let the wallet advance locally; unknown reload recovery may
408
+ need one host-owned queue read, never a per-plan nonce gate. Check the active wallet
409
+ account/provider chain after asynchronous work, and never automatically replay a write.
413
410
  The following local-account loop signs only when explicitly called by your application.
414
411
  Use a new owner-only journal path inside a private directory; on reload, restore the
415
412
  original plan and receipt references before calling it. Journal records contain secrets.
@@ -437,7 +434,7 @@ export async function executeLaunch(
437
434
  confirmations: planned.confirmations, ufg: planned.ufg, receipts });
438
435
  for (;;) {
439
436
  const next = await buildNextTransaction({
440
- client, planned, receipts, submissionClient: client,
437
+ client, planned, receipts,
441
438
  });
442
439
  if (!next) {
443
440
  const progress = await readLaunchProgress({ client, planned, receipts });
@@ -448,29 +445,21 @@ export async function executeLaunch(
448
445
  }
449
446
  return { progress, activationHash };
450
447
  }
451
- if (!next.admission?.admitted || next.gas === undefined || next.gasPrice === undefined) {
448
+ const approval = next.kind === "approve" || next.kind === "approve-reset";
449
+ if (!next.admission?.admitted || !approval && (next.gas === undefined || next.gasPrice === undefined)) {
452
450
  throw new Error("Immediate transaction is not admitted");
453
451
  }
454
- const [nonce, pendingBalance] = await Promise.all([
455
- client.getTransactionCount({ address: next.from, blockTag: "pending" }),
456
- client.getBalance({ address: next.from, blockTag: "pending" }),
457
- ]);
458
- const dataFee = next.estimate?.dataFee;
459
- if (next.nonce === undefined || BigInt(nonce) !== next.nonce || dataFee === undefined
460
- || pendingBalance < next.value + next.gas * next.gasPrice + dataFee) {
461
- throw new Error("Pending nonce or complete affordability changed; revalidate");
462
- }
452
+ const request = await wallet.prepareTransactionRequest({
453
+ chain: wallet.chain, account: wallet.account,
454
+ to: next.to, data: next.data, value: next.value, gas: next.gas, gasPrice: next.gasPrice,
455
+ });
463
456
  const [address] = await wallet.getAddresses();
464
457
  if (wallet.chain.id !== next.chainId || await wallet.getChainId() !== next.chainId
465
- || await client.getChainId() !== next.chainId
466
458
  || address?.toLowerCase() !== next.from.toLowerCase()
467
459
  || wallet.account.address.toLowerCase() !== planned.account.toLowerCase()) {
468
460
  throw new Error("Wallet account or chain changed");
469
461
  }
470
- const raw = await wallet.signTransaction({
471
- chain: wallet.chain, account: wallet.account, nonce,
472
- to: next.to, data: next.data, value: next.value, gas: next.gas, gasPrice: next.gasPrice,
473
- });
462
+ const raw = await wallet.signTransaction(request);
474
463
  const hash = keccak256(raw);
475
464
  await record({ transactionId: next.id, kind: next.kind, hash, raw });
476
465
  const sent = await client.sendRawTransaction({ serializedTransaction: raw });
@@ -483,7 +472,7 @@ export async function executeLaunch(
483
472
  throw new Error("Reverted or replaced transaction; reconcile before continuing");
484
473
  }
485
474
  receipts.push({ transactionHash: hash, confirmations: planned.confirmations,
486
- observedBlockNumber: receipt.blockNumber, observedBlockHash: receipt.blockHash });
475
+ nonce: BigInt(request.nonce), observedBlockNumber: receipt.blockNumber, observedBlockHash: receipt.blockHash });
487
476
  if (next.kind === "atomic" || next.kind === "activate") activationHash = hash;
488
477
  await record({ receipts, activationHash });
489
478
  }
@@ -494,7 +483,7 @@ A send timeout is ambiguous: the hash may already be mined. Stop, query the save
494
483
  hash, and reconcile pending nonce/receipt state; do not automatically resend.
495
484
  For an interactive review delay, pass the previously displayed command as
496
485
  `reviewedTransaction` to a fresh `buildNextTransaction` before signing.
497
- That directly replays the same immediate envelope at its held nonce, gas and gas price.
486
+ That revalidates the same immediate intent at its held gas/fee; the wallet owns its nonce.
498
487
 
499
488
  Completion has **four checks**: receipt confirmed → markets active → metadata
500
489
  published → API indexed. A successful transaction alone does not establish the last two.
@@ -0,0 +1,90 @@
1
+ # Lifecycle gas, capacity, execution evidence and RPC budgets
2
+
3
+ Version 0.15.0 separates the native transaction ceiling, conservative capacity bounds, exact curve quotes and actual execution proof. A local quote or submitted hash is not an execution receipt.
4
+
5
+ ## One native ceiling, not component-sized gas
6
+
7
+ Every launch command (begin, prepare, activate, atomic and cancel) uses the chain's native total transaction ceiling. On Robinhood4663 this is `ROBINHOOD_NATIVE_TRANSACTION_GAS_LIMIT = 32_000_000n`, also exposed as `getKnownLifecycleDeployment({ chainId, orchestrator }).nativeTransactionGasLimit`. The32M includes poster gas. Other chains retain their resolved generic ceiling.
8
+
9
+ Unused gas is refunded. The payer must still reserve `value + gasLimit * gasPrice` upfront. The SDK never shrinks the ceiling to accommodate a tight balance, adds poster gas to32M, or retries with a smaller envelope. Approvals/reset approvals are not launch steps: their returned `gas`, `gasPrice` and estimates are omitted for wallet preparation.
10
+
11
+ A reviewed launch gas differing from the ceiling is stale and refuses with `STALE_REVIEWED_GAS`; re-review rather than silently rewriting it. A caller complete-envelope cap below the ceiling refuses too. `fixedFinalEnvelope`, `LifecycleFinalEnvelope`, stored compute-sizing hints and unvalidated gas-sizing retries are removed.
12
+
13
+ ## Capacity selects the mode, not the gas limit
14
+
15
+ `computeLifecycleLaunchGasBounds({ plan, predictedToken, ufg?, headroomBps? })` returns conservative `atomicComputeGasUpperBound` and `activationComputeGasUpperBound`, excluding poster gas, or undefined for unknown coverage. The versioned model accounts for token/reward creation, actual UFG proxy/treasury route, market/position work, ordered buys, NFT minting and HMM forwarding overhead. UFG route overhead is independent of market profile names.
16
+
17
+ An atomic request is a preference. A conservative atomic bound plus poster allocation above the ceiling selects staged; explicit staged remains staged. An actual atomic capacity failure can also select staged with fresh full-sequence admission. Review and persist returned `planned.mode`, not the requested mode. No positions, markets or buys are dropped.
18
+
19
+ A large conservative activation upper bound is uncertainty, not proof of overflow. Uncertain activation receives exact full-sequence execution before begin. An actual activation capacity failure returns `capacityConstraint: "activation"` and asks the user to reduce positions/pools; staging cannot split activation. For example, an independently observed24-position activation fit32M despite a larger conservative upper bound, while a32-position deep Abyss activation needed a47.48M minimum successful envelope. Neither observation licenses a universal count-only hard cap.
20
+
21
+ ## Which admission path runs
22
+
23
+ | Command | Covered direct plan with proven-fit activation | Plan containing an aggregator conversion |
24
+ | --- | --- | --- |
25
+ | Approval/reset | Wallet prepares gas/fees | Wallet prepares gas/fees |
26
+ | Begin | Conditional template admission | Exact native execution of the conversion |
27
+ | Prepare markets/hooks | Conditional template admission | Conditional admission when isolated after begin |
28
+ | Activate and opening buys | Conditional admission and exact local curve math | Exact native execution consuming conversion funding |
29
+ | Atomic launch | Conditional admission and exact local curve math | Exact native execution of the complete transaction |
30
+ | Cancel | Conditional admission | Conditional admission when isolated |
31
+
32
+ A conversion review proves the complete staged sequence through activation in one validated `eth_simulateV1` call, with every launch call at32M. Unknown template/currency coverage, another chain/ArbOS epoch or uncertain activation also uses real execution. A refused full review cannot authorize a new begin from a successful prefix; already-started recovery and cancellation remain available. Explicit `simulateLaunchPlan` always requests execution. A generic EVM fork is not Nitro protocol proof.
33
+
34
+ Unknown curve behavior retains a separate provisional, unvalidated buy-output diagnostic at the same ceiling before protecting minima. It is not gas sizing, final admission or a retry. The final protected commitment still requires its exact execution. There is no SDK-invented50M aggregate window; explicit `maxSimulationGas` policies remain enforced against complete observed work without prefix admission.
35
+
36
+ ### Honest result fields
37
+
38
+ - Conditional admission: `backend/confidence: "profiled"`, `executionProof: "not-run"`, `protocolFit: "profiled"`. `gasProfile` carries `version`, capacity `bounds` and local `initialBuys`, not per-step estimates or fabricated receipts.
39
+ - The immediate fixed-ceiling budget is `simulation.estimate`, with `feeConfidence: "native-ceiling-and-data"` and no invented `gasUsed`. Approval budgets are absent.
40
+ - Successful exact native execution reports `backend: "eth_simulateV1"`, `executionProof: "proved"`, `protocolFit: "proved"` after required postconditions.
41
+ - Only an immediate launch command receives final gas/price/estimate/admission. Exact suffix steps remain `provisional: true` with no executable estimate. Build-next constructs only the canonical next command at a fresh pin; it never treats a suffix observation as an estimate.
42
+
43
+ ## Retained empirical evidence
44
+
45
+ `robinhood-4663-arbos61-v1` covers shipped Abyss configuration-v1 and current pool-bound V4 configuration-v6 templates, including HMM/UFG, on ArbOS61 with an EOA payer and known release quote implementations. This is capacity coverage, not a currency admission allowlist. Unknown currencies remain supported through exact execution; smart-account proof is not claimed.
46
+
47
+ Research retained176 lifecycle receipts, including75 successful current-template atomic/activation observations with opening buys. Isolated forks extend depth, buys and combinations; failed CREATE2 cases were not counted as successful coverage. One Abyss and one fixed-V4 historical native/fork calibration matched compute exactly (19,272,603 and18,130,251 gas), while minimum successful envelopes were higher (20,527,230 and19,356,279). These two calibrations do not establish general Anvil/Nitro equivalence. Compute and poster components remain separate. Profiles are empirical capacity bounds, never transaction gas sizing or proof about arbitrary upgrades/future ArbOS rules.
48
+
49
+ ## Exact ordered opening-buy math
50
+
51
+ `computeLifecycleOpeningBuys({ plan, predictedToken })` follows all liquidity bands, prior buys, initialized zero-net ticks, bitmap boundaries, both currency directions, LP/opening-hook fees, partial fills and integer output floors. HMM opening work occurs after initial buys. V4's zero price-limit sentinel resolves locally to the contract-defined directional limit without changing calldata; Abyss still rejects zero.
52
+
53
+ Covered `buySlippageBps` protection uses `floor(tokenOut * (10000 - bps) / 10000)`. A zero floor rejects, never becomes1. Independent parity matched token output, quote spent and final square-root price across97 native/fork cases, including both directions, overlapping bands and gaps. Portable historical vectors and focused rounding/sentinel cases live under `test/fixtures/lifecycle-opening-buys.json` and `test/lifecycle-opening-buys.test.mjs`. These conditional curve quotes do not prove conversion, funding or wallet submission.
54
+
55
+ ## One same-review Nitro price observation
56
+
57
+ The initial L2-pinned aggregate includes `ArbGasInfo.getPricesInWei`. There are no per-transaction `NodeInterface.gasEstimateL1Component` calls or separate4663 `eth_gasPrice` calls. Tuple element1 supplies L1 per-byte price; element5 supplies L2 price. Fresh gas price is max(L2 price, twice header base fee). A held price must meet max(L2 price, header base fee), but is not bumped to the fresh recommendation.
58
+
59
+ For empty-access-list EOA legacy calldata of `D` bytes:
60
+
61
+ ```text
62
+ N = D + 384
63
+ B = N + 8 * floor(N / 1024) + 64
64
+ posterFeeBound = B * l1PricePerByte
65
+ posterGas = 2 * ceil(posterFeeBound / l2GasPrice)
66
+ ```
67
+
68
+ The local serialization/Brotli bound and2x allocation are conservative, not an observation of the eventual compressed signature or a promise about future L1 prices. Poster stays inside32M. `dataFeeIncludedInGas` is true, `dataFee` is zero and `totalFee = gasLimit * gasPrice`; never add poster fee again.
69
+
70
+ ## 0.15.0 caller migration
71
+
72
+ - Wallet nonce is absent from unsigned `LifecycleTransaction`; `LaunchPlanV1.nonce` remains its domain identity. Let the wallet assign send nonce. Learn actual nonce from wallet/transaction, retain optional exact `LifecycleReceiptReference.nonce`, and advance the wallet-owned queue locally. A supplied nonce mismatch refuses receipt attribution. Portable journals use decimal strings, not JSON numbers.
73
+ - Progress has no confirmed/head/pending account nonce gates. Unrelated pending transactions are queued by the wallet, not an SDK confirmation-safety refusal. Planning/build-next make no `eth_getTransactionCount`; unknown reload recovery may need one host-owned read.
74
+ - `BuildNextTransactionOptions.submissionClient` and proof `transportPreflight` are removed. Keep wallet account/provider-chain checks and never automatically replay an ambiguous write.
75
+ - Retain each bound client; chain identity is read at most once per client object. Recreate the client after wallet/chain changes. Cache invalidation does not repoint an existing client to another chain.
76
+ - Persist selected `planned.mode`. Handle approval envelopes without gas/fees, `STALE_REVIEWED_GAS`, actionable activation capacity refusal, optional `simulation.estimate` and capacity-only `gasProfile.bounds`. Remove `gasProfile.estimates` and `computeGasRequired` usage.
77
+ - Economic review schema v2 separates `local-exact-curve` from `simulated-execution`; consume `initialBuy.reviewedBuys`, not assumed receipt fields. `transactionGasEstimate` is removed; unsigned compilation and preparation packing remain available.
78
+
79
+ ## Observed recording-transport budgets
80
+
81
+ The same historical, already-protected plans and explicit 200M aggregate policy use deterministic recording-transport block/state/execution responses, without requesting buy recalibration. This is RPC counting, not live admission. Both commitments remain unchanged. Counts exclude wallet preparation/send, polling and supplied receipt/transaction/canonicality reads, which vary with confirmation policy.
82
+
83
+ | Case | Version | Prepare/review | Each build-next | Prepare + first build | Prepare + all builds |
84
+ | --- | --- | ---: | ---: | ---: | ---: |
85
+ | Conversion historical plan (`0xf05…fe98fe98`, four builds) | 0.14.1 | 12 | 8 | 20 | 44 |
86
+ | Same conversion plan | 0.15.0 | 7 | 3 | 10 | 19 |
87
+ | Direct NativeWrap historical plan (`0x4cbc…85231`, three builds) | 0.14.1 | 12 | 8 | 20 | 36 |
88
+ | Same direct plan | 0.15.0 | 5 | 2 | 7 | 11 |
89
+
90
+ The conversion case retains six native simulation RPCs across review/builds because its historical currencies are outside capacity coverage: one session capability, one full review and four next-step proofs. The covered direct case drops six simulation RPCs to zero. Both cases have one total chain read and zero account-nonce, separate gas-price or per-transaction poster-oracle reads. Cold costs include session attestations/capability; warm counts are not cold totals. These are SDK-only figures, not whole-application telemetry.
package/docs/reference.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use the [launch guide](launch-lifecycle.md) for the end-to-end flow and the
4
4
  [runner reference](../examples/README.md) for environment and recovery artifacts.
5
- This page covers SDK **0.14.0** addresses, limits, wire formats, fees, and diagnostics.
5
+ This page covers SDK **0.14.1** addresses, limits, wire formats, fees, and diagnostics.
6
6
 
7
7
  ## Deployed infrastructure
8
8
 
@@ -19,6 +19,7 @@ start historical log queries there, in chunks of at most **10M blocks**.
19
19
  | `UFG_LAUNCH_PROXY_ADDRESS` | `0xf6673d859DE03eB74A0b01696Edb97f941dFD0CA` |
20
20
  | `UFG_TREASURY_FACTORY_ADDRESS` | `0x26Aa5D52134c8E6c4C01E9fb53A7568c0C64901F` |
21
21
  | `UFG_UPSTREAM_FACTORY_ADDRESS` | `0xA170b5A58C111334A7237F2Ea2c428ec5022f68E` |
22
+ | Known deployment `launchLens` | `0xcb4bb3caca71fe52eace8170cf83e901418646f8` |
22
23
 
23
24
  `getKnownLifecycleDeployment`, `getKnownLifecycleProfile`, and
24
25
  `listKnownLifecycleProfiles` are pure selectors keyed by chain/core. Unknown
@@ -55,7 +56,7 @@ These are structural maxima, not a guarantee that activation fits gas.
55
56
  | Initial executor bounty | 0–1,000 bps; UFG requires 0 |
56
57
  | Gas-envelope caps | Positive uint64 bigint |
57
58
  | Gas headroom | `headroomBps`: 0–10,000; default 1,500 |
58
- | Robinhood simulation-used gas | `maxSimulationGas`: default 50,000,000 aggregate |
59
+ | Robinhood simulation-used gas | `maxSimulationGas`: optional aggregate policy ceiling; no SDK-invented default |
59
60
 
60
61
  Use `LIFECYCLE_MAX_ERC404_SUPPLY` and `LIFECYCLE_MAX_REWARD_ERC20_SUPPLY` for the
61
62
  exported supply bounds. Market token budgets equal total minted supply; position
@@ -157,49 +158,44 @@ splits are separate values. The example's 3000/60 is not the venue's sole fee ti
157
158
 
158
159
  ## Account for Nitro compute and poster gas
159
160
 
160
- On chain 4663, the SDK reads ArbSys (`0x64`) `arbOSVersion` and ArbGasInfo (`0x6c`)
161
- `getMaxTxGasLimit` / `getMaxBlockGasLimit` at the pinned block. ArbSys returns
162
- 55 + logical version; raw must be at least 105. `limits.arbOSVersion` reports the
163
- logical version. The minimum validated compute getter is `executionGasCeiling`.
164
- Failed getters cannot fall back to the large header gas limit or a hard-coded 32M.
165
-
166
- `transactionGasCeiling`, when set, is the minimum complete-envelope chain/RPC/account
167
- restriction. It is separate from compute. NodeInterface (`0xc8`)
168
- `gasEstimateL1Component` estimates poster allocation once for the next final
169
- transaction, using its exact sender/target/calldata/value at the same block.
170
- Compute-only calibration and fresh poster allocation size the immediate envelope
171
- before native validation. `step.computeGasRequired` retains a separable compute
172
- observation, never the old poster charge or provisional budget. A fresh poster
173
- quote is combined once when that command becomes next. Both unvalidated sizing
174
- and the final exact pass use affordable pinned envelopes; validation:false does
175
- not disable Nitro's upfront funds check. The final pass uses exactly returned gas.
176
- Sizing starts with per-call ceilings because unused gas is refunded between calls.
177
- Only a genuine upfront-funds refusal permits one second unvalidated sizing attempt
178
- with the budget shared across the sequence. Other failures do not retry; the final
179
- exact validated pass is never replayed.
180
-
181
- A tight payer balance can cover smaller exact staged envelopes yet not the
182
- discovery margin. This may return `failureCategory: "affordability"` even though
183
- the underlying launch could fit. The refused RPC exposes no successful-prefix
184
- results; the SDK does not invent them or add more metering attempts.
185
-
186
- Suffix steps are marked `provisional: true` and have no transaction estimate:
187
- their conservative complete budgets check sequence feasibility, bounded across
188
- the pinned affordable remaining balance. `buildNextTransaction` never reuses
189
- those budgets as estimates; it freshly quotes and proves only the next command.
161
+ On chain4663, `ROBINHOOD_NATIVE_TRANSACTION_GAS_LIMIT` and the deployment preset's
162
+ `nativeTransactionGasLimit` specify32M **total** gas for begin, prepare, activate,
163
+ atomic and cancel. This includes poster gas. Guard-only maximum-gas getters are
164
+ not read. Pinned ArbSys version selects capacity coverage/native capability, not
165
+ a gas size. Other chains retain their resolved generic transaction ceiling.
166
+
167
+ `transactionGasCeiling`, when set, is a caller complete-envelope restriction.
168
+ Below the native ceiling it refuses; it never shrinks a launch step. Approvals
169
+ omit gas/fees and leave preparation to the wallet. One `ArbGasInfo.getPricesInWei`
170
+ leg in the initial aggregate supplies L1 per-byte and L2 prices, with no per-tx
171
+ NodeInterface oracle. See [capacity and poster evidence](lifecycle-gas-profiles.md).
172
+
173
+ `computeLifecycleLaunchGasBounds({ plan, predictedToken, ufg? })` returns conservative
174
+ atomic/activation compute upper bounds, excluding poster, or undefined for unknown
175
+ coverage. These select modes, not gas limits. Atomic is a preference that may select
176
+ staged; persist returned `planned.mode`. A large upper bound is uncertain, not
177
+ proof of overflow. Unknown activation gets full-sequence execution before begin.
178
+ Conversion-carrying commands/consuming activation always retain exact execution.
179
+
180
+ Only an immediate launch command receives a final gas/price/estimate/admission.
181
+ Suffix execution metrics stay provisional; build-next constructs only the canonical
182
+ next command at the same native ceiling with fresh fees and required admission.
183
+ There are no sizing passes or funds-only retries. Balance must cover value plus
184
+ the entire ceiling fee even when actual execution uses less gas. Incomplete proof
185
+ cannot authorize begin; explicit aggregate policies still refuse excessive work.
190
186
 
191
187
  On Nitro, `estimate.posterGas` / `posterFee` are buffered allocations **inside**
192
188
  `gasLimit`; `dataFeeIncludedInGas` is true, `dataFee` is zero, and `totalFee` equals
193
189
  `gasLimit × gasPrice`. Do not add poster fees a second time. Custom `estimateDataFee`
194
190
  is rejected on Nitro; generic EVM clients can use it for an external fee.
195
- `feeConfidence` distinguishes `execution-and-data` from `execution-only` estimates.
196
- Initial legacy gas price is the greater of fresh RPC recommendation and twice pinned
197
- base fee. Reviewed immediate envelopes retain their exact held gas/price.
191
+ `feeConfidence` distinguishes actual execution evidence from the conditional
192
+ `native-ceiling-and-data` budget. Fresh gas price is max(pinned price, twice base fee).
193
+ Held Nitro price must meet max(ArbGasInfo L2 price, header base fee), without an
194
+ automatic bump. Reviewed gas differing from the ceiling is stale and refuses.
198
195
 
199
- HMM atomic/activation sizing adds one forwarding target of
200
- `4,250,000 + 500,000 × (HMM markets - 1)` gas. Staged packing estimates 14.5M per HMM
201
- market and 16M per other market before measurement. These are sizing inputs, not
202
- fixed transaction fees or proof that every permitted topology fits.
196
+ Capacity-only profiles account for route, position and HMM forwarding overhead.
197
+ Staged packing retains conservative per-market grouping, but never changes the
198
+ gas assigned to a launch transaction or splits its final activation.
203
199
 
204
200
  ## Cache static reads and inspect timing
205
201
 
@@ -209,24 +205,30 @@ fixed transaction fees or proof that every permitted topology fits.
209
205
  | `sessionCache: createLifecycleSessionCache()` | Caller-owned reuse of SDK-selected static reads at one pin; successful deployment/backend observations also survive across blocks. Without it, those observations belong to the supplied client object. |
210
206
  | `onDiagnostic(event)` | Local opt-in stage/RPC timing listener; no automatic console output or telemetry. |
211
207
 
212
- Call `sessionCache.invalidate()` on wallet/chain switches and after each confirmed
213
- transaction to discard pinned static values. Session deployment/backend facts are
214
- keyed by chain and account where applicable and live until the session owner is
215
- discarded. `sessionCache.block` is readonly `{ number, hash }` or undefined.
208
+ Call `sessionCache.invalidate()` after confirmed transactions to discard pinned
209
+ static values. Deployment/backend facts are retained for the session owner and
210
+ keyed by chain/account where applicable. Chain identity is cached by bound client
211
+ object; create a new client on a chain change rather than mutating/reusing it.
212
+ `sessionCache.block` is readonly `{ number, hash }` or undefined.
216
213
  Planning pins retain the actual RPC L2 block number and header hash. EVM
217
214
  `BLOCKNUMBER`/`BLOCKHASH`, including Multicall3's metadata getters, expose L1 values
218
215
  on Nitro and are not L2 pin sources.
219
- Balances, allowances, current progress, receipts, nonces, policy callbacks, and
220
- stateful execution proof stay fresh. Session caching does not extend admission.
216
+ Balances, allowances, current progress, receipts, policy callbacks and required
217
+ execution proof stay fresh. Planning/build-next do not read account queue nonces;
218
+ the wallet assigns them and retains the observed submitted nonce for recovery.
219
+ Session caching does not extend admission.
221
220
 
222
221
  One RPC L2 header supplies number, hash, timestamp, gas limit and base fee.
223
222
  The initial Multicall3 call uses that explicit L2 block and includes native balance,
224
- funding/progress and Nitro getters. Independent getters are aggregated with no
225
- minimum-count threshold. Runtime code is attested once per
226
- session. The optional preset `launchLens` remains unset until deployment; once set,
227
- one `launchLensAbi.snapshot` call replaces dependent token/hook/market/funding reads
228
- inside that aggregate. The deployed preset `hookSaltMiner` replaces local mining
229
- during combined preparation; every returned winner is verified locally.
223
+ funding/progress, Nitro getters and `getPricesInWei`. Independent getters are aggregated with no
224
+ minimum-count threshold. Multicall3 runtime code is attested once per session.
225
+ The 4663 preset enables `launchLensAbi.snapshot` without caller configuration:
226
+ one call replaces dependent token/hook/market/funding reads inside that aggregate.
227
+ Its `launchLensCodeHash` pins the reviewed deployed runtime as frozen release
228
+ metadata, like `tokenFactoryCodeHash`, without another guard-only RPC.
229
+ The deployed preset `hookSaltMiner` replaces local mining during combined
230
+ preparation; every returned winner is verified locally.
231
+ Lens failures surface directly; planning does not retry through legacy reads.
230
232
 
231
233
  Diagnostic events carry `stage`, `phase`, optional `durationMs`, `queueMs`,
232
234
  `requestId`, allowlisted RPC `method`, and cache `hits` / `misses` / `reuses`.
@@ -1,6 +1,6 @@
1
1
  # Run the examples
2
2
 
3
- These commands use the checkout's built `@black-market/sdk` **0.14.0** and viem.
3
+ These commands use the checkout's built `@black-market/sdk` **0.14.1** and viem.
4
4
  Use **Node 24+** for direct TypeScript execution. Start with the one-market
5
5
  `launch-erc20-abyss.ts`; larger cases can exceed the RPC's simulation budget.
6
6
  For valuation, token ordering, ranges, and buy protection, read the
@@ -20,7 +20,7 @@ chmod 600 .env
20
20
  Launch wrappers load `.env` from the working directory with `process.loadEnvFile`.
21
21
  Existing environment values take precedence. Values are literal; shell interpolation
22
22
  is not applied. Use the matching SDK version when copying wrappers into a consumer project:
23
- `pnpm add @black-market/sdk@0.14.0 viem`.
23
+ `pnpm add @black-market/sdk@0.14.1 viem`.
24
24
  Copy `launch-example.ts`, `launch-example-support.ts`, and `launch-example-kyber.ts` with the wrapper.
25
25
 
26
26
  ### Configure the environment
@@ -44,7 +44,7 @@ Copy `launch-example.ts`, `launch-example-support.ts`, and `launch-example-kyber
44
44
  | `EXAMPLE_ACCOUNT_GAS_CAP` | Optional wallet/account transaction gas-envelope ceiling. |
45
45
  | `EXAMPLE_MAX_CALLDATA_BYTES` | Optional whole-transaction byte ceiling. |
46
46
  | `EXAMPLE_HEADROOM_BPS` | Gas headroom, default `1500`; accepted range 0–10,000. |
47
- | `EXAMPLE_SIMULATION_GAS_CAP` | Aggregate simulation-used gas budget; default 50M on chain 4663. |
47
+ | `EXAMPLE_SIMULATION_GAS_CAP` | Optional aggregate simulation-used gas ceiling; no SDK-invented default window. |
48
48
 
49
49
  Configure **exactly one** of `PRIVATE_KEY` and `EXAMPLE_KEYSTORE_PATH`.
50
50
  A keystore must be a regular file owned by your user with owner-only permissions.
@@ -117,7 +117,7 @@ node examples/launch-erc20-abyss.ts --resume "launch-results/<original-run-dir>"
117
117
 
118
118
  | Mode | Reads / writes | Identity |
119
119
  | --- | --- | --- |
120
- | No flags | Live discovery, funding quotes, preparation, simulation, economic output; unsigned, no API writes | Fresh plan/run directory |
120
+ | No flags | Live discovery, funding quotes, preparation, profiled or executed economic review; unsigned, no API writes | Fresh plan/run directory |
121
121
  | `--broadcast` | Signs, spends, stages/uploads metadata, deploys, verifies, and publishes; no further prompt | **Fresh plan**, not the preceding dry run |
122
122
  | `--resume <original-run-dir>` | May sign remaining steps or finish publication | Retained plan, receipts, mode, confirmation policy, and API session |
123
123
 
@@ -125,10 +125,11 @@ Dry-run needs the signer source, RPC/API, and sufficient funds for execution adm
125
125
  Review its economics, then review the fresh broadcast output too. Mode flags cannot
126
126
  be combined or duplicated. Resume is an execution authorization; omit `--broadcast`.
127
127
 
128
- The default proof window is **50M aggregate used gas**, not a per-transaction limit.
129
- Opening-buy calibration needs activation inside the proven prefix. A deferred activation
130
- cannot produce protected buy minima. Raise `EXAMPLE_SIMULATION_GAS_CAP` only when your
131
- provider supports it; start with one market when checking an unfamiliar RPC.
128
+ Covered template steps use generous gas profiles and exact local ordered curve math.
129
+ Conversions and activation consuming conversion funding still require exact native
130
+ execution of the complete staged sequence; a successful prefix is not admission.
131
+ An explicit `EXAMPLE_SIMULATION_GAS_CAP` may tighten policy, not authorize partial proof.
132
+ See [coverage and migration](../docs/lifecycle-gas-profiles.md) for evidence and limitations.
132
133
 
133
134
  ### Fund opening buys
134
135
 
@@ -166,8 +167,10 @@ It does not automatically retry sends, adopt replacements, cancel, or create ano
166
167
  | Unstarted / Cancelled / unresolved signed hash | Stops for reconciliation; do not use a new invocation as a retry. |
167
168
 
168
169
  Resume retains salts and buy minima; it does not rerun preparation or recalibrate economics.
169
- For replacements, retain original `transactionHash` and effective `replacementHash`,
170
- plus observed block number/hash. A missing receipt alone does not establish a reorg.
170
+ For replacements, retain original `transactionHash`, effective `replacementHash`,
171
+ observed block number/hash and the actual submitted nonce as an exact bigint
172
+ (decimal string in journals). SDK planning has no account-queue nonce gate; the
173
+ wallet assigns and tracks nonces. A missing receipt alone does not establish a reorg.
171
174
 
172
175
  Metadata is staged before deployment. Publication uses the **original activation hash**.
173
176
  A `LaunchPublishPending` response means indexing is pending; the runner polls for up