@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/README.md
CHANGED
|
@@ -416,7 +416,8 @@ need a field or a method the tier above does not expose, and through
|
|
|
416
416
|
code reads through: fixed include sets, BCS content decoded through `Schema`
|
|
417
417
|
with the object's Move type checked first, `Option` where absence is normal,
|
|
418
418
|
batch reads chunked to 50 and checked for missing or duplicated ids — per-item
|
|
419
|
-
`Result` from `getObjects`, first-error-wins from `
|
|
419
|
+
`Result` from `getObjects`, first-error-wins from `getObjectsStrict` (the same
|
|
420
|
+
function as the deprecated `getObjectsOrFail`) — pagination
|
|
420
421
|
as `Stream`, one lock per sender so two transactions from one address cannot
|
|
421
422
|
pick the same gas coin, and the chain's own clock. A Move type with no type
|
|
422
423
|
arguments matches every instantiation of it, wherever a type is compared, so one
|
|
@@ -427,7 +428,8 @@ was built over as `sui.core`, which is why every `Tx.*` function needs only
|
|
|
427
428
|
## The transaction lifecycle
|
|
428
429
|
|
|
429
430
|
`Tx` is the lifecycle as functions — `build`, `sign`, `cosign`, `sponsored`,
|
|
430
|
-
`submit`, `reconcile`, `run`, `reconcileAll` — each
|
|
431
|
+
`submit`, `submitVia`, `reconcile`, `recorded`, `run`, `reconcileAll` — each
|
|
432
|
+
with a closed error union
|
|
431
433
|
and `R = Sui`. `Tx.run` holds the sender lock from build through submit, builds
|
|
432
434
|
(which always simulates before anything is signed — the SDK's resolver does it
|
|
433
435
|
when there is anything to resolve, and `Tx.build` runs one explicitly when
|
|
@@ -438,7 +440,12 @@ timeout, waits for the execution to be visible to reads before it releases the
|
|
|
438
440
|
lock, and if it still does not know what happened, reconciles: `Executed`,
|
|
439
441
|
`ExecutionFailed`, `NotApplied { evidence }`, or `SubmissionUnknown` carrying
|
|
440
442
|
the bytes. A `TransportError` never escapes once bytes may have been sent —
|
|
441
|
-
from `submit`, and from `reconcile` and `reconcileAll` too
|
|
443
|
+
from `submit`, and from `reconcile` and `reconcileAll` too — with one exception:
|
|
444
|
+
a gRPC **`INVALID_ARGUMENT`**, which is the node refusing the request outright
|
|
445
|
+
(malformed bytes, or a sponsored transaction carrying one signature). Nothing
|
|
446
|
+
was executed, so `Tx.submit` reports that error as it is rather than
|
|
447
|
+
reconciling, because a reconcile would go on to ask whether that digest is on
|
|
448
|
+
chain — a question about a transaction that was never sent. `Signer` is a
|
|
442
449
|
value, not a service, so one process can hold two credentials; `SubmitConfig`
|
|
443
450
|
and `Journal` are `Context.Reference`s with working defaults, so none of this
|
|
444
451
|
needs wiring, and `@unconfirmed/sui-effect/journal` swaps the memory journal for a durable
|
|
@@ -469,6 +476,30 @@ do not build a retry loop that expects `NotApplied { inputConsumed }`. Before
|
|
|
469
476
|
any of this, reconcile compares the chain the bytes were built for with
|
|
470
477
|
`sui.chainId` and refuses to reason across chains.
|
|
471
478
|
|
|
479
|
+
**`Tx.run` has a hook between signing and sending.** `onSigned(signed)` runs
|
|
480
|
+
inside the sender lock, after the last signature and before the first
|
|
481
|
+
`executeTransaction`, for the record the journal does not hold — a domain row
|
|
482
|
+
joining the digest to a batch, an outbox, an idempotency key. Failing it fails
|
|
483
|
+
the run with nothing sent; its error is `JournalError`, which is already in
|
|
484
|
+
`Tx.run`'s union and already means "the record could not be written and nothing
|
|
485
|
+
has gone out".
|
|
486
|
+
|
|
487
|
+
**`Tx.submitVia(signed, send)` is the lifecycle when someone else submits.** A
|
|
488
|
+
relay or a sponsorship service that holds the only key allowed to talk to the
|
|
489
|
+
node gets the bytes from you; this keeps everything around that. It journals
|
|
490
|
+
`Signed` before calling `send`, calls it exactly once, turns the reply into an
|
|
491
|
+
`Executed` when it carries one (an SDK `TransactionResult`, a reduced envelope,
|
|
492
|
+
or a bare digest, in which case it asks the chain), reconciles an ambiguous
|
|
493
|
+
`send` failure with the full evidence rules, and journals the terminal answer.
|
|
494
|
+
A `send` error whose instance declares `outcome: "not_applied"` is taken at its
|
|
495
|
+
word and fails straight through.
|
|
496
|
+
|
|
497
|
+
**`Tx.reconcileAll()` returns only what was unresolved**, as a tagged union —
|
|
498
|
+
`{ _tag: "Executed", executed }`, `{ _tag: "ExecutionFailed", error }`,
|
|
499
|
+
`{ _tag: "NotApplied", error }`, `{ _tag: "SubmissionUnknown", error }`. A
|
|
500
|
+
digest that had already settled is not in it; `Tx.recorded(digest)` answers with
|
|
501
|
+
that entry (`Option<JournalEntry>`).
|
|
502
|
+
|
|
472
503
|
**A sponsored `Tx.run` needs both signatures.** When the gas owner is not the
|
|
473
504
|
sender, pass `sponsor`: `Tx.run(recipe, { signer, gasOwner, sponsor })`. Without
|
|
474
505
|
it the run fails with `SigningError` before anything is built, because one
|
|
@@ -532,7 +563,7 @@ no error inheritance to match on.
|
|
|
532
563
|
| `ObjectNotFound` / `ObjectDeleted` / `ObjectUnavailable` | `objectId`, `version?` | The three `ObjectError.reason` values |
|
|
533
564
|
| `TransactionNotFound` | `digest` | No transaction with that digest is known |
|
|
534
565
|
| `NetworkMismatch` | `expected`, `actual` | The node is on another chain than the layer was built for |
|
|
535
|
-
| `DecodeError` | `objectId?`, `expectedType?`, `issue` | BCS content or a schema boundary did not decode |
|
|
566
|
+
| `DecodeError` | `objectId?`, `expectedType?`, `kind`, `issue` | BCS content or a schema boundary did not decode. `kind` is `"type"` (the Move type was not the one expected — nothing was parsed, and the one a caller may answer with a 404), `"bytes"` (the BCS parse failed: a layout mismatch, never safe to swallow) or `"shape"` (a domain schema refused a parsed or JSON value). Branch on `kind`, never on `issue`, whose wording changes between releases |
|
|
536
567
|
| `SimulationFailed` | `reason`, `message` | Simulation reported an execution failure. No gas charged |
|
|
537
568
|
| `ExecutionFailed` | `digest`, `reason`, `command?`, `effects` | Applied on chain and failed. Gas charged |
|
|
538
569
|
| `SubmissionUnknown` | `digest`, `signed?`, `cause` | Bytes may have been sent; the outcome is unknown. Carries them, unless it came from reconciling a bare digest |
|
|
@@ -547,8 +578,15 @@ no error inheritance to match on.
|
|
|
547
578
|
|
|
548
579
|
`ExecutionReason` mirrors the SDK's `ExecutionError` variant for variant, with
|
|
549
580
|
`MoveAbort.abortCode` as a `bigint` and clever-error constant names decoded.
|
|
550
|
-
|
|
551
|
-
`
|
|
581
|
+
**Every one of them has a readable `.message`**: for the classes that carry no
|
|
582
|
+
`message` field of their own it is a getter returning `SuiError.describe(this)`,
|
|
583
|
+
so anything that surfaces `error.message` — a log line, a UI, another library's
|
|
584
|
+
formatter — shows the actionable line instead of an empty string. It is not a
|
|
585
|
+
schema field and does not appear in `SuiError.toJson`'s output.
|
|
586
|
+
|
|
587
|
+
`SuiError.isRetryable`, `SuiError.outcome`, `SuiError.isTaxonomy`,
|
|
588
|
+
`SuiError.describe` and `SuiError.toJson` are the helpers every repo otherwise
|
|
589
|
+
hand-rolls;
|
|
552
590
|
`outcome` puts every failure on the `"applied" | "not_applied" | "unknown"`
|
|
553
591
|
axis, and an extension error may declare its own. An error that is neither a tag
|
|
554
592
|
above nor declares an `outcome` is *unclassified*: `outcome` answers `"unknown"`,
|
|
@@ -556,7 +594,23 @@ because an unrecognised tag is no evidence that nothing happened, and
|
|
|
556
594
|
`Script.exitCode` exits 1 rather than 3, because it is no evidence that anything
|
|
557
595
|
was sent either. Declare `outcome` on every error your extension defines — as a
|
|
558
596
|
class field is fine, `toJson` reads it off the instance and serializes it either
|
|
559
|
-
way
|
|
597
|
+
way, and the check duck-types the field, so an existing `Error` subclass with an
|
|
598
|
+
`outcome` property lands on the axis without becoming a `Schema.TaggedError`
|
|
599
|
+
first.
|
|
600
|
+
|
|
601
|
+
`SuiError.outcome(error, { phase: "pre-submit" })` changes exactly one answer:
|
|
602
|
+
an unrecognised tag caught **before** anything could have been sent — in a
|
|
603
|
+
`catchAll` around a build, a simulate or a signature — is `"not_applied"`
|
|
604
|
+
rather than `"unknown"`, which is true there by construction. The default stays
|
|
605
|
+
`"post-submit"`. `SuiError.isTaxonomy(error)` answers the question underneath
|
|
606
|
+
it, and `SuiError.describe` accepts a foreign error too, falling back to its tag
|
|
607
|
+
and message rather than returning nothing.
|
|
608
|
+
|
|
609
|
+
**A wrapper error must carry what it wrapped.** `Script.exitCode` honours a
|
|
610
|
+
declared `outcome` before the tag, so a `catchAll` that re-raises its own error
|
|
611
|
+
type around a `Tx.run` must copy `outcome: SuiError.outcome(cause)` and the
|
|
612
|
+
digest, or a charged `ExecutionFailed` becomes exit 1 or, worse, exit 4 — and
|
|
613
|
+
the wrapper retries a transaction that already ran.
|
|
560
614
|
|
|
561
615
|
## Scripts
|
|
562
616
|
|
|
@@ -567,7 +621,7 @@ way.
|
|
|
567
621
|
| `SUI_NETWORK` | yes, no default | `mainnet`, `testnet`, `devnet`, `localnet` or your own |
|
|
568
622
|
| `SUI_ALLOW_MAINNET` | only for mainnet | `1` or `true`; a script that means mainnet has to say so twice |
|
|
569
623
|
| `SUI_RPC_URL` | no | The gRPC endpoint; defaulted per known network |
|
|
570
|
-
| `SUI_PRIVATE_KEY` | `Script` only | A Bech32 `suiprivkey1…` key, read through `Config.redacted`. A key that does not decode fails with one fixed sentence and no cause: the Bech32 decoder quotes the whole input it rejected, so nothing derived from it is ever printed |
|
|
624
|
+
| `SUI_PRIVATE_KEY` | `Script` only | A Bech32 `suiprivkey1…` key **or a 32-byte hex seed** (64 hex characters, `0x` optional, read as Ed25519), through `Config.redacted`. A key that does not decode fails with one fixed sentence and no cause: the Bech32 decoder quotes the whole input it rejected, so nothing derived from it is ever printed |
|
|
571
625
|
|
|
572
626
|
`Script.layerReadOnly` provides `ScriptReadOnly`, which has no signer at all —
|
|
573
627
|
a separate service key, so a script written to sign cannot silently build over a
|
|
@@ -591,9 +645,110 @@ bytes finish.
|
|
|
591
645
|
| 5 | applied on chain: `ExecutionFailed` (gas charged) or `UnexpectedEffects` (it ran; the receipt is missing) |
|
|
592
646
|
| 130 | interrupted, with nothing outstanding in the journal |
|
|
593
647
|
|
|
648
|
+
**`Script.report(exit, { stderr?, journal? })`** is those last two steps on
|
|
649
|
+
their own — the diagnostic lines and the unresolved entries, with the exit code
|
|
650
|
+
as the answer — for a CLI that owns its own argv parsing and process. Assign it
|
|
651
|
+
to `process.exitCode` rather than calling `process.exit`.
|
|
652
|
+
|
|
594
653
|
A timeout or an interrupt asks the journal: with an unresolved submission in it
|
|
595
654
|
the exit is 3, not 4 or 130, because an `Effect.timeout` wrapped around a
|
|
596
|
-
submission interrupts it from the outside and the bytes may be on the wire.
|
|
655
|
+
submission interrupts it from the outside and the bytes may be on the wire. Each
|
|
656
|
+
unresolved entry is printed three ways: the digest and tag, the raw base64
|
|
657
|
+
bytes, and the whole entry encoded through the `JournalEntry` schema — the same
|
|
658
|
+
JSON a durable journal stores — so a wrapper can hand stderr to a recovery
|
|
659
|
+
process verbatim.
|
|
660
|
+
|
|
661
|
+
**Every `SubmitConfig` field is overridable, and one of them usually should be.**
|
|
662
|
+
`SubmitConfig` is a `Context.Reference` with the spec's defaults, including a
|
|
663
|
+
`maxGasBudget` of **50 SUI** — a ceiling, not a budget, but far above what a
|
|
664
|
+
sponsor policy typically allows. Narrow it once, where the runtime is built:
|
|
665
|
+
|
|
666
|
+
```ts
|
|
667
|
+
program.pipe(SubmitConfig.with({
|
|
668
|
+
maxGasBudget: Mist.make(1_000_000_000n), // 1 SUI
|
|
669
|
+
lockSender: false // see below
|
|
670
|
+
}))
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
`SubmitConfig.with(overrides)` spreads `SubmitConfig.defaults` for you and
|
|
674
|
+
provides the whole value, which is what a `Context.Reference` holds;
|
|
675
|
+
`SubmitConfig.layer(overrides)` is the same thing as a `Layer`, for an
|
|
676
|
+
application that sets its policy once where the runtime is built.
|
|
677
|
+
|
|
678
|
+
`lockSender` is the other one worth a decision. The lock exists because two
|
|
679
|
+
concurrent builds from one address can pick the same gas coin; with
|
|
680
|
+
`tx.setGasPayment([])` there is no coin to pick — the node pays from the address
|
|
681
|
+
balance — and the lock buys nothing. That is the case for every transaction
|
|
682
|
+
built with `Tx.sponsored`, whose empty gas payment `Tx.build` preserves through
|
|
683
|
+
the resolver, and it is the only setting that makes sense across isolates
|
|
684
|
+
(Workers, Durable Objects), where a per-runtime semaphore is not a lock at all.
|
|
685
|
+
|
|
686
|
+
## Relay and sponsor envelopes
|
|
687
|
+
|
|
688
|
+
`Executed` describes the SDK's own execute include set. A relay, a sponsor or
|
|
689
|
+
any service that submitted on your behalf returns whatever *it* asked the node
|
|
690
|
+
for, which is usually less: `changedObjects` with an `objectId` and an
|
|
691
|
+
`idOperation` and nothing else, no `objectTypes`, no `balanceChanges`, no
|
|
692
|
+
checkpoint, events as JSON with no BCS.
|
|
693
|
+
|
|
694
|
+
`Executed.fromPartial(envelope)` decodes exactly that, and what it was not told
|
|
695
|
+
stays "not told": input and output states are `Unknown` rather than a guessed
|
|
696
|
+
`ObjectWrite`, versions and digests are `null`, and the accessors read `Unknown`
|
|
697
|
+
as "the envelope did not say", so `created()` and `deleted()` still classify
|
|
698
|
+
from the id operation alone. JSON spellings are accepted where the SDK's types
|
|
699
|
+
are not JSON — `bcs` as base64 or a byte array, every `u64` as a number or a
|
|
700
|
+
`bigint` as well as the decimal string the wire uses. Two things it cannot
|
|
701
|
+
invent: the **types** (`created(type)` and `expectCreated(type)` match against
|
|
702
|
+
the `objectTypes` join, so without one they match nothing — use `created()` or
|
|
703
|
+
`createdWhere(predicate)`), and the **gas** (`gasUsedTotal` is `0n` for an
|
|
704
|
+
envelope that reported none, which means "not reported", not "free").
|
|
705
|
+
|
|
706
|
+
`Executed.fromTransactionResult(result)` is the strict constructor, for an SDK
|
|
707
|
+
`TransactionResult` read with the full include set.
|
|
708
|
+
|
|
709
|
+
The whole sequence, for a service that co-signs and submits: `Tx.build` with
|
|
710
|
+
`Tx.sponsored`, `Tx.sign`, hand `toBase64(signed.bytes)` and `signed.signatures[0]`
|
|
711
|
+
to the service, and then either `Executed.fromPartial(reply)` or — through
|
|
712
|
+
`Tx.submitVia`, which keeps the journal — `Tx.reconcile(signed)`. The digest
|
|
713
|
+
does not change when the sponsor adds its signature, so `signed.digest` is what
|
|
714
|
+
to record. `docs/extensions.md` has the section.
|
|
715
|
+
|
|
716
|
+
**`Executed.events` is `ReadonlyArray<Event>`, not `SuiClientTypes.Event[]`**:
|
|
717
|
+
the same fields with branded ids, and `json` present only when whatever produced
|
|
718
|
+
the `Executed` carried one (a relay envelope, never a gRPC execute). Decode an
|
|
719
|
+
event with `SuiSchema.decode(codec, event.bcs)`. Code typed against the SDK's
|
|
720
|
+
`Event[]` does not accept these.
|
|
721
|
+
|
|
722
|
+
**`bigint` throws in `JSON.stringify`.** Gas, balances, versions and
|
|
723
|
+
`checkpoint` are all `bigint`; anything that logs, persists or returns one over
|
|
724
|
+
HTTP needs `.toString()` or a replacer. Decimal strings are what the wire uses
|
|
725
|
+
and what every schema here decodes from.
|
|
726
|
+
|
|
727
|
+
## Applications, Workers and Durable Objects
|
|
728
|
+
|
|
729
|
+
An application that consumes this library — an SPA, a Worker, a Durable Object —
|
|
730
|
+
wants one `ManagedRuntime` at module scope over
|
|
731
|
+
`Sui.layerNoDepsWith({ chainId })` and `SuiCore.layerFromClient(client)`, and
|
|
732
|
+
should know four things:
|
|
733
|
+
|
|
734
|
+
- **a `ManagedRuntime` memoizes its layer build, failure included.** One flaky
|
|
735
|
+
`getChainIdentifier` at boot and every later use of that runtime fails with the
|
|
736
|
+
same stale `TransportError`. Pass `SuiLayerOptions.retry` (a `Schedule` for
|
|
737
|
+
that one read), dispose and rebuild on a build failure, or use
|
|
738
|
+
`Sui.layerNoDepsPinned(chainId)`, which makes no call at all;
|
|
739
|
+
- **the default `Journal` is process-wide memory.** In a browser tab a refresh
|
|
740
|
+
is a new process and two tabs are two journals and two sender locks; what an
|
|
741
|
+
app actually holds is the `SubmissionUnknown` and its bytes, so persist that
|
|
742
|
+
and reconcile it on the next boot, or provide the durable journal;
|
|
743
|
+
- **the sender lock does not cross isolates**, so correctness there rests on
|
|
744
|
+
address-balance gas (`tx.setGasPayment([])`, `lockSender: false`) or on
|
|
745
|
+
serializing an address through one Durable Object;
|
|
746
|
+
- **there is no `process`** in a Worker: `Script` is a Node entrypoint, and
|
|
747
|
+
configuration comes from `ConfigProvider.fromEnvRecord(env)`.
|
|
748
|
+
|
|
749
|
+
`docs/extensions.md` sections 17 and 18 have the runtime module, the HMR
|
|
750
|
+
dispose, the vitest double and the `KeyValueStore.makeStringOnly` adapter over
|
|
751
|
+
Durable Object storage.
|
|
597
752
|
|
|
598
753
|
## Testing
|
|
599
754
|
|
|
@@ -605,6 +760,17 @@ else the extension's layer requires), and `SuiTest`
|
|
|
605
760
|
for driving the fake's state and reading back what it was sent. No test in this
|
|
606
761
|
repository touches the network, and neither should yours.
|
|
607
762
|
|
|
763
|
+
Four things a test on the fake has to know. `layerTest` is the production layer,
|
|
764
|
+
so a script naming `mainnet` or `testnet` must report that network's real chain
|
|
765
|
+
identifier — use `localnet` (the default) in fixtures. `Tx.submit` reconciles
|
|
766
|
+
through `getTransaction`, so a submit test that does not mean "this landed"
|
|
767
|
+
scripts `getTransaction: [FakeOutcome.notFound()]`. A **sponsored** submit needs
|
|
768
|
+
`Tx.cosign` first: the fake refuses an under-signed or wrongly-signed submission
|
|
769
|
+
with a gRPC `INVALID_ARGUMENT`, the way a validator does. And the build's
|
|
770
|
+
simulate is the resolver's — recorded, so `SuiTest.calls("simulateTransaction")`
|
|
771
|
+
sees it, and answered by `FakeScript.buildSimulate` if there is one and by the
|
|
772
|
+
ordered `simulate` script otherwise.
|
|
773
|
+
|
|
608
774
|
## Versions
|
|
609
775
|
|
|
610
776
|
| Package | Range | Tested against |
|
package/dist/domain/bcs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bcs.d.ts","sourceRoot":"","sources":["../../src/domain/bcs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAgD,MAAM,QAAQ,CAAA;AACrF,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"bcs.d.ts","sourceRoot":"","sources":["../../src/domain/bcs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAgD,MAAM,QAAQ,CAAA;AACrF,OAAO,EAAE,WAAW,EAAiB,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAY5C;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,SAAS,KAAK,EAAE,KAAK,EACxC,SAAS,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,EAC1B,eAAe,MAAM,KACpB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAmD5B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,KAAK,EAAE,KAAK,EAAE,CAAC,EAClD,SAAS,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,EAC1B,cAAc,MAAM,GAAG,SAAS,EAChC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,KACpB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAqC5B,CAAA;AAuBD;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,MAAM,GAAG,SAC/C,CAAA;AAU5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,EAAE,QAAQ,MAAM,KAAG,OAU9D,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,EAC7B,QAAQ,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,EACnC,SAAS,UAAU,EACnB,UAAU;IACR,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B,KACA,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,CAmC9B,CAAA"}
|
package/dist/domain/bcs.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { normalizeStructTag, parseStructTag } from "@mysten/sui/utils";
|
|
2
2
|
import { Effect, Schema, SchemaAST, SchemaIssue, SchemaTransformation } from "effect";
|
|
3
|
-
import { DecodeError } from "./errors.js";
|
|
3
|
+
import { DecodeError, decodePayload } from "./errors.js";
|
|
4
4
|
const SUI_TYPE_ANNOTATION = "sui-effect/suiType";
|
|
5
5
|
const normalizeSafe = (value) => {
|
|
6
6
|
try {
|
|
@@ -37,7 +37,10 @@ export const bcs = (bcsType, expectedType) => {
|
|
|
37
37
|
// A BCS layout carries no runtime type to test a decoded value against: the
|
|
38
38
|
// parse below is the validation, so the target schema accepts whatever the
|
|
39
39
|
// layout produced.
|
|
40
|
-
const target = Schema.declare((_u) => true
|
|
40
|
+
const target = Schema.declare((_u) => true, {
|
|
41
|
+
identifier: label,
|
|
42
|
+
description: `BCS layout ${label}`
|
|
43
|
+
});
|
|
41
44
|
return Schema.Uint8Array.pipe(Schema.decodeTo(target, SchemaTransformation.transformOrFail({
|
|
42
45
|
decode: (bytes, options) => Effect.try({
|
|
43
46
|
try: () => {
|
|
@@ -57,7 +60,7 @@ export const bcs = (bcsType, expectedType) => {
|
|
|
57
60
|
try: () => bcsType.serialize(value).toBytes(),
|
|
58
61
|
catch: (cause) => new SchemaIssue.InvalidValue({ message: `Could not serialize ${label} to BCS: ${String(cause)}` }, value, options)
|
|
59
62
|
})
|
|
60
|
-
}))).annotate(normalized === undefined ? {} : { [SUI_TYPE_ANNOTATION]: normalized });
|
|
63
|
+
}))).annotate(normalized === undefined ? {} : { [SUI_TYPE_ANNOTATION]: normalized }).pipe(Schema.revealCodec);
|
|
61
64
|
};
|
|
62
65
|
/**
|
|
63
66
|
* A BCS layout plus the mapping into a domain value, as one codec.
|
|
@@ -103,18 +106,22 @@ export const bcs = (bcsType, expectedType) => {
|
|
|
103
106
|
* ```
|
|
104
107
|
*/
|
|
105
108
|
export const decodeWith = (bcsType, expectedType, map) => {
|
|
106
|
-
const
|
|
109
|
+
const label = expectedType ?? bcsType.name;
|
|
110
|
+
const target = Schema.declare((_u) => true, {
|
|
111
|
+
identifier: label,
|
|
112
|
+
description: `BCS layout ${label}`
|
|
113
|
+
});
|
|
107
114
|
return bcs(bcsType, expectedType).pipe(Schema.decodeTo(target, SchemaTransformation.transformOrFail({
|
|
108
115
|
decode: (parsed, options) => Effect.try({
|
|
109
116
|
try: () => map(parsed),
|
|
110
117
|
catch: (cause) => new SchemaIssue.InvalidValue({
|
|
111
|
-
message: `Could not map ${
|
|
118
|
+
message: `Could not map ${label} into its domain value: ${String(cause)}`
|
|
112
119
|
}, parsed, options)
|
|
113
120
|
}),
|
|
114
121
|
encode: (value, options) => Effect.fail(new SchemaIssue.Forbidden({
|
|
115
|
-
message: `${
|
|
122
|
+
message: `${label} was built with SuiSchema.decodeWith, which has no encoder: serialize with the BCS layout instead`
|
|
116
123
|
}, value, options))
|
|
117
|
-
})));
|
|
124
|
+
})), Schema.revealCodec);
|
|
118
125
|
};
|
|
119
126
|
const MAX_ENCODING_DEPTH = 32;
|
|
120
127
|
/**
|
|
@@ -228,13 +235,22 @@ export const decodeContent = (schema, content, context) => {
|
|
|
228
235
|
return Effect.fail(new DecodeError({
|
|
229
236
|
...withObject,
|
|
230
237
|
...withExpected,
|
|
238
|
+
// The type tag did not match, so not a byte was parsed: this is the
|
|
239
|
+
// decode failure a caller may answer with "not one of mine".
|
|
240
|
+
kind: "type",
|
|
231
241
|
issue: `${context?.objectId === undefined ? "the bytes have" : `object ${context.objectId} has`} type ${actual}`
|
|
232
242
|
}));
|
|
233
243
|
}
|
|
234
|
-
|
|
244
|
+
// `{ errors: "all" }` so a value that is wrong in three places reports three
|
|
245
|
+
// paths on `DecodeError.issues`, not just the first sentence.
|
|
246
|
+
return Schema.decodeUnknownEffect(schema)(content, { errors: "all" }).pipe(Effect.mapError((error) => new DecodeError({
|
|
235
247
|
...withObject,
|
|
236
248
|
...withExpected,
|
|
237
|
-
|
|
249
|
+
// The tag matched (or there was none to check) and the bytes
|
|
250
|
+
// themselves did not parse: a layout mismatch or a corrupt object,
|
|
251
|
+
// never something to swallow.
|
|
252
|
+
kind: "bytes",
|
|
253
|
+
...decodePayload(error)
|
|
238
254
|
})));
|
|
239
255
|
};
|
|
240
256
|
//# sourceMappingURL=bcs.js.map
|
package/dist/domain/bcs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bcs.js","sourceRoot":"","sources":["../../src/domain/bcs.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAA;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"bcs.js","sourceRoot":"","sources":["../../src/domain/bcs.ts"],"names":[],"mappings":"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"}
|