stxer 0.6.1 → 0.8.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.
package/src/types.ts CHANGED
@@ -7,26 +7,42 @@
7
7
  // Sidecar Tip Types
8
8
  // =============================================================================
9
9
 
10
+ /**
11
+ * Rust `u64` / `u128` fields serialize as JSON numbers but can exceed JS
12
+ * `Number.MAX_SAFE_INTEGER` (2^53 - 1). Accept either form: numbers are
13
+ * convenient for small values, decimal strings preserve full precision
14
+ * for large ones. Mirrors how `pox_addrs[k].payout` (u128) is typed.
15
+ *
16
+ * In practice nearly all values fit in `Number` — this typing exists so
17
+ * code that *might* see a large value (post-genesis cumulative cost
18
+ * counters, accumulated stx_burned in long simulations) cannot silently
19
+ * lose precision. Use `BigInt(x)` to normalize before arithmetic when in
20
+ * doubt.
21
+ */
22
+ export type U64 = number | string;
23
+ /** Rust `u128`. See {@link U64} for usage notes. */
24
+ export type U128 = number | string;
25
+
10
26
  export interface TenureCost {
11
- read_count: number;
12
- read_length: number;
13
- write_count: number;
14
- write_length: number;
15
- runtime: number;
27
+ read_count: U64;
28
+ read_length: U64;
29
+ write_count: U64;
30
+ write_length: U64;
31
+ runtime: U64;
16
32
  }
17
33
 
18
34
  export interface SidecarTip {
19
35
  bitcoin_height: number;
20
36
  block_hash: string;
21
- block_height: number;
22
- block_time: number;
37
+ block_height: U64;
38
+ block_time: U64;
23
39
  burn_block_height: number;
24
- burn_block_time: number;
40
+ burn_block_time: U64;
25
41
  consensus_hash: string;
26
42
  index_block_hash: string;
27
43
  is_nakamoto: boolean;
28
44
  tenure_cost: TenureCost;
29
- tenure_height: number;
45
+ tenure_height: U64;
30
46
  sortition_id: string;
31
47
  epoch_id: string;
32
48
  }
@@ -110,7 +126,32 @@ export type ClarityEpoch =
110
126
  | 'Epoch34'
111
127
  | 'Epoch35';
112
128
 
113
- export type ClarityVersion = 'Clarity1' | 'Clarity2' | 'Clarity3' | 'Clarity4';
129
+ /**
130
+ * Wire-format Clarity version name as emitted by the stxer AST parser
131
+ * (`/contracts:parse-ast`). Used in {@link ClarityAbi.clarity_version}.
132
+ *
133
+ * **Distinct from the numeric `ClarityVersion` enum re-exported by
134
+ * `@stacks/transactions`** (1..5), which is what the SDK builder
135
+ * methods (`addContractDeploy`, `makeUnsignedContractDeploy`, etc.)
136
+ * accept. To build transactions:
137
+ *
138
+ * import { ClarityVersion } from '@stacks/transactions';
139
+ * // ClarityVersion.Clarity5 -> 5
140
+ *
141
+ * To check an AST response:
142
+ *
143
+ * import type { ClarityVersionName } from 'stxer';
144
+ * if (abi.clarity_version === 'Clarity5') { ... }
145
+ */
146
+ export type ClarityVersionName =
147
+ | 'Clarity1'
148
+ | 'Clarity2'
149
+ | 'Clarity3'
150
+ | 'Clarity4'
151
+ | 'Clarity5';
152
+
153
+ /** @deprecated Renamed to {@link ClarityVersionName} in 0.8.0 to avoid collision with `@stacks/transactions`'s numeric `ClarityVersion` enum. Re-exported for back-compat — will be removed in a future major. */
154
+ export type ClarityVersion = ClarityVersionName;
114
155
 
115
156
  export interface ClarityAbi {
116
157
  functions: ClarityAbiFunction[];
@@ -119,7 +160,7 @@ export interface ClarityAbi {
119
160
  fungible_tokens: ClarityAbiFungibleToken[];
120
161
  non_fungible_tokens: ClarityAbiNonFungibleToken[];
121
162
  epoch: ClarityEpoch;
122
- clarity_version: ClarityVersion;
163
+ clarity_version: ClarityVersionName;
123
164
  }
124
165
 
125
166
  export interface SymbolicExpressionField {
@@ -187,21 +228,73 @@ export interface ContractAST {
187
228
  // =============================================================================
188
229
 
189
230
  export interface ExecutionCost {
190
- read_count: number;
191
- read_length: number;
192
- write_count: number;
193
- write_length: number;
194
- runtime: number;
231
+ read_count: U64;
232
+ read_length: U64;
233
+ write_count: U64;
234
+ write_length: U64;
235
+ runtime: U64;
195
236
  }
196
237
 
238
+ /**
239
+ * Receipt for a transaction that the engine executed to completion.
240
+ *
241
+ * "Successful execution" does NOT imply contract-level success. Four
242
+ * failure signals to check, in this order:
243
+ * 1. Outer `Err` on `Result.Transaction` — engine could not run the tx
244
+ * at all (deserialization failure etc.); no receipt is produced.
245
+ * 2. `post_condition_aborted: true` — execution ran, post-condition
246
+ * tripped, state was rolled back.
247
+ * 3. `vm_error: string` (without `post_condition_aborted`) — Clarity
248
+ * VM raised a runtime error or static analysis failed.
249
+ * 4. `(err uX)` inside `result` — contract returned a Clarity error
250
+ * response. Application-level; NOT signalled by any field above.
251
+ * Decode `result` to detect.
252
+ *
253
+ * `post_condition_aborted` and `vm_error` are NOT independent: when a
254
+ * PC trips the upstream sets `post_condition_aborted: true` AND writes
255
+ * the PC abort reason into `vm_error` as a side effect. The reverse is
256
+ * not true — `vm_error` alone (with `post_condition_aborted: false`)
257
+ * means a VM / analysis failure that is not a PC abort.
258
+ */
197
259
  export interface TransactionReceipt {
260
+ /**
261
+ * Clarity return value, SIP-005 hex-serialized. For contract-call txs
262
+ * this includes the `(ok ...)` / `(err ...)` response wrapper —
263
+ * Clarity-level `(err uX)` lives here, NOT on `vm_error` or the outer
264
+ * `Err`.
265
+ */
198
266
  result: string;
199
- stx_burned: number;
267
+ /**
268
+ * STX (in micro-STX) burned by this transaction. u128 — accept as
269
+ * `number | string` to preserve precision above 2^53.
270
+ */
271
+ stx_burned: U128;
200
272
  tx_index: number;
273
+ /**
274
+ * Error message from the upstream Clarity VM. `null` when the tx had
275
+ * no VM-level issue. When `post_condition_aborted` is `true` this
276
+ * field is also populated with the PC abort reason — check
277
+ * `post_condition_aborted` first to disambiguate.
278
+ */
201
279
  vm_error: string | null;
280
+ /**
281
+ * `true` when one or more post-conditions failed and the tx was
282
+ * aborted. Implies `vm_error` is also set (to the abort reason); the
283
+ * reverse does not hold.
284
+ */
202
285
  post_condition_aborted: boolean;
286
+ /** Wall-clock simulation time in milliseconds. */
203
287
  costs: number;
204
288
  execution_cost: ExecutionCost;
289
+ /**
290
+ * Events emitted during execution (contract logs, STX transfers,
291
+ * FT/NFT events, etc.). Each entry is a JSON-encoded **string** —
292
+ * call `JSON.parse(events[i])` to get the event object. Items are
293
+ * NOT JSON objects in the array.
294
+ *
295
+ * For typed access, use {@link parseSimulationEvent} or cast:
296
+ * `JSON.parse(events[i]) as SimulationEvent`.
297
+ */
205
298
  events: string[];
206
299
  }
207
300
 
@@ -213,33 +306,251 @@ export interface TransactionErrResult {
213
306
  Err: string;
214
307
  }
215
308
 
309
+ // =============================================================================
310
+ // Simulation Events
311
+ // =============================================================================
312
+ // Wire format for entries inside `TransactionReceipt.events[]` (each entry
313
+ // there is a JSON-encoded string carrying one of these payloads).
314
+ //
315
+ // Source of truth: `clarity/src/vm/events.rs` in
316
+ // https://github.com/stacks-network/stacks-core —
317
+ // `StacksTransactionEvent::json_serialize`. These types intentionally
318
+ // differ from `@stacks/stacks-blockchain-api-types.TransactionEvent`,
319
+ // which describes Hiro API responses with a different envelope.
320
+ //
321
+ // Numeric fields that the rust source emits via `format!("{}", u128)` /
322
+ // `format!("{}", u64)` are typed as `string`, not `number` — the wire
323
+ // carries them as decimal strings to preserve full precision.
324
+
325
+ /** Common envelope present on every event variant. */
326
+ interface SimulationEventBase {
327
+ /** Hex txid with leading `0x`. */
328
+ txid: string;
329
+ event_index: number;
330
+ /**
331
+ * `true` when the event was emitted from successfully committed code.
332
+ * `false` when the tx was rolled back (post-condition abort, vm_error).
333
+ * Tracks rust `tx_receipt.vm_error.is_none() && !post_condition_aborted`.
334
+ */
335
+ committed: boolean;
336
+ }
337
+
338
+ /** Payload for `print` events and other contract-emitted events. */
339
+ export interface SmartContractEventData {
340
+ /** `<address>.<contract_name>` of the contract that emitted the event. */
341
+ contract_identifier: string;
342
+ /** Topic key — `"print"` for `(print …)` calls. */
343
+ topic: string;
344
+ /**
345
+ * Structured Clarity Value JSON (the rust `Value` enum's serde output).
346
+ * The shape is complex and varies by Clarity type; prefer `raw_value`
347
+ * for typed decoding.
348
+ */
349
+ value: unknown;
350
+ /**
351
+ * SIP-005 hex of the value, with leading `0x`. Pass to
352
+ * `deserializeCV()` from `@stacks/transactions` for typed decoding.
353
+ */
354
+ raw_value: string;
355
+ }
356
+
357
+ export interface StxTransferEventData {
358
+ sender: string;
359
+ recipient: string;
360
+ /** uSTX amount as a decimal string (rust serializes u128 via Display). */
361
+ amount: string;
362
+ /** Hex memo, possibly empty. */
363
+ memo: string;
364
+ }
365
+
366
+ export interface StxMintEventData {
367
+ recipient: string;
368
+ amount: string;
369
+ }
370
+
371
+ export interface StxBurnEventData {
372
+ sender: string;
373
+ amount: string;
374
+ }
375
+
376
+ export interface StxLockEventData {
377
+ locked_amount: string;
378
+ /** Decimal string (rust serializes u64 via Display). */
379
+ unlock_height: string;
380
+ locked_address: string;
381
+ contract_identifier: string;
382
+ }
383
+
384
+ export interface NftTransferEventData {
385
+ /** `<contract_id>::<asset_name>`. */
386
+ asset_identifier: string;
387
+ sender: string;
388
+ recipient: string;
389
+ value: unknown;
390
+ raw_value: string;
391
+ }
392
+
393
+ export interface NftMintEventData {
394
+ asset_identifier: string;
395
+ recipient: string;
396
+ value: unknown;
397
+ raw_value: string;
398
+ }
399
+
400
+ export interface NftBurnEventData {
401
+ asset_identifier: string;
402
+ sender: string;
403
+ value: unknown;
404
+ raw_value: string;
405
+ }
406
+
407
+ export interface FtTransferEventData {
408
+ asset_identifier: string;
409
+ sender: string;
410
+ recipient: string;
411
+ amount: string;
412
+ }
413
+
414
+ export interface FtMintEventData {
415
+ asset_identifier: string;
416
+ recipient: string;
417
+ amount: string;
418
+ }
419
+
420
+ export interface FtBurnEventData {
421
+ asset_identifier: string;
422
+ sender: string;
423
+ amount: string;
424
+ }
425
+
426
+ /**
427
+ * Discriminated union of every event variant the simulator emits.
428
+ * The `type` discriminator names the per-variant payload key — e.g.
429
+ * `type: 'contract_event'` carries the payload at `event.contract_event`.
430
+ *
431
+ * ```ts
432
+ * const event = parseSimulationEvent(receipt.events[0]);
433
+ * if (event.type === 'contract_event') {
434
+ * // event.contract_event.{contract_identifier, topic, raw_value, value}
435
+ * }
436
+ * ```
437
+ */
438
+ export type SimulationEvent =
439
+ | (SimulationEventBase & {
440
+ type: 'contract_event';
441
+ contract_event: SmartContractEventData;
442
+ })
443
+ | (SimulationEventBase & {
444
+ type: 'stx_transfer_event';
445
+ stx_transfer_event: StxTransferEventData;
446
+ })
447
+ | (SimulationEventBase & {
448
+ type: 'stx_mint_event';
449
+ stx_mint_event: StxMintEventData;
450
+ })
451
+ | (SimulationEventBase & {
452
+ type: 'stx_burn_event';
453
+ stx_burn_event: StxBurnEventData;
454
+ })
455
+ | (SimulationEventBase & {
456
+ type: 'stx_lock_event';
457
+ stx_lock_event: StxLockEventData;
458
+ })
459
+ | (SimulationEventBase & {
460
+ type: 'nft_transfer_event';
461
+ nft_transfer_event: NftTransferEventData;
462
+ })
463
+ | (SimulationEventBase & {
464
+ type: 'nft_mint_event';
465
+ nft_mint_event: NftMintEventData;
466
+ })
467
+ | (SimulationEventBase & {
468
+ type: 'nft_burn_event';
469
+ nft_burn_event: NftBurnEventData;
470
+ })
471
+ | (SimulationEventBase & {
472
+ type: 'ft_transfer_event';
473
+ ft_transfer_event: FtTransferEventData;
474
+ })
475
+ | (SimulationEventBase & {
476
+ type: 'ft_mint_event';
477
+ ft_mint_event: FtMintEventData;
478
+ })
479
+ | (SimulationEventBase & {
480
+ type: 'ft_burn_event';
481
+ ft_burn_event: FtBurnEventData;
482
+ });
483
+
484
+ /** Convenience parser for `TransactionReceipt.events[i]`. */
485
+ export function parseSimulationEvent(raw: string): SimulationEvent {
486
+ return JSON.parse(raw) as SimulationEvent;
487
+ }
488
+
216
489
  // Read step types
217
490
  export interface MapEntryStep {
218
- MapEntry: [string, string, string]; // [contract_id, map_name, key_hex]
491
+ MapEntry: [contract_id: string, map_name: string, key_hex: string];
219
492
  }
220
493
 
221
494
  export interface DataVarStep {
222
- DataVar: [string, string]; // [contract_id, variable_name]
495
+ DataVar: [contract_id: string, variable_name: string];
223
496
  }
224
497
 
498
+ /**
499
+ * Evaluate an arbitrary read-only Clarity expression in the context of
500
+ * `sender` (and optional `sponsor`). The Clarity analyzer rejects any
501
+ * expression that would mutate state, so this is a pure projection.
502
+ *
503
+ * Use when a plain `DataVar` / `MapEntry` read isn't enough — read-only
504
+ * `contract-call?` projections, custom expressions, or anything that
505
+ * needs a specific sender principal in scope. Cheaper than `Eval` (no
506
+ * write access, no step slot) and the only sender-context read shape.
507
+ *
508
+ * Choosing between read variants:
509
+ * - `DataVar` / `MapEntry` — direct storage reads, no Clarity
510
+ * evaluation; cheapest.
511
+ * - `EvalReadonly` — arbitrary read-only Clarity in sender/sponsor
512
+ * context; analyzer-enforced no writes.
513
+ * - `Eval` (top-level step variant on {@link SimulationStepInput},
514
+ * NOT a Reads sub-type) — arbitrary Clarity with **write access**.
515
+ * Use only when you need to mutate state.
516
+ * - `Transaction` — real Stacks tx with receipt, events,
517
+ * post-conditions, fee, nonce.
518
+ *
519
+ * @example
520
+ * { EvalReadonly: ['SP...sender', '', 'SP...contract', '(get-counter)'] }
521
+ * { EvalReadonly: ['SP...sender', '', 'SP...oracle', "(contract-call? .oracle get-value 'STX-USD)"] }
522
+ */
225
523
  export interface EvalReadonlyStep {
226
- EvalReadonly: [string, string, string, string]; // [sender, sponsor, contract_id, code]
524
+ /** `sponsor` is `""` (empty string) when there is no sponsor. */
525
+ EvalReadonly: [
526
+ sender: string,
527
+ sponsor: string,
528
+ contract_id: string,
529
+ code: string,
530
+ ];
227
531
  }
228
532
 
229
533
  export interface StxBalanceStep {
230
- StxBalance: string; // principal
534
+ /** Principal whose STX balance to read. */
535
+ StxBalance: string;
231
536
  }
232
537
 
233
538
  export interface FtBalanceStep {
234
- FtBalance: [string, string, string]; // [contract_id, token_name, principal]
539
+ /**
540
+ * Reads the FT balance via three separate parameters. Note: the batch
541
+ * `ft_balance` field on `SimulationBatchReadsRequest` uses a different
542
+ * `<contract_id>::<token_name>` combined identifier shape.
543
+ */
544
+ FtBalance: [contract_id: string, token_name: string, principal: string];
235
545
  }
236
546
 
237
547
  export interface FtSupplyStep {
238
- FtSupply: [string, string]; // [contract_id, token_name]
548
+ FtSupply: [contract_id: string, token_name: string];
239
549
  }
240
550
 
241
551
  export interface NonceStep {
242
- Nonce: string; // principal
552
+ /** Principal whose nonce to read. */
553
+ Nonce: string;
243
554
  }
244
555
 
245
556
  export type ReadStep =
@@ -261,9 +572,121 @@ export interface ReadErrResult {
261
572
 
262
573
  export type ReadResult = ReadOkResult | ReadErrResult;
263
574
 
575
+ /**
576
+ * Tenure-extend cause. `Extended` resets all cost dimensions; the
577
+ * SIP-034 variants reset a single dimension only.
578
+ */
579
+ export type TenureExtendCause =
580
+ | 'Extended'
581
+ | 'ExtendedRuntime'
582
+ | 'ExtendedReadCount'
583
+ | 'ExtendedReadLength'
584
+ | 'ExtendedWriteCount'
585
+ | 'ExtendedWriteLength';
586
+
587
+ /** PoX address used inside `AdvanceBlocksRequest.pox_addrs`. */
588
+ export interface PoxAddrInput {
589
+ /** Address version byte (0..255). */
590
+ version: number;
591
+ /** Address hashbytes as hex (no `0x` prefix). */
592
+ hashbytes: string;
593
+ }
594
+
595
+ /**
596
+ * Request payload for the `AdvanceBlocks` step variant. Synthesizes
597
+ * bitcoin and stacks blocks on top of the simulation's pinned parent
598
+ * tip. Hex strings for 32-byte hashes / VRF seeds; PoX address
599
+ * overrides use the tuple form `[addrs, payout_ustx]` on the wire.
600
+ */
601
+ export interface AdvanceBlocksRequest {
602
+ bitcoin_blocks: number;
603
+ stacks_blocks_per_bitcoin: number;
604
+ /** Defaults to 600 (mainnet target) upstream when omitted. */
605
+ bitcoin_interval_secs?: U64;
606
+ /**
607
+ * Per-burn-index burn-header-hash overrides, keyed by 0-based burn
608
+ * index within this batch. Hex strings (32 bytes, with or without
609
+ * `0x` prefix).
610
+ */
611
+ burn_header_hashes?: Record<string, string>;
612
+ /**
613
+ * Per-burn-index PoX address overrides as `[addrs, payout_ustx]`.
614
+ * `payout_ustx` is `u128` upstream — see {@link U128}.
615
+ */
616
+ pox_addrs?: Record<string, [PoxAddrInput[], U128]>;
617
+ /** Per-burn-index VRF-seed overrides as 32-byte hex strings. */
618
+ vrf_seeds?: Record<string, string>;
619
+ }
620
+
621
+ /**
622
+ * One synthesized block produced by an `AdvanceBlocks` step. Returned
623
+ * inside `SimulationStepResult.AdvanceBlocks.Ok` and as the `tip`
624
+ * fields when synthetic.
625
+ */
626
+ export interface AdvancedBlockSummary {
627
+ stacks_height: U64;
628
+ burn_height: number;
629
+ coinbase_height: number;
630
+ index_block_hash: string;
631
+ burn_header_hash: string;
632
+ vrf_seed: string;
633
+ block_time: U64;
634
+ burn_block_time: U64;
635
+ /**
636
+ * `true` when this synthetic block is the first stacks block in a
637
+ * new tenure (i.e. follows a synthesized bitcoin block).
638
+ */
639
+ tenure_change: boolean;
640
+ }
641
+
642
+ /**
643
+ * Response shape for `GET /devtools/v2/simulations/{id}/tip`. When
644
+ * `synthetic` is `false`, fields mirror the parent metadata pinned at
645
+ * session start; `vrf_seed` and `tenure_change` are omitted in that
646
+ * case.
647
+ */
648
+ export interface SimulationTipResponse {
649
+ synthetic: boolean;
650
+ stacks_height: U64;
651
+ burn_height: number;
652
+ coinbase_height: number;
653
+ block_time: U64;
654
+ burn_block_time: U64;
655
+ index_block_hash: string;
656
+ consensus_hash: string;
657
+ burn_header_hash: string;
658
+ sortition_id: string;
659
+ epoch: string;
660
+ /** Only present when `synthetic` is `true`. */
661
+ vrf_seed?: string;
662
+ /** Only present when `synthetic` is `true`. */
663
+ tenure_change?: boolean;
664
+ }
665
+
666
+ /**
667
+ * Per-step result returned by `POST /devtools/v2/simulations/{id}` (the
668
+ * "submit steps" endpoint). Externally tagged — exactly one variant key
669
+ * is present per object.
670
+ *
671
+ * Distinct from `SimulationStepSummary`, which is what
672
+ * `GET /devtools/v2/simulations/{id}` returns and includes the original
673
+ * step input alongside the result.
674
+ */
675
+ export type SimulationStepResult =
676
+ | { Transaction: TransactionOkResult | TransactionErrResult }
677
+ | { Eval: { Ok: string } | { Err: string } }
678
+ | { SetContractCode: { Ok: null } | { Err: string } }
679
+ | { Reads: ReadResult[] }
680
+ | { TenureExtend: ExecutionCost }
681
+ | {
682
+ AdvanceBlocks: { Ok: AdvancedBlockSummary[] } | { Err: string };
683
+ };
684
+
264
685
  // Simulation step types (summary format from GET /devtools/v2/simulations/{id})
265
686
  export interface TransactionStepSummary {
266
- Transaction: string; // tx hex
687
+ /** Transaction serialized to hex. */
688
+ Transaction: string;
689
+ /** Hex-encoded txid. Empty string `""` when the tx failed engine-level. */
267
690
  TxId: string;
268
691
  Result: {
269
692
  Transaction: TransactionOkResult | TransactionErrResult;
@@ -279,36 +702,66 @@ export interface ReadsStepSummary {
279
702
  }
280
703
 
281
704
  export interface SetContractCodeStepSummary {
282
- SetContractCode: [string, string, number]; // [contract_id, code, clarity_version]
705
+ SetContractCode: [contract_id: string, code: string, clarity_version: number];
283
706
  Result: {
284
707
  SetContractCode: { Ok: null } | { Err: string };
285
708
  };
286
709
  }
287
710
 
288
711
  export interface EvalStepSummary {
289
- Eval: [string, string, string, string]; // [sender, sponsor, contract_id, code]
712
+ /** `sponsor` is `""` (empty string) when there is no sponsor. */
713
+ Eval: [sender: string, sponsor: string, contract_id: string, code: string];
290
714
  Result: {
291
715
  Eval: { Ok: string } | { Err: string };
292
716
  };
293
717
  }
294
718
 
719
+ /**
720
+ * Echoed `AdvanceBlocks` input as serialized in the summary response.
721
+ * Differs from the request shape ({@link AdvanceBlocksRequest}) in two
722
+ * places: `bitcoin_interval_secs` is nullable (serde `Option`); each
723
+ * `pox_addrs` value is the `{addrs, payout}` object form (vs. the
724
+ * request's tuple form).
725
+ */
726
+ export interface AdvanceBlocksStepEcho {
727
+ bitcoin_blocks: number;
728
+ stacks_blocks_per_bitcoin: number;
729
+ bitcoin_interval_secs: U64 | null;
730
+ burn_header_hashes: Record<string, string>;
731
+ pox_addrs: Record<string, { addrs: PoxAddrInput[]; payout: U128 }>;
732
+ vrf_seeds: Record<string, string>;
733
+ }
734
+
295
735
  export interface TenureExtendStepSummary {
736
+ /**
737
+ * Echoed input shape. The server normalizes legacy `{TenureExtend: []}`
738
+ * inputs to `{cause: 'Extended'}` at parse time, so the summary always
739
+ * carries the modern form regardless of how the step was submitted.
740
+ */
741
+ TenureExtend: { cause: TenureExtendCause };
296
742
  Result: {
297
743
  TenureExtend: ExecutionCost;
298
744
  };
299
745
  }
300
746
 
747
+ export interface AdvanceBlocksStepSummary {
748
+ AdvanceBlocks: AdvanceBlocksStepEcho;
749
+ Result: {
750
+ AdvanceBlocks: { Ok: AdvancedBlockSummary[] } | { Err: string };
751
+ };
752
+ }
753
+
301
754
  export type SimulationStepSummary =
302
755
  | TransactionStepSummary
303
756
  | ReadsStepSummary
304
757
  | SetContractCodeStepSummary
305
758
  | EvalStepSummary
306
- | TenureExtendStepSummary;
759
+ | TenureExtendStepSummary
760
+ | AdvanceBlocksStepSummary;
307
761
 
308
762
  // Simulation metadata
309
763
  export interface SimulationMetadata {
310
- ast_rules: 0 | 1;
311
- block_height: number;
764
+ block_height: U64;
312
765
  block_hash: string;
313
766
  burn_block_height: number;
314
767
  burn_block_hash: string;
@@ -327,7 +780,7 @@ export interface SimulationResult {
327
780
 
328
781
  // Create session request
329
782
  export interface CreateSimulationRequest {
330
- block_height?: number;
783
+ block_height?: U64;
331
784
  block_hash?: string;
332
785
  skip_tracing?: boolean;
333
786
  }
@@ -336,57 +789,139 @@ export interface CreateSimulationResponse {
336
789
  id: string;
337
790
  }
338
791
 
339
- // Submit steps request
792
+ /**
793
+ * One step submitted to `POST /devtools/v2/simulations/{id}`. Tagged
794
+ * union — exactly one variant key per object.
795
+ *
796
+ * **Picking the right Clarity-execution shape** — `Transaction` /
797
+ * `Eval` / `Reads` differ on side-effects, cost, and what they emit:
798
+ *
799
+ * - `Transaction` — full Stacks tx mechanics. Generates a
800
+ * `TransactionReceipt` (events, vm_error, post_condition_aborted,
801
+ * execution_cost), consumes nonce, charges fee, enforces
802
+ * post-conditions. The only variant that emits a receipt. Use when
803
+ * simulating a real user action.
804
+ * - `Eval` — arbitrary Clarity with **write access** to contract
805
+ * storage; no fee, no nonce, no post-conditions, no receipt — just
806
+ * the resulting Clarity value or err. Use to stub state mid-session
807
+ * (`var-set`, `map-set`, …) or run code with side-effects without
808
+ * tx ceremony.
809
+ * - `Reads` (batch of {@link ReadStep}, including `EvalReadonly`) —
810
+ * pure projection, no state changes, cheapest. Use when you only
811
+ * need to read derived data; `EvalReadonly` provides the
812
+ * sender/sponsor context that `DataVar` / `MapEntry` cannot.
813
+ *
814
+ * `SetContractCode` replaces a contract's code (write side-effects, no
815
+ * fee/nonce/receipt — like `Eval` but at the contract level).
816
+ * `TenureExtend` resets cost dimensions. `AdvanceBlocks` synthesizes
817
+ * burn/stacks blocks (see {@link AdvanceBlocksRequest}).
818
+ *
819
+ * `TenureExtend` accepts both legacy `[]` (treated server-side as
820
+ * `cause: 'Extended'`) and modern `{ cause }` shapes. SDK 0.8.0 emits
821
+ * the modern form via {@link SimulationBuilder.addTenureExtend}; the
822
+ * legacy shape stays in this union so consumers passing literal step
823
+ * objects (not via the builder) still type-check.
824
+ */
340
825
  export type SimulationStepInput =
341
- | { Transaction: string } // tx hex
342
- | { Eval: [string, string, string, string] } // [sender, sponsor, contract_id, code]
343
- | { SetContractCode: [string, string, number] } // [contract_id, code, clarity_version]
826
+ | { Transaction: string }
827
+ | {
828
+ /** `sponsor` is `""` when there is no sponsor. */
829
+ Eval: [
830
+ sender: string,
831
+ sponsor: string,
832
+ contract_id: string,
833
+ code: string,
834
+ ];
835
+ }
836
+ | {
837
+ SetContractCode: [
838
+ contract_id: string,
839
+ code: string,
840
+ clarity_version: number,
841
+ ];
842
+ }
344
843
  | { Reads: ReadStep[] }
345
- | { TenureExtend: [] };
844
+ | { TenureExtend: [] | { cause: TenureExtendCause } }
845
+ | { AdvanceBlocks: AdvanceBlocksRequest };
346
846
 
347
847
  export interface SubmitSimulationStepsRequest {
348
848
  steps: SimulationStepInput[];
349
849
  }
350
850
 
351
851
  export interface SubmitSimulationStepsResponse {
352
- steps: SimulationStepSummary[];
852
+ steps: SimulationStepResult[];
353
853
  }
354
854
 
355
855
  // Batch reads from simulation
356
856
  export interface SimulationBatchReadsRequest {
357
- vars?: [string, string][]; // [contract_id, variable_name]
358
- maps?: [string, string, string][]; // [contract_id, map_name, key_hex]
359
- readonly?: Array<string | [string, string, string, string]>; // [contract_id, function_name, ...args]
360
- readonly_with_sender?: Array<
361
- // [sender, sponsor, contract_id, function_name, ...args]
362
- [string, string, string, string, ...string[]]
363
- >;
364
- stx?: string[]; // principals
365
- nonces?: string[]; // principals
366
- ft_balance?: [string, string][]; // [token_identifier, principal]
367
- ft_supply?: [string, string][]; // [contract_id, ft_token_name]
857
+ /** `[contract_id, variable_name]` per entry. */
858
+ vars?: [contract_id: string, variable_name: string][];
859
+ /** `[contract_id, map_name, key_hex]` per entry. */
860
+ maps?: [contract_id: string, map_name: string, key_hex: string][];
861
+ /**
862
+ * `[contract_id, function_name, ...arg_hex]` per entry. The first two
863
+ * positions are fixed; remaining elements are hex-encoded Clarity
864
+ * values, one per function argument (so the length matches the
865
+ * function's arity, not arbitrary).
866
+ */
867
+ readonly?: [
868
+ contract_id: string,
869
+ function_name: string,
870
+ ...args_hex: string[],
871
+ ][];
872
+ /**
873
+ * `[sender, sponsor, contract_id, function_name, ...arg_hex]` per
874
+ * entry. The first four positions are fixed (`sponsor` is `""` when
875
+ * there is no sponsor); remaining elements are hex-encoded Clarity
876
+ * values, one per function argument.
877
+ */
878
+ readonly_with_sender?: [
879
+ sender: string,
880
+ sponsor: string,
881
+ contract_id: string,
882
+ function_name: string,
883
+ ...args_hex: string[],
884
+ ][];
885
+ /** Principals to read STX balances for. */
886
+ stx?: string[];
887
+ /** Principals to read nonces for. */
888
+ nonces?: string[];
889
+ /** `[<contract_id>::<token_name>, principal]` per entry. */
890
+ ft_balance?: [token_identifier: string, principal: string][];
891
+ /**
892
+ * Flat array of FT identifiers in `<contract_id>::<token_name>` form,
893
+ * one entry per token to look up. Any length.
894
+ */
895
+ ft_supply?: string[];
368
896
  }
369
897
 
898
+ /**
899
+ * Each category is omitted from the JSON response when the corresponding
900
+ * request field was empty/absent (rust uses
901
+ * `serde(skip_serializing_if = "Vec::is_empty")` per field).
902
+ */
370
903
  export interface SimulationBatchReadsResponse {
371
- vars: ReadResult[];
372
- maps: ReadResult[];
373
- readonly: ReadResult[];
374
- readonly_with_sender: ReadResult[];
375
- stx: ReadResult[];
376
- nonces: ReadResult[];
377
- ft_balance: ReadResult[];
378
- ft_supply: ReadResult[];
904
+ vars?: ReadResult[];
905
+ maps?: ReadResult[];
906
+ readonly?: ReadResult[];
907
+ readonly_with_sender?: ReadResult[];
908
+ stx?: ReadResult[];
909
+ nonces?: ReadResult[];
910
+ ft_balance?: ReadResult[];
911
+ ft_supply?: ReadResult[];
379
912
  }
380
913
 
381
914
  // Instant simulation
382
915
  export interface InstantSimulationRequest {
383
- transaction: string; // tx hex
384
- block_height?: number;
916
+ /** Transaction serialized to hex. */
917
+ transaction: string;
918
+ block_height?: U64;
385
919
  block_hash?: string;
386
920
  reads?: ReadStep[];
387
921
  }
388
922
 
389
923
  export interface InstantSimulationResponse {
390
- reads?: ReadResult[];
924
+ /** Always present (may be `[]`). Aligned positionally with the request `reads`. */
925
+ reads: ReadResult[];
391
926
  receipt: TransactionReceipt;
392
927
  }