@unconfirmed/sui-effect 0.1.0 → 0.1.1

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 (53) hide show
  1. package/AGENTS.md +16 -6
  2. package/CHANGELOG.md +40 -0
  3. package/LLMS.md +1609 -1098
  4. package/README.md +347 -3
  5. package/dist/domain/bcs.d.ts +44 -0
  6. package/dist/domain/bcs.d.ts.map +1 -1
  7. package/dist/domain/bcs.js +57 -0
  8. package/dist/domain/bcs.js.map +1 -1
  9. package/dist/domain/errors.d.ts +63 -21
  10. package/dist/domain/errors.d.ts.map +1 -1
  11. package/dist/domain/errors.js +35 -7
  12. package/dist/domain/errors.js.map +1 -1
  13. package/dist/domain/executed.d.ts +54 -18
  14. package/dist/domain/executed.d.ts.map +1 -1
  15. package/dist/domain/journal-entry.d.ts +6 -2
  16. package/dist/domain/journal-entry.d.ts.map +1 -1
  17. package/dist/domain/schemas.d.ts +207 -66
  18. package/dist/domain/schemas.d.ts.map +1 -1
  19. package/dist/domain/schemas.js +62 -2
  20. package/dist/domain/schemas.js.map +1 -1
  21. package/dist/domain/sui-schema.d.ts +3 -2
  22. package/dist/domain/sui-schema.d.ts.map +1 -1
  23. package/dist/domain/sui-schema.js +3 -2
  24. package/dist/domain/sui-schema.js.map +1 -1
  25. package/dist/extension.d.ts +1 -1
  26. package/dist/extension.d.ts.map +1 -1
  27. package/dist/extension.js +1 -1
  28. package/dist/extension.js.map +1 -1
  29. package/dist/services/SuiCore.d.ts +12 -0
  30. package/dist/services/SuiCore.d.ts.map +1 -1
  31. package/dist/services/SuiCore.js +124 -0
  32. package/dist/services/SuiCore.js.map +1 -1
  33. package/dist/services/SuiCoreFake.d.ts +12 -0
  34. package/dist/services/SuiCoreFake.d.ts.map +1 -1
  35. package/dist/services/SuiCoreFake.js +6 -1
  36. package/dist/services/SuiCoreFake.js.map +1 -1
  37. package/dist/services/SuiExtension.d.ts +127 -14
  38. package/dist/services/SuiExtension.d.ts.map +1 -1
  39. package/dist/services/SuiExtension.js +125 -28
  40. package/dist/services/SuiExtension.js.map +1 -1
  41. package/dist/services/SuiGraphQL.d.ts +13 -0
  42. package/dist/services/SuiGraphQL.d.ts.map +1 -1
  43. package/dist/services/SuiGraphQL.js +13 -0
  44. package/dist/services/SuiGraphQL.js.map +1 -1
  45. package/dist/services/Tx.d.ts +3 -1
  46. package/dist/services/Tx.d.ts.map +1 -1
  47. package/dist/testing.d.ts +21 -3
  48. package/dist/testing.d.ts.map +1 -1
  49. package/dist/testing.js +30 -3
  50. package/dist/testing.js.map +1 -1
  51. package/docs/extensions.md +338 -25
  52. package/examples/extension-template/test/escrow.test.ts +91 -2
  53. package/package.json +3 -2
package/README.md CHANGED
@@ -67,6 +67,341 @@ That is `examples/script-claim.ts`, which a test runs against the in-memory
67
67
  fake. Every failure it can produce is in the generator's inferred error type and
68
68
  has its own exit code, with no handling lines anywhere.
69
69
 
70
+ ## Side by side
71
+
72
+ The same two tasks, once against the canonical `@mysten/sui` 2.30 SDK (a
73
+ gRPC client, the Core API, `Transaction`) and once against sui-effect. Both
74
+ sides are exercised in `test/examples.test.ts`, and this section is asserted
75
+ to be the literal text of the four files it quotes.
76
+
77
+ ### Read
78
+
79
+ `examples/compare-read.sdk.ts`:
80
+
81
+ ```ts
82
+ /**
83
+ * Reads one Escrow object and an optional dynamic field on it, written
84
+ * against the canonical 2.30 SDK: a gRPC client, the Core API, manual BCS.
85
+ *
86
+ * Compare with `examples/compare-read.effect.ts`. Both print identical
87
+ * output for the same id.
88
+ *
89
+ * Run with `SUI_NETWORK=testnet ESCROW_ID=0x… bun examples/compare-read.sdk.ts`.
90
+ */
91
+ import { bcs } from "@mysten/sui/bcs"
92
+ import type { ClientWithCoreApi } from "@mysten/sui/client"
93
+ import { ObjectError } from "@mysten/sui/client"
94
+ import { SuiGrpcClient } from "@mysten/sui/grpc"
95
+
96
+ const PKG = "0x0000000000000000000000000000000000000000000000000000000000000002"
97
+ const ESCROW_TYPE = `${PKG}::escrow::Escrow`
98
+ const EscrowBcs = bcs.struct("Escrow", { id: bcs.Address, amount: bcs.u64() })
99
+ // A note some escrows carry, keyed by the literal index 0. The key is a
100
+ // primitive `u64`, not a struct tag, so nothing here parses it as one.
101
+ const NOTE_NAME = { type: "u64", bcs: bcs.u64().serialize(0).toBytes() }
102
+
103
+ /** Reads the escrow at `id` plus its optional note. */
104
+ export const readEscrow = async (
105
+ client: ClientWithCoreApi,
106
+ id: string
107
+ ): Promise<{ id: string; amount: string; note: string | undefined }> => {
108
+ let object
109
+ try {
110
+ ;({ object } = await client.core.getObject({ objectId: id, include: { content: true } }))
111
+ } catch (error) {
112
+ // `getObject` throws rather than returning a value that says which of
113
+ // "missing", "deleted" or "unreachable" happened; that three-way split
114
+ // is `ObjectError.reason`, read by hand.
115
+ if (error instanceof ObjectError) {
116
+ if (error.reason === "notFound") throw new Error(`escrow ${id} does not exist`)
117
+ if (error.reason === "deleted") throw new Error(`escrow ${id} was deleted`)
118
+ throw new Error(`escrow ${id}: node could not say what happened to it`, { cause: error })
119
+ }
120
+ throw error
121
+ }
122
+ // No type parameters on this tag, so a plain string comparison is honest;
123
+ // a generic type would need to be parsed and compared piece by piece,
124
+ // which is what sui-effect's bridge does for every caller.
125
+ if (object.type !== ESCROW_TYPE) {
126
+ throw new Error(`${id} is a ${object.type}, not ${ESCROW_TYPE}`)
127
+ }
128
+ const { id: escrowId, amount } = EscrowBcs.parse(object.content)
129
+
130
+ let note: string | undefined
131
+ try {
132
+ const { dynamicField } = await client.core.getDynamicField({ parentId: id, name: NOTE_NAME })
133
+ note = bcs.u64().parse(dynamicField.value.bcs)
134
+ } catch (error) {
135
+ // Absence is normal here; only a reason other than "notFound"/"deleted"
136
+ // is a real problem.
137
+ if (!(error instanceof ObjectError) || error.reason === "unknown") throw error
138
+ }
139
+
140
+ return { id: escrowId, amount, note }
141
+ }
142
+
143
+ if (import.meta.main) {
144
+ const id = process.env.ESCROW_ID
145
+ if (!id) throw new Error("ESCROW_ID is required")
146
+ const client = new SuiGrpcClient({
147
+ network: (process.env.SUI_NETWORK ?? "testnet") as "testnet",
148
+ baseUrl: process.env.SUI_RPC_URL ?? "https://fullnode.testnet.sui.io:443"
149
+ })
150
+ const escrow = await readEscrow(client, id)
151
+ console.log(`${escrow.id} holds ${escrow.amount}, note: ${escrow.note ?? "none"}`)
152
+ }
153
+ ```
154
+
155
+ `examples/compare-read.effect.ts`:
156
+
157
+ ```ts
158
+ /**
159
+ * Reads one Escrow object and its optional note through sui-effect.
160
+ *
161
+ * Compare with `examples/compare-read.sdk.ts`, which reads the same two
162
+ * things with the canonical SDK client. Both print identical output.
163
+ *
164
+ * Run with `SUI_NETWORK=testnet ESCROW_ID=0x… bun examples/compare-read.effect.ts`.
165
+ * Every failure this program can produce is in the generator's inferred error
166
+ * type: `ObjectNotFound`, `ObjectDeleted`, `ObjectUnavailable` and
167
+ * `DecodeError` (the last one is what a wrong Move type becomes, because
168
+ * `getObject`'s tag check runs before a byte is parsed), plus `TransportError`
169
+ * from both reads and, from the layer, `ConfigError` and `NetworkMismatch`.
170
+ */
171
+ import { bcs } from "@mysten/sui/bcs"
172
+ import { Config, Console, Effect, Option } from "effect"
173
+ import { ObjectId, Sui, SuiSchema } from "../src/index.ts"
174
+
175
+ const PKG = "0x0000000000000000000000000000000000000000000000000000000000000002"
176
+
177
+ const Escrow = SuiSchema.bcs(
178
+ bcs.struct("Escrow", { id: bcs.Address, amount: bcs.u64() }),
179
+ `${PKG}::escrow::Escrow`
180
+ )
181
+ // The note's value has no struct tag of its own, so its codec carries none;
182
+ // the key is a primitive `u64`, which is why nothing here reaches for
183
+ // `normalizeStructTag` on it.
184
+ const Note = SuiSchema.bcs(bcs.u64())
185
+ const NOTE_NAME = { type: "u64", bcs: bcs.u64().serialize(0).toBytes() }
186
+
187
+ /** The program itself, exported so a test can run it against the fake. */
188
+ export const program = Effect.gen(function*() {
189
+ const sui = yield* Sui
190
+ const id = yield* Config.schema(ObjectId, "ESCROW_ID")
191
+ // No `ObjectError.reason` switch and no manual type comparison: a missing
192
+ // or deleted escrow and a wrong Move type are already three different tags
193
+ // in the type this line returns.
194
+ const escrow = yield* sui.getObject(id, { schema: Escrow })
195
+ const field = yield* sui.getDynamicFieldOption(id, NOTE_NAME)
196
+ const note = yield* Option.match(field, {
197
+ onNone: () => Effect.void,
198
+ onSome: (entry) => SuiSchema.decode(Note, entry.value.bcs)
199
+ })
200
+ yield* Console.log(`${escrow.id} holds ${escrow.content.amount}, note: ${note ?? "none"}`)
201
+ })
202
+
203
+ if (import.meta.main) {
204
+ // Imported here rather than at the top so that a test can import `program`
205
+ // without pulling a platform package into the test process.
206
+ const { BunRuntime } = await import("@effect/platform-bun")
207
+ BunRuntime.runMain(program.pipe(Effect.provide(Sui.layerConfig)))
208
+ }
209
+ ```
210
+
211
+ ### Write
212
+
213
+ `examples/compare-write.sdk.ts`:
214
+
215
+ ```ts
216
+ /**
217
+ * Claims an escrow through a PTB, written against the canonical 2.30 SDK.
218
+ *
219
+ * Compare with `examples/compare-write.effect.ts`, which does the same thing
220
+ * through `Tx.run` and notes what that adds over this file. Both sign with
221
+ * `SUI_PRIVATE_KEY` and print the created receipt's object id.
222
+ *
223
+ * Run with:
224
+ * SUI_NETWORK=testnet SUI_PRIVATE_KEY=suiprivkey1… ESCROW_ID=0x… bun examples/compare-write.sdk.ts
225
+ */
226
+ import { bcs } from "@mysten/sui/bcs"
227
+ import type { ClientWithCoreApi } from "@mysten/sui/client"
228
+ import type { Keypair } from "@mysten/sui/cryptography"
229
+ import { decodeSuiPrivateKey } from "@mysten/sui/cryptography"
230
+ import { SuiGrpcClient } from "@mysten/sui/grpc"
231
+ import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519"
232
+ import { Secp256k1Keypair } from "@mysten/sui/keypairs/secp256k1"
233
+ import { Secp256r1Keypair } from "@mysten/sui/keypairs/secp256r1"
234
+ import { Transaction } from "@mysten/sui/transactions"
235
+
236
+ const PKG = "0x0000000000000000000000000000000000000000000000000000000000000002"
237
+ const RECEIPT_TYPE = `${PKG}::escrow::Receipt`
238
+ const EscrowBcs = bcs.struct("Escrow", { id: bcs.Address, amount: bcs.u64() })
239
+
240
+ // The scheme flag on a Bech32 key names one of three keypair classes;
241
+ // nothing else decodes it, and a fourth scheme has no keypair class at all.
242
+ const KEYPAIR_FOR: Record<string, undefined | ((secretKey: Uint8Array) => Keypair)> = {
243
+ ED25519: Ed25519Keypair.fromSecretKey,
244
+ Secp256k1: Secp256k1Keypair.fromSecretKey,
245
+ Secp256r1: Secp256r1Keypair.fromSecretKey
246
+ }
247
+
248
+ /**
249
+ * Reads the escrow, claims it, and returns the created receipt's object id.
250
+ *
251
+ * Builds, signs and executes as three explicit steps rather than the
252
+ * one-call `signAndExecuteTransaction`, so this can run against an in-memory
253
+ * client with no live network or signer behind it.
254
+ */
255
+ export const claimEscrow = async (
256
+ client: ClientWithCoreApi,
257
+ escrowId: string,
258
+ keypair: Keypair
259
+ ): Promise<string> => {
260
+ const { object } = await client.core.getObject({ objectId: escrowId, include: { content: true } })
261
+ const { amount } = EscrowBcs.parse(object.content)
262
+
263
+ const tx = new Transaction()
264
+ tx.setSenderIfNotSet(keypair.toSuiAddress())
265
+ tx.moveCall({ target: `${PKG}::escrow::claim`, arguments: [tx.object(escrowId), tx.pure.u64(amount)] })
266
+ const bytes = await tx.build({ client })
267
+ const { signature } = await keypair.signTransaction(bytes)
268
+
269
+ const result = await client.core.executeTransaction({
270
+ transaction: bytes,
271
+ signatures: [signature],
272
+ include: { effects: true, objectTypes: true }
273
+ })
274
+ const digest = (result.Transaction ?? result.FailedTransaction).digest
275
+ await client.core.waitForTransaction({ digest })
276
+
277
+ if (result.$kind === "FailedTransaction") {
278
+ const { error } = result.FailedTransaction.status
279
+ if (error?.$kind === "MoveAbort") {
280
+ const { abortCode, cleverError } = error.MoveAbort
281
+ throw new Error(`claim aborted: code ${abortCode}${cleverError?.constantName ? ` (${cleverError.constantName})` : ""}`)
282
+ }
283
+ throw new Error(`claim failed: ${error?.message}`)
284
+ }
285
+
286
+ // Effects list every changed object by id; only the `objectTypes` join
287
+ // says which one is the receipt. sui-effect's `expectCreated` is this join,
288
+ // plus a check that exactly one match exists.
289
+ const { changedObjects } = result.Transaction.effects
290
+ const created = changedObjects.find(
291
+ (change) => change.idOperation === "Created" && result.Transaction.objectTypes[change.objectId] === RECEIPT_TYPE
292
+ )
293
+ if (created === undefined) throw new Error(`claim applied (${digest}) but created no ${RECEIPT_TYPE}`)
294
+ return created.objectId
295
+ }
296
+
297
+ if (import.meta.main) {
298
+ const escrowId = process.env.ESCROW_ID
299
+ const key = process.env.SUI_PRIVATE_KEY
300
+ if (!escrowId || !key) throw new Error("ESCROW_ID and SUI_PRIVATE_KEY are required")
301
+ const parsed = decodeSuiPrivateKey(key)
302
+ const fromSecretKey = KEYPAIR_FOR[parsed.scheme]
303
+ if (!fromSecretKey) throw new Error(`${parsed.scheme} has no keypair class here (use a remote signer)`)
304
+ const client = new SuiGrpcClient({
305
+ network: (process.env.SUI_NETWORK ?? "testnet") as "testnet",
306
+ baseUrl: process.env.SUI_RPC_URL ?? "https://fullnode.testnet.sui.io:443"
307
+ })
308
+ console.log(await claimEscrow(client, escrowId, fromSecretKey(parsed.secretKey)))
309
+ }
310
+ ```
311
+
312
+ `examples/compare-write.effect.ts`:
313
+
314
+ ```ts
315
+ /**
316
+ * Claims an escrow through `Tx.run`, sui-effect's write path.
317
+ *
318
+ * Compare with `examples/compare-write.sdk.ts`, which does the same thing
319
+ * against the canonical SDK client. Both sign with `SUI_PRIVATE_KEY` and
320
+ * print the created receipt's object id.
321
+ *
322
+ * What `Tx.run` adds over the SDK file: a default expiration bounded to the
323
+ * current epoch, a journal entry written before the first execute so a crash
324
+ * mid-flight leaves a record, resending the identical signed bytes rather
325
+ * than rebuilding on a transient failure, `reconcile` when a submission's
326
+ * outcome is unknown, and a sender lock so two concurrent claims from one
327
+ * address cannot pick the same gas coin. What it costs is the Effect
328
+ * vocabulary below.
329
+ *
330
+ * Run with:
331
+ * SUI_NETWORK=testnet SUI_PRIVATE_KEY=suiprivkey1… ESCROW_ID=0x… bun examples/compare-write.effect.ts
332
+ */
333
+ import { bcs } from "@mysten/sui/bcs"
334
+ import { Config, Console, Effect } from "effect"
335
+ import { ObjectId, SuiSchema } from "../src/index.ts"
336
+ import { Script } from "../src/script.ts"
337
+ import { Tx } from "../src/tx.ts"
338
+
339
+ const PKG = "0x0000000000000000000000000000000000000000000000000000000000000002"
340
+
341
+ const Escrow = SuiSchema.bcs(
342
+ bcs.struct("Escrow", { id: bcs.Address, amount: bcs.u64() }),
343
+ `${PKG}::escrow::Escrow`
344
+ )
345
+
346
+ /**
347
+ * The program itself, exported so a test can run it against the fake. Every
348
+ * failure it can produce is in the generator's inferred error type, with no
349
+ * handling lines anywhere in this file: `ObjectNotFound`, `ObjectDeleted`,
350
+ * `ObjectUnavailable`, `DecodeError`, `TransportError`, `BuildError`,
351
+ * `SimulationFailed`, `SigningError`, `PolicyDenied`, `NotApplied`,
352
+ * `JournalError`, `UnexpectedEffects`, `ExecutionFailed`, `SubmissionUnknown`,
353
+ * plus `ConfigError` and `NetworkMismatch` from the layer.
354
+ */
355
+ export const program = Effect.gen(function*() {
356
+ const { signer, sui } = yield* Script
357
+ const id = yield* Config.schema(ObjectId, "ESCROW_ID")
358
+ const escrow = yield* sui.getObject(id, { schema: Escrow })
359
+ const executed = yield* Tx.run((tx) => {
360
+ tx.moveCall({
361
+ target: `${PKG}::escrow::claim`,
362
+ arguments: [tx.object(id), tx.pure.u64(escrow.content.amount)]
363
+ })
364
+ }, { signer })
365
+ const receipt = yield* executed.expectCreated(`${PKG}::escrow::Receipt`)
366
+ yield* Console.log(receipt.id)
367
+ })
368
+
369
+ if (import.meta.main) {
370
+ await Script.run(program)
371
+ }
372
+ ```
373
+
374
+ ### What differs
375
+
376
+ - **Absence.** The SDK throws `ObjectError` and the reason (`notFound`,
377
+ `deleted`, `unknown`) is read off the caught value by hand; sui-effect's
378
+ `getObject` fails with `ObjectNotFound` / `ObjectDeleted` / `ObjectUnavailable`,
379
+ three separate tags a caller can `catchTag` without an `if` chain.
380
+ - **Wrong type.** The SDK compares `object.type` itself, and only gets away
381
+ with a plain string equality because this particular type has no type
382
+ parameters; a generic Move type would need the same piecewise comparison
383
+ sui-effect's bridge (`typeMatches`) already runs inside every `getObject`.
384
+ - **BCS.** Both sides hand a `BcsType` to a struct; the SDK calls `.parse`
385
+ itself, sui-effect calls it once, inside `getObject`, after the type check
386
+ above has already passed.
387
+ - **Signing.** Both decode `SUI_PRIVATE_KEY` and dispatch on the scheme flag
388
+ to the matching keypair class; sui-effect's version is `Signer.fromConfig`,
389
+ one call, done once in `src/services/Signer.ts` rather than in every script.
390
+ - **Effects.** The SDK inspects `$kind`, `status.error` and joins
391
+ `changedObjects` against `objectTypes` by hand to find the created object;
392
+ sui-effect's `expectCreated(type)` is that join, plus a check that exactly
393
+ one match exists, as a single call on `Executed`.
394
+ - **What sui-effect adds that neither SDK file has:** a default expiration
395
+ bounded to the current epoch, a journal entry written before the first
396
+ execute, resending identical signed bytes instead of rebuilding on a
397
+ transient failure, `reconcile` when a submission's outcome is unknown, and
398
+ a sender lock so two concurrent writes from one address cannot pick the
399
+ same gas coin.
400
+ - **What it costs.** The sui-effect files import `effect` and run inside
401
+ `Effect.gen`; a reader who does not already know Effect's vocabulary
402
+ (`Effect.fn`, `catchTag`, `Option.match`, `yield*`) has that to learn before
403
+ either file is legible.
404
+
70
405
  ## The two tiers
71
406
 
72
407
  `SuiCore` is the mechanical tier: a one-to-one Effect wrap of the SDK's
@@ -172,7 +507,12 @@ pattern. A Promise face's **synchronous** members (recipe builders, a package
172
507
  id) are real only once the runtime exists, so either `await client.<name>.$ready()`
173
508
  once or register with `warm`; calling one before that fails with
174
509
  `ExtensionNotReady` rather than returning a Promise the type does not mention
175
- (`Effect` and `Stream` members work cold, as Promises and as async iterables).
510
+ (`Effect` and `Stream` members work cold: a cold call is a real `Promise` that
511
+ is also an `AsyncIterable`, and its rejection is pre-handled so an un-awaited
512
+ one cannot abort the process). A namespace member may be an `interface` — the
513
+ face maps it by type, not by declaration style — while a class instance with
514
+ `Effect`-returning methods is declared `SuiExtension.Leaf<T>` and built with
515
+ `SuiExtension.leaf(value)`.
176
516
  Every registration on one client **shares one `Sui`**, and therefore one
177
517
  sender-lock map, so two extensions never select gas for the same address at
178
518
  once; `$dispose()` releases that shared base only when the last registration on
@@ -214,7 +554,9 @@ axis, and an extension error may declare its own. An error that is neither a tag
214
554
  above nor declares an `outcome` is *unclassified*: `outcome` answers `"unknown"`,
215
555
  because an unrecognised tag is no evidence that nothing happened, and
216
556
  `Script.exitCode` exits 1 rather than 3, because it is no evidence that anything
217
- was sent either. Declare `outcome` on every error your extension defines.
557
+ was sent either. Declare `outcome` on every error your extension defines — as a
558
+ class field is fine, `toJson` reads it off the instance and serializes it either
559
+ way.
218
560
 
219
561
  ## Scripts
220
562
 
@@ -257,7 +599,9 @@ submission interrupts it from the outside and the bytes may be on the wire.
257
599
 
258
600
  `@unconfirmed/sui-effect/testing` ships the in-memory `SuiCoreFake`, `layerTest(script)` (the
259
601
  real `Sui` over the fake, so tests exercise the production high tier),
260
- `layerExtensionTest(layer, script)` for an extension's own tests, and `SuiTest`
602
+ `layerExtensionTest(layer, script, { extra })` for an extension's own tests
603
+ (`SuiGraphQL.layerUnavailable` is provided by default; `extra` is for anything
604
+ else the extension's layer requires), and `SuiTest`
261
605
  for driving the fake's state and reading back what it was sent. No test in this
262
606
  repository touches the network, and neither should yours.
263
607
 
@@ -32,6 +32,50 @@ import type { ObjectId } from "./schemas.ts";
32
32
  * from an object, which is every `getObject(id, { schema })` read.
33
33
  */
34
34
  export declare const bcs: <T extends Input, Input>(bcsType: BcsType<T, Input>, expectedType?: string) => Schema.Codec<T, Uint8Array>;
35
+ /**
36
+ * A BCS layout plus the mapping into a domain value, as one codec.
37
+ *
38
+ * This is the shape every extension writes by hand and writes slightly
39
+ * differently: parse the bytes with a layout, then hand the raw struct to a
40
+ * constructor or a mapping function that may throw (an id that has to be
41
+ * branded, a `bigint` that has to be range-checked, a discriminant that has to
42
+ * become a union). Written out it is `SuiSchema.bcs(...)` piped into a
43
+ * `Schema.decodeTo` with a `transformOrFail` and an `Effect.try`, and the part
44
+ * that gets forgotten is turning the thrown value into a schema issue, so the
45
+ * failure arrives as a defect instead of a `DecodeError`.
46
+ *
47
+ * `map` is called with whatever the layout parsed. Returning a value decodes
48
+ * it; **throwing** fails the decode, and the thrown value's message becomes the
49
+ * `DecodeError.issue` the caller sees, with the expected type already on it.
50
+ * The result is a `Schema.Codec<A, Uint8Array>` like any other: pass it as
51
+ * `sui.getObject(id, { schema })`, and the Move type check still runs first
52
+ * because the annotation {@link bcs} leaves behind survives the composition.
53
+ *
54
+ * Encoding is not supported: a mapping function has no inverse, and inventing
55
+ * one silently is worse than saying so. Encode with the layout itself when you
56
+ * need bytes back.
57
+ *
58
+ * Fails with: `DecodeError` (through the schema), when the bytes do not parse
59
+ * or `map` throws.
60
+ *
61
+ * @since 0.1.1
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { ObjectId, SuiSchema } from "@unconfirmed/sui-effect"
66
+ *
67
+ * class Escrow {
68
+ * constructor(readonly id: ObjectId, readonly amount: bigint) {}
69
+ * }
70
+ *
71
+ * const EscrowContent = SuiSchema.decodeWith(
72
+ * EscrowLayout,
73
+ * `${packageId}::escrow::Escrow`,
74
+ * (raw) => new Escrow(ObjectId.normalize(raw.id), BigInt(raw.amount))
75
+ * )
76
+ * ```
77
+ */
78
+ export declare const decodeWith: <T extends Input, Input, A>(bcsType: BcsType<T, Input>, expectedType: string | undefined, map: (parsed: T) => A) => Schema.Codec<A, Uint8Array>;
35
79
  /**
36
80
  * The normalized Move type a codec built by {@link bcs} expects, or `undefined`
37
81
  * for any other codec. `Sui.getObject` compares it with the object's own type
@@ -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,EAAE,MAAM,aAAa,CAAA;AACzC,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,CAgD5B,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,CA0B9B,CAAA"}
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,EAAE,MAAM,aAAa,CAAA;AACzC,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,CAgD5B,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,CAmC5B,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,CA0B9B,CAAA"}
@@ -59,6 +59,63 @@ export const bcs = (bcsType, expectedType) => {
59
59
  })
60
60
  }))).annotate(normalized === undefined ? {} : { [SUI_TYPE_ANNOTATION]: normalized });
61
61
  };
62
+ /**
63
+ * A BCS layout plus the mapping into a domain value, as one codec.
64
+ *
65
+ * This is the shape every extension writes by hand and writes slightly
66
+ * differently: parse the bytes with a layout, then hand the raw struct to a
67
+ * constructor or a mapping function that may throw (an id that has to be
68
+ * branded, a `bigint` that has to be range-checked, a discriminant that has to
69
+ * become a union). Written out it is `SuiSchema.bcs(...)` piped into a
70
+ * `Schema.decodeTo` with a `transformOrFail` and an `Effect.try`, and the part
71
+ * that gets forgotten is turning the thrown value into a schema issue, so the
72
+ * failure arrives as a defect instead of a `DecodeError`.
73
+ *
74
+ * `map` is called with whatever the layout parsed. Returning a value decodes
75
+ * it; **throwing** fails the decode, and the thrown value's message becomes the
76
+ * `DecodeError.issue` the caller sees, with the expected type already on it.
77
+ * The result is a `Schema.Codec<A, Uint8Array>` like any other: pass it as
78
+ * `sui.getObject(id, { schema })`, and the Move type check still runs first
79
+ * because the annotation {@link bcs} leaves behind survives the composition.
80
+ *
81
+ * Encoding is not supported: a mapping function has no inverse, and inventing
82
+ * one silently is worse than saying so. Encode with the layout itself when you
83
+ * need bytes back.
84
+ *
85
+ * Fails with: `DecodeError` (through the schema), when the bytes do not parse
86
+ * or `map` throws.
87
+ *
88
+ * @since 0.1.1
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * import { ObjectId, SuiSchema } from "@unconfirmed/sui-effect"
93
+ *
94
+ * class Escrow {
95
+ * constructor(readonly id: ObjectId, readonly amount: bigint) {}
96
+ * }
97
+ *
98
+ * const EscrowContent = SuiSchema.decodeWith(
99
+ * EscrowLayout,
100
+ * `${packageId}::escrow::Escrow`,
101
+ * (raw) => new Escrow(ObjectId.normalize(raw.id), BigInt(raw.amount))
102
+ * )
103
+ * ```
104
+ */
105
+ export const decodeWith = (bcsType, expectedType, map) => {
106
+ const target = Schema.declare((_u) => true);
107
+ return bcs(bcsType, expectedType).pipe(Schema.decodeTo(target, SchemaTransformation.transformOrFail({
108
+ decode: (parsed, options) => Effect.try({
109
+ try: () => map(parsed),
110
+ catch: (cause) => new SchemaIssue.InvalidValue({
111
+ message: `Could not map ${expectedType ?? bcsType.name} into its domain value: ${String(cause)}`
112
+ }, parsed, options)
113
+ }),
114
+ encode: (value, options) => Effect.fail(new SchemaIssue.Forbidden({
115
+ message: `${expectedType ?? bcsType.name} was built with SuiSchema.decodeWith, which has no encoder: serialize with the BCS layout instead`
116
+ }, value, options))
117
+ })));
118
+ };
62
119
  const MAX_ENCODING_DEPTH = 32;
63
120
  /**
64
121
  * Walks the encoding chain looking for the annotation {@link bcs} leaves
@@ -1 +1 @@
1
- {"version":3,"file":"bcs.js","sourceRoot":"","sources":["../../src/domain/bcs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bcs.js","sourceRoot":"","sources":["../../src/domain/bcs.ts"],"names":[],"mappings":"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"}