@unconfirmed/sui-effect 0.1.1 → 0.1.3
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/AGENTS.md +34 -11
- package/CHANGELOG.md +77 -0
- package/LLMS.md +630 -704
- package/README.md +175 -9
- package/dist/domain/bcs.d.ts.map +1 -1
- package/dist/domain/bcs.js +25 -9
- package/dist/domain/bcs.js.map +1 -1
- package/dist/domain/errors.d.ts +178 -40
- package/dist/domain/errors.d.ts.map +1 -1
- package/dist/domain/errors.js +271 -37
- package/dist/domain/errors.js.map +1 -1
- package/dist/domain/executed.d.ts +71 -2
- package/dist/domain/executed.d.ts.map +1 -1
- package/dist/domain/executed.js +210 -9
- package/dist/domain/executed.js.map +1 -1
- package/dist/domain/journal-entry.d.ts +37 -37
- package/dist/domain/journal-entry.js +1 -1
- package/dist/domain/schemas.d.ts +172 -65
- package/dist/domain/schemas.d.ts.map +1 -1
- package/dist/domain/schemas.js +131 -32
- package/dist/domain/schemas.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/script.d.ts +1 -1
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +1 -1
- package/dist/script.js.map +1 -1
- package/dist/services/Script.d.ts +42 -0
- package/dist/services/Script.d.ts.map +1 -1
- package/dist/services/Script.js +112 -77
- package/dist/services/Script.js.map +1 -1
- package/dist/services/Signer.d.ts +32 -7
- package/dist/services/Signer.d.ts.map +1 -1
- package/dist/services/Signer.js +69 -10
- package/dist/services/Signer.js.map +1 -1
- package/dist/services/SubmitConfig.d.ts +3 -22
- package/dist/services/SubmitConfig.d.ts.map +1 -1
- package/dist/services/SubmitConfig.js +54 -9
- package/dist/services/SubmitConfig.js.map +1 -1
- package/dist/services/Sui.d.ts +42 -1
- package/dist/services/Sui.d.ts.map +1 -1
- package/dist/services/Sui.js +46 -17
- package/dist/services/Sui.js.map +1 -1
- package/dist/services/SuiCore.d.ts.map +1 -1
- package/dist/services/SuiCore.js +47 -33
- package/dist/services/SuiCore.js.map +1 -1
- package/dist/services/SuiCoreFake.d.ts +47 -4
- package/dist/services/SuiCoreFake.d.ts.map +1 -1
- package/dist/services/SuiCoreFake.js +193 -22
- package/dist/services/SuiCoreFake.js.map +1 -1
- package/dist/services/Tx.d.ts +236 -402
- package/dist/services/Tx.d.ts.map +1 -1
- package/dist/services/Tx.js +205 -10
- package/dist/services/Tx.js.map +1 -1
- package/dist/testing.d.ts +1 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +9 -0
- package/dist/testing.js.map +1 -1
- package/dist/tx.d.ts +1 -1
- package/dist/tx.d.ts.map +1 -1
- package/dist/tx.js +1 -1
- package/dist/tx.js.map +1 -1
- package/docs/extensions.md +608 -19
- package/examples/extension-template/src/Escrow.ts +1 -1
- package/examples/extension-template/src/errors.ts +29 -0
- package/examples/extension-template/src/schema.ts +8 -17
- package/examples/extension-template/test/escrow.test.ts +44 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -28,7 +28,9 @@ the work plan. Where this file and the spec disagree, fix this file.
|
|
|
28
28
|
await its `Exit` and exit.
|
|
29
29
|
- No `any`. No `unknown` in an error channel. No `console.log` in `src/`. The
|
|
30
30
|
one `console.warn` is `SuiCore.mapSdkError`'s duplicate-SDK warning, which
|
|
31
|
-
fires at most once per process and is documented where it lives.
|
|
31
|
+
fires at most once per process and is documented where it lives. **Nothing in
|
|
32
|
+
`src/` writes to stderr otherwise** — `test/release-0-1-2.test.ts` captures it
|
|
33
|
+
around a full `Tx.run` on the fake and asserts it is empty.
|
|
32
34
|
- **A branded id from a shorthand spelling** comes from `SuiAddress.normalize`
|
|
33
35
|
/ `ObjectId.normalize` (decode, then brand); `.make` validates without
|
|
34
36
|
decoding and is for the padded form only. Neither is for a value that came
|
|
@@ -73,7 +75,7 @@ the work plan. Where this file and the spec disagree, fix this file.
|
|
|
73
75
|
| Tier | What it is | When to use it |
|
|
74
76
|
|---|---|---|
|
|
75
77
|
| `SuiCore` | A 1:1 Effect wrap of `ClientWithCoreApi`. One member per `SuiClientTypes.TransportMethods` key plus `getObject`, `getDynamicObjectField`, `waitForTransaction`, `signAndExecuteTransaction` and `use`. `Include` generics preserved. | Reaching a field or method `Sui` does not expose, and inside extension implementations. |
|
|
76
|
-
| `Sui` | The opinionated tier over `SuiCore`: fixed include sets, decoded BCS content, `Option` where absence is normal, chunked and integrity-checked batch reads (`getObjects` per-item `Result`, `
|
|
78
|
+
| `Sui` | The opinionated tier over `SuiCore`: fixed include sets, decoded BCS content, `Option` where absence is normal, chunked and integrity-checked batch reads (`getObjects` per-item `Result`, `getObjectsStrict` first-error-wins — `getObjectsOrFail` is the deprecated alias), `Stream` pagination, one sender lock. | Almost all application and extension code. |
|
|
77
79
|
|
|
78
80
|
Reads go through `Sui`; writes go through `Tx`. An extension never calls
|
|
79
81
|
`SuiCore.executeTransaction` directly. `Sui` exposes the `SuiCore` it was built
|
|
@@ -85,7 +87,7 @@ and nothing else.
|
|
|
85
87
|
| Name | What it is |
|
|
86
88
|
|---|---|
|
|
87
89
|
| `Signer` | A credential as a **value**, never a service: `{ address, scheme, signTransaction, signPersonalMessage }`. One process may hold two. Secret material never reaches the value. |
|
|
88
|
-
| `Tx.build/sign/cosign/sponsored/submit/reconcile/run/reconcileAll` | The lifecycle as functions, each with a closed error union, all `R = Sui`. |
|
|
90
|
+
| `Tx.build/sign/cosign/sponsored/submit/submitVia/reconcile/recorded/run/reconcileAll` | The lifecycle as functions, each with a closed error union, all `R = Sui`. `submitVia` is `submit` for a submission somebody else makes; `recorded(digest)` reads one journal entry, which is what `reconcileAll` — unresolved entries only — cannot answer. `Tx.run` takes `onSigned`, the hook between the last signature and the first send. |
|
|
89
91
|
| `SubmitConfig` | A `Context.Reference` holding expiration policy, the optional `validFor` wall-clock bound, the gas-budget ceiling, `preflight`, the sender lock, the resubmit schedule, attempts, timeout and expiry margin, plus `expiryEvidence`, `reconcileRecheck`, `awaitVisibility`, `visibilityTimeout` and `nonce`. |
|
|
90
92
|
| `Journal` | A `Context.Reference` with an in-memory default. `@unconfirmed/sui-effect/journal` swaps in a durable one over `KeyValueStore`; `Tx.reconcileAll()` is the explicit startup call. |
|
|
91
93
|
| `Script` | `{ sui, core, signer, network }` plus `Script.run` and `Script.exitCode`. `ScriptReadOnly` is the signer-less variant, a separate key on purpose. |
|
|
@@ -105,7 +107,12 @@ copyable package every block of that guide is quoted from, and
|
|
|
105
107
|
`Tx.submit` journals `Signed` before the first execute, re-sends the identical
|
|
106
108
|
bytes (never a rebuild) on a retryable `TransportError` or a timeout, and
|
|
107
109
|
reconciles when the retries run out. A `TransportError` never escapes once bytes
|
|
108
|
-
may have been sent: it becomes `SubmissionUnknown`, which carries them.
|
|
110
|
+
may have been sent: it becomes `SubmissionUnknown`, which carries them. **The
|
|
111
|
+
one exception is a gRPC `INVALID_ARGUMENT`** (`REFUSED_OUTRIGHT` in `Tx.ts`):
|
|
112
|
+
the node refused the request, nothing executed, and reconciling would ask
|
|
113
|
+
whether a never-sent transaction is on chain — a question a lagging or scripted
|
|
114
|
+
node can answer yes. That error escapes as itself, which is why `SubmitError`
|
|
115
|
+
includes `TransportError`.
|
|
109
116
|
`JournalError` escapes only from the `Signed` write, before anything is sent;
|
|
110
117
|
after the network has answered, a failed journal write is logged and the answer
|
|
111
118
|
stands.
|
|
@@ -157,7 +164,7 @@ Every failure is one flat tag; there is no error inheritance.
|
|
|
157
164
|
| `ObjectNotFound` / `ObjectDeleted` / `ObjectUnavailable` | The three `ObjectError.reason` values. |
|
|
158
165
|
| `TransactionNotFound` | No transaction with that digest is known. |
|
|
159
166
|
| `NetworkMismatch` | The node is on another chain than the layer was built for. |
|
|
160
|
-
| `DecodeError` | BCS content or a schema boundary did not decode. |
|
|
167
|
+
| `DecodeError` | BCS content or a schema boundary did not decode. `kind` is `"type"` (tag mismatch, nothing parsed), `"bytes"` (BCS parse or trailing bytes) or `"shape"` (a domain schema). Every producer sets it; consumers branch on it, never on `issue`. |
|
|
161
168
|
| `SimulationFailed` | Simulation reported an execution failure. No gas charged. |
|
|
162
169
|
| `ExecutionFailed` | Applied on chain and failed. Gas charged. |
|
|
163
170
|
| `SubmissionUnknown` | Bytes may have been sent; the outcome is unknown. Carries the signed bytes, unless it came from reconciling a bare digest. |
|
|
@@ -170,8 +177,13 @@ Every failure is one flat tag; there is no error inheritance.
|
|
|
170
177
|
`"not_applied"` for every other tag in the taxonomy, and `"unknown"` for
|
|
171
178
|
anything that is neither one of those tags nor declares an `outcome`.
|
|
172
179
|
`Script.exitCode` exits 1 for that last case rather than 3. An extension error
|
|
173
|
-
may declare its own `outcome`, and should. `SuiError.
|
|
174
|
-
|
|
180
|
+
may declare its own `outcome`, and should. `SuiError.outcome` also takes `{ phase: "pre-submit" }`, which changes only the
|
|
181
|
+
unclassified answer (`"not_applied"` instead of `"unknown"`, true by
|
|
182
|
+
construction before a send). `SuiError.isRetryable`, `SuiError.isTaxonomy`,
|
|
183
|
+
`SuiError.describe` (one actionable line, and total over foreign errors) and
|
|
184
|
+
`SuiError.toJson` round it out. **Every error class without a `message` schema
|
|
185
|
+
field carries `override get message()` returning `describe(this)`**, so
|
|
186
|
+
`.message` is never empty; it is a getter, so it stays out of the encoding — and `toJson` adds `outcome` from the instance
|
|
175
187
|
when the error declares one, which is almost always a class field rather than a
|
|
176
188
|
schema field.
|
|
177
189
|
|
|
@@ -186,8 +198,11 @@ by default and `extra` for any other dependency the layer requires) and `SuiTest
|
|
|
186
198
|
an extension's tests need. Call recording is reached through `SuiTest.calls`,
|
|
187
199
|
not off the fake handle. The fake serves in-memory objects with
|
|
188
200
|
BCS content, the Clock object `0x6`, and scripted outcomes
|
|
189
|
-
(`FakeOutcome.succeed`, `failWith
|
|
190
|
-
|
|
201
|
+
(`FakeOutcome.succeed`, `failWith` — which takes the SDK's wire `ExecutionError`
|
|
202
|
+
**or** sui-effect's decoded `ExecutionReason`, encoding the second and throwing
|
|
203
|
+
on anything else — `transportError`, `notFound`, `timeoutThen`)
|
|
204
|
+
for simulate, execute, `getObject` (read-failure injection), `getTransaction` —
|
|
205
|
+
which is also what drives every
|
|
191
206
|
`waitForTransaction` outcome — `coinMetadata`, and the resolver's budget simulation
|
|
192
207
|
(`buildSimulate`, which is how a test makes `Tx.build` fail with
|
|
193
208
|
`SimulationFailed`). It records every call so a test can
|
|
@@ -214,6 +229,14 @@ rather than failing a `Simulation` decode.
|
|
|
214
229
|
The fake enforces the invariants the lifecycle depends on: a known digest
|
|
215
230
|
executes idempotently, gas selection excludes object inputs, the coin set
|
|
216
231
|
evolves (deleted, mutated with `FakeChange.balance`, gas-bumped, created), a
|
|
217
|
-
submission
|
|
232
|
+
submission whose signatures do not cover the addresses the bytes name — by count
|
|
233
|
+
**and** by the addresses recovered from the signatures — is refused the way a
|
|
234
|
+
validator refuses it (an `RpcError` carrying `INVALID_ARGUMENT`, so `Tx.submit`
|
|
235
|
+
fails fast instead of reconciling into a scripted success), and a
|
|
218
236
|
version history is served through `tryGetPastObject`, which is what
|
|
219
|
-
`SuiCore.getObjectAtVersion` reads.
|
|
237
|
+
`SuiCore.getObjectAtVersion` reads. The resolver's budget simulate is recorded
|
|
238
|
+
as a `simulateTransaction` call (`resolver: true`) and answered by
|
|
239
|
+
`FakeScript.buildSimulate` when there is one and by the ordered `simulate`
|
|
240
|
+
script otherwise, so "building always simulates" is observable on the harness.
|
|
241
|
+
`getBalance` and `listBalances` are keyed by owner and coin type; a `FakeBalance`
|
|
242
|
+
with no `owner` answers for everyone.
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,83 @@
|
|
|
3
3
|
All notable changes to `@unconfirmed/sui-effect`. The format is one line per
|
|
4
4
|
change, newest release first.
|
|
5
5
|
|
|
6
|
+
## 0.1.3 (2026-09-12)
|
|
7
|
+
|
|
8
|
+
Unreleased. Sixteen ergonomics changes from an audit of this package against
|
|
9
|
+
Effect v4 rc.112's own documentation. Nothing was removed and no signature
|
|
10
|
+
changed: an extension or an application built against 0.1.2 compiles unchanged.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`SubmitConfig.with(overrides)` and `SubmitConfig.layer(overrides)`.** A `Context.Reference` holds one whole value, so every override used to be `Effect.provideService(effect, SubmitConfig, { ...SubmitConfig.defaults, maxGasBudget })` — with a cast on every branded literal. `run.pipe(SubmitConfig.with({ maxGasBudget: Mist.make(1_000_000_000n) }))` is the same thing in one call, and `SubmitConfig.layer` is the `Layer` form for an application that sets its policy where the runtime is built. `SubmitConfig.defaults` is unchanged.
|
|
15
|
+
- **`DecodeError.issues`**: every issue the schema reported, as `{ path, message }`, beside the `issue` sentence. The three producers decode with `{ errors: "all" }`, so a relay envelope with three bad fields reports three paths rather than the first one. `issue` still describes exactly **one** issue — the first — and a failure that only ever had one comes through byte for byte, so anything printing it is unaffected. The `issues` key is absent when the producer had no structured issue to carry, so `SuiError.toJson` round-trips exactly as before. `kind` is still the field to branch on.
|
|
16
|
+
- **`SuiError.toJson` always carries a `message`.** Fifteen of the eighteen error classes hold their sentence in an `override get message()`, and a getter is not part of the encoding, so a JSON log line had a human sentence for three tags and nothing for the rest. It is now in the same key for every error — `SuiError.describe` for a taxonomy error, the instance's own `.message` for an extension error — added only when the encoding produced none, and ignored on decode.
|
|
17
|
+
- **Span attributes on the calls a trace has to be joined to.** `sui.object_id`, `sui.object_count`, `sui.digest`, `sui.signature_count`, `sui.sender`, `sui.gas_owner`, `sui.signer`, `sui.attempt` and `sui.evidence`, plus a static `sui.network` on every `SuiCore` span. An OTLP trace of a stuck submission can now be searched by digest and by sender without reading the logs.
|
|
18
|
+
- **`identifier` and `description` on every reusable schema**, so a failure reads `Expected ObjectId` instead of `Expected string`, a mis-shaped BCS value names its Move type instead of `<Declaration>`, and `Schema.toJsonSchemaDocument(ObjectRef)` produces named `$defs` instead of one anonymous inlined object.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **`Built`, `Signed`, `Simulation`, `ObjectRef`, `ObjectEnvelope`, `Balance`, `DynamicField` and `DynamicFieldEntry` print by name.** They were `typeof Schema.Type` aliases, which TypeScript expands at every use site, so `Tx.build` rendered as forty lines of structure in editor hover and in `LLMS.md`. They are interfaces over the same types now — structurally identical, so nothing breaks — and the `Tx` block of `LLMS.md` is 69 lines instead of 464.
|
|
23
|
+
- **`Sui.getObjects` fetches its chunks concurrently**, four at a time. A 500-id read is three round trips instead of ten. Input order, the per-item `Result`s, the integrity checks and first-failure semantics are unchanged.
|
|
24
|
+
- **`Script.exitCode` can no longer exit 1 for a real taxonomy error.** Its per-tag `switch` had a `default:` that silently answered "defect", so a tag added to the taxonomy and forgotten there exited 1 instead of 3, 4 or 5. There is no tag list left: the mapping goes through `SuiError.isTaxonomy` and `SuiError.outcome`, which are derived from the error schema. No exit code changed — `NetworkMismatch` is still 2.
|
|
25
|
+
- **A `NaN` or an `Infinity` in a JSON number field is a `DecodeError`**, not a value: the seventeen fields that model a JSON number use `Schema.Finite`. The decoded type is still `number`.
|
|
26
|
+
- **`SuiAddress.normalize` and `ObjectId.normalize` document what they actually throw**: a `SchemaError` (`Schema.isSchemaError`) carrying `.issue`, because they are `Schema.decodeSync`. `.make` is the one that throws a plain `Error` with the issue in `cause`.
|
|
27
|
+
- Internals with no consumer-visible effect: `Encoding.encodeBase64` replaces a hand-rolled base64 helper, `Schema.revealCodec` replaces the two `as unknown as` casts in the BCS bridge, and the runtime type guards go through `Predicate`.
|
|
28
|
+
|
|
29
|
+
### Documentation
|
|
30
|
+
|
|
31
|
+
- **Extension authors:** the guide's claim that the halfway shape of a `Schema.decodeTo` into a domain class "must be an explicit interface" was wrong. `typeof Settlement.Encoded` is exactly that shape and compiles; only `typeof Settlement.Type` — the instance side — inverts the transformation. The template drops its hand-written `SettlementParts` for it, so there is one fewer interface per domain class and nothing left to drift.
|
|
32
|
+
- **Extension authors:** `outcome: Schema.tag("not_applied")` is documented beside the class-field form as the schema-visible way to declare an outcome — it is encoded without a patch-back, decodable back into an error, and visible to `Schema.is`. The class-field form keeps working and the template still uses it.
|
|
33
|
+
- **Extension authors:** every error in the template now defines a real `.message` — a getter over its own fields for two of them, the existing `message` schema field for the third — and the guide says plainly that `SuiError.toJson` emits a `message` key only for an error that has one. `Schema.TaggedError` leaves `.message` empty, so an error that defines neither logs as an empty string.
|
|
34
|
+
- The template's `Settlement` class identifier is `"escrow/Settlement"`, following the guide's own `"<package>/<Name>"` rule: an identifier is the class's runtime marker and its JSON-Schema `$ref` key, and two extensions with a `Settlement` class collided.
|
|
35
|
+
- README: the `SubmitConfig` override section shows `SubmitConfig.with` / `SubmitConfig.layer`.
|
|
36
|
+
|
|
37
|
+
## 0.1.2
|
|
38
|
+
|
|
39
|
+
Two defects from the first three downstream conversions, and the surface they
|
|
40
|
+
exposed. Nothing was removed. Two shapes changed: `Tx.reconcileAll` now returns
|
|
41
|
+
a tagged union, and `Tx.submit`'s error union gained `TransportError` for the
|
|
42
|
+
one case where a node refuses a submission outright.
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- **`Tx.submit` no longer reconciles a submission the node refused.** A gRPC `INVALID_ARGUMENT` — malformed bytes, or a sponsored transaction carrying only the sender's signature — is the node answering that it did not execute anything, so it escapes as the `TransportError` it is. Reconciling it asked "is this digest on chain?" about a transaction that was never sent, and a lagging node (or a scripted `getTransaction`) could answer yes: an app's sponsored, under-signed submission was reported as a **successful `Executed`**. `SubmitError` therefore includes `TransportError`; every other transport failure still becomes `SubmissionUnknown`.
|
|
47
|
+
- **`SuiCoreFake` refuses an under-signed or wrongly-signed submission the way a validator does**, with an `RpcError` carrying `INVALID_ARGUMENT` rather than a plain `Error` that `mapSdkError` classified as a *retryable* transport failure. It checks the signature count and, when the signatures parse, the addresses they were made by. A sponsored submit against the fake needs `Tx.cosign` (or `Tx.run`'s `sponsor`) first, exactly as it does against a node.
|
|
48
|
+
- **The fake's resolver simulate is recorded**, so `SuiTest.calls("simulateTransaction")` sees the simulate that `Tx.build` promises, and it is answered by `FakeScript.buildSimulate` when there is one and by the ordered `simulate` script otherwise — `simulate: [FakeOutcome.failWith(...)]` now surfaces through `Tx.build` and `Tx.run` as `SimulationFailed` instead of vanishing.
|
|
49
|
+
- **Nothing in `src/` writes to stderr** (the one documented `console.warn` aside). A test captures stderr around a full `Tx.run` on the fake, with `bigint`s in the script, and asserts it is empty: the reported `console.error("DEBUG …", JSON.stringify(outcomes))` lines are in no published 0.1.1 artefact, but a `JSON.stringify` over a scripted `bigint` throws, and the throw surfaced later as an unrelated `FakeUnimplemented`.
|
|
50
|
+
- **Every error class has a real `.message`.** `Schema.TaggedError` leaves it empty, so anything surfacing `error.message` showed nothing; the classes without a `message` schema field now carry `override get message()` returning `SuiError.describe(this)`. It is a getter, so `SuiError.toJson`'s encoding is unchanged.
|
|
51
|
+
- **`SuiError.describe` accepts a foreign error** instead of returning `undefined` from an exhaustive `switch` while its signature promised a `string`. An extension's error, or any `{ _tag }`, gets its tag and message.
|
|
52
|
+
- **`SuiCoreFake.getBalance` is keyed by owner**, not by coin type alone. A `FakeBalance` may carry an `owner`; one without answers for every owner, which is what a pre-0.1.2 script meant.
|
|
53
|
+
- **`FakeOutcome.failWith` accepts sui-effect's decoded `ExecutionReason`** as well as the SDK's wire `ExecutionError`, encoding the first into the second. A fixture in the wrong shape used to decode-fail several calls later, on a different method, after the outcome cursor had already moved; it now throws where the fixture is written, naming both shapes.
|
|
54
|
+
|
|
55
|
+
### Added
|
|
56
|
+
|
|
57
|
+
- **`DecodeError.kind`**: `"type"` (the Move type was not the expected one — nothing was parsed, and the one a consumer may answer with a 404), `"bytes"` (the BCS parse failed or left trailing bytes — never safe to swallow), `"shape"` (a domain schema refused a parsed or JSON value). Every producer sets it, `SuiError.describe` prints it, and it defaults to `"shape"`, so an extension constructing a `DecodeError` without one still compiles. Branch on `kind`, never on `issue`.
|
|
58
|
+
- **`Tx.reconcileAll` returns a `Schema.TaggedUnion`**: `{ _tag: "Executed", executed }`, `{ _tag: "ExecutionFailed", error }`, `{ _tag: "NotApplied", error }`, `{ _tag: "SubmissionUnknown", error }`. The old bare union — an `Executed` with no discriminator beside three errors that had one — is exported as the deprecated type `ReconciledOutcome`.
|
|
59
|
+
- **`Tx.recorded(digest)`**: the journal entry for one digest, as an `Option`. `reconcileAll` returns **only** the entries that were unresolved, and this is how to ask about one that already settled.
|
|
60
|
+
- **`Tx.submitVia(signed, send)`**: the submission lifecycle when a relay or a sponsorship service does the sending. Journals `Signed` before calling `send`, calls it exactly once, decodes whatever it answers (an SDK `TransactionResult`, a reduced envelope, a bare digest, or nothing — in which case it asks the chain), reconciles an ambiguous failure with the full evidence rules, and journals the terminal answer. A `send` error whose instance declares `outcome: "not_applied"` fails straight through without a reconcile.
|
|
61
|
+
- **`Tx.run`'s `onSigned` hook**: called with the signed bytes after the last signature and before the first `executeTransaction`, inside the sender lock, for the record the journal does not hold. Its failure is a `JournalError` and fails the run with nothing sent.
|
|
62
|
+
- **`Executed.fromPartial(envelope)`**: an `Executed` from a reduced relay or sponsor envelope. `changedObjects` entries need only `objectId` and `idOperation`; what the envelope did not say stays `Unknown` rather than being guessed, and the accessors read `Unknown` as "not said" so `created()` and `deleted()` still classify. JSON spellings are accepted (`bcs` as base64 or a byte array, every `u64` as a number or a `bigint`). It cannot invent the `objectTypes` join, so the type-filtered accessors match nothing without it, and `gasUsedTotal` is `0n` for an envelope that reported no gas.
|
|
63
|
+
- **`Executed.fromTransactionResult(result)`** is public: the strict constructor, for an SDK `TransactionResult` read with the full include set.
|
|
64
|
+
- **`Event.json`**: kept when the source carried one, which in practice means a relay envelope whose events have no BCS. Never populated from a gRPC execute.
|
|
65
|
+
- **`SuiError.outcome(error, { phase: "pre-submit" })`** answers `"not_applied"` rather than `"unknown"` for an unclassified error, which is true by construction before anything is sent. The default is `"post-submit"`, the 0.1.1 behaviour. **`SuiError.isTaxonomy(error)`** answers whether an error is one of the tags this package owns.
|
|
66
|
+
- **`Sui.getObjectsStrict`**: `getObjectsOrFail` under a name that reads correctly in isolation. The old name stays as a deprecated alias of the same function.
|
|
67
|
+
- **`Signer.fromConfig` accepts a 32-byte hex seed** (64 hex characters, `0x` optional, read as Ed25519) as well as a Bech32 `suiprivkey`, so a raw seed from a secret manager no longer needs `fromHex` in application code.
|
|
68
|
+
- **`Signer.fromSdkSigner` validates its argument** and throws a `TypeError` naming the missing member. A double without `getKeyScheme` produced `scheme: undefined` and nothing complained until a validator did. Its JSDoc now states that `toSuiAddress()` and `getKeyScheme()` are read at construction, and that clear-signing inputs are the SDK signer's own concern.
|
|
69
|
+
- **`SuiLayerOptions.retry`**: a `Schedule` for the one `getChainIdentifier` a `Sui` layer makes. A `ManagedRuntime` memoizes its layer build, failure included, so one unlucky read at boot otherwise poisons a browser tab or a Worker isolate for its whole life.
|
|
70
|
+
- **`FakeScript.getObject`** (and `SuiTest.scriptGetObject`): scripted outcomes for a **read**, so a test can inject a transport failure, a miss or a timeout into `getObject`. An absent or exhausted script serves the object map as before.
|
|
71
|
+
- **`Script.report(exit, { stderr?, journal? })`**: the diagnostic lines and the unresolved-entry printing `Script.run` does at the end, returning the exit code, for a CLI that owns its own argv parser and process and cannot hand the entrypoint over.
|
|
72
|
+
- **`Script.run` prints each unresolved journal entry encoded through the `JournalEntry` schema** — the same JSON a durable journal stores, bytes base64 — beside the two human lines it already printed.
|
|
73
|
+
|
|
74
|
+
### Documentation
|
|
75
|
+
|
|
76
|
+
- The extension guide gains three sections: **"Application consumers"** (a module-level `ManagedRuntime` over `Sui.layerNoDepsWith({ chainId })` and `SuiCore.layerFromClient`, HMR disposal, the memoized-failed-build trap, the in-memory journal in a browser, mapping `outcome` onto UI states with the pre-submit caveat, signing with an external cosigner, and a `layerTest`-backed double for an app's own `runSui`), **"Workers and Durable Objects"** (no `process`, `ConfigProvider.fromEnvRecord(env)`, one runtime per isolate, the sender lock not crossing isolates and address-balance gas, DO alarms versus `Schedule` sleeps, and the whole `KeyValueStore.makeStringOnly` adapter over DO storage), and **"Relay and sponsor envelopes"** (`Executed.fromPartial`, what it cannot invent, and `Tx.submitVia`).
|
|
77
|
+
- A **"Sponsored by an external service"** recipe in the signers section: build with `Tx.sponsored`, sign, hand over the base64 bytes and the serialized signature, and reconcile by the digest — which a co-signature does not change.
|
|
78
|
+
- The testing section gains: `getTransaction` is what a submit test's reconcile reads (script `notFound` unless the test means "this landed"), a sponsored submit needs `Tx.cosign` and should assert the signature count on `SuiTest.calls("executeTransaction")`, which script slot answers the build's simulate, that `layerTest` asserts the built-in chain id for `mainnet` and `testnet`, how to inject a read failure, and why an isolated-consumer fixture in the package `tsconfig`'s `include` typechecks your code against the tarball it last installed.
|
|
79
|
+
- Error guidance: tag strings are namespaced by whoever defined them and must be copied from the installed package; `DecodeError.kind` replaces branching on `issue`; a wrapper error must copy the `outcome` and digest of what it wrapped, because `Script.exitCode` honours `outcome` first.
|
|
80
|
+
- Migration-table rows for a hand-rolled idempotent submitter, `sui.core.getTransaction` for a transaction that may have failed, a predecessor `ready()` genesis check mapping to `Sui.layerNoDepsWith({ chainId })`, and a removed standalone read export; plus the `.find(... type?.includes(...))`-then-throw grep pattern that `Executed.expectCreated` replaces, and the rule that a consumer-edit table is regenerated from the published `exports` map rather than from facade call sites.
|
|
81
|
+
- README: the `INVALID_ARGUMENT` rule, `onSigned`, `submitVia`, the `Reconciled` shape and `Tx.recorded`, `DecodeError.kind`, the error `.message` getter, `outcome`'s phase, relay envelopes and `Executed.events`' exact type, `bigint` at the JSON boundary, the `SubmitConfig` override idiom with `maxGasBudget`'s 50 SUI default and when `lockSender: false` is correct, and a section on applications, Workers and Durable Objects.
|
|
82
|
+
|
|
6
83
|
## 0.1.1
|
|
7
84
|
|
|
8
85
|
Seventeen fixes from the first downstream conversion. Nothing in the public API
|