stxer 0.7.0 → 0.9.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/CHANGELOG.md +141 -0
- package/README.md +237 -56
- package/dist/ast.d.ts +1 -1
- package/dist/bitcoin.d.ts +121 -0
- package/dist/index.d.ts +2 -0
- package/dist/simulation-api.d.ts +52 -3
- package/dist/simulation.d.ts +70 -3
- package/dist/stxer.cjs.development.js +906 -101
- package/dist/stxer.cjs.development.js.map +1 -1
- package/dist/stxer.cjs.production.min.js +1 -1
- package/dist/stxer.cjs.production.min.js.map +1 -1
- package/dist/stxer.esm.js +887 -104
- package/dist/stxer.esm.js.map +1 -1
- package/dist/transaction.d.ts +71 -0
- package/dist/types.d.ts +247 -25
- package/package.json +26 -23
- package/src/ast.ts +1 -1
- package/src/bitcoin.ts +391 -0
- package/src/index.ts +2 -0
- package/src/simulation-api.ts +109 -12
- package/src/simulation.ts +247 -46
- package/src/transaction.ts +141 -0
- package/src/types.ts +256 -27
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the `stxer` SDK are documented here. The format
|
|
4
|
+
loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
|
|
5
|
+
versioning is [SemVer](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## 0.9.0
|
|
8
|
+
|
|
9
|
+
Adopts Stacks **Epoch 4.0 / Clarity 6** (stacks-core 4.0.1).
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `'Epoch40'` member on the `ClarityEpoch` union and `'Clarity6'` on
|
|
14
|
+
`ClarityVersionName`; `parseContract` now accepts
|
|
15
|
+
`clarityVersion: '6'`.
|
|
16
|
+
- `ClarityVersion.Clarity6` accepted by `addContractDeploy` /
|
|
17
|
+
`addSetContractCode` (via the upgraded `@stacks/transactions`), and
|
|
18
|
+
serialized as wire value `6` for `SetContractCode` steps.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- `@stacks/transactions` bumped `7.4.0` → `7.5.0` (first release whose
|
|
23
|
+
`ClarityVersion` enum includes `Clarity6`).
|
|
24
|
+
- Unknown future clarity versions now serialize as `6` (previously
|
|
25
|
+
silently clamped to `5`).
|
|
26
|
+
- Deploy defaults remain `ClarityVersion.Clarity5` until Epoch 4.0
|
|
27
|
+
activates on mainnet (burn height 960,230); pass
|
|
28
|
+
`clarity_version: ClarityVersion.Clarity6` explicitly to opt in.
|
|
29
|
+
|
|
30
|
+
## 0.8.0
|
|
31
|
+
|
|
32
|
+
Pairs with **stxer-api ≥ schema-v2** (the simulator build that ships
|
|
33
|
+
`AdvanceBlocks` + `/tip` + the typed 409 / 410 status codes). Older
|
|
34
|
+
deployments respond `404` for `getSimulationTip` and reject
|
|
35
|
+
`AdvanceBlocks` step variants.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- **`addAdvanceBlocks(request)` on `SimulationBuilder`** plus the
|
|
40
|
+
`{ AdvanceBlocks: AdvanceBlocksRequest }` variant on
|
|
41
|
+
`SimulationStepInput`. Synthesizes bitcoin / stacks blocks on top of
|
|
42
|
+
the simulation's pinned parent tip — used to model burn-block /
|
|
43
|
+
tenure boundaries (PoX cycles, locked-STX unlock, time-locked
|
|
44
|
+
redemptions, bridge contract finalization). See the
|
|
45
|
+
[`AdvanceBlocks` section in the README](./README.md#advanceblocks-burn-block-scenarios)
|
|
46
|
+
and the worked examples under `src/sample/`.
|
|
47
|
+
- **`getSimulationTip(sessionId, options?)`** — reads the current tip
|
|
48
|
+
of a simulation session. Returns the latest synthetic tip when at
|
|
49
|
+
least one `AdvanceBlocks` step has run (`synthetic: true`, includes
|
|
50
|
+
`vrf_seed` and `tenure_change`); otherwise returns the parent
|
|
51
|
+
metadata pinned at session start.
|
|
52
|
+
- **Typed `SimulationError`** thrown by every `simulation-api.ts`
|
|
53
|
+
fetch wrapper. Carries `.status` (HTTP code), `.marker` (typed
|
|
54
|
+
`'simulation_busy' | 'simulation_outdated' | null`), and `.body`
|
|
55
|
+
(raw upstream message). Branch on `.marker` to distinguish a
|
|
56
|
+
retry-the-same-request 409 from a start-a-new-session 410. Pre-0.8.0
|
|
57
|
+
threw plain `Error`; the message format
|
|
58
|
+
(`${operation} (HTTP ${status}): ${body}`) is preserved so log
|
|
59
|
+
scrapers keep working.
|
|
60
|
+
- **`src/sim-helpers.ts`** — session-bound wrappers: `callContract`,
|
|
61
|
+
`getStxBalance`, `getFtBalance`, `getNonce`, `readDataVar`. Uses
|
|
62
|
+
`simulationBatchReads` underneath so demos can lean on typed reads
|
|
63
|
+
without hand-rolling the batch envelope.
|
|
64
|
+
- **`src/transaction.ts`** — `setSender`, `buildUnsignedContractCallHex`,
|
|
65
|
+
`ftPrincipal`, `ContractCallTxArgs`. Extracted from `simulation.ts`
|
|
66
|
+
and the old `sample/_helpers.ts` so consumers can build unsigned tx
|
|
67
|
+
hex without instantiating `SimulationBuilder`.
|
|
68
|
+
- **`src/bitcoin.ts`** — SPV / merkle-proof / forged-tx primitives used
|
|
69
|
+
by the bridge demos: `sha256`, `sha256d`, `hexToBytes`, `bytesToHex`,
|
|
70
|
+
`p2wpkhScript`, `p2pkhScript`, `opReturnScript`, `forgeBitcoinTx`,
|
|
71
|
+
`buildBitcoinHeader`, `singleTxMerkleRoot`, `merkleProof`,
|
|
72
|
+
`verifyMerkleProof`. Pairs with `addAdvanceBlocks`'
|
|
73
|
+
`burn_header_hashes` override for sBTC / Brotocol bridge scenarios.
|
|
74
|
+
- **`addTenureExtend(cause?)`** now accepts an optional
|
|
75
|
+
`TenureExtendCause` (`'Extended' | 'ExtendedRuntime' | ...`) so
|
|
76
|
+
callers can reset a single SIP-034 cost dimension.
|
|
77
|
+
- **Six new vitest demos** under `src/sample/*-vitest.test.ts`:
|
|
78
|
+
`locked-stx`, `sbtc-deposit`, `brotocol-pegin`, `hbtc-vault`,
|
|
79
|
+
`zest-borrow`, `granite-leverage`. **The `src/sample` directory is
|
|
80
|
+
intentionally excluded from the npm tarball** to keep package size
|
|
81
|
+
down — browse them on
|
|
82
|
+
[GitHub](https://github.com/stxer/stxer-sdk/tree/master/src/sample).
|
|
83
|
+
|
|
84
|
+
### Changed (breaking)
|
|
85
|
+
|
|
86
|
+
- **`addTenureExtend()` zero-arg now emits the modern wire shape**
|
|
87
|
+
(`{ TenureExtend: { cause: 'Extended' } }`) instead of the legacy
|
|
88
|
+
`{ TenureExtend: [] }`. The TypeScript signature is back-compat —
|
|
89
|
+
zero-arg call sites keep compiling — but anyone snapshotting JSON
|
|
90
|
+
request bodies will see the new shape. The server still parses the
|
|
91
|
+
legacy `[]` form for raw consumers.
|
|
92
|
+
- **`SimulationStepResult.TenureExtend` summaries always carry
|
|
93
|
+
`{ cause }`.** Previously typed as `[] | { cause }`; the server
|
|
94
|
+
normalizes legacy `[]` inputs to `{ cause: 'Extended' }` at parse
|
|
95
|
+
time, so the summary echo can never carry `[]`. The narrower type
|
|
96
|
+
is now reflected on `TenureExtendStepSummary.TenureExtend`.
|
|
97
|
+
- **HTTP responses now propagate as 4xx where they used to be masked
|
|
98
|
+
as 200.** The stxer-api proxy was forwarding upstream
|
|
99
|
+
`simulation_busy:` / `simulation_outdated:` / 4xx bodies with status
|
|
100
|
+
200; the proxy now forwards the upstream status verbatim. SDK
|
|
101
|
+
callers are unaffected (the fetch wrappers already threw on `!ok`),
|
|
102
|
+
but raw-curl consumers reading 200 as success will now see
|
|
103
|
+
exceptions on those paths. The body content is unchanged.
|
|
104
|
+
- **`BatchReadsResult.tip` renamed to `BatchReadsResult.index_block_hash`**
|
|
105
|
+
to match the wire field name.
|
|
106
|
+
- **Numeric u64 / u128 fields are typed as `U64` / `U128`** (`number |
|
|
107
|
+
string`) instead of plain `number` to avoid silent precision loss
|
|
108
|
+
above 2^53. Affected fields: `TransactionReceipt.stx_burned`
|
|
109
|
+
(u128), `ExecutionCost.{read_count,read_length,write_count,
|
|
110
|
+
write_length,runtime}` (u64), `AdvancedBlockSummary.{stacks_height,
|
|
111
|
+
block_time,burn_block_time}` (u64), `SimulationTipResponse.
|
|
112
|
+
{stacks_height,block_time,burn_block_time}` (u64),
|
|
113
|
+
`SimulationMetadata.block_height` (u64), `SidecarTip.
|
|
114
|
+
{block_height,block_time,burn_block_time,tenure_height}` (u64),
|
|
115
|
+
`TenureCost.*` (u64), `AdvanceBlocksRequest.bitcoin_interval_secs`
|
|
116
|
+
and `AdvanceBlocksStepEcho.bitcoin_interval_secs` (u64),
|
|
117
|
+
`CreateSimulationRequest.block_height` /
|
|
118
|
+
`InstantSimulationRequest.block_height` (u64). Use `BigInt(x)` to
|
|
119
|
+
normalize before arithmetic.
|
|
120
|
+
- **`ClarityVersion` (the SDK string-literal type) renamed to
|
|
121
|
+
`ClarityVersionName`** to disambiguate from the numeric enum
|
|
122
|
+
re-exported by `@stacks/transactions`. The old name is preserved as
|
|
123
|
+
a deprecated alias for one major; use `ClarityVersionName` for
|
|
124
|
+
`ClarityAbi.clarity_version` matches and `@stacks/transactions`'s
|
|
125
|
+
numeric `ClarityVersion` enum (`ClarityVersion.Clarity4` → `4`) for
|
|
126
|
+
builder calls.
|
|
127
|
+
|
|
128
|
+
### Server-side note
|
|
129
|
+
|
|
130
|
+
This release is paired with a server-side schema bump (`v=2`).
|
|
131
|
+
Simulation sessions created against an older simulator are rejected
|
|
132
|
+
with **HTTP 410 `simulation_outdated:`** after the cutover; SDK callers
|
|
133
|
+
see this as `SimulationError` with `marker: 'simulation_outdated'` and
|
|
134
|
+
should start a new session. Sim ids are random per-session and never
|
|
135
|
+
expected to persist across releases by design.
|
|
136
|
+
|
|
137
|
+
## 0.7.0
|
|
138
|
+
|
|
139
|
+
See `git log` for prior releases. 0.7.0 was the last release without
|
|
140
|
+
`AdvanceBlocks` / `getSimulationTip` and treated all upstream errors as
|
|
141
|
+
plain `Error`.
|
package/README.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# STXER SDK
|
|
2
2
|
|
|
3
3
|
A powerful SDK for Stacks blockchain that provides transaction simulation, batch operations, contract AST parsing, and chain tip information.
|
|
4
4
|
|
|
5
|
+
Pairs with the [stxer-api](https://api.stxer.xyz) (mainnet) and
|
|
6
|
+
[testnet-api](https://testnet-api.stxer.xyz). See
|
|
7
|
+
[`CHANGELOG.md`](./CHANGELOG.md) for release notes.
|
|
8
|
+
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
7
11
|
```bash
|
|
@@ -10,6 +14,30 @@ npm install stxer
|
|
|
10
14
|
yarn add stxer
|
|
11
15
|
```
|
|
12
16
|
|
|
17
|
+
## When to use what
|
|
18
|
+
|
|
19
|
+
Pick the right tool for the task — these are not interchangeable:
|
|
20
|
+
|
|
21
|
+
| Goal | Use |
|
|
22
|
+
|---|---|
|
|
23
|
+
| Wallet preview / pre-broadcast safety check (single tx, no session, **no debug tracing**) | [`instantSimulation`](#instant-simulation) |
|
|
24
|
+
| Quick scripted multi-step simulation, browsable in the [stxer debug UI](https://stxer.xyz) | [`SimulationBuilder`](#1-transaction-simulation-v2-api) |
|
|
25
|
+
| CI / Vitest contract test with custom assertions on per-step results | [`createSimulationSession`](#session-based-simulation) + [`submitSimulationSteps`](#session-based-simulation) + [`sim-helpers`](#sim-helpers-callcontract-getstxbalance-getftbalance-getnonce-readdatavar) |
|
|
26
|
+
| Burn-block / tenure scenarios (PoX cycles, locked-STX unlock, time-locked redemptions) | [`addAdvanceBlocks`](#advanceblocks-burn-block-scenarios) + [`getSimulationTip`](#advanceblocks-burn-block-scenarios) |
|
|
27
|
+
| Bridge / SPV peg-in (sBTC, Brotocol) | raw API + [`bitcoin.ts`](#bitcoin-spv--bridge-primitives) + [`transaction.ts`](#transaction-builders) — see the bridge demos in [`src/sample`](https://github.com/stxer/stxer-sdk/tree/master/src/sample) |
|
|
28
|
+
| Bulk read against current chain state | [`batchRead`](#batch-operations) (sidecar) or [`simulationBatchReads`](#session-based-simulation) (against a session's forked state) |
|
|
29
|
+
| Read-only contract calls with ABI decoding | [`callReadonly`](#clarity-api) / [`readVariable`](#clarity-api) / [`readMap`](#clarity-api) |
|
|
30
|
+
|
|
31
|
+
`instantSimulation` is intentionally transient — it has **no debug
|
|
32
|
+
tracing** and the simulation isn't viewable in the stxer UI. Use
|
|
33
|
+
sessions when you need either of those.
|
|
34
|
+
|
|
35
|
+
The bridge / `AdvanceBlocks` patterns deliberately bypass
|
|
36
|
+
`SimulationBuilder` because they need typed access to per-step results
|
|
37
|
+
(builder only returns the final `simulation_id`). The decision table
|
|
38
|
+
above is the canonical mapping; the in-tree bridge vitest demos are
|
|
39
|
+
the canonical worked examples.
|
|
40
|
+
|
|
13
41
|
## Features
|
|
14
42
|
|
|
15
43
|
### 1. Transaction Simulation (V2 API)
|
|
@@ -42,7 +70,7 @@ const simulationId = await SimulationBuilder.new({
|
|
|
42
70
|
contract_name: 'my-contract',
|
|
43
71
|
source_code: '(define-public (hello) (ok "world"))',
|
|
44
72
|
deployer: 'SP...', // Optional: overrides default sender
|
|
45
|
-
clarity_version: 4, //
|
|
73
|
+
clarity_version: 4, // 1 / 2 / 3 / 4 / 5 / 6 — or `ClarityVersion.Clarity6` from `@stacks/transactions`
|
|
46
74
|
})
|
|
47
75
|
.run();
|
|
48
76
|
|
|
@@ -51,10 +79,19 @@ const simulationId = await SimulationBuilder.new({
|
|
|
51
79
|
|
|
52
80
|
#### Advanced V2 Step Types
|
|
53
81
|
|
|
54
|
-
The SDK supports all V2 simulation step types
|
|
82
|
+
The SDK supports all V2 simulation step types. Three of them — `Transaction`, `Eval`, and `EvalReadonly` (a `Reads` sub-type) — all execute Clarity but differ on side-effects, cost, and what they emit. Pick by **what you need to come out of the step**:
|
|
83
|
+
|
|
84
|
+
| Step | Side effects | Receipt + events | Fee / nonce | Post-conditions | When to use |
|
|
85
|
+
|---|---|---|---|---|---|
|
|
86
|
+
| `Transaction` | full tx execution | ✅ `TransactionReceipt` | ✅ | ✅ | Simulating a real user action; need a receipt; want PCs enforced |
|
|
87
|
+
| `Eval` | **write access** | ❌ | ❌ | ❌ | Stub state mid-session, run code with side-effects without tx ceremony |
|
|
88
|
+
| `EvalReadonly` (in `Reads`) | none — analyzer-enforced read-only | ❌ | ❌ | ❌ | Read-only contract calls / projections / custom expressions that need sender-context |
|
|
89
|
+
|
|
90
|
+
Cost order, cheapest first: `EvalReadonly` < `Eval` < `Transaction`. Use the cheapest variant that gives you what you need — running a `(var-get counter)` projection through `Eval` is wasteful when an `EvalReadonly` (or a plain `DataVar` read) gets the same answer for less.
|
|
55
91
|
|
|
56
92
|
```typescript
|
|
57
|
-
import { SimulationBuilder
|
|
93
|
+
import { SimulationBuilder } from 'stxer';
|
|
94
|
+
import { ClarityVersion } from '@stacks/transactions';
|
|
58
95
|
|
|
59
96
|
const simulationId = await SimulationBuilder.new()
|
|
60
97
|
.withSender('SP...')
|
|
@@ -77,11 +114,11 @@ const simulationId = await SimulationBuilder.new()
|
|
|
77
114
|
clarity_version: ClarityVersion.Clarity4,
|
|
78
115
|
})
|
|
79
116
|
|
|
80
|
-
// === Eval
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
//
|
|
117
|
+
// === Eval Step (write access, no tx ceremony) ===
|
|
118
|
+
// Use Eval when you need to mutate contract state WITHOUT a real tx —
|
|
119
|
+
// no fee, no nonce, no post-conditions, no receipt; just the Clarity
|
|
120
|
+
// value or err. For pure reads, prefer the `Reads` batch below
|
|
121
|
+
// (`EvalReadonly` is cheaper and analyzer-enforced read-only).
|
|
85
122
|
.addEvalCode('SP...contract', '(var-set counter u100)')
|
|
86
123
|
|
|
87
124
|
// === SetContractCode Step ===
|
|
@@ -93,22 +130,61 @@ const simulationId = await SimulationBuilder.new()
|
|
|
93
130
|
})
|
|
94
131
|
|
|
95
132
|
// === Reads Batch Step ===
|
|
96
|
-
// Batch multiple read operations
|
|
133
|
+
// Batch multiple read operations into one step. `EvalReadonly` is the
|
|
134
|
+
// sender-context read variant — analyzer-enforced no writes; use it
|
|
135
|
+
// for read-only contract calls / projections / custom expressions
|
|
136
|
+
// that need a specific sender principal in scope.
|
|
97
137
|
.addReads([
|
|
98
138
|
{ DataVar: ['SP...contract', 'counter'] },
|
|
99
139
|
{ DataVar: ['SP...contract', 'enabled'] },
|
|
100
140
|
{ StxBalance: 'SP...' },
|
|
101
141
|
{ Nonce: 'SP...' },
|
|
102
142
|
{ EvalReadonly: ['SP...', '', 'SP...contract', '(get-counter)'] },
|
|
143
|
+
{
|
|
144
|
+
EvalReadonly: [
|
|
145
|
+
'SP...',
|
|
146
|
+
'',
|
|
147
|
+
'SP...oracle',
|
|
148
|
+
"(contract-call? .oracle get-value 'STX-USD)",
|
|
149
|
+
],
|
|
150
|
+
},
|
|
103
151
|
])
|
|
104
152
|
|
|
105
153
|
// === TenureExtend Step ===
|
|
106
|
-
// Extend tenure (resets execution cost)
|
|
107
|
-
|
|
154
|
+
// Extend tenure (resets execution cost). Defaults to 'Extended'
|
|
155
|
+
// (full reset); pass a SIP-034 cause to reset only one dimension.
|
|
156
|
+
.addTenureExtend('ExtendedRuntime')
|
|
157
|
+
|
|
158
|
+
// === AdvanceBlocks Step ===
|
|
159
|
+
// Synthesize bitcoin and stacks blocks on top of the pinned parent
|
|
160
|
+
// tip — used to model burn-block / tenure boundaries (bridge
|
|
161
|
+
// contracts, time-locked redemptions, locked-STX unlock).
|
|
162
|
+
.addAdvanceBlocks({ bitcoin_blocks: 1, stacks_blocks_per_bitcoin: 1 })
|
|
108
163
|
|
|
109
164
|
.run();
|
|
110
165
|
```
|
|
111
166
|
|
|
167
|
+
#### Schema cutover (v0.8.0)
|
|
168
|
+
|
|
169
|
+
The 0.8.0 release coincides with a server-side schema bump for
|
|
170
|
+
simulation sessions. **Existing simulation session ids started before
|
|
171
|
+
the upgrade return `HTTP 410 Gone`** — start a fresh session via
|
|
172
|
+
`SimulationBuilder.run()` / `createSimulationSession()` to get a
|
|
173
|
+
schema-v=2 id. Sim ids are random per-call and not persisted across
|
|
174
|
+
releases by design, so this only affects in-flight callers.
|
|
175
|
+
|
|
176
|
+
The fetch wrappers in `simulation-api` now throw a typed
|
|
177
|
+
`SimulationError` (with `status` and `marker` fields) on non-2xx
|
|
178
|
+
responses; `marker` is `'simulation_busy'` (HTTP 409),
|
|
179
|
+
`'simulation_outdated'` (HTTP 410), or `null`. Pre-0.8.0 the SDK
|
|
180
|
+
threw a plain `Error` whose message embedded the body — message format
|
|
181
|
+
is unchanged so existing log scrapers keep working.
|
|
182
|
+
|
|
183
|
+
`addTenureExtend(cause?)` now accepts an optional `TenureExtendCause`.
|
|
184
|
+
The on-the-wire request shape is `{ TenureExtend: { cause } }`; the
|
|
185
|
+
legacy `{ TenureExtend: [] }` shape stays parseable on the server but
|
|
186
|
+
the SDK builder no longer emits it.
|
|
187
|
+
|
|
112
188
|
#### Reads Batch Sub-Types
|
|
113
189
|
|
|
114
190
|
The `Reads` step supports multiple read operation types:
|
|
@@ -170,6 +246,7 @@ import {
|
|
|
170
246
|
createSimulationSession,
|
|
171
247
|
submitSimulationSteps,
|
|
172
248
|
getSimulationResult,
|
|
249
|
+
getSimulationTip,
|
|
173
250
|
simulationBatchReads
|
|
174
251
|
} from 'stxer';
|
|
175
252
|
|
|
@@ -188,18 +265,25 @@ const stepResults = await submitSimulationSteps(sessionId, {
|
|
|
188
265
|
{ DataVar: ['SP...contract', 'my-var'] },
|
|
189
266
|
{ StxBalance: 'SP...' }
|
|
190
267
|
]},
|
|
191
|
-
{ TenureExtend:
|
|
268
|
+
{ TenureExtend: { cause: 'Extended' } },
|
|
269
|
+
{ AdvanceBlocks: { bitcoin_blocks: 1, stacks_blocks_per_bitcoin: 1 } }
|
|
192
270
|
]
|
|
193
271
|
});
|
|
194
272
|
|
|
195
273
|
console.log(`Executed ${stepResults.steps.length} steps`);
|
|
196
274
|
|
|
197
|
-
// 3.
|
|
275
|
+
// 3. Inspect the current tip — `synthetic` flips to `true` once
|
|
276
|
+
// `AdvanceBlocks` has run; `vrf_seed` and `tenure_change` are
|
|
277
|
+
// populated only on synthetic tips.
|
|
278
|
+
const tip = await getSimulationTip(sessionId);
|
|
279
|
+
console.log(tip.synthetic, tip.stacks_height, tip.burn_height);
|
|
280
|
+
|
|
281
|
+
// 4. Get full simulation results
|
|
198
282
|
const result = await getSimulationResult(sessionId);
|
|
199
283
|
console.log(result.metadata);
|
|
200
284
|
console.log(result.steps);
|
|
201
285
|
|
|
202
|
-
//
|
|
286
|
+
// 5. Batch reads from simulation state
|
|
203
287
|
const reads = await simulationBatchReads(sessionId, {
|
|
204
288
|
vars: [['SP...contract', 'my-var']],
|
|
205
289
|
maps: [['SP...contract', 'my-map', '0x...']],
|
|
@@ -286,7 +370,7 @@ console.log(ast.abi);
|
|
|
286
370
|
const parsed = await parseContract({
|
|
287
371
|
contractId: 'SP...contract-name',
|
|
288
372
|
sourceCode: '(define-public (hello) (ok "world"))',
|
|
289
|
-
clarityVersion: '4', // Optional: '1' | '2' | '3' | '4'
|
|
373
|
+
clarityVersion: '4', // Optional: '1' | '2' | '3' | '4' | '5' | '6'
|
|
290
374
|
epoch: 'Epoch33' // Optional
|
|
291
375
|
});
|
|
292
376
|
```
|
|
@@ -460,7 +544,15 @@ const ast = await getContractAST({
|
|
|
460
544
|
|
|
461
545
|
## Samples
|
|
462
546
|
|
|
463
|
-
Runnable end-to-end examples live in
|
|
547
|
+
Runnable end-to-end examples live in
|
|
548
|
+
[`src/sample/`](https://github.com/stxer/stxer-sdk/tree/master/src/sample)
|
|
549
|
+
on GitHub. **The `src/sample/` directory is intentionally excluded from
|
|
550
|
+
the published npm tarball** to keep the package size down — clone the
|
|
551
|
+
repo to run them locally. Samples track `master` and may evolve faster
|
|
552
|
+
than published SDK versions; if you pin a specific SDK version, browse
|
|
553
|
+
the matching git tag.
|
|
554
|
+
|
|
555
|
+
### Core flows
|
|
464
556
|
|
|
465
557
|
| Sample | What it demonstrates |
|
|
466
558
|
|---|---|
|
|
@@ -472,72 +564,161 @@ Runnable end-to-end examples live in [`src/sample/`](https://github.com/stxer/st
|
|
|
472
564
|
| [`verify-types.ts`](https://github.com/stxer/stxer-sdk/blob/master/src/sample/verify-types.ts) | Runtime type-drift detector. Hits every endpoint, dereferences every documented field, asserts each value's runtime type matches the declared SDK type. Run it before publishing your client after upstream changes. |
|
|
473
565
|
| [`read.ts`](https://github.com/stxer/stxer-sdk/blob/master/src/sample/read.ts) | `batchRead`, `BatchProcessor`, and the high-level `clarity-api` helpers (`callReadonly`, `readVariable`, `readMap`). |
|
|
474
566
|
|
|
567
|
+
### `AdvanceBlocks` + bridge / time-locked scenarios (0.8.0)
|
|
568
|
+
|
|
569
|
+
The vitest demos below are the canonical reference for the new
|
|
570
|
+
`addAdvanceBlocks` / `getSimulationTip` / `bitcoin.ts` / `sim-helpers`
|
|
571
|
+
patterns. All target real **mainnet** contracts at pinned settled
|
|
572
|
+
blocks — every assertion is exact.
|
|
573
|
+
|
|
574
|
+
| Sample | What it demonstrates |
|
|
575
|
+
|---|---|
|
|
576
|
+
| [`locked-stx-vitest.test.ts`](https://github.com/stxer/stxer-sdk/blob/master/src/sample/locked-stx-vitest.test.ts) | PoX-4 locked-STX unlock: read `(stx-account ...)`, attempt pre-unlock transfer (`err u1`), `addAdvanceBlocks` past `unlock_height`, transfer the now-released amount. Includes the parent-burn-probe trick (advance with `bitcoin_blocks: 0` first to learn the parent burn height before computing N). |
|
|
577
|
+
| [`sbtc-deposit-vitest.test.ts`](https://github.com/stxer/stxer-sdk/blob/master/src/sample/sbtc-deposit-vitest.test.ts) | sBTC bridge deposit, end-to-end. Uses `forgeBitcoinTx` + `AdvanceBlocks { burn_header_hashes: ... }` so `(get-burn-block-info? header-hash …)` resolves to a value we control. |
|
|
578
|
+
| [`brotocol-pegin-vitest.test.ts`](https://github.com/stxer/stxer-sdk/blob/master/src/sample/brotocol-pegin-vitest.test.ts) | Brotocol BTC peg-in. Forges a Bitcoin tx + 2-tx Merkle proof + 80-byte block header; calls `finalize-peg-in-0`; asserts mint and replay rejection. The full `bitcoin.ts` SPV pipeline. |
|
|
579
|
+
| [`hbtc-vault-vitest.test.ts`](https://github.com/stxer/stxer-sdk/blob/master/src/sample/hbtc-vault-vitest.test.ts) | hBTC yield-bearing vault: deposit, request-redeem, `AdvanceBlocks +1 day` to cross the rewarder window, `log-reward`, fund-claim, `AdvanceBlocks +3 days` to clear the cooldown, redeem, transfer. Exact yield arithmetic. |
|
|
580
|
+
| [`zest-borrow-vitest.test.ts`](https://github.com/stxer/stxer-sdk/blob/master/src/sample/zest-borrow-vitest.test.ts) | Zest V2 lend / borrow / repay with a forged Pyth v4 price update. Patches `pyth-pnau-decoder-v3` via `SetContractCode` to bypass the Wormhole quorum / Merkle / data-source checks; `AdvanceBlocks +1` so storage's freshness gate has a synthetic-tip block_time. |
|
|
581
|
+
| [`granite-leverage-vitest.test.ts`](https://github.com/stxer/stxer-sdk/blob/master/src/sample/granite-leverage-vitest.test.ts) | Granite leverage open with a forged Pyth v3 price update. Same patch-decoder pattern as Zest, applied through Granite's gl-api → gl-oracle → pyth-oracle-v3 chain. |
|
|
582
|
+
|
|
475
583
|
Run any of them locally by cloning the SDK repo and:
|
|
476
584
|
|
|
477
585
|
```bash
|
|
478
586
|
pnpm install
|
|
479
587
|
pnpm sample:counter # or sample:instant / failure-modes / batch-categories / verify-types
|
|
480
|
-
pnpm sample:vitest # run the Vitest
|
|
588
|
+
pnpm sample:vitest # run the Vitest sample suite (counter + 6 bridge / locked-STX demos)
|
|
481
589
|
```
|
|
482
590
|
|
|
483
591
|
## API Reference
|
|
484
592
|
|
|
485
593
|
### Constants
|
|
486
594
|
|
|
487
|
-
- `STXER_API_MAINNET`
|
|
488
|
-
- `STXER_API_TESTNET`
|
|
489
|
-
- `DEFAULT_STXER_API`
|
|
595
|
+
- `STXER_API_MAINNET` — Mainnet API endpoint (`https://api.stxer.xyz`)
|
|
596
|
+
- `STXER_API_TESTNET` — Testnet API endpoint (`https://testnet-api.stxer.xyz`)
|
|
597
|
+
- `DEFAULT_STXER_API` — Default API endpoint (same as `STXER_API_MAINNET`)
|
|
490
598
|
|
|
491
|
-
### Simulation Builder (
|
|
599
|
+
### Simulation Builder (high-level)
|
|
492
600
|
|
|
493
|
-
- `SimulationBuilder.new(options)`
|
|
494
|
-
- `builder.useBlockHeight(height)`
|
|
495
|
-
- `builder.withSender(address)`
|
|
601
|
+
- `SimulationBuilder.new(options)` — Create a new simulation builder
|
|
602
|
+
- `builder.useBlockHeight(height)` — Pin the parent block to fork at
|
|
603
|
+
- `builder.withSender(address)` — Default sender address for unsigned txs
|
|
496
604
|
|
|
497
605
|
**Transaction Steps:**
|
|
498
|
-
- `builder.addContractCall(params)`
|
|
499
|
-
- `builder.addSTXTransfer(params)`
|
|
500
|
-
- `builder.addContractDeploy(params)`
|
|
606
|
+
- `builder.addContractCall(params)` — Add a contract call step
|
|
607
|
+
- `builder.addSTXTransfer(params)` — Add an STX transfer step
|
|
608
|
+
- `builder.addContractDeploy(params)` — Add a contract deployment step
|
|
501
609
|
|
|
502
610
|
**V2 Step Types:**
|
|
503
|
-
- `builder.addEvalCode(contractId, code)`
|
|
504
|
-
- `builder.addSetContractCode(params)`
|
|
505
|
-
- `builder.addReads(reads[])`
|
|
506
|
-
- `builder.addTenureExtend()`
|
|
611
|
+
- `builder.addEvalCode(contractId, code)` — Arbitrary code evaluation with write access
|
|
612
|
+
- `builder.addSetContractCode(params)` — Replace contract code without a transaction
|
|
613
|
+
- `builder.addReads(reads[])` — Batch read operations interleaved with other steps
|
|
614
|
+
- `builder.addTenureExtend(cause?)` — Reset execution cost. Default `'Extended'` resets all dimensions; pass an explicit `TenureExtendCause` to reset only one SIP-034 dimension
|
|
615
|
+
- `builder.addAdvanceBlocks(request)` — *(0.8.0)* Synthesize bitcoin / stacks blocks on the fork. See the [`AdvanceBlocks` section](#advanceblocks-burn-block-scenarios)
|
|
507
616
|
|
|
508
617
|
**Execution:**
|
|
509
|
-
- `builder.run()`
|
|
510
|
-
|
|
511
|
-
### Programmatic
|
|
512
|
-
|
|
513
|
-
**Instant
|
|
514
|
-
- `instantSimulation(request, options?)`
|
|
515
|
-
|
|
516
|
-
**Session
|
|
517
|
-
- `createSimulationSession(options?, apiOptions?)`
|
|
518
|
-
- `submitSimulationSteps(sessionId, request, options?)`
|
|
519
|
-
- `getSimulationResult(sessionId, options?)`
|
|
520
|
-
- `
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
- `
|
|
618
|
+
- `builder.run()` — Submit the session and return the `simulation_id`. Note: returns only the id; if you need typed per-step results, use the low-level API + `sim-helpers` instead
|
|
619
|
+
|
|
620
|
+
### Programmatic simulation APIs (low-level)
|
|
621
|
+
|
|
622
|
+
**Instant simulation:**
|
|
623
|
+
- `instantSimulation(request, options?)` — Simulate a single transaction without a session. Transient: **no debug tracing**, not viewable in the stxer UI
|
|
624
|
+
|
|
625
|
+
**Session management:**
|
|
626
|
+
- `createSimulationSession(options?, apiOptions?)` — Create a new session, returns `id: string`
|
|
627
|
+
- `submitSimulationSteps(sessionId, request, options?)` — Submit one or more steps; returns typed per-step results
|
|
628
|
+
- `getSimulationResult(sessionId, options?)` — Get full session results (metadata + step summaries)
|
|
629
|
+
- `getSimulationTip(sessionId, options?)` — *(0.8.0)* Read the current synthetic tip after `AdvanceBlocks` steps. See the [`AdvanceBlocks` section](#advanceblocks-burn-block-scenarios)
|
|
630
|
+
- `simulationBatchReads(sessionId, request, options?)` — Batch-read the session's forked state without consuming a step slot
|
|
631
|
+
|
|
632
|
+
**Errors:**
|
|
633
|
+
- `class SimulationError extends Error` — *(0.8.0)* Typed error thrown by every fetch wrapper. Fields:
|
|
634
|
+
- `.status: number` — HTTP status (409 retry, 410 start-new-session, 400 validation, 404 not found, ...)
|
|
635
|
+
- `.marker: 'simulation_busy' | 'simulation_outdated' | null` — server-side classification
|
|
636
|
+
- `.body: string` — raw upstream message
|
|
637
|
+
- `.message: string` — formatted as `"${operation} (HTTP ${status}): ${body}"`
|
|
638
|
+
- `type SimulationErrorMarker` — *(0.8.0)* Exported union for `.marker`
|
|
639
|
+
|
|
640
|
+
### Sim helpers (`callContract`, `getStxBalance`, `getFtBalance`, `getNonce`, `readDataVar`)
|
|
641
|
+
|
|
642
|
+
*New in 0.8.0.* Session-bound wrappers around `simulationBatchReads`
|
|
643
|
+
that produce typed reads without hand-rolling the batch envelope. Useful
|
|
644
|
+
for vitest-style tests that interleave reads with mutating steps.
|
|
645
|
+
|
|
646
|
+
- `callContract(sessionId, args, options?)` — Build an unsigned contract-call tx, submit it as one step, decode the result. Returns `{ result, vmError, pcAborted, events, txid, executionCost }` for direct `expect(...)` assertions
|
|
647
|
+
- `getStxBalance(sessionId, principal, options?): Promise<bigint>`
|
|
648
|
+
- `getFtBalance(sessionId, contractAndToken, principal, options?): Promise<bigint>`
|
|
649
|
+
- `getNonce(sessionId, principal, options?): Promise<bigint>` — session-bound (do not confuse with the Hiro-API `getOnChainNonce` in `src/sample/_helpers.ts`)
|
|
650
|
+
- `readDataVar(sessionId, contractId, varName, options?)` — Returns the deserialized Clarity value
|
|
651
|
+
- `parseSimulationEvent(eventJson)` — Parse one entry from `TransactionReceipt.events[]` into a typed `SimulationEvent`
|
|
652
|
+
|
|
653
|
+
### Transaction builders
|
|
654
|
+
|
|
655
|
+
*New in 0.8.0.* Build unsigned transaction hex without `SimulationBuilder`
|
|
656
|
+
— useful when you want to control sender via the simulator's
|
|
657
|
+
no-signature trust model.
|
|
658
|
+
|
|
659
|
+
- `setSender(tx, sender)` — Rewrite an unsigned `StacksTransactionWire`'s spending condition so the simulator treats `sender` as the origin. Mutates and returns `tx`
|
|
660
|
+
- `buildUnsignedContractCallHex(args)` — `args: { sender, contract, functionName, functionArgs, fee?, nonce? }` → hex string
|
|
661
|
+
- `ftPrincipal(contractAndToken: 'SP....contract::token-name'): ClarityValue` — Build a `(contract-of (use-trait <ft-trait>))` literal for FT contract calls
|
|
662
|
+
|
|
663
|
+
### Bitcoin SPV / bridge primitives
|
|
664
|
+
|
|
665
|
+
*New in 0.8.0.* Forge Bitcoin transactions and SPV proofs for bridge
|
|
666
|
+
peg-in scenarios. Pairs with `addAdvanceBlocks`'
|
|
667
|
+
`burn_header_hashes` override so on-chain
|
|
668
|
+
`(get-burn-block-info? header-hash …)` resolves to a value you control.
|
|
669
|
+
|
|
670
|
+
- `forgeBitcoinTx(opts)` — Build a Bitcoin tx with chosen inputs / outputs / OP_RETURN. Returns `{ rawTx, txid, inputs, outputs }`
|
|
671
|
+
- `buildBitcoinHeader(opts)` — 80-byte BTC block header with chosen prev-hash / merkle root / time / bits / nonce. Returns `{ rawHeader, hash }` where `hash` is the double-sha256 (display order, ready for `burn_header_hashes`)
|
|
672
|
+
- `singleTxMerkleRoot(txid: Uint8Array): Uint8Array` — 1-tx merkle root (the txid itself)
|
|
673
|
+
- `merkleProof(txids, txIndex): { hashes: Uint8Array[], treeDepth: number }`
|
|
674
|
+
- `verifyMerkleProof(txid, proof, root): boolean`
|
|
675
|
+
- `p2wpkhScript(pubKeyHash20)` / `p2pkhScript(pubKeyHash20)` / `opReturnScript(data)` — scriptPubKey builders
|
|
676
|
+
- `sha256(data)` / `sha256d(data)` / `hexToBytes(s)` / `bytesToHex(b)`
|
|
677
|
+
|
|
678
|
+
### `AdvanceBlocks` (burn-block scenarios)
|
|
679
|
+
|
|
680
|
+
*New in 0.8.0.* Synthesize bitcoin / stacks blocks on top of the
|
|
681
|
+
simulation's pinned parent tip — used to model burn-block / tenure
|
|
682
|
+
boundaries (PoX cycles, locked-STX unlock, time-locked redemptions,
|
|
683
|
+
bridge contract finalization).
|
|
684
|
+
|
|
685
|
+
- `builder.addAdvanceBlocks(request)` — builder method
|
|
686
|
+
- `submitSimulationSteps(id, { steps: [{ AdvanceBlocks: ... }] }, opts)` — raw step
|
|
687
|
+
- `getSimulationTip(id, opts?)` — read the current synthetic tip; `synthetic: true` after at least one `AdvanceBlocks` step has run
|
|
688
|
+
- `AdvanceBlocksRequest` (key fields):
|
|
689
|
+
- `bitcoin_blocks: number` — burn blocks to synthesize
|
|
690
|
+
- `stacks_blocks_per_bitcoin: number`
|
|
691
|
+
- `bitcoin_interval_secs?: U64` — burn-block-time delta; defaults to 600s
|
|
692
|
+
- `burn_header_hashes?: Record<string, string>` — per-burn-index hash override (32-byte hex), keyed by 0-based index
|
|
693
|
+
- `pox_addrs?: Record<string, [PoxAddrInput[], U128]>` — per-burn-index PoX-payout override
|
|
694
|
+
- `vrf_seeds?: Record<string, string>` — per-burn-index VRF-seed override
|
|
695
|
+
|
|
696
|
+
For the canonical worked examples — including the parent-burn-probe
|
|
697
|
+
trick for computing N, the `burn_header_hashes` + Merkle-proof bridge
|
|
698
|
+
pattern, and the `SetContractCode` + `AdvanceBlocks` Pyth-decoder
|
|
699
|
+
pattern — see the
|
|
700
|
+
[bridge / time-locked vitest demos](#advanceblocks--bridge--time-locked-scenarios-080)
|
|
701
|
+
on GitHub.
|
|
702
|
+
|
|
703
|
+
### Chain tip
|
|
704
|
+
|
|
705
|
+
- `getTip(options?)` — Global mainnet chain tip (sidecar). Distinct from `getSimulationTip` (per-session synthetic tip)
|
|
525
706
|
|
|
526
707
|
### Contract AST
|
|
527
708
|
|
|
528
|
-
- `getContractAST({ contractId, stxerApi? })`
|
|
529
|
-
- `parseContract({ sourceCode, contractId, clarityVersion?, epoch?, stxerApi? })`
|
|
709
|
+
- `getContractAST({ contractId, stxerApi? })` — Fetch on-chain contract AST
|
|
710
|
+
- `parseContract({ sourceCode, contractId, clarityVersion?, epoch?, stxerApi? })` — Parse source code to AST. `clarityVersion` is `ClarityVersionName` (`'Clarity1' | ... | 'Clarity6'`) — distinct from `@stacks/transactions`'s numeric `ClarityVersion` enum
|
|
530
711
|
|
|
531
|
-
### Batch
|
|
712
|
+
### Batch operations
|
|
532
713
|
|
|
533
|
-
- `batchRead(reads, options?)`
|
|
534
|
-
- `new BatchProcessor({ stxerAPIEndpoint?, batchDelayMs })` -
|
|
714
|
+
- `batchRead(reads, options?)` — Execute batch read operations against current chain state via the sidecar
|
|
715
|
+
- `new BatchProcessor({ stxerAPIEndpoint?, batchDelayMs })` — Queue-based batch processor for high-throughput read pipelines
|
|
535
716
|
|
|
536
717
|
### Clarity API
|
|
537
718
|
|
|
538
|
-
- `callReadonly(params)`
|
|
539
|
-
- `readVariable(params)`
|
|
540
|
-
- `readMap(params)`
|
|
719
|
+
- `callReadonly(params)` — Call a read-only contract function
|
|
720
|
+
- `readVariable(params)` — Read a contract variable
|
|
721
|
+
- `readMap(params)` — Read from a contract map
|
|
541
722
|
|
|
542
723
|
## Support
|
|
543
724
|
|
package/dist/ast.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export declare function getContractAST(options: GetContractAstOptions): Promise<
|
|
|
20
20
|
export interface ParseContractOptions extends AstOptions {
|
|
21
21
|
sourceCode: string;
|
|
22
22
|
contractId: string;
|
|
23
|
-
clarityVersion?: '1' | '2' | '3' | '4';
|
|
23
|
+
clarityVersion?: '1' | '2' | '3' | '4' | '5' | '6';
|
|
24
24
|
epoch?: ClarityEpoch;
|
|
25
25
|
}
|
|
26
26
|
/**
|