@hazbase/simplicity 0.0.5 → 0.2.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 (61) hide show
  1. package/README.md +140 -1038
  2. package/dist/cli.js +3341 -269
  3. package/dist/client/SimplicityClient.d.ts +91 -290
  4. package/dist/client/SimplicityClient.js +93 -23
  5. package/dist/core/executor.js +67 -92
  6. package/dist/core/lineage.d.ts +18 -0
  7. package/dist/core/lineage.js +30 -0
  8. package/dist/core/outputBinding.d.ts +61 -0
  9. package/dist/core/outputBinding.js +552 -0
  10. package/dist/core/reporting.d.ts +22 -0
  11. package/dist/core/reporting.js +40 -0
  12. package/dist/core/schnorr.d.ts +5 -0
  13. package/dist/core/schnorr.js +46 -0
  14. package/dist/core/types.d.ts +799 -1
  15. package/dist/docs/definitions/bond-anchor.simf +19 -0
  16. package/dist/docs/definitions/bond-definition.json +10 -0
  17. package/dist/docs/definitions/bond-descriptor-bound-settlement-machine.simf +144 -0
  18. package/dist/docs/definitions/bond-issuance-anchor.simf +26 -0
  19. package/dist/docs/definitions/bond-issuance-state-partial-redemption.json +18 -0
  20. package/dist/docs/definitions/bond-issuance-state-redeemed.json +18 -0
  21. package/dist/docs/definitions/bond-issuance-state.json +12 -0
  22. package/dist/docs/definitions/bond-redemption-state-machine.simf +118 -0
  23. package/dist/docs/definitions/bond-redemption-transition.simf +41 -0
  24. package/dist/docs/definitions/bond-script-bound-settlement-machine.simf +142 -0
  25. package/dist/docs/definitions/fund-capital-call-open.simf +82 -0
  26. package/dist/docs/definitions/fund-capital-call-refund-only.simf +67 -0
  27. package/dist/docs/definitions/fund-capital-call-state.json +11 -0
  28. package/dist/docs/definitions/fund-definition.json +8 -0
  29. package/dist/docs/definitions/fund-distribution-claim.simf +57 -0
  30. package/dist/docs/definitions/receivable-definition.json +9 -0
  31. package/dist/docs/definitions/receivable-funding-claim.json +13 -0
  32. package/dist/docs/definitions/receivable-funding-claim.simf +58 -0
  33. package/dist/docs/definitions/receivable-repayment-claim.json +13 -0
  34. package/dist/docs/definitions/receivable-repayment-claim.simf +59 -0
  35. package/dist/docs/definitions/receivable-state-funded.json +20 -0
  36. package/dist/docs/definitions/receivable-state-originated.json +19 -0
  37. package/dist/docs/definitions/receivable-state-repaid.json +20 -0
  38. package/dist/docs/definitions/recursive-delay-direct-next.simf +60 -0
  39. package/dist/docs/definitions/recursive-delay-optional.simf +88 -0
  40. package/dist/docs/definitions/recursive-delay-required.simf +72 -0
  41. package/dist/docs/definitions/recursive-delay.simf +83 -0
  42. package/dist/docs/definitions/recursive-policy-transfer-machine.simf +65 -0
  43. package/dist/domain/bond.d.ts +8649 -720
  44. package/dist/domain/bond.js +1398 -8
  45. package/dist/domain/bondSettlementValidation.d.ts +2 -0
  46. package/dist/domain/bondSettlementValidation.js +28 -0
  47. package/dist/domain/bondValidation.d.ts +37 -1
  48. package/dist/domain/bondValidation.js +137 -11
  49. package/dist/domain/fund.d.ts +2452 -0
  50. package/dist/domain/fund.js +1756 -0
  51. package/dist/domain/fundValidation.d.ts +152 -0
  52. package/dist/domain/fundValidation.js +767 -0
  53. package/dist/domain/policies.d.ts +1064 -0
  54. package/dist/domain/policies.js +1625 -0
  55. package/dist/domain/receivable.d.ts +824 -0
  56. package/dist/domain/receivable.js +1375 -0
  57. package/dist/domain/receivableValidation.d.ts +147 -0
  58. package/dist/domain/receivableValidation.js +831 -0
  59. package/dist/index.d.ts +8 -2
  60. package/dist/index.js +137 -21
  61. package/package.json +20 -2
package/README.md CHANGED
@@ -2,385 +2,48 @@
2
2
  [![npm version](https://badge.fury.io/js/@hazbase%2Fsimplicity.svg)](https://badge.fury.io/js/@hazbase%2Fsimplicity)
3
3
  [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
4
4
 
5
- `@hazbase/simplicity` is a Node.js / TypeScript SDK for working with Simplicity contracts on Liquid with an EVM-like developer workflow. It lets you compile SimplicityHL (`.simf`) contracts, derive the contract address, fund that address, inspect the spend you are about to make, execute the contract, and optionally run fee-sponsored flows through a sponsor wallet or relayer. It also ships with built-in presets so you can start from known-good contract templates before moving to custom `.simf` code.
5
+ ## What This SDK Is
6
6
 
7
- This SDK is designed to help Node developers get productive quickly, but it is still opinionated and early-stage:
8
- - SimplicityHL is still upstream work-in-progress and is not production-ready.
9
- - This SDK currently optimizes for explicit / unblinded success paths first.
10
- - Gasless support exists, but it comes in multiple modes with different tradeoffs.
7
+ `@hazbase/simplicity` is a Node.js / TypeScript SDK for building and validating Simplicity-based flows on Liquid.
11
8
 
12
- Consumer validation note:
13
- - The published npm package has been validated from a fresh external Node.js project using `npm install @hazbase/simplicity`.
14
- - Verified flows include preset-based contract execution, custom `.simf` execution, and relayer-backed gasless execution on `liquidtestnet`.
9
+ Today, the SDK is best understood as a **permissioned settlement / lineage / finality toolkit**. It helps developers compile and fund Simplicity contracts, execute constrained payouts, verify off-chain definitions and state documents, and export evidence or finality payloads for higher-level review.
15
10
 
16
- ## Validated Scenarios
11
+ It is intentionally narrower than a full market stack. It does **not** try to be a full investor registry, KYC/AML system, fund-admin platform, market-ops layer, or open retail trading protocol.
17
12
 
18
- The published package has been exercised from a blank external consumer project. For the full reproducible fixture, see [docs/consumer-validation/README.md](./docs/consumer-validation/README.md).
13
+ This SDK is designed to help Node developers get productive quickly, but it is still opinionated, early-stage, and best suited today to permissioned settlement pilots on Liquid.
19
14
 
20
- | Scenario | Status | Notes |
21
- | --- | --- | --- |
22
- | Fresh install + JS import | Success | `npm install @hazbase/simplicity` and `import { createSimplicityClient } from "@hazbase/simplicity"` both worked |
23
- | CLI smoke | Success | `npx simplicity-cli presets list` worked from the external project |
24
- | Preset flow (`p2pkLockHeight`) | Success | compile -> fund -> inspect -> execute(`broadcast=true`) |
25
- | Custom `.simf` flow | Success | `compileFromFile(...)` -> fund -> inspect -> execute(`broadcast=true`) |
26
- | Relayer-backed gasless flow | Success | `executeGasless(...)` succeeded from the external project |
15
+ ## What You Can Build
27
16
 
28
- ## Who This Is For
17
+ With the current public SDK you can build and test:
18
+ - constrained transfers with explicit next-hop rules
19
+ - output binding with public support/fallback reporting
20
+ - bond redemption / settlement / close-out flows
21
+ - LP fund capital call / distribution / close-out flows
22
+ - receivable repayment-first funding / repayment / closing flows
23
+ - evidence, trust summary, lineage, and finality exports
29
24
 
30
- This README is for you if:
31
- - you are comfortable with Node.js / TypeScript,
32
- - you want to experiment with Simplicity on Liquid without building everything from scratch,
33
- - you want a clear path from `compile` to `fund` to `inspect` to `execute`,
34
- - you want to understand how presets, custom contracts, witnesses, and gasless execution fit together.
25
+ ## Public Architecture
35
26
 
36
- This README is not assuming you already know Simplicity well. It will explain the model first, then show the happy path, then move into advanced topics.
27
+ The public SDK is organized into five layers:
28
+ - `sdk.outputBinding`: shared output-binding support, evaluation, and fallback behavior
29
+ - `sdk.policies`: generic constrained transfer and recursive policy engine
30
+ - `sdk.bonds`: private bond / credit settlement business layer
31
+ - `sdk.funds`: LP fund settlement business layer
32
+ - `sdk.receivables`: repayment-first receivable business layer
37
33
 
38
- ## Mental Model First
34
+ A useful mental model is:
35
+ - `sdk.outputBinding` + `sdk.policies` provide the shared settlement kernel
36
+ - `sdk.bonds`, `sdk.funds`, and `sdk.receivables` build domain flows on top of that kernel
39
37
 
40
- Before touching the API, it helps to anchor on how Simplicity on Liquid differs from an EVM contract.
38
+ ## Quickstart
41
39
 
42
- - A **Simplicity contract** is a spend condition that can be tied to a contract address.
43
- - **Deploying** a contract is not a separate bytecode deployment transaction. In practice, you compile the contract, get its derived address, and fund that address with a UTXO.
44
- - An **artifact** is the compile output plus the metadata you need later to inspect and execute that contract again.
45
- - **Executing** a contract means consuming the contract UTXO and building a new transaction that satisfies the contract's witness rules.
46
- - **Inspecting** a contract call means building the spend first and reviewing what will happen before broadcasting.
47
- - **Gasless** means the fee is paid by a sponsor wallet or relayer instead of by the contract caller directly.
48
-
49
- If you come from Ethereum, a helpful translation is:
50
- - EVM `deploy contract` -> Simplicity `compile contract and fund its address`
51
- - EVM `call contract` -> Simplicity `spend a contract UTXO with the correct witness`
52
- - EVM `transaction preview / wallet confirmation` -> Simplicity `inspectCall()` / summary hash review
53
-
54
- ## What You Can Build With This SDK
55
-
56
- With the current SDK you can build and test flows such as:
57
- - single-sig contract spends,
58
- - single-sig spends gated by block height,
59
- - HTLC-style contracts,
60
- - cooperative transfer with unilateral timeout recovery,
61
- - relayer-backed fee-sponsored contract execution,
62
- - custom `.simf` contract workflows driven from TypeScript or CLI.
63
-
64
- You can also design more advanced systems such as ERC20-like token behavior, but the model is different from Ethereum. On Liquid/Simplicity, you usually represent state transitions as UTXO transitions instead of account storage updates. So the SDK can support that kind of application, but it does not mean you port Solidity account logic 1:1.
65
-
66
- ## Trusted Definition JSON
67
-
68
- When your contract depends on off-chain business metadata such as a bond definition, coupon schedule, note terms, or asset terms, you usually do not want to trust a plain JSON file by itself. This SDK now supports a **hash-anchor** model for definition JSON.
69
-
70
- What that means:
71
- - the SDK canonicalizes the JSON using stable key ordering,
72
- - computes `sha256(canonicalJson)`,
73
- - stores that hash in the artifact as a definition anchor,
74
- - injects `DEFINITION_HASH` and `DEFINITION_ID` into compile-time template vars when a definition is provided,
75
- - lets you verify later that the JSON you are reading still matches the contract/artifact it was compiled against.
76
-
77
- There are now two anchor modes:
78
- - `artifact-hash-anchor`: the JSON hash is anchored in the artifact and verified later against that artifact.
79
- - `on-chain-constant-committed`: the JSON hash is anchored in the artifact and also committed into executed contract logic, so it materially affects the compiled program, CMR, and contract address.
80
-
81
- Today, `on-chain-constant-committed` is guaranteed for custom `.simf` contracts that include the blessed `require_definition_anchor()` helper pattern. Built-in presets still default to artifact-only anchors for now.
82
- The SDK does **not** trust artifact JSON alone for this verdict. `trust.onChainAnchorVerified` only becomes `true` when the SDK can read the source file again and re-detect the blessed helper pattern. If the source file is unavailable, the claimed mode may still be `on-chain-constant-committed`, but `onChainAnchorVerified` will remain `false`.
83
-
84
- Minimal TypeScript flow:
85
-
86
- ```ts
87
- const definition = await sdk.loadDefinition({
88
- type: "bond",
89
- id: "BOND-2026-001",
90
- jsonPath: "./docs/definitions/bond-definition.json",
91
- });
92
-
93
- const compiled = await sdk.compileFromFile({
94
- simfPath: "./docs/definitions/bond-anchor.simf",
95
- templateVars: {
96
- MIN_HEIGHT: 2344430,
97
- SIGNER_XONLY: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
98
- },
99
- definition: {
100
- type: definition.definitionType,
101
- id: definition.definitionId,
102
- schemaVersion: definition.schemaVersion,
103
- jsonPath: definition.sourcePath,
104
- anchorMode: "on-chain-constant-committed",
105
- },
106
- artifactPath: "./bond.artifact.json",
107
- });
108
-
109
- const verification = await sdk.verifyDefinitionAgainstArtifact({
110
- artifactPath: "./bond.artifact.json",
111
- jsonPath: "./docs/definitions/bond-definition.json",
112
- type: "bond",
113
- id: "BOND-2026-001",
114
- });
115
-
116
- console.log(verification.ok);
117
- console.log(verification.trust.effectiveMode);
118
- ```
119
-
120
- CLI equivalents:
121
-
122
- ```bash
123
- simplicity-cli definition show \
124
- --type bond \
125
- --id BOND-2026-001 \
126
- --json-path ./docs/definitions/bond-definition.json
127
-
128
- simplicity-cli definition verify \
129
- --artifact ./bond.artifact.json \
130
- --type bond \
131
- --id BOND-2026-001 \
132
- --json-path ./docs/definitions/bond-definition.json
133
- ```
134
-
135
- For a bond-oriented walkthrough, see [docs/definitions/README.md](./docs/definitions/README.md).
136
-
137
- ## Trusted Issuance State JSON
138
-
139
- The same hash-anchor model now also applies to issuance state documents such as a bond issuance record.
140
-
141
- This is useful when you want to say not only:
142
-
143
- - "these are the bond terms,"
144
-
145
- but also:
146
-
147
- - "this bond was issued in this amount, with this outstanding principal, under this controller."
148
-
149
- The SDK now supports:
150
-
151
- - loading and hashing a state JSON with `sdk.loadStateDocument(...)`,
152
- - storing its hash in the artifact,
153
- - committing `STATE_HASH` into custom `.simf` contract logic,
154
- - verifying later that the issuance state JSON still matches the compiled contract.
155
-
156
- For Bond issuance, the recommended shape is:
157
-
158
- ```json
159
- {
160
- "issuanceId": "BOND-2026-001-ISSUE-1",
161
- "bondId": "BOND-2026-001",
162
- "issuerEntityId": "hazbase-treasury",
163
- "issuedPrincipal": 1000000,
164
- "outstandingPrincipal": 1000000,
165
- "redeemedPrincipal": 0,
166
- "currencyAssetId": "bitcoin",
167
- "controllerXonly": "<xonly>",
168
- "issuedAt": "2026-03-10T00:00:00Z",
169
- "status": "ISSUED"
170
- }
171
- ```
172
-
173
- To move from an issued bond into a redemption state, the SDK now also supports a minimal state transition model:
174
-
175
- - `ISSUED -> PARTIALLY_REDEEMED`
176
- - `ISSUED/PARTIALLY_REDEEMED -> REDEEMED`
177
-
178
- The next state records:
179
-
180
- - `previousStateHash`
181
- - `lastTransition.type`
182
- - `lastTransition.amount`
183
- - `lastTransition.at`
184
-
185
- and the SDK verifies the principal invariant:
186
-
187
- - `issuedPrincipal = outstandingPrincipal + redeemedPrincipal`
188
-
189
- On top of that, the SDK can now build a `BondSettlementDescriptor`, which bundles the intended settlement envelope into one canonical document:
190
-
191
- - `definitionHash`
192
- - `previousStateHash`
193
- - `nextStateHash`
194
- - `nextContractAddress`
195
- - `nextAmountSat`
196
- - `maxFeeSat`
197
- - status progression and principal deltas
198
-
199
- The redemption machine commits that settlement descriptor hash as an additional anchor. This does not yet mean full runtime output introspection, but it does mean the machine can now honestly claim a committed settlement envelope instead of just a scattered set of fields.
200
-
201
- Minimal TypeScript flow:
202
-
203
- ```ts
204
- const compiled = await sdk.bonds.defineBond({
205
- definitionPath: "./docs/definitions/bond-definition.json",
206
- issuancePath: "./docs/definitions/bond-issuance-state.json",
207
- simfPath: "./docs/definitions/bond-issuance-anchor.simf",
208
- artifactPath: "./bond-issuance.artifact.json",
209
- });
210
-
211
- const verification = await sdk.bonds.verifyBond({
212
- artifactPath: "./bond-issuance.artifact.json",
213
- definitionPath: "./docs/definitions/bond-definition.json",
214
- issuancePath: "./docs/definitions/bond-issuance-state.json",
215
- });
216
-
217
- console.log(verification.crossChecks.principalInvariantValid);
218
- console.log(verification.issuance.trust.effectiveMode);
219
- ```
220
-
221
- Minimal redemption flow:
222
-
223
- ```ts
224
- const preview = await sdk.bonds.buildBondRedemption({
225
- definitionPath: "./docs/definitions/bond-definition.json",
226
- previousIssuancePath: "./docs/definitions/bond-issuance-state.json",
227
- amount: 250000,
228
- redeemedAt: "2027-03-10T00:00:00Z",
229
- });
230
-
231
- const compiled = await sdk.bonds.redeemBond({
232
- definitionPath: "./docs/definitions/bond-definition.json",
233
- previousIssuancePath: "./docs/definitions/bond-issuance-state.json",
234
- amount: 250000,
235
- redeemedAt: "2027-03-10T00:00:00Z",
236
- simfPath: "./docs/definitions/bond-issuance-anchor.simf",
237
- artifactPath: "./bond-redemption.artifact.json",
238
- });
239
-
240
- const transition = await sdk.bonds.verifyBondTransition({
241
- previousIssuancePath: "./docs/definitions/bond-issuance-state.json",
242
- nextIssuancePath: "./docs/definitions/bond-issuance-state-partial-redemption.json",
243
- });
244
-
245
- const payload = await sdk.bonds.buildBondPayload({
246
- artifactPath: "./bond-redemption.artifact.json",
247
- definitionPath: "./docs/definitions/bond-definition.json",
248
- issuancePath: "./docs/definitions/bond-issuance-state-partial-redemption.json",
249
- });
250
-
251
- const transitionPayload = await sdk.bonds.buildBondTransitionPayload({
252
- definitionPath: "./docs/definitions/bond-definition.json",
253
- previousIssuancePath: "./docs/definitions/bond-issuance-state.json",
254
- nextIssuancePath: "./docs/definitions/bond-issuance-state-partial-redemption.json",
255
- });
256
-
257
- console.log(preview.nextHash);
258
- console.log(compiled.state()?.hash);
259
- console.log(transition.transition.statusProgressionValid);
260
- console.log(payload.payload);
261
- console.log(transitionPayload.payload.redeemAmount);
262
- ```
263
-
264
- CLI equivalents:
265
-
266
- ```bash
267
- simplicity-cli state show \
268
- --type bond-issuance \
269
- --id BOND-2026-001-ISSUE-1 \
270
- --json-path ./docs/definitions/bond-issuance-state.json
271
-
272
- simplicity-cli state verify \
273
- --artifact ./bond-issuance.artifact.json \
274
- --type bond-issuance \
275
- --id BOND-2026-001-ISSUE-1 \
276
- --json-path ./docs/definitions/bond-issuance-state.json
277
-
278
- simplicity-cli bond verify \
279
- --artifact ./bond-issuance.artifact.json \
280
- --definition-json ./docs/definitions/bond-definition.json \
281
- --issuance-json ./docs/definitions/bond-issuance-state.json
282
-
283
- simplicity-cli bond redeem \
284
- --definition-json ./docs/definitions/bond-definition.json \
285
- --previous-issuance-json ./docs/definitions/bond-issuance-state.json \
286
- --amount 250000 \
287
- --redeemed-at 2027-03-10T00:00:00Z \
288
- --simf ./docs/definitions/bond-issuance-anchor.simf \
289
- --next-issuance-out ./next-bond-issuance-state.json \
290
- --artifact ./bond-redemption.artifact.json
291
-
292
- simplicity-cli bond verify-transition \
293
- --previous-issuance-json ./docs/definitions/bond-issuance-state.json \
294
- --next-issuance-json ./docs/definitions/bond-issuance-state-partial-redemption.json
295
-
296
- simplicity-cli bond compile-transition \
297
- --definition-json ./docs/definitions/bond-definition.json \
298
- --previous-issuance-json ./docs/definitions/bond-issuance-state.json \
299
- --next-issuance-json ./docs/definitions/bond-issuance-state-partial-redemption.json \
300
- --simf ./docs/definitions/bond-redemption-transition.simf \
301
- --artifact ./bond-transition.artifact.json
302
-
303
- simplicity-cli bond compile-redemption-machine \
304
- --definition-json ./docs/definitions/bond-definition.json \
305
- --previous-issuance-json ./docs/definitions/bond-issuance-state.json \
306
- --next-issuance-json ./docs/definitions/bond-issuance-state-partial-redemption.json \
307
- --simf ./docs/definitions/bond-redemption-state-machine.simf \
308
- --artifact ./bond-redemption-machine.artifact.json
309
-
310
- simplicity-cli bond verify-machine \
311
- --artifact ./bond-redemption-machine.artifact.json \
312
- --definition-json ./docs/definitions/bond-definition.json \
313
- --previous-issuance-json ./docs/definitions/bond-issuance-state.json \
314
- --next-issuance-json ./docs/definitions/bond-issuance-state-partial-redemption.json
315
-
316
- simplicity-cli bond plan-rollover \
317
- --current-artifact ./bond-issuance.artifact.json \
318
- --definition-json ./docs/definitions/bond-definition.json \
319
- --previous-issuance-json ./docs/definitions/bond-issuance-state.json \
320
- --next-issuance-json ./docs/definitions/bond-issuance-state-partial-redemption.json \
321
- --next-simf ./docs/definitions/bond-issuance-anchor.simf \
322
- --next-artifact ./bond-next.artifact.json
323
-
324
- simplicity-cli bond plan-machine-rollover \
325
- --current-artifact ./bond-issuance.artifact.json \
326
- --definition-json ./docs/definitions/bond-definition.json \
327
- --previous-issuance-json ./docs/definitions/bond-issuance-state.json \
328
- --next-issuance-json ./docs/definitions/bond-issuance-state-partial-redemption.json \
329
- --machine-simf ./docs/definitions/bond-redemption-state-machine.simf \
330
- --machine-artifact ./bond-redemption-machine.artifact.json
331
-
332
- simplicity-cli bond transition-payload \
333
- --definition-json ./docs/definitions/bond-definition.json \
334
- --previous-issuance-json ./docs/definitions/bond-issuance-state.json \
335
- --next-issuance-json ./docs/definitions/bond-issuance-state-partial-redemption.json
336
-
337
- simplicity-cli bond payload \
338
- --artifact ./bond-redemption.artifact.json \
339
- --definition-json ./docs/definitions/bond-definition.json \
340
- --issuance-json ./docs/definitions/bond-issuance-state-partial-redemption.json
341
- ```
342
-
343
- ## Install
344
-
345
- You need three things:
346
- 1. the npm package,
347
- 2. a local Simplicity toolchain,
348
- 3. a reachable Elements / Liquid RPC endpoint.
349
-
350
- ### Package
40
+ Install the package:
351
41
 
352
42
  ```bash
353
43
  npm install @hazbase/simplicity
354
44
  ```
355
45
 
356
- ### Runtime assumptions
357
-
358
- The current SDK assumes you have access to:
359
- - `simc`
360
- - `hal-simplicity`
361
- - an Elements-compatible RPC endpoint
362
- - a wallet-enabled RPC when you want to inspect or execute spends
363
-
364
- ### Node version
365
-
366
- - Node.js `>= 20`
367
-
368
- ## Quickstart: First Working Contract
369
-
370
- This section is the shortest path to a real success case. We will:
371
- 1. create a client,
372
- 2. compile the built-in `p2pkLockHeight` preset,
373
- 3. get the contract address,
374
- 4. fund it,
375
- 5. confirm the contract UTXO exists,
376
- 6. inspect the call,
377
- 7. execute it.
378
-
379
- We use `p2pkLockHeight` first because it has a simple witness model and is the easiest way to understand how the SDK works end to end.
380
-
381
- ### Step 1: Create a client
382
-
383
- This is the main entrypoint for the SDK.
46
+ Create a client:
384
47
 
385
48
  ```ts
386
49
  import { createSimplicityClient } from "@hazbase/simplicity";
@@ -388,734 +51,173 @@ import { createSimplicityClient } from "@hazbase/simplicity";
388
51
  const sdk = createSimplicityClient({
389
52
  network: "liquidtestnet",
390
53
  rpc: {
391
- url: process.env.ELEMENTS_RPC_URL || "http://127.0.0.1:18884",
392
- username: process.env.ELEMENTS_RPC_USER || "<rpc-user>",
393
- password: process.env.ELEMENTS_RPC_PASSWORD || "<rpc-password>",
394
- wallet: process.env.ELEMENTS_RPC_WALLET || "simplicity-test",
54
+ url: process.env.ELEMENTS_RPC_URL ?? "http://127.0.0.1:18884",
55
+ username: process.env.ELEMENTS_RPC_USER ?? "<rpc-user>",
56
+ password: process.env.ELEMENTS_RPC_PASSWORD ?? "<rpc-password>",
57
+ wallet: process.env.ELEMENTS_RPC_WALLET ?? "simplicity-test",
395
58
  },
396
59
  toolchain: {
397
- simcPath: process.env.SIMC_PATH || "simc",
398
- halSimplicityPath: process.env.HAL_SIMPLICITY_PATH || "hal-simplicity",
399
- elementsCliPath: process.env.ELEMENTS_CLI_PATH || "eltc",
400
- },
401
- });
402
- ```
403
-
404
- If you are wondering whether a public RPC endpoint is enough: usually not for full execution flows. Public RPC endpoints often do not expose wallet methods such as `walletprocesspsbt`, so for real `inspect` / `execute` flows you should assume a trusted, authenticated RPC.
405
-
406
- CLI equivalent for discovery starts here:
407
-
408
- ```bash
409
- simplicity-cli presets list
410
- simplicity-cli presets show --preset p2pkLockHeight
411
- ```
412
-
413
- ### Step 2: Compile a preset
414
-
415
- Now compile the built-in preset and save an artifact.
416
-
417
- ```ts
418
- const compiled = await sdk.compileFromPreset({
419
- preset: "p2pkLockHeight",
420
- params: {
421
- MIN_HEIGHT: 2344430,
422
- SIGNER_XONLY: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
423
- },
424
- artifactPath: "./artifact.json",
425
- });
426
-
427
- console.log(compiled.deployment());
428
- ```
429
-
430
- What you get back:
431
- - a `CompiledContract`,
432
- - a deployable contract address,
433
- - the CMR,
434
- - the internal key,
435
- - an artifact you can reload later.
436
-
437
- CLI equivalent:
438
-
439
- ```bash
440
- simplicity-cli preset compile \
441
- --preset p2pkLockHeight \
442
- --param MIN_HEIGHT=2344430 \
443
- --param SIGNER_XONLY=79be... \
444
- --artifact ./artifact.json
445
- ```
446
-
447
- ### Step 3: Understand the deployment output
448
-
449
- `compiled.deployment()` tells you where to send funds and what contract you just created.
450
-
451
- The most important fields are:
452
- - `contractAddress`: where you send L-BTC to make the contract live,
453
- - `cmr`: the commitment merkle root for the compiled contract,
454
- - `internalKey`: the internal taproot key used in the address derivation.
455
-
456
- This is the point where Simplicity differs from EVM most clearly: **you are not broadcasting a separate deployment transaction here**. You are preparing a spend condition and then making it live by funding the resulting address.
457
-
458
- ### Step 4: Fund the contract
459
-
460
- Send L-BTC to the `contractAddress` from your Liquid wallet.
461
-
462
- Example with `eltc`:
463
-
464
- ```bash
465
- eltc -rpcwallet=simplicity-test sendtoaddress "<contract-address>" 0.00002
466
- ```
467
-
468
- You can then wait for the UTXO from TypeScript:
469
-
470
- ```ts
471
- const contract = compiled.at();
472
-
473
- await contract.waitForFunding({
474
- minAmountSat: 1000,
475
- pollIntervalMs: 5000,
476
- timeoutMs: 120000,
477
- });
478
- ```
479
-
480
- Or inspect the artifact status from the CLI:
481
-
482
- ```bash
483
- simplicity-cli artifact show --artifact ./artifact.json
484
- ```
485
-
486
- What `artifact show` tells you:
487
- - whether the contract is unfunded,
488
- - whether only unconfirmed UTXOs are visible,
489
- - whether it is executable,
490
- - which contract UTXOs are currently visible.
491
-
492
- The state you usually want before calling `execute` is:
493
- - `status: executable`
494
- - `ready: yes`
495
-
496
- ### Step 5: Inspect before broadcast
497
-
498
- Before broadcasting a contract spend, build it and inspect it.
499
-
500
- ```ts
501
- const inspectResult = await contract.inspectCall({
502
- wallet: "simplicity-test",
503
- toAddress: "tex1...",
504
- signer: {
505
- type: "schnorrPrivkeyHex",
506
- privkeyHex: process.env.SIMPLICITY_PRIMARY_PRIVKEY || "<primary-privkey-hex>",
507
- },
508
- });
509
-
510
- console.log(inspectResult.summaryHash);
511
- console.log(inspectResult.summary);
512
- ```
513
-
514
- Why this matters:
515
- - you see the candidate transaction before broadcasting,
516
- - you can inspect inputs, outputs, and fee behavior,
517
- - you can log or verify the `summaryHash` in higher-level applications.
518
-
519
- CLI equivalent:
520
-
521
- ```bash
522
- simplicity-cli contract inspect \
523
- --artifact ./artifact.json \
524
- --wallet simplicity-test \
525
- --privkey <primary-privkey-hex> \
526
- --to-address tex1...
527
- ```
528
-
529
- A practical rule: use `inspect` first, especially when you are still learning the contract or changing witness logic.
530
-
531
- ### Step 6: Execute
532
-
533
- Once you are satisfied with the preview, execute the spend.
534
-
535
- A safe first step is to build the final raw transaction without broadcasting:
536
-
537
- ```ts
538
- const executeResult = await contract.execute({
539
- wallet: "simplicity-test",
540
- toAddress: "tex1...",
541
- signer: {
542
- type: "schnorrPrivkeyHex",
543
- privkeyHex: process.env.SIMPLICITY_PRIMARY_PRIVKEY || "<primary-privkey-hex>",
60
+ simcPath: process.env.SIMC_PATH ?? "simc",
61
+ halSimplicityPath: process.env.HAL_SIMPLICITY_PATH ?? "hal-simplicity",
62
+ elementsCliPath: process.env.ELEMENTS_CLI_PATH ?? "eltc",
544
63
  },
545
- broadcast: false,
546
64
  });
547
65
 
548
- console.log(executeResult.rawTxHex);
66
+ console.log(sdk.policies.listTemplates());
67
+ console.log(sdk.outputBinding.describeSupport());
549
68
  ```
550
69
 
551
- Then switch to broadcast mode when you are ready:
552
-
553
- ```ts
554
- const broadcastResult = await contract.execute({
555
- wallet: "simplicity-test",
556
- toAddress: "tex1...",
557
- signer: {
558
- type: "schnorrPrivkeyHex",
559
- privkeyHex: process.env.SIMPLICITY_PRIMARY_PRIVKEY || "<primary-privkey-hex>",
560
- },
561
- broadcast: true,
562
- });
563
-
564
- console.log(broadcastResult.txId);
565
- ```
566
-
567
- CLI equivalent:
70
+ Quick CLI checks:
568
71
 
569
72
  ```bash
570
- simplicity-cli contract execute \
571
- --artifact ./artifact.json \
572
- --wallet simplicity-test \
573
- --privkey <primary-privkey-hex> \
574
- --to-address tex1... \
575
- --broadcast
576
- ```
577
-
578
- Recommended habit:
579
- 1. compile
580
- 2. fund
581
- 3. artifact check
582
- 4. inspect
583
- 5. execute with `broadcast: false`
584
- 6. execute with `broadcast: true`
585
-
586
- ## Step-by-Step Walkthrough
587
-
588
- This section explains the same flow in terms of the SDK types and responsibilities.
589
-
590
- ### Create a Client
591
-
592
- Use `createSimplicityClient(config)` to define three pieces of infrastructure:
593
- - which Liquid network you are targeting,
594
- - which RPC endpoint and wallet you will use,
595
- - where the local toolchain binaries live.
596
-
597
- This client is the root object for both JS/TS flows and relayer integrations.
598
-
599
- ### Compile a Built-in Preset
600
-
601
- Use `sdk.compileFromPreset(...)` when you want the fastest route to a working contract.
602
-
603
- Use it when:
604
- - you are learning Simplicity with the SDK,
605
- - your contract matches a built-in pattern,
606
- - you want a known witness schema and a stable example path.
607
-
608
- The return value is a `CompiledContract`, which gives you:
609
- - `deployment()`
610
- - `saveArtifact(path)`
611
- - `at()` to turn it into a deployed contract handle.
612
-
613
- ### Understand Deployment
614
-
615
- `deployment()` gives you the metadata you need to make the contract live:
616
- - `contractAddress`
617
- - `cmr`
618
- - `internalKey`
619
- - `instructions`
620
-
621
- This is the point where the README should change your mental model: **compiling does not put anything on chain yet**. Funding the derived address is what makes the contract usable.
622
-
623
- ### Fund the Contract
624
-
625
- A compiled contract becomes executable only after a UTXO exists at its address.
626
-
627
- Helpful SDK / CLI tools here:
628
- - `contract.waitForFunding(...)`
629
- - `contract.findUtxos()`
630
- - `simplicity-cli artifact show --artifact ...`
631
-
632
- Use `artifact show` when you want a human-readable view of:
633
- - address,
634
- - compile source,
635
- - linked preset,
636
- - live UTXO status.
637
-
638
- ### Inspect Before Broadcast
639
-
640
- `inspectCall()` is the safe preview path.
641
-
642
- It answers:
643
- - which UTXO is being spent,
644
- - where the outputs go,
645
- - what fee output exists,
646
- - what summary hash represents the proposed spend.
647
-
648
- This is especially important if you intend to build signing UX or higher-level approval logic later.
649
-
650
- ### Execute
651
-
652
- `execute()` is the direct contract spend path.
653
-
654
- Use:
655
- - `broadcast: false` when you want to generate and inspect the final raw transaction,
656
- - `broadcast: true` when you actually want to submit the spend.
657
-
658
- For beginners, the safest practice is:
659
- - inspect first,
660
- - dry-run execute second,
661
- - broadcast last.
662
-
663
- ## Common Workflow Patterns
664
-
665
- This section helps you choose the right path for real work.
666
-
667
- ### Pattern A: Start from a preset
668
-
669
- Best for:
670
- - first experiments,
671
- - demos,
672
- - validating a toolchain setup,
673
- - learning witness behavior.
674
-
675
- Use:
676
- - `p2pkLockHeight` first,
677
- - then `p2pk` if you do not need a timelock.
678
-
679
- ### Pattern B: Move to custom `.simf`
680
-
681
- Best for:
682
- - your own contract logic,
683
- - app-specific spend rules,
684
- - moving from prototype to product-specific behavior.
685
-
686
- Use:
687
- - `sdk.compileFromFile(...)`
688
- - `templateVars`
689
- - `artifactPath`
690
-
691
- A common progression is:
692
- 1. start from a preset,
693
- 2. inspect the preset's witness model,
694
- 3. write your own `.simf`,
695
- 4. keep the same artifact / inspect / execute lifecycle.
696
-
697
- ### Pattern C: Multi-witness contracts
698
-
699
- Best for:
700
- - HTLC-style logic,
701
- - cooperative spends,
702
- - timeout recovery,
703
- - flows where multiple branches of witness data are possible.
704
-
705
- Relevant SDK features:
706
- - `witness.values`
707
- - `witness.signers`
708
- - witness schema validation
709
-
710
- Relevant presets:
711
- - `htlc`
712
- - `transferWithTimeout`
713
-
714
- ### Pattern D: Gasless execution
715
-
716
- Best for:
717
- - developer experience where the caller should not manage fees directly,
718
- - fee-sponsored app flows,
719
- - relayer-backed applications.
720
-
721
- There are three different gasless-style paths in this SDK, and they are not interchangeable:
722
- - standard L-BTC transfer through a relayer,
723
- - local sponsor wallet mode for Simplicity contract execution,
724
- - relayer-backed Simplicity execution.
725
-
726
- ## Presets Overview
727
-
728
- These presets are built into the SDK and are the best place to start.
729
-
730
- | Preset | What it does | When to use it | Custom witness? | Relayer execute? | Best first use |
731
- | --- | --- | --- | --- | --- | --- |
732
- | `p2pkLockHeight` | Single signer spend gated by block height | First end-to-end tutorial, timelocked tests | No | Yes | Yes |
733
- | `p2pk` | Basic single key spend | Minimal happy path | No | Yes | Yes |
734
- | `htlc` | Hash/time based branch contract | Preimage or timeout experiments | Yes | Yes | After presets without custom witness |
735
- | `transferWithTimeout` | Cooperative transfer with unilateral timeout fallback | Multi-witness and branch logic | Yes | Yes | After HTLC basics |
736
-
737
- Use the CLI to inspect presets interactively:
738
-
739
- ```bash
740
- simplicity-cli presets list
741
- simplicity-cli presets show --preset transferWithTimeout
742
- simplicity-cli presets scaffold --preset transferWithTimeout --write-dir ./transfer-timeout-scaffold
743
- ```
744
-
745
- ## Custom `.simf` Contracts
746
-
747
- When built-in presets are no longer enough, move to your own `.simf` file.
748
-
749
- ```ts
750
- const compiled = await sdk.compileFromFile({
751
- simfPath: "./contracts/my-contract.simf",
752
- templateVars: {
753
- ADMIN_XONLY: "79be...",
754
- MIN_HEIGHT: 2344430,
755
- },
756
- artifactPath: "./artifacts/my-contract.artifact.json",
757
- });
73
+ npx simplicity-cli presets list
74
+ npx simplicity-cli binding describe-support
75
+ npx simplicity-cli --help
758
76
  ```
759
77
 
760
- Use custom `.simf` when:
761
- - your business logic is not represented by a preset,
762
- - you need your own parameterization,
763
- - you want to build app-specific wrappers on top of the generic SDK.
78
+ For richer walkthroughs and sample JSON / `.simf` files, use [`docs/definitions/README.md`](./docs/definitions/README.md).
764
79
 
765
- A real external-consumer validation of this path has been completed with:
766
- - a fresh project created outside this repo,
767
- - a local `contract.simf` file owned by that project,
768
- - `compileFromFile(...)`,
769
- - funding + inspect + `broadcast: true` execution.
80
+ ## Domain Overview
770
81
 
771
- Recommended path:
772
- - learn the lifecycle with a preset first,
773
- - then move to `compileFromFile(...)` once the model is clear.
82
+ ### Policy
774
83
 
775
- ## Witnesses Explained
84
+ Use `sdk.policies` when you want constrained transfers, recursive next-hop rules, or restricted OTC-style settlement kernels.
776
85
 
777
- A **witness** is the runtime data needed to satisfy a Simplicity contract spend.
86
+ Main entrypoints:
87
+ - `sdk.policies.listTemplates(...)`
88
+ - `sdk.policies.describeTemplate(...)`
89
+ - `sdk.policies.issue(...)`
90
+ - `sdk.policies.prepareTransfer(...)`
91
+ - `sdk.policies.inspectTransfer(...)`
92
+ - `sdk.policies.executeTransfer(...)`
93
+ - `sdk.policies.verifyTransfer(...)`
94
+ - `sdk.policies.exportEvidence(...)`
778
95
 
779
- ### Auto-generated witness
96
+ Representative example:
97
+ - [show-policy-restricted-otc-transfer.ts](./examples/show-policy-restricted-otc-transfer.ts)
780
98
 
781
- For the simplest presets, you usually do not need to build witness data manually.
99
+ ### Bonds
782
100
 
783
- Examples:
784
- - `p2pkLockHeight`
785
- - `p2pk`
101
+ Use `sdk.bonds` for permissioned private bond or private credit flows where definition, issuance, settlement, closing, and lineage all matter.
786
102
 
787
- These rely on the default signature path and use the primary signer you pass to `inspectCall()` or `execute()`.
103
+ Main entrypoints:
104
+ - `sdk.bonds.define(...)`
105
+ - `sdk.bonds.verify(...)`
106
+ - `sdk.bonds.verifyIssuanceHistory(...)`
107
+ - `sdk.bonds.prepareRedemption(...)`
108
+ - `sdk.bonds.buildSettlement(...)`
109
+ - `sdk.bonds.prepareClosing(...)`
110
+ - `sdk.bonds.verifyClosing(...)`
111
+ - `sdk.bonds.exportFinalityPayload(...)`
788
112
 
789
- ### `witness.values`
113
+ Representative example:
114
+ - [show-bond-business-flow.ts](./examples/show-bond-business-flow.ts)
790
115
 
791
- Use `witness.values` when the contract needs structured runtime data in addition to the primary signer.
116
+ ### Funds
792
117
 
793
- Example:
118
+ Use `sdk.funds` for LP fund settlement flows such as capital calls, rollover into refund-only, distributions, receipt reconciliation, and close-out.
794
119
 
795
- ```ts
796
- witness: {
797
- values: {
798
- COMPLETE_OR_CANCEL: {
799
- type: "Either<(u256, Signature), Signature>",
800
- value: "Left((0x0000000000000000000000000000000000000000000000000000000000000000, ${SIGNATURE}))",
801
- },
802
- },
803
- }
804
- ```
805
-
806
- ### `${SIGNATURE}`
807
-
808
- `${SIGNATURE}` is replaced by the SDK with the actual Simplicity signature for the current contract input.
120
+ Main entrypoints:
121
+ - `sdk.funds.define(...)`
122
+ - `sdk.funds.prepareCapitalCall(...)`
123
+ - `sdk.funds.executeCapitalCallClaim(...)`
124
+ - `sdk.funds.executeCapitalCallRollover(...)`
125
+ - `sdk.funds.executeCapitalCallRefund(...)`
126
+ - `sdk.funds.prepareDistribution(...)`
127
+ - `sdk.funds.verifyPositionReceiptChain(...)`
128
+ - `sdk.funds.exportFinalityPayload(...)`
809
129
 
810
- This means you can express witness templates declaratively while letting the SDK calculate the actual signature material.
130
+ Representative example:
131
+ - [show-fund-claim-close-flow.ts](./examples/show-fund-claim-close-flow.ts)
811
132
 
812
- ### `${SIGNATURE:NAME}` and `witness.signers`
133
+ ### Receivables
813
134
 
814
- Use named signer placeholders when a contract requires more than one signature source.
135
+ Use `sdk.receivables` for repayment-first receivable or invoice-style pilots where you want canonical state transitions, runtime claim descriptors, lineage verification, and terminal closing.
815
136
 
816
- Example:
817
-
818
- ```ts
819
- witness: {
820
- signers: {
821
- RECIPIENT: {
822
- type: "schnorrPrivkeyHex",
823
- privkeyHex: "<recipient-privkey-hex>",
824
- },
825
- },
826
- values: {
827
- SENDER_SIG: {
828
- type: "Signature",
829
- value: "${SIGNATURE}",
830
- },
831
- TRANSFER_OR_TIMEOUT: {
832
- type: "Option<Signature>",
833
- value: "Some(${SIGNATURE:RECIPIENT})",
834
- },
835
- },
836
- }
837
- ```
137
+ Main entrypoints:
138
+ - `sdk.receivables.define(...)`
139
+ - `sdk.receivables.prepareFunding(...)`
140
+ - `sdk.receivables.prepareFundingClaim(...)`
141
+ - `sdk.receivables.prepareRepayment(...)`
142
+ - `sdk.receivables.prepareRepaymentClaim(...)`
143
+ - `sdk.receivables.prepareClosing(...)`
144
+ - `sdk.receivables.verifyStateHistory(...)`
145
+ - `sdk.receivables.exportFinalityPayload(...)`
838
146
 
839
- ### Validation rules
147
+ Representative example:
148
+ - [show-receivable-business-flow.ts](./examples/show-receivable-business-flow.ts)
840
149
 
841
- The SDK validates preset witness usage before calling `simc`.
150
+ ## CLI and Confidence Commands
842
151
 
843
- That means it can reject mistakes such as:
844
- - missing required witness fields,
845
- - mismatched witness type strings,
846
- - a named signature placeholder without a matching signer entry.
152
+ ### Validation Surface
847
153
 
848
- ### Which presets need custom witness?
849
-
850
- - `p2pkLockHeight`: no
851
- - `p2pk`: no
852
- - `htlc`: yes
853
- - `transferWithTimeout`: yes
854
-
855
- ## Gasless Modes Explained
856
-
857
- Gasless support exists in three forms, and it is important to understand the difference.
858
-
859
- ### 1. Standard gasless transfer
860
-
861
- Use this when you want a relayer to sponsor a normal L-BTC payment flow.
862
-
863
- ```ts
864
- const result = await sdk.payments.gaslessTransfer({
865
- relayer: sdk.relayer({
866
- baseUrl: process.env.SIMPLICITY_RELAYER_URL || "http://127.0.0.1:3000",
867
- apiKey: process.env.SIMPLICITY_RELAYER_API_KEY || "<relayer-api-key>",
868
- }),
869
- amount: 0.0001,
870
- toAddress: "tex1...",
871
- fromLabel: "user-1",
872
- userWallet: "userwallet",
873
- });
874
- ```
875
-
876
- Use it when:
877
- - you want fee sponsorship,
878
- - you are sending L-BTC,
879
- - you are not executing a Simplicity contract input.
880
-
881
- ### 2. Local sponsor wallet mode
882
-
883
- Use this when the contract spend is local, but another wallet on the same system should pay the fee.
884
-
885
- ```ts
886
- const result = await compiled.at().executeGasless({
887
- wallet: "simplicity-test",
888
- sponsorWallet: "sponsorwallet",
889
- toAddress: "tex1...",
890
- signer: {
891
- type: "schnorrPrivkeyHex",
892
- privkeyHex: process.env.SIMPLICITY_PRIMARY_PRIVKEY || "<primary-privkey-hex>",
893
- },
894
- broadcast: true,
895
- });
896
- ```
897
-
898
- Use it when:
899
- - you control both wallets,
900
- - you do not need a separate external relayer service,
901
- - you want a local fee-sponsored contract execution path.
902
-
903
- ### 3. Relayer-backed Simplicity execution
904
-
905
- Use this when a separate relayer service should sponsor and submit the Simplicity execution.
906
-
907
- ```ts
908
- const relayer = sdk.relayer({
909
- baseUrl: process.env.SIMPLICITY_RELAYER_URL || "http://127.0.0.1:3000",
910
- apiKey: process.env.SIMPLICITY_RELAYER_API_KEY || "<relayer-api-key>",
911
- });
912
-
913
- const result = await compiled.at().executeGasless({
914
- relayer,
915
- fromLabel: "demo-user",
916
- wallet: "simplicity-test",
917
- toAddress: "tex1...",
918
- signer: {
919
- type: "schnorrPrivkeyHex",
920
- privkeyHex: process.env.SIMPLICITY_PRIMARY_PRIVKEY || "<primary-privkey-hex>",
921
- },
922
- });
923
- ```
154
+ The public package is exercised through:
155
+ - unit / integration tests
156
+ - packaged consumer smoke runs
157
+ - public local / testnet e2e commands
924
158
 
925
- Use it when:
926
- - your app has a relayer backend,
927
- - users should not manage fees directly,
928
- - you want contract execution plus fee sponsorship.
929
-
930
- ## CLI Guide
931
-
932
- If you prefer the CLI, the same lifecycle is available there.
933
-
934
- ### Discover
935
-
936
- ```bash
937
- simplicity-cli presets list
938
- simplicity-cli presets show --preset p2pkLockHeight
939
- simplicity-cli presets show --preset htlc
940
- ```
941
-
942
- ### Scaffold
943
-
944
- ```bash
945
- simplicity-cli presets scaffold --preset transferWithTimeout
946
- simplicity-cli presets scaffold --preset transferWithTimeout --write-dir ./transfer-timeout-scaffold
947
- ```
948
-
949
- Use scaffold when you want a starting bundle with:
950
- - params JSON,
951
- - witness JSON,
952
- - compile / execute command examples,
953
- - `.env.example`,
954
- - a small TypeScript example.
955
-
956
- ### Compile and deploy
159
+ Core confidence commands:
957
160
 
958
161
  ```bash
959
- simplicity-cli preset compile \
960
- --preset p2pkLockHeight \
961
- --param MIN_HEIGHT=2344430 \
962
- --param SIGNER_XONLY=79be... \
963
- --artifact ./artifact.json
964
-
965
- simplicity-cli artifact show --artifact ./artifact.json
162
+ npm test
163
+ npm run e2e:policy-consumer
164
+ npm run e2e:bond-consumer
165
+ npm run e2e:fund-consumer
166
+ npm run e2e:receivable-consumer
966
167
  ```
967
168
 
968
- ### Execute
169
+ Public runtime confidence commands:
969
170
 
970
171
  ```bash
971
- simplicity-cli contract inspect \
972
- --artifact ./artifact.json \
973
- --wallet simplicity-test \
974
- --privkey <primary-privkey-hex> \
975
- --to-address tex1...
172
+ npm run e2e:policy-local
173
+ npm run e2e:policy-restricted-otc-local
174
+ npm run e2e:policy-restricted-otc-testnet
175
+ POLICY_OUTPUT_BINDING_MODE=script-bound npm run e2e:policy-testnet
176
+ POLICY_OUTPUT_BINDING_MODE=descriptor-bound npm run e2e:policy-testnet
976
177
 
977
- simplicity-cli contract execute \
978
- --artifact ./artifact.json \
979
- --wallet simplicity-test \
980
- --privkey <primary-privkey-hex> \
981
- --to-address tex1... \
982
- --broadcast
178
+ BOND_OUTPUT_BINDING_MODE=script-bound npm run e2e:bond-testnet
179
+ BOND_OUTPUT_BINDING_MODE=descriptor-bound npm run e2e:bond-testnet
983
180
 
984
- simplicity-cli contract execute-gasless \
985
- --artifact ./artifact.json \
986
- --wallet simplicity-test \
987
- --relayer http://127.0.0.1:3000 \
988
- --api-key <relayer-api-key> \
989
- --from-label demo-user \
990
- --privkey <primary-privkey-hex> \
991
- --to-address tex1...
992
- ```
181
+ npm run e2e:fund-local
182
+ FUND_OUTPUT_BINDING_MODE=script-bound npm run e2e:fund-testnet
183
+ FUND_OUTPUT_BINDING_MODE=descriptor-bound npm run e2e:fund-testnet
184
+ FUND_FLOW_MODE=refund FUND_OUTPUT_BINDING_MODE=script-bound npm run e2e:fund-testnet
993
185
 
994
- ### Gasless transfer
995
-
996
- ```bash
997
- simplicity-cli gasless request \
998
- --relayer http://127.0.0.1:3000 \
999
- --api-key <relayer-api-key> \
1000
- --from-label user-1 \
1001
- --to-address tex1... \
1002
- --amount 0.0001
186
+ npm run e2e:receivable-local
187
+ RECEIVABLE_OUTPUT_BINDING_MODE=script-bound npm run e2e:receivable-testnet
188
+ RECEIVABLE_OUTPUT_BINDING_MODE=descriptor-bound npm run e2e:receivable-testnet
1003
189
  ```
1004
190
 
1005
- ## Examples Map
1006
-
1007
- These examples are included to help you jump to the right workflow quickly.
1008
-
1009
- - [compile-custom.ts](./examples/compile-custom.ts): compile a custom `.simf` file.
1010
- - [compile-preset.ts](./examples/compile-preset.ts): compile a built-in preset.
1011
- - [inspect-contract.ts](./examples/inspect-contract.ts): inspect a contract spend before broadcast.
1012
- - [execute-contract.ts](./examples/execute-contract.ts): execute a contract directly.
1013
- - [execute-contract-gasless.ts](./examples/execute-contract-gasless.ts): execute with a local sponsor wallet paying fees.
1014
- - [execute-contract-gasless-relayer.ts](./examples/execute-contract-gasless-relayer.ts): execute through a relayer-backed gasless flow.
1015
- - [execute-htlc.ts](./examples/execute-htlc.ts): HTLC preset with custom witness values.
1016
- - [execute-transfer-with-timeout-cooperative.ts](./examples/execute-transfer-with-timeout-cooperative.ts): cooperative multi-witness timeout flow.
1017
- - [gasless-transfer.ts](./examples/gasless-transfer.ts): standard relayer-backed gasless L-BTC transfer.
1018
- - [define-bond.ts](./examples/define-bond.ts): compile a bond example with a trusted definition hash anchor.
1019
- - [show-bond-definition.ts](./examples/show-bond-definition.ts): verify and retrieve a trusted bond definition from JSON + artifact.
1020
- - [define-bond-issuance.ts](./examples/define-bond-issuance.ts): compile a bond example with both trusted definition and issuance state anchors.
1021
- - [show-bond-issuance.ts](./examples/show-bond-issuance.ts): load a bond artifact together with its verified issuance state.
1022
- - [verify-bond-issuance.ts](./examples/verify-bond-issuance.ts): run combined Bond definition/state verification and invariant checks.
1023
- - [redeem-bond-issuance.ts](./examples/redeem-bond-issuance.ts): build the next redemption state and compile a new anchored artifact.
1024
- - [verify-bond-transition.ts](./examples/verify-bond-transition.ts): verify a previous/next issuance state transition.
1025
- - [compile-bond-transition.ts](./examples/compile-bond-transition.ts): compile a transition contract that commits both previous and next issuance state hashes.
1026
- - [compile-bond-redemption-machine.ts](./examples/compile-bond-redemption-machine.ts): compile a redemption transition contract that also commits redeem amount and transition kind.
1027
- - [verify-bond-redemption-machine.ts](./examples/verify-bond-redemption-machine.ts): verify a compiled redemption machine artifact against definition, previous state, and next state inputs.
1028
- - [plan-bond-rollover.ts](./examples/plan-bond-rollover.ts): build a runtime rollover plan that spends the current state UTXO into the next state's contract address.
1029
- - [show-bond-transition-payload.ts](./examples/show-bond-transition-payload.ts): emit a bridge-ready payload for a previous/next redemption transition.
1030
- - [show-bond-payload.ts](./examples/show-bond-payload.ts): emit a bridge-ready payload from a verified bond artifact.
1031
- - [redeem-bond-issuance.ts](./examples/redeem-bond-issuance.ts): build a partially redeemed bond issuance state and anchor it in a new artifact.
1032
- - [verify-bond-transition.ts](./examples/verify-bond-transition.ts): verify a redemption transition between two issuance state documents.
191
+ These commands are useful both as reproducible checks and as examples of the SDK's current validated surface.
1033
192
 
1034
- In addition to the in-repo examples, the package has also been validated from a blank external consumer project with:
1035
- - `npm install @hazbase/simplicity`
1036
- - JS/TS import of `createSimplicityClient`
1037
- - preset compile -> fund -> inspect -> execute
1038
- - custom `.simf` compile -> fund -> inspect -> execute
1039
- - relayer-backed gasless execution
193
+ ## Where To Go Next
1040
194
 
1041
- ## FAQ / Practical Notes
195
+ If you want to go deeper, use these entrypoints:
196
+ - [`docs/definitions/README.md`](./docs/definitions/README.md) for the public domain deep-dive and sample JSON / `.simf` assets
197
+ - [`examples/`](./examples) for runnable code samples across policy, bond, fund, and receivable flows
198
+ - `npx simplicity-cli --help` for the full CLI surface
1042
199
 
1043
- ### Can I use a public RPC endpoint?
200
+ A good next path is:
201
+ 1. read the architecture and flow notes in [`docs/definitions/README.md`](./docs/definitions/README.md)
202
+ 2. run one representative example from [`examples/`](./examples)
203
+ 3. run one consumer smoke or local/testnet e2e command that matches your target domain
1044
204
 
1045
- Sometimes for read-only or light inspection flows, but usually not for full execution. Many public endpoints do not expose wallet RPC methods, and this SDK relies on wallet-aware flows for inspect / execute in practical setups.
205
+ ## Practical Notes / FAQ
1046
206
 
1047
207
  ### What does “deploy” mean here?
1048
208
 
1049
- It means: compile the contract, derive its address, then fund that address with a UTXO. There is no separate EVM-style bytecode deployment transaction.
209
+ In the Simplicity-on-Liquid model, “deploy” means compile a contract, derive its contract address, and fund that address with a UTXO. There is no separate EVM-style bytecode deployment transaction.
1050
210
 
1051
211
  ### What is an artifact?
1052
212
 
1053
- An artifact is the contract's compile output plus the metadata needed to reload, inspect, and execute it later. Think of it as the bridge between compilation time and on-chain execution time.
1054
-
1055
- When you compile with `definition: { ... }`, the artifact also carries:
1056
- - `definitionType`
1057
- - `definitionId`
1058
- - `schemaVersion`
1059
- - `hash`
1060
- - `trustMode`
1061
- - `anchorMode`
1062
-
1063
- That is what allows the SDK and CLI to verify that an off-chain JSON definition still matches the contract you compiled.
1064
-
1065
- When you also compile with `state: { ... }`, the artifact can additionally carry:
1066
- - `stateType`
1067
- - `stateId`
1068
- - `schemaVersion`
1069
- - `hash`
1070
- - `trustMode`
1071
- - `anchorMode`
1072
-
1073
- That is what allows the SDK and CLI to verify that an off-chain issuance state document still matches the contract you compiled.
1074
-
1075
- ### When should I use a preset instead of a custom `.simf` file?
1076
-
1077
- Use a preset first when you are learning the lifecycle or your use case already matches a built-in contract. Move to custom `.simf` when your business rules are app-specific.
1078
-
1079
- ### Does gasless mean the contract itself is free?
1080
-
1081
- No. It means someone else pays the transaction fee. The transaction still has a fee; the caller just does not provide it directly.
1082
-
1083
- ### Can I build an ERC20-like token with this SDK?
1084
-
1085
- Yes, but not by copying the EVM account model directly. On Liquid/Simplicity, you usually model token logic as UTXO state transitions rather than storage mappings. The SDK can support that workflow, but the contract design is different from Solidity.
1086
-
1087
- ## Practical Limitations
1088
-
1089
- Be aware of these current constraints:
1090
- - SimplicityHL is still upstream work-in-progress.
1091
- - The SDK currently prioritizes explicit / unblinded paths.
1092
- - Public RPC endpoints are usually not enough for full wallet-based execution.
1093
- - Gasless support exists in multiple modes and should be chosen deliberately.
1094
- - This is not a browser SDK.
1095
- - Full confidential / blinded support is not the current success path.
1096
-
1097
- ## E2E Note
1098
-
1099
- The repository also includes an E2E script for relayer-backed Simplicity execution:
1100
-
1101
- ```bash
1102
- PATH="/tmp:$PATH" npm run e2e:simplicity-relayer
1103
- ```
1104
-
1105
- Helpful env vars include:
1106
- - `SIMPLICITY_ARTIFACT`
1107
- - `SIMPLICITY_RELAYER_PORT`
1108
- - `SIMPLICITY_RELAYER_API_KEY`
1109
- - `SIMPLICITY_RELAYER_DIR`
1110
- - `SIMPLICITY_FROM_LABEL`
1111
- - `SIMPLICITY_PRIVKEY`
1112
- - `ELEMENTS_RPC_URL`
1113
- - `ELEMENTS_RPC_USER`
1114
- - `ELEMENTS_RPC_PASSWORD`
1115
- - `ELEMENTS_RPC_WALLET`
213
+ An artifact is the SDK's durable compile output plus the metadata needed to reload, inspect, verify, and execute a contract later. It is the bridge between contract definition time and spend time.
1116
214
 
1117
- You do not need this script to understand the SDK, but it is useful once you want to validate relayer-backed flows end to end.
215
+ ### What do I need locally?
1118
216
 
1119
- ## License
217
+ For practical usage you typically need:
218
+ - Node.js 20+
219
+ - the npm package itself
220
+ - a local Simplicity toolchain (`simc`, `hal-simplicity`, and usually `eltc`)
221
+ - a reachable Elements / Liquid RPC endpoint
1120
222
 
1121
- Apache-2.0
223
+ Some commands are SDK-only and work without live spends. Local and testnet e2e flows need the toolchain and, for broadcasted flows, an RPC environment.