@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/LLMS.md
CHANGED
|
@@ -17,7 +17,7 @@ contract for building an extension package on top of it.
|
|
|
17
17
|
## `@unconfirmed/sui-effect`
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
84 exported symbols.
|
|
21
21
|
|
|
22
22
|
### `Balance` (const)
|
|
23
23
|
|
|
@@ -229,14 +229,43 @@ The return values and mutated references of one command. Mirrors `SuiClientTypes
|
|
|
229
229
|
|
|
230
230
|
```ts
|
|
231
231
|
export declare class DecodeError extends DecodeError_base {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
readonly expectedType: string | undefined
|
|
232
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
233
|
+
get message(): string;
|
|
235
234
|
}
|
|
236
235
|
```
|
|
237
236
|
|
|
238
237
|
BCS content or a schema boundary did not decode.
|
|
239
238
|
|
|
239
|
+
`kind` says which of the three (`"type"`, `"bytes"`, `"shape"`) and is what a
|
|
240
|
+
consumer branches on; `issue` is the sentence for a human and is not stable.
|
|
241
|
+
It defaults to `"shape"` when neither a constructor nor an encoded value
|
|
242
|
+
carries one, so an extension that builds a `DecodeError` with no `kind` still
|
|
243
|
+
compiles and still answers the question conservatively.
|
|
244
|
+
|
|
245
|
+
### `DecodeKind` (const)
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
declare const DecodeKind: Schema
|
|
249
|
+
// decodes to: "bytes" | "type" | "shape"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Which of the three things that can go wrong at a decode boundary went wrong.
|
|
253
|
+
|
|
254
|
+
- `"type"`: the object, the field or the event **is not of the expected Move
|
|
255
|
+
type**. The bytes were never parsed. This is the one a caller answers with
|
|
256
|
+
"that is not one of mine" — a 404 for a foreign object, a `filter` over a
|
|
257
|
+
heterogeneous list — and the one it is safe to swallow.
|
|
258
|
+
- `"bytes"`: the type matched and the **BCS parse failed**, or left trailing
|
|
259
|
+
bytes. Either the layout this package was built with is not the layout the
|
|
260
|
+
package on chain writes, or the object is corrupt. Never safe to swallow.
|
|
261
|
+
- `"shape"`: a **domain schema** refused a value that was already parsed or
|
|
262
|
+
that came from the node as JSON — a missing field in a node response, a
|
|
263
|
+
number that is not a timestamp, a simulation with no such command. A bug
|
|
264
|
+
here is in this library, the node, or the caller's expectations.
|
|
265
|
+
|
|
266
|
+
Branch on this, never on `DecodeError`'s `issue`: `issue` is a human
|
|
267
|
+
sentence and its wording changes between releases.
|
|
268
|
+
|
|
240
269
|
### `Digest` (const)
|
|
241
270
|
|
|
242
271
|
```ts
|
|
@@ -258,8 +287,8 @@ declare const DynamicField: Schema
|
|
|
258
287
|
// readonly type: string;
|
|
259
288
|
// readonly bcs: Uint8Array<ArrayBufferLike>;
|
|
260
289
|
// };
|
|
261
|
-
// readonly fieldId: ObjectId;
|
|
262
290
|
// readonly type: string;
|
|
291
|
+
// readonly fieldId: ObjectId;
|
|
263
292
|
// readonly name: {
|
|
264
293
|
// readonly type: string;
|
|
265
294
|
// readonly bcs: Uint8Array<ArrayBufferLike>;
|
|
@@ -279,8 +308,8 @@ declare const DynamicFieldEntry: Schema
|
|
|
279
308
|
// decodes to:
|
|
280
309
|
// {
|
|
281
310
|
// readonly $kind: "DynamicField" | "DynamicObject";
|
|
282
|
-
// readonly fieldId: ObjectId;
|
|
283
311
|
// readonly type: string;
|
|
312
|
+
// readonly fieldId: ObjectId;
|
|
284
313
|
// readonly name: {
|
|
285
314
|
// readonly type: string;
|
|
286
315
|
// readonly bcs: Uint8Array<ArrayBufferLike>;
|
|
@@ -305,10 +334,18 @@ The BCS-encoded name of a dynamic field. Mirrors `SuiClientTypes.DynamicFieldNam
|
|
|
305
334
|
|
|
306
335
|
```ts
|
|
307
336
|
declare const Event: Schema
|
|
308
|
-
// decodes to: { readonly
|
|
337
|
+
// decodes to: { readonly sender: SuiAddress; readonly bcs: Uint8Array<ArrayBufferLike>; readonly packageId: ObjectId; readonly module: string; readonly eventType: string; readonly json?: unknown; }
|
|
309
338
|
```
|
|
310
339
|
|
|
311
|
-
An emitted Move event. Mirrors `SuiClientTypes.Event
|
|
340
|
+
An emitted Move event. Mirrors `SuiClientTypes.Event` with the branded ids
|
|
341
|
+
this package uses.
|
|
342
|
+
|
|
343
|
+
The decode a caller wants is `SuiSchema.decode(codec, event.bcs)`, which
|
|
344
|
+
gives a typed value; `json` is the node's own rendering and is **not**
|
|
345
|
+
something to build on — it is absent on most transports and its shape follows
|
|
346
|
+
whatever the node feels like. It is kept only when the source carried it,
|
|
347
|
+
which in practice means a relay or sponsor envelope decoded through
|
|
348
|
+
`Executed.fromPartial`, where it may be the only form of the event there is.
|
|
312
349
|
|
|
313
350
|
### `Executed` (class)
|
|
314
351
|
|
|
@@ -364,6 +401,16 @@ export declare class Executed extends Executed_base {
|
|
|
364
401
|
* Never fails.
|
|
365
402
|
*/
|
|
366
403
|
wrapped(): ReadonlyArray<ChangedRef>;
|
|
404
|
+
/**
|
|
405
|
+
* Whether this change wrote an object, treating `Unknown` as "the envelope
|
|
406
|
+
* did not say".
|
|
407
|
+
*
|
|
408
|
+
* A node always reports the output state; a reduced envelope from a relay or
|
|
409
|
+
* a sponsor often reports nothing but the id and the id operation, and
|
|
410
|
+
* {@link Executed.fromPartial} leaves what it was not told as `Unknown`
|
|
411
|
+
* rather than inventing `ObjectWrite`. Reading `Unknown` as "not an object
|
|
412
|
+
* write" would make `created()` silently empty for exactly those envelopes.
|
|
413
|
+
*/
|
|
367
414
|
/**
|
|
368
415
|
* Packages this transaction published (`PackageWrite` plus `Created`), as
|
|
369
416
|
* full refs like every other accessor. A package's `type` is the literal
|
|
@@ -376,6 +423,53 @@ export declare class Executed extends Executed_base {
|
|
|
376
423
|
balanceChange(address: SuiAddress, coinType: CoinType): bigint;
|
|
377
424
|
/** Computation plus storage less the storage rebate, in MIST. Can be negative. Never fails. */
|
|
378
425
|
get gasUsedTotal(): bigint;
|
|
426
|
+
/**
|
|
427
|
+
* An `Executed` from the SDK's own `TransactionResult`, read with
|
|
428
|
+
* {@link EXECUTE_INCLUDE}.
|
|
429
|
+
*
|
|
430
|
+
* This is what `Tx.submit` uses, exported so a caller holding a result from
|
|
431
|
+
* somewhere else — `client.core.executeTransaction`, a sponsor's SDK call —
|
|
432
|
+
* can get the accessors without re-implementing the decode.
|
|
433
|
+
*
|
|
434
|
+
* Fails with: `ExecutionFailed` (the transaction applied and failed),
|
|
435
|
+
* `DecodeError` (the response does not carry the include set).
|
|
436
|
+
*
|
|
437
|
+
* @since 0.1.2
|
|
438
|
+
*/
|
|
439
|
+
static readonly fromTransactionResult: (result: SuiClientTypes.TransactionResult<typeof EXECUTE_INCLUDE>) => Effect.Effect<Executed, ExecutionFailed | DecodeError>;
|
|
440
|
+
/**
|
|
441
|
+
* An `Executed` from a **reduced** execute envelope: what a relay, a sponsor
|
|
442
|
+
* or another service hands back, over JSON, after submitting on your behalf.
|
|
443
|
+
*
|
|
444
|
+
* Such an envelope is rarely the SDK's full include set. Everything optional
|
|
445
|
+
* is filled in with "the node did not say" rather than refused:
|
|
446
|
+
*
|
|
447
|
+
* - `changedObjects` entries need only `objectId` and `idOperation`; the
|
|
448
|
+
* version, digest and owner on either side default to `null`, and
|
|
449
|
+
* `outputState` defaults to `ObjectWrite` (`DoesNotExist` for a
|
|
450
|
+
* `Deleted`), so {@link created} and {@link deleted} classify correctly
|
|
451
|
+
* from the id operation alone.
|
|
452
|
+
* - `objectTypes` defaults to `{}`. **The type filters need it**:
|
|
453
|
+
* `created(type)`, `mutated(type)` and `expectCreated(type)` can only
|
|
454
|
+
* match a change whose type the envelope carried, so without
|
|
455
|
+
* `objectTypes` they return nothing. `created()` with no argument, and
|
|
456
|
+
* {@link createdWhere}, still list every created id.
|
|
457
|
+
* - `balanceChanges` and `events` default to `[]`, `checkpoint` and
|
|
458
|
+
* `timestampMs` to `null`, `gasUsed` to zeros, and `effects.status` to
|
|
459
|
+
* success.
|
|
460
|
+
* - **JSON spellings are accepted** where the SDK's types are not JSON:
|
|
461
|
+
* `bcs` as base64 or as an array of byte values as well as a
|
|
462
|
+
* `Uint8Array`, and every `u64` (versions, balances, gas, `checkpoint`)
|
|
463
|
+
* as a number or a `bigint` as well as the decimal string the wire uses.
|
|
464
|
+
*
|
|
465
|
+
* An envelope with no usable digest, or whose values are the wrong shape
|
|
466
|
+
* rather than merely absent, fails: absence is filled in, nonsense is not.
|
|
467
|
+
*
|
|
468
|
+
* Fails with: `DecodeError`.
|
|
469
|
+
*
|
|
470
|
+
* @since 0.1.2
|
|
471
|
+
*/
|
|
472
|
+
static readonly fromPartial: (envelope: unknown) => Effect.Effect<Executed, DecodeError>;
|
|
379
473
|
/**
|
|
380
474
|
* The single object of this type the transaction created.
|
|
381
475
|
*
|
|
@@ -389,220 +483,22 @@ export declare class Executed extends Executed_base {
|
|
|
389
483
|
A transaction the network executed, built from the fixed execute include set:
|
|
390
484
|
effects, events, balance changes and object types.
|
|
391
485
|
|
|
486
|
+
**`events` is `ReadonlyArray<Event>`, not `SuiClientTypes.Event[]`.** It is
|
|
487
|
+
that type minus `json`: `packageId`, `module`, `sender`, `eventType` and
|
|
488
|
+
`bcs`, with the branded ids this package uses. The SDK's `json` is dropped on
|
|
489
|
+
purpose — it is the node's own rendering, it is absent on most transports,
|
|
490
|
+
and the decode a caller wants is `SuiSchema.decode(codec, event.bcs)`, which
|
|
491
|
+
gives a typed value rather than a shape that changes with the node. Code
|
|
492
|
+
typed against the SDK's `Event[]` therefore does not accept these; take
|
|
493
|
+
`ReadonlyArray<Event>` from `@unconfirmed/sui-effect`, or map the fields you
|
|
494
|
+
need.
|
|
495
|
+
|
|
392
496
|
### `ExecutionFailed` (class)
|
|
393
497
|
|
|
394
498
|
```ts
|
|
395
499
|
export declare class ExecutionFailed extends ExecutionFailed_base {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
readonly $kind: "MoveAbort";
|
|
399
|
-
readonly MoveAbort: {
|
|
400
|
-
readonly abortCode: bigint;
|
|
401
|
-
readonly location?: {
|
|
402
|
-
readonly function?: number | undefined;
|
|
403
|
-
readonly module?: string | undefined;
|
|
404
|
-
readonly package?: string | undefined;
|
|
405
|
-
readonly functionName?: string | undefined;
|
|
406
|
-
readonly instruction?: number | undefined;
|
|
407
|
-
} | undefined;
|
|
408
|
-
readonly cleverError?: {
|
|
409
|
-
readonly errorCode?: number | undefined;
|
|
410
|
-
readonly lineNumber?: number | undefined;
|
|
411
|
-
readonly constantName?: string | undefined;
|
|
412
|
-
readonly constantType?: string | undefined;
|
|
413
|
-
readonly value?: string | undefined;
|
|
414
|
-
} | undefined;
|
|
415
|
-
};
|
|
416
|
-
} | {
|
|
417
|
-
readonly $kind: "SizeError";
|
|
418
|
-
readonly SizeError: {
|
|
419
|
-
readonly name: string;
|
|
420
|
-
readonly size: number;
|
|
421
|
-
readonly maxSize: number;
|
|
422
|
-
};
|
|
423
|
-
} | {
|
|
424
|
-
readonly $kind: "CommandArgumentError";
|
|
425
|
-
readonly CommandArgumentError: {
|
|
426
|
-
readonly argument: number;
|
|
427
|
-
readonly name: string;
|
|
428
|
-
};
|
|
429
|
-
} | {
|
|
430
|
-
readonly $kind: "TypeArgumentError";
|
|
431
|
-
readonly TypeArgumentError: {
|
|
432
|
-
readonly typeArgument: number;
|
|
433
|
-
readonly name: string;
|
|
434
|
-
};
|
|
435
|
-
} | {
|
|
436
|
-
readonly $kind: "PackageUpgradeError";
|
|
437
|
-
readonly PackageUpgradeError: {
|
|
438
|
-
readonly name: string;
|
|
439
|
-
readonly digest?: string | undefined;
|
|
440
|
-
readonly packageId?: string | undefined;
|
|
441
|
-
};
|
|
442
|
-
} | {
|
|
443
|
-
readonly $kind: "IndexError";
|
|
444
|
-
readonly IndexError: {
|
|
445
|
-
readonly index?: number | undefined;
|
|
446
|
-
readonly subresult?: number | undefined;
|
|
447
|
-
};
|
|
448
|
-
} | {
|
|
449
|
-
readonly $kind: "CoinDenyListError";
|
|
450
|
-
readonly CoinDenyListError: {
|
|
451
|
-
readonly coinType: string;
|
|
452
|
-
readonly name: string;
|
|
453
|
-
readonly address?: string | undefined;
|
|
454
|
-
};
|
|
455
|
-
} | {
|
|
456
|
-
readonly $kind: "CongestedObjects";
|
|
457
|
-
readonly CongestedObjects: {
|
|
458
|
-
readonly name: string;
|
|
459
|
-
readonly objects: readonly string[];
|
|
460
|
-
};
|
|
461
|
-
} | {
|
|
462
|
-
readonly $kind: "ObjectIdError";
|
|
463
|
-
readonly ObjectIdError: {
|
|
464
|
-
readonly objectId: string;
|
|
465
|
-
readonly name?: string | undefined;
|
|
466
|
-
};
|
|
467
|
-
} | {
|
|
468
|
-
readonly $kind: "Unknown";
|
|
469
|
-
}
|
|
470
|
-
readonly effects: {
|
|
471
|
-
readonly version: number;
|
|
472
|
-
readonly status: {
|
|
473
|
-
readonly success: boolean;
|
|
474
|
-
};
|
|
475
|
-
readonly gasUsed: {
|
|
476
|
-
readonly computationCost: Mist;
|
|
477
|
-
readonly storageCost: Mist;
|
|
478
|
-
readonly storageRebate: Mist;
|
|
479
|
-
readonly nonRefundableStorageFee: Mist;
|
|
480
|
-
};
|
|
481
|
-
readonly transactionDigest: Digest;
|
|
482
|
-
readonly gasObject: {
|
|
483
|
-
readonly objectId: ObjectId;
|
|
484
|
-
readonly inputState: "Unknown" | "DoesNotExist" | "Exists";
|
|
485
|
-
readonly inputVersion: Version | null;
|
|
486
|
-
readonly inputDigest: string | null;
|
|
487
|
-
readonly inputOwner: {
|
|
488
|
-
readonly $kind: "AddressOwner";
|
|
489
|
-
readonly AddressOwner: SuiAddress;
|
|
490
|
-
} | {
|
|
491
|
-
readonly $kind: "ObjectOwner";
|
|
492
|
-
readonly ObjectOwner: ObjectId;
|
|
493
|
-
} | {
|
|
494
|
-
readonly $kind: "Shared";
|
|
495
|
-
readonly Shared: {
|
|
496
|
-
readonly initialSharedVersion: Version;
|
|
497
|
-
};
|
|
498
|
-
} | {
|
|
499
|
-
readonly $kind: "Immutable";
|
|
500
|
-
readonly Immutable: true;
|
|
501
|
-
} | {
|
|
502
|
-
readonly $kind: "ConsensusAddressOwner";
|
|
503
|
-
readonly ConsensusAddressOwner: {
|
|
504
|
-
readonly startVersion: Version;
|
|
505
|
-
readonly owner: SuiAddress;
|
|
506
|
-
};
|
|
507
|
-
} | {
|
|
508
|
-
readonly $kind: "Unknown";
|
|
509
|
-
} | null;
|
|
510
|
-
readonly outputState: "Unknown" | "DoesNotExist" | "ObjectWrite" | "PackageWrite" | "AccumulatorWriteV1";
|
|
511
|
-
readonly outputVersion: Version | null;
|
|
512
|
-
readonly outputDigest: string | null;
|
|
513
|
-
readonly outputOwner: {
|
|
514
|
-
readonly $kind: "AddressOwner";
|
|
515
|
-
readonly AddressOwner: SuiAddress;
|
|
516
|
-
} | {
|
|
517
|
-
readonly $kind: "ObjectOwner";
|
|
518
|
-
readonly ObjectOwner: ObjectId;
|
|
519
|
-
} | {
|
|
520
|
-
readonly $kind: "Shared";
|
|
521
|
-
readonly Shared: {
|
|
522
|
-
readonly initialSharedVersion: Version;
|
|
523
|
-
};
|
|
524
|
-
} | {
|
|
525
|
-
readonly $kind: "Immutable";
|
|
526
|
-
readonly Immutable: true;
|
|
527
|
-
} | {
|
|
528
|
-
readonly $kind: "ConsensusAddressOwner";
|
|
529
|
-
readonly ConsensusAddressOwner: {
|
|
530
|
-
readonly startVersion: Version;
|
|
531
|
-
readonly owner: SuiAddress;
|
|
532
|
-
};
|
|
533
|
-
} | {
|
|
534
|
-
readonly $kind: "Unknown";
|
|
535
|
-
} | null;
|
|
536
|
-
readonly idOperation: "None" | "Unknown" | "Created" | "Deleted";
|
|
537
|
-
} | null;
|
|
538
|
-
readonly eventsDigest: string | null;
|
|
539
|
-
readonly dependencies: readonly string[];
|
|
540
|
-
readonly lamportVersion: Version | null;
|
|
541
|
-
readonly changedObjects: readonly {
|
|
542
|
-
readonly objectId: ObjectId;
|
|
543
|
-
readonly inputState: "Unknown" | "DoesNotExist" | "Exists";
|
|
544
|
-
readonly inputVersion: Version | null;
|
|
545
|
-
readonly inputDigest: string | null;
|
|
546
|
-
readonly inputOwner: {
|
|
547
|
-
readonly $kind: "AddressOwner";
|
|
548
|
-
readonly AddressOwner: SuiAddress;
|
|
549
|
-
} | {
|
|
550
|
-
readonly $kind: "ObjectOwner";
|
|
551
|
-
readonly ObjectOwner: ObjectId;
|
|
552
|
-
} | {
|
|
553
|
-
readonly $kind: "Shared";
|
|
554
|
-
readonly Shared: {
|
|
555
|
-
readonly initialSharedVersion: Version;
|
|
556
|
-
};
|
|
557
|
-
} | {
|
|
558
|
-
readonly $kind: "Immutable";
|
|
559
|
-
readonly Immutable: true;
|
|
560
|
-
} | {
|
|
561
|
-
readonly $kind: "ConsensusAddressOwner";
|
|
562
|
-
readonly ConsensusAddressOwner: {
|
|
563
|
-
readonly startVersion: Version;
|
|
564
|
-
readonly owner: SuiAddress;
|
|
565
|
-
};
|
|
566
|
-
} | {
|
|
567
|
-
readonly $kind: "Unknown";
|
|
568
|
-
} | null;
|
|
569
|
-
readonly outputState: "Unknown" | "DoesNotExist" | "ObjectWrite" | "PackageWrite" | "AccumulatorWriteV1";
|
|
570
|
-
readonly outputVersion: Version | null;
|
|
571
|
-
readonly outputDigest: string | null;
|
|
572
|
-
readonly outputOwner: {
|
|
573
|
-
readonly $kind: "AddressOwner";
|
|
574
|
-
readonly AddressOwner: SuiAddress;
|
|
575
|
-
} | {
|
|
576
|
-
readonly $kind: "ObjectOwner";
|
|
577
|
-
readonly ObjectOwner: ObjectId;
|
|
578
|
-
} | {
|
|
579
|
-
readonly $kind: "Shared";
|
|
580
|
-
readonly Shared: {
|
|
581
|
-
readonly initialSharedVersion: Version;
|
|
582
|
-
};
|
|
583
|
-
} | {
|
|
584
|
-
readonly $kind: "Immutable";
|
|
585
|
-
readonly Immutable: true;
|
|
586
|
-
} | {
|
|
587
|
-
readonly $kind: "ConsensusAddressOwner";
|
|
588
|
-
readonly ConsensusAddressOwner: {
|
|
589
|
-
readonly startVersion: Version;
|
|
590
|
-
readonly owner: SuiAddress;
|
|
591
|
-
};
|
|
592
|
-
} | {
|
|
593
|
-
readonly $kind: "Unknown";
|
|
594
|
-
} | null;
|
|
595
|
-
readonly idOperation: "None" | "Unknown" | "Created" | "Deleted";
|
|
596
|
-
}[];
|
|
597
|
-
readonly unchangedConsensusObjects: readonly {
|
|
598
|
-
readonly kind: "Unknown" | "ReadOnlyRoot" | "MutateConsensusStreamEnded" | "ReadConsensusStreamEnded" | "Cancelled" | "PerEpochConfig";
|
|
599
|
-
readonly objectId: ObjectId;
|
|
600
|
-
readonly version: Version | null;
|
|
601
|
-
readonly digest: string | null;
|
|
602
|
-
}[];
|
|
603
|
-
readonly auxiliaryDataDigest: string | null;
|
|
604
|
-
}
|
|
605
|
-
readonly command: number | undefined
|
|
500
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
501
|
+
get message(): string;
|
|
606
502
|
}
|
|
607
503
|
```
|
|
608
504
|
|
|
@@ -710,8 +606,8 @@ representation of an on-chain failure.
|
|
|
710
606
|
|
|
711
607
|
```ts
|
|
712
608
|
export declare class ExtensionNotReady extends ExtensionNotReady_base {
|
|
713
|
-
|
|
714
|
-
|
|
609
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
610
|
+
get message(): string;
|
|
715
611
|
}
|
|
716
612
|
```
|
|
717
613
|
|
|
@@ -749,8 +645,8 @@ What can go wrong reading one object with a schema.
|
|
|
749
645
|
|
|
750
646
|
```ts
|
|
751
647
|
export declare class GraphQLUnavailable extends GraphQLUnavailable_base {
|
|
752
|
-
|
|
753
|
-
|
|
648
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
649
|
+
get message(): string;
|
|
754
650
|
}
|
|
755
651
|
```
|
|
756
652
|
|
|
@@ -786,7 +682,8 @@ the documented retry idiom to send again on no evidence at all.
|
|
|
786
682
|
|
|
787
683
|
```ts
|
|
788
684
|
export declare class JournalError extends JournalError_base {
|
|
789
|
-
|
|
685
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
686
|
+
get message(): string;
|
|
790
687
|
}
|
|
791
688
|
```
|
|
792
689
|
|
|
@@ -854,8 +751,8 @@ The network a client is pointed at. Mirrors `SuiClientTypes.Network`.
|
|
|
854
751
|
|
|
855
752
|
```ts
|
|
856
753
|
export declare class NetworkMismatch extends NetworkMismatch_base {
|
|
857
|
-
|
|
858
|
-
|
|
754
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
755
|
+
get message(): string;
|
|
859
756
|
}
|
|
860
757
|
```
|
|
861
758
|
|
|
@@ -865,8 +762,8 @@ The chain identifier the node reported is not the one the layer was built for.
|
|
|
865
762
|
|
|
866
763
|
```ts
|
|
867
764
|
export declare class NotApplied extends NotApplied_base {
|
|
868
|
-
|
|
869
|
-
|
|
765
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
766
|
+
get message(): string;
|
|
870
767
|
}
|
|
871
768
|
```
|
|
872
769
|
|
|
@@ -900,8 +797,8 @@ cannot drift.
|
|
|
900
797
|
|
|
901
798
|
```ts
|
|
902
799
|
export declare class ObjectDeleted extends ObjectDeleted_base {
|
|
903
|
-
|
|
904
|
-
|
|
800
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
801
|
+
get message(): string;
|
|
905
802
|
}
|
|
906
803
|
```
|
|
907
804
|
|
|
@@ -967,8 +864,17 @@ The failures of an object lookup.
|
|
|
967
864
|
|
|
968
865
|
```ts
|
|
969
866
|
export declare class ObjectNotFound extends ObjectNotFound_base {
|
|
970
|
-
|
|
971
|
-
|
|
867
|
+
/**
|
|
868
|
+
* The one actionable line `SuiError.describe` produces for this error.
|
|
869
|
+
*
|
|
870
|
+
* `Schema.TaggedError` gives every class the `Error` constructor and no
|
|
871
|
+
* message of its own, so `error.message` was the empty string — and a
|
|
872
|
+
* consumer that surfaces `.message` (a log line, a UI, another library's
|
|
873
|
+
* error formatter) showed nothing at all. A getter rather than a schema
|
|
874
|
+
* field, so it is always in step with `describe`, costs nothing to
|
|
875
|
+
* construct, and stays out of `SuiError.toJson`'s encoding.
|
|
876
|
+
*/
|
|
877
|
+
get message(): string;
|
|
972
878
|
}
|
|
973
879
|
```
|
|
974
880
|
|
|
@@ -1029,8 +935,8 @@ readable object like any other.
|
|
|
1029
935
|
|
|
1030
936
|
```ts
|
|
1031
937
|
export declare class ObjectUnavailable extends ObjectUnavailable_base {
|
|
1032
|
-
|
|
1033
|
-
|
|
938
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
939
|
+
get message(): string;
|
|
1034
940
|
}
|
|
1035
941
|
```
|
|
1036
942
|
|
|
@@ -1045,6 +951,22 @@ export type Outcome = "applied" | "not_applied" | "unknown";
|
|
|
1045
951
|
What a failure says about the transaction it came from, on the axis a caller
|
|
1046
952
|
or a wrapper script acts on.
|
|
1047
953
|
|
|
954
|
+
### `OutcomePhase` (type)
|
|
955
|
+
|
|
956
|
+
```ts
|
|
957
|
+
export type OutcomePhase = "pre-submit" | "post-submit";
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
Where in the lifecycle a failure was caught, which is the only thing that
|
|
961
|
+
can classify an error the taxonomy does not own.
|
|
962
|
+
|
|
963
|
+
`"post-submit"` (the default, and the 0.1.1 behaviour) is "bytes may have
|
|
964
|
+
gone out": a tag nobody here recognises proves nothing, so the answer is
|
|
965
|
+
`"unknown"`. `"pre-submit"` is a failure caught while **building, simulating
|
|
966
|
+
or signing** — an extension's own `PriceTooLow`, a validation error from the
|
|
967
|
+
caller's code — where nothing has been sent by construction and the honest
|
|
968
|
+
answer is `"not_applied"`.
|
|
969
|
+
|
|
1048
970
|
### `Owner` (const)
|
|
1049
971
|
|
|
1050
972
|
```ts
|
|
@@ -1178,7 +1100,8 @@ The expiration the transaction was built with rides along, because it is what
|
|
|
1178
1100
|
|
|
1179
1101
|
```ts
|
|
1180
1102
|
export declare class SigningError extends SigningError_base {
|
|
1181
|
-
|
|
1103
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
1104
|
+
get message(): string;
|
|
1182
1105
|
}
|
|
1183
1106
|
```
|
|
1184
1107
|
|
|
@@ -1327,11 +1250,12 @@ declare const Simulation: Schema
|
|
|
1327
1250
|
// readonly auxiliaryDataDigest: string | null;
|
|
1328
1251
|
// };
|
|
1329
1252
|
// readonly events: readonly {
|
|
1253
|
+
// readonly sender: SuiAddress;
|
|
1254
|
+
// readonly bcs: Uint8Array<ArrayBufferLike>;
|
|
1330
1255
|
// readonly packageId: ObjectId;
|
|
1331
1256
|
// readonly module: string;
|
|
1332
|
-
// readonly sender: SuiAddress;
|
|
1333
1257
|
// readonly eventType: string;
|
|
1334
|
-
// readonly
|
|
1258
|
+
// readonly json?: unknown;
|
|
1335
1259
|
// }[];
|
|
1336
1260
|
// readonly balanceChanges: readonly {
|
|
1337
1261
|
// readonly coinType: CoinType;
|
|
@@ -1460,46 +1384,8 @@ decode so `0x2::sui::SUI` and its padded form compare equal.
|
|
|
1460
1384
|
|
|
1461
1385
|
```ts
|
|
1462
1386
|
export declare class SubmissionUnknown extends SubmissionUnknown_base {
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
readonly signed: {
|
|
1466
|
-
readonly digest: Digest;
|
|
1467
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
1468
|
-
readonly sender: SuiAddress;
|
|
1469
|
-
readonly signatures: readonly Signature[];
|
|
1470
|
-
readonly expiration?: {
|
|
1471
|
-
readonly $kind: "None";
|
|
1472
|
-
readonly None: true;
|
|
1473
|
-
} | {
|
|
1474
|
-
readonly $kind: "Epoch";
|
|
1475
|
-
readonly Epoch: bigint;
|
|
1476
|
-
} | {
|
|
1477
|
-
readonly $kind: "ValidDuring";
|
|
1478
|
-
readonly ValidDuring: {
|
|
1479
|
-
readonly minEpoch: bigint | null;
|
|
1480
|
-
readonly maxEpoch: bigint | null;
|
|
1481
|
-
readonly minTimestamp: bigint | null;
|
|
1482
|
-
readonly maxTimestamp: bigint | null;
|
|
1483
|
-
readonly chain: string;
|
|
1484
|
-
readonly nonce: number;
|
|
1485
|
-
};
|
|
1486
|
-
} | {
|
|
1487
|
-
readonly $kind: "Validity";
|
|
1488
|
-
readonly Validity: {
|
|
1489
|
-
readonly allowedProposers: {
|
|
1490
|
-
readonly epoch: bigint;
|
|
1491
|
-
readonly proposers: readonly number[];
|
|
1492
|
-
} | null;
|
|
1493
|
-
readonly minEpoch: bigint | null;
|
|
1494
|
-
readonly maxEpoch: bigint | null;
|
|
1495
|
-
readonly minTimestamp: bigint | null;
|
|
1496
|
-
readonly maxTimestamp: bigint | null;
|
|
1497
|
-
readonly chain: string;
|
|
1498
|
-
readonly nonce: number;
|
|
1499
|
-
};
|
|
1500
|
-
} | undefined;
|
|
1501
|
-
readonly chain?: string | undefined;
|
|
1502
|
-
} | undefined
|
|
1387
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
1388
|
+
get message(): string;
|
|
1503
1389
|
}
|
|
1504
1390
|
```
|
|
1505
1391
|
|
|
@@ -1826,6 +1712,26 @@ export interface SuiLayerOptions {
|
|
|
1826
1712
|
* network are regenerated, so set this when the program must pin one.
|
|
1827
1713
|
*/
|
|
1828
1714
|
readonly chainId?: string;
|
|
1715
|
+
/**
|
|
1716
|
+
* How to retry the one `getChainIdentifier` this layer makes, when it fails
|
|
1717
|
+
* with a **retryable** `TransportError`.
|
|
1718
|
+
*
|
|
1719
|
+
* It matters more than one round trip usually would, because of what holds
|
|
1720
|
+
* the result: a `ManagedRuntime` — which is how a browser app, a Worker or a
|
|
1721
|
+
* Durable Object keeps one runtime per isolate — **memoizes the layer build,
|
|
1722
|
+
* failure included, for its whole lifetime**. One unlucky request at boot and
|
|
1723
|
+
* every later use of that runtime fails with the same stale
|
|
1724
|
+
* `TransportError`, until something disposes it. A short schedule here is the
|
|
1725
|
+
* cheap half of the cure; disposing the runtime when its build failed is the
|
|
1726
|
+
* other half (see the guide's "Application consumers" section), and
|
|
1727
|
+
* `layerNoDepsPinned` avoids the read altogether when the chain id is already
|
|
1728
|
+
* known.
|
|
1729
|
+
*
|
|
1730
|
+
* Unset, the read is made once, as it always was.
|
|
1731
|
+
*
|
|
1732
|
+
* @since 0.1.2
|
|
1733
|
+
*/
|
|
1734
|
+
readonly retry?: Schedule.Schedule<unknown, TransportError>;
|
|
1829
1735
|
}
|
|
1830
1736
|
```
|
|
1831
1737
|
|
|
@@ -2063,6 +1969,27 @@ export interface SuiService {
|
|
|
2063
1969
|
*
|
|
2064
1970
|
* Fails with: `ObjectNotFound`, `ObjectDeleted`, `ObjectUnavailable`,
|
|
2065
1971
|
* `DecodeError`, `TransportError`.
|
|
1972
|
+
*
|
|
1973
|
+
* @since 0.1.2
|
|
1974
|
+
*/
|
|
1975
|
+
readonly getObjectsStrict: {
|
|
1976
|
+
<S>(ids: ReadonlyArray<ObjectId>, opts: {
|
|
1977
|
+
readonly schema: Schema.Codec<S, Uint8Array>;
|
|
1978
|
+
readonly expectedType?: string;
|
|
1979
|
+
}): Effect.Effect<ReadonlyArray<SuiObject<S>>, BatchItemError | TransportError>;
|
|
1980
|
+
(ids: ReadonlyArray<ObjectId>, opts?: {
|
|
1981
|
+
readonly schema?: undefined;
|
|
1982
|
+
readonly expectedType?: string;
|
|
1983
|
+
}): Effect.Effect<ReadonlyArray<SuiObject<Uint8Array>>, BatchItemError | TransportError>;
|
|
1984
|
+
};
|
|
1985
|
+
/**
|
|
1986
|
+
* {@link getObjectsStrict} under its 0.1.0 name.
|
|
1987
|
+
*
|
|
1988
|
+
* `getObjectsOrFail` reads, out of context, as though failing were the point
|
|
1989
|
+
* — `getObjects(ids).orFail()` — rather than as the strictness of the read.
|
|
1990
|
+
* The two are the same function.
|
|
1991
|
+
*
|
|
1992
|
+
* @deprecated Use `getObjectsStrict`. This alias stays for 0.1.x.
|
|
2066
1993
|
*/
|
|
2067
1994
|
readonly getObjectsOrFail: {
|
|
2068
1995
|
<S>(ids: ReadonlyArray<ObjectId>, opts: {
|
|
@@ -2357,7 +2284,8 @@ The failures of a transaction lookup.
|
|
|
2357
2284
|
|
|
2358
2285
|
```ts
|
|
2359
2286
|
export declare class TransactionNotFound extends TransactionNotFound_base {
|
|
2360
|
-
|
|
2287
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
2288
|
+
get message(): string;
|
|
2361
2289
|
}
|
|
2362
2290
|
```
|
|
2363
2291
|
|
|
@@ -2398,6 +2326,8 @@ export declare class TransportError extends TransportError_base {
|
|
|
2398
2326
|
* ```
|
|
2399
2327
|
*/
|
|
2400
2328
|
static readonly fromUnknown: (method: string, cause: unknown, retryable?: boolean) => TransportError;
|
|
2329
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
2330
|
+
get message(): string;
|
|
2401
2331
|
}
|
|
2402
2332
|
```
|
|
2403
2333
|
|
|
@@ -2428,9 +2358,8 @@ Mirrors `SuiClientTypes.UnchangedConsensusObject`.
|
|
|
2428
2358
|
|
|
2429
2359
|
```ts
|
|
2430
2360
|
export declare class UnexpectedEffects extends UnexpectedEffects_base {
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
readonly found: readonly ObjectId[]
|
|
2361
|
+
/** The one actionable line `SuiError.describe` produces for this error. */
|
|
2362
|
+
get message(): string;
|
|
2434
2363
|
}
|
|
2435
2364
|
```
|
|
2436
2365
|
|
|
@@ -2577,7 +2506,7 @@ object has no output version, and nothing can be consumed without both.
|
|
|
2577
2506
|
## `@unconfirmed/sui-effect/tx`
|
|
2578
2507
|
|
|
2579
2508
|
|
|
2580
|
-
|
|
2509
|
+
42 exported symbols.
|
|
2581
2510
|
|
|
2582
2511
|
### `Built` (const)
|
|
2583
2512
|
|
|
@@ -2873,13 +2802,43 @@ export type ReconcileInput = Digest | Signed | SubmissionUnknown;
|
|
|
2873
2802
|
|
|
2874
2803
|
What `Tx.reconcile` can be asked about.
|
|
2875
2804
|
|
|
2876
|
-
### `Reconciled` (
|
|
2805
|
+
### `Reconciled` (const)
|
|
2877
2806
|
|
|
2878
2807
|
```ts
|
|
2879
|
-
|
|
2808
|
+
declare const Reconciled: Schema
|
|
2809
|
+
// decodes to:
|
|
2810
|
+
// {
|
|
2811
|
+
// readonly _tag: "NotApplied";
|
|
2812
|
+
// readonly error: NotApplied;
|
|
2813
|
+
// } | {
|
|
2814
|
+
// readonly _tag: "Executed";
|
|
2815
|
+
// readonly executed: Executed;
|
|
2816
|
+
// } | {
|
|
2817
|
+
// readonly _tag: "ExecutionFailed";
|
|
2818
|
+
// readonly error: ExecutionFailed;
|
|
2819
|
+
// } | {
|
|
2820
|
+
// readonly _tag: "SubmissionUnknown";
|
|
2821
|
+
// readonly error: SubmissionUnknown;
|
|
2822
|
+
// }
|
|
2880
2823
|
```
|
|
2881
2824
|
|
|
2882
|
-
What one entry of `Tx.reconcileAll` settled to.
|
|
2825
|
+
What one entry of `Tx.reconcileAll` settled to, as a tagged union.
|
|
2826
|
+
|
|
2827
|
+
Every case carries **one** discriminator in the same place: `_tag` is
|
|
2828
|
+
`"Executed"`, `"ExecutionFailed"`, `"NotApplied"` or `"SubmissionUnknown"`,
|
|
2829
|
+
and the payload is `executed` for the first and `error` for the other three.
|
|
2830
|
+
Before 0.1.2 this was a bare union of an `Executed` (which has no `_tag`) and
|
|
2831
|
+
three errors (which do), so the only way to tell a success from a failure was
|
|
2832
|
+
`"_tag" in entry` — a shape nothing could `Schema.match` or serialize.
|
|
2833
|
+
|
|
2834
|
+
### `ReconciledOutcome` (type)
|
|
2835
|
+
|
|
2836
|
+
```ts
|
|
2837
|
+
export type ReconciledOutcome = Executed | ExecutionFailed | NotApplied | SubmissionUnknown;
|
|
2838
|
+
```
|
|
2839
|
+
|
|
2840
|
+
The shape `Tx.reconcileAll` returned in 0.1.0 and 0.1.1: the four outcomes as
|
|
2841
|
+
a bare union, with the successful one carrying no discriminator at all.
|
|
2883
2842
|
|
|
2884
2843
|
### `RemoteSigner` (interface)
|
|
2885
2844
|
|
|
@@ -2921,13 +2880,18 @@ export type SignatureScheme = "ED25519" | "Secp256k1" | "Secp256r1" | "MultiSig"
|
|
|
2921
2880
|
|
|
2922
2881
|
The signature schemes a `Signer` built by this module can carry.
|
|
2923
2882
|
|
|
2924
|
-
### `Signed` (
|
|
2883
|
+
### `Signed` (interface)
|
|
2925
2884
|
|
|
2926
2885
|
```ts
|
|
2927
|
-
export
|
|
2886
|
+
export interface Signed extends SignedTransaction {
|
|
2887
|
+
}
|
|
2928
2888
|
```
|
|
2929
2889
|
|
|
2930
|
-
Signed bytes: everything `executeTransaction` needs, plus what `reconcile`
|
|
2890
|
+
Signed bytes: everything `executeTransaction` needs, plus what `reconcile`
|
|
2891
|
+
needs.
|
|
2892
|
+
|
|
2893
|
+
An interface rather than a type alias so the name survives into `.d.ts`,
|
|
2894
|
+
editor hover and `LLMS.md`; structurally it is `SignedTransaction`.
|
|
2931
2895
|
|
|
2932
2896
|
### `Signer` (interface)
|
|
2933
2897
|
|
|
@@ -2963,16 +2927,11 @@ caller's error union does not grow a branch per credential kind.
|
|
|
2963
2927
|
```ts
|
|
2964
2928
|
declare const SubmitConfig: Context.Reference<SubmitConfigService> & {
|
|
2965
2929
|
defaults: SubmitConfigService;
|
|
2930
|
+
layer: (overrides: Partial<SubmitConfigService>) => Layer.Layer<never>;
|
|
2931
|
+
with: (overrides: Partial<SubmitConfigService>) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
2966
2932
|
}
|
|
2967
2933
|
```
|
|
2968
2934
|
|
|
2969
|
-
The lifecycle settings.
|
|
2970
|
-
|
|
2971
|
-
Because this is a `Context.Reference` and not a service, it never appears in
|
|
2972
|
-
an `R`: a one-shot script gets the defaults with no wiring, and an
|
|
2973
|
-
application overrides what it cares about with
|
|
2974
|
-
`Effect.provideService(effect, SubmitConfig, { ...SubmitConfig.defaults, validFor: "30 seconds" })`.
|
|
2975
|
-
|
|
2976
2935
|
### `SubmitConfigService` (interface)
|
|
2977
2936
|
|
|
2978
2937
|
```ts
|
|
@@ -3094,7 +3053,7 @@ Every decision `Tx.build`, `Tx.submit` and `Tx.reconcile` read from context.
|
|
|
3094
3053
|
### `SubmitError` (type)
|
|
3095
3054
|
|
|
3096
3055
|
```ts
|
|
3097
|
-
export type SubmitError = ExecutionFailed | NotApplied | SubmissionUnknown | JournalError;
|
|
3056
|
+
export type SubmitError = ExecutionFailed | NotApplied | SubmissionUnknown | JournalError | TransportError;
|
|
3098
3057
|
```
|
|
3099
3058
|
|
|
3100
3059
|
Everything `submit` can fail with, as one name.
|
|
@@ -3102,6 +3061,30 @@ Everything `submit` can fail with, as one name.
|
|
|
3102
3061
|
An extension that wraps a submission spells its own errors plus this, rather
|
|
3103
3062
|
than repeating four tags that will grow with the taxonomy.
|
|
3104
3063
|
|
|
3064
|
+
### `SubmitViaError` (type)
|
|
3065
|
+
|
|
3066
|
+
```ts
|
|
3067
|
+
export type SubmitViaError = ExecutionFailed | NotApplied | SubmissionUnknown | JournalError;
|
|
3068
|
+
```
|
|
3069
|
+
|
|
3070
|
+
Everything `submitVia` can fail with, before the sender's own errors.
|
|
3071
|
+
|
|
3072
|
+
### `SubmitViaReply` (type)
|
|
3073
|
+
|
|
3074
|
+
```ts
|
|
3075
|
+
export type SubmitViaReply = unknown;
|
|
3076
|
+
```
|
|
3077
|
+
|
|
3078
|
+
What a third party answers when it has submitted your bytes.
|
|
3079
|
+
|
|
3080
|
+
Three shapes are understood, in this order: an SDK `TransactionResult` (the
|
|
3081
|
+
service ran `executeTransaction` and passed the whole thing on), a reduced
|
|
3082
|
+
execute envelope (anything with a `digest` or an `effects`, decoded through
|
|
3083
|
+
`Executed.fromPartial`), and a bare digest string. Anything else — a
|
|
3084
|
+
`void`, an acknowledgement with no digest — means "ask the chain", and
|
|
3085
|
+
`submitVia` reconciles by the digest it already has, which is the digest of
|
|
3086
|
+
the bytes it handed over.
|
|
3087
|
+
|
|
3105
3088
|
### `TransactionExpiration` (const)
|
|
3106
3089
|
|
|
3107
3090
|
Re-exported from `@unconfirmed/sui-effect`.
|
|
@@ -3113,200 +3096,17 @@ declare const Tx: {
|
|
|
3113
3096
|
readonly build: (input: Transaction | Recipe, opts: {
|
|
3114
3097
|
readonly sender: SuiAddress;
|
|
3115
3098
|
readonly gasOwner?: SuiAddress;
|
|
3116
|
-
}) => Effect.Effect<
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
3120
|
-
readonly chain?: string | undefined;
|
|
3121
|
-
readonly expiration?: {
|
|
3122
|
-
readonly $kind: "None";
|
|
3123
|
-
readonly None: true;
|
|
3124
|
-
} | {
|
|
3125
|
-
readonly $kind: "Epoch";
|
|
3126
|
-
readonly Epoch: bigint;
|
|
3127
|
-
} | {
|
|
3128
|
-
readonly $kind: "ValidDuring";
|
|
3129
|
-
readonly ValidDuring: {
|
|
3130
|
-
readonly minEpoch: bigint | null;
|
|
3131
|
-
readonly maxEpoch: bigint | null;
|
|
3132
|
-
readonly minTimestamp: bigint | null;
|
|
3133
|
-
readonly maxTimestamp: bigint | null;
|
|
3134
|
-
readonly chain: string;
|
|
3135
|
-
readonly nonce: number;
|
|
3136
|
-
};
|
|
3137
|
-
} | {
|
|
3138
|
-
readonly $kind: "Validity";
|
|
3139
|
-
readonly Validity: {
|
|
3140
|
-
readonly allowedProposers: {
|
|
3141
|
-
readonly epoch: bigint;
|
|
3142
|
-
readonly proposers: readonly number[];
|
|
3143
|
-
} | null;
|
|
3144
|
-
readonly minEpoch: bigint | null;
|
|
3145
|
-
readonly maxEpoch: bigint | null;
|
|
3146
|
-
readonly minTimestamp: bigint | null;
|
|
3147
|
-
readonly maxTimestamp: bigint | null;
|
|
3148
|
-
readonly chain: string;
|
|
3149
|
-
readonly nonce: number;
|
|
3150
|
-
};
|
|
3151
|
-
} | undefined;
|
|
3152
|
-
readonly gasOwner?: SuiAddress | undefined;
|
|
3153
|
-
}, TransportError | SimulationFailed | BuildError, Sui>;
|
|
3154
|
-
readonly sign: (built: {
|
|
3155
|
-
readonly digest: Digest;
|
|
3156
|
-
readonly sender: SuiAddress;
|
|
3157
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
3158
|
-
readonly chain?: string | undefined;
|
|
3159
|
-
readonly expiration?: {
|
|
3160
|
-
readonly $kind: "None";
|
|
3161
|
-
readonly None: true;
|
|
3162
|
-
} | {
|
|
3163
|
-
readonly $kind: "Epoch";
|
|
3164
|
-
readonly Epoch: bigint;
|
|
3165
|
-
} | {
|
|
3166
|
-
readonly $kind: "ValidDuring";
|
|
3167
|
-
readonly ValidDuring: {
|
|
3168
|
-
readonly minEpoch: bigint | null;
|
|
3169
|
-
readonly maxEpoch: bigint | null;
|
|
3170
|
-
readonly minTimestamp: bigint | null;
|
|
3171
|
-
readonly maxTimestamp: bigint | null;
|
|
3172
|
-
readonly chain: string;
|
|
3173
|
-
readonly nonce: number;
|
|
3174
|
-
};
|
|
3175
|
-
} | {
|
|
3176
|
-
readonly $kind: "Validity";
|
|
3177
|
-
readonly Validity: {
|
|
3178
|
-
readonly allowedProposers: {
|
|
3179
|
-
readonly epoch: bigint;
|
|
3180
|
-
readonly proposers: readonly number[];
|
|
3181
|
-
} | null;
|
|
3182
|
-
readonly minEpoch: bigint | null;
|
|
3183
|
-
readonly maxEpoch: bigint | null;
|
|
3184
|
-
readonly minTimestamp: bigint | null;
|
|
3185
|
-
readonly maxTimestamp: bigint | null;
|
|
3186
|
-
readonly chain: string;
|
|
3187
|
-
readonly nonce: number;
|
|
3188
|
-
};
|
|
3189
|
-
} | undefined;
|
|
3190
|
-
readonly gasOwner?: SuiAddress | undefined;
|
|
3191
|
-
}, signer: Signer) => Effect.Effect<{
|
|
3192
|
-
readonly digest: Digest;
|
|
3193
|
-
readonly sender: SuiAddress;
|
|
3194
|
-
readonly signatures: readonly Signature[];
|
|
3195
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
3196
|
-
readonly chain?: string | undefined;
|
|
3197
|
-
readonly expiration?: {
|
|
3198
|
-
readonly $kind: "None";
|
|
3199
|
-
readonly None: true;
|
|
3200
|
-
} | {
|
|
3201
|
-
readonly $kind: "Epoch";
|
|
3202
|
-
readonly Epoch: bigint;
|
|
3203
|
-
} | {
|
|
3204
|
-
readonly $kind: "ValidDuring";
|
|
3205
|
-
readonly ValidDuring: {
|
|
3206
|
-
readonly minEpoch: bigint | null;
|
|
3207
|
-
readonly maxEpoch: bigint | null;
|
|
3208
|
-
readonly minTimestamp: bigint | null;
|
|
3209
|
-
readonly maxTimestamp: bigint | null;
|
|
3210
|
-
readonly chain: string;
|
|
3211
|
-
readonly nonce: number;
|
|
3212
|
-
};
|
|
3213
|
-
} | {
|
|
3214
|
-
readonly $kind: "Validity";
|
|
3215
|
-
readonly Validity: {
|
|
3216
|
-
readonly allowedProposers: {
|
|
3217
|
-
readonly epoch: bigint;
|
|
3218
|
-
readonly proposers: readonly number[];
|
|
3219
|
-
} | null;
|
|
3220
|
-
readonly minEpoch: bigint | null;
|
|
3221
|
-
readonly maxEpoch: bigint | null;
|
|
3222
|
-
readonly minTimestamp: bigint | null;
|
|
3223
|
-
readonly maxTimestamp: bigint | null;
|
|
3224
|
-
readonly chain: string;
|
|
3225
|
-
readonly nonce: number;
|
|
3226
|
-
};
|
|
3227
|
-
} | undefined;
|
|
3228
|
-
}, SigningError, never>;
|
|
3229
|
-
readonly cosign: (signed: {
|
|
3230
|
-
readonly digest: Digest;
|
|
3231
|
-
readonly sender: SuiAddress;
|
|
3232
|
-
readonly signatures: readonly Signature[];
|
|
3233
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
3234
|
-
readonly chain?: string | undefined;
|
|
3235
|
-
readonly expiration?: {
|
|
3236
|
-
readonly $kind: "None";
|
|
3237
|
-
readonly None: true;
|
|
3238
|
-
} | {
|
|
3239
|
-
readonly $kind: "Epoch";
|
|
3240
|
-
readonly Epoch: bigint;
|
|
3241
|
-
} | {
|
|
3242
|
-
readonly $kind: "ValidDuring";
|
|
3243
|
-
readonly ValidDuring: {
|
|
3244
|
-
readonly minEpoch: bigint | null;
|
|
3245
|
-
readonly maxEpoch: bigint | null;
|
|
3246
|
-
readonly minTimestamp: bigint | null;
|
|
3247
|
-
readonly maxTimestamp: bigint | null;
|
|
3248
|
-
readonly chain: string;
|
|
3249
|
-
readonly nonce: number;
|
|
3250
|
-
};
|
|
3251
|
-
} | {
|
|
3252
|
-
readonly $kind: "Validity";
|
|
3253
|
-
readonly Validity: {
|
|
3254
|
-
readonly allowedProposers: {
|
|
3255
|
-
readonly epoch: bigint;
|
|
3256
|
-
readonly proposers: readonly number[];
|
|
3257
|
-
} | null;
|
|
3258
|
-
readonly minEpoch: bigint | null;
|
|
3259
|
-
readonly maxEpoch: bigint | null;
|
|
3260
|
-
readonly minTimestamp: bigint | null;
|
|
3261
|
-
readonly maxTimestamp: bigint | null;
|
|
3262
|
-
readonly chain: string;
|
|
3263
|
-
readonly nonce: number;
|
|
3264
|
-
};
|
|
3265
|
-
} | undefined;
|
|
3266
|
-
}, signer: Signer) => Effect.Effect<{
|
|
3267
|
-
readonly digest: Digest;
|
|
3268
|
-
readonly sender: SuiAddress;
|
|
3269
|
-
readonly signatures: readonly Signature[];
|
|
3270
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
3271
|
-
readonly chain?: string | undefined;
|
|
3272
|
-
readonly expiration?: {
|
|
3273
|
-
readonly $kind: "None";
|
|
3274
|
-
readonly None: true;
|
|
3275
|
-
} | {
|
|
3276
|
-
readonly $kind: "Epoch";
|
|
3277
|
-
readonly Epoch: bigint;
|
|
3278
|
-
} | {
|
|
3279
|
-
readonly $kind: "ValidDuring";
|
|
3280
|
-
readonly ValidDuring: {
|
|
3281
|
-
readonly minEpoch: bigint | null;
|
|
3282
|
-
readonly maxEpoch: bigint | null;
|
|
3283
|
-
readonly minTimestamp: bigint | null;
|
|
3284
|
-
readonly maxTimestamp: bigint | null;
|
|
3285
|
-
readonly chain: string;
|
|
3286
|
-
readonly nonce: number;
|
|
3287
|
-
};
|
|
3288
|
-
} | {
|
|
3289
|
-
readonly $kind: "Validity";
|
|
3290
|
-
readonly Validity: {
|
|
3291
|
-
readonly allowedProposers: {
|
|
3292
|
-
readonly epoch: bigint;
|
|
3293
|
-
readonly proposers: readonly number[];
|
|
3294
|
-
} | null;
|
|
3295
|
-
readonly minEpoch: bigint | null;
|
|
3296
|
-
readonly maxEpoch: bigint | null;
|
|
3297
|
-
readonly minTimestamp: bigint | null;
|
|
3298
|
-
readonly maxTimestamp: bigint | null;
|
|
3299
|
-
readonly chain: string;
|
|
3300
|
-
readonly nonce: number;
|
|
3301
|
-
};
|
|
3302
|
-
} | undefined;
|
|
3303
|
-
}, SigningError, never>;
|
|
3099
|
+
}) => Effect.Effect<Built, TransportError | SimulationFailed | BuildError, Sui>;
|
|
3100
|
+
readonly sign: (built: Built, signer: Signer) => Effect.Effect<Signed, SigningError, never>;
|
|
3101
|
+
readonly cosign: (signed: Signed, signer: Signer) => Effect.Effect<Signed, SigningError, never>;
|
|
3304
3102
|
readonly sponsored: (opts: {
|
|
3305
3103
|
readonly sender: SuiAddress;
|
|
3306
3104
|
readonly gasOwner: SuiAddress;
|
|
3307
3105
|
}) => (recipe: Recipe) => Recipe;
|
|
3308
3106
|
readonly submit: (signed: Signed) => Effect.Effect<Executed, SubmitError, Sui>;
|
|
3107
|
+
readonly submitVia: <E, R>(signed: Signed, send: (bytes: Uint8Array, signatures: ReadonlyArray<Signature>) => Effect.Effect<SubmitViaReply, E, R>) => Effect.Effect<Executed, SubmitViaError | E, Sui | R>;
|
|
3309
3108
|
readonly reconcile: (input: ReconcileInput) => Effect.Effect<Executed, TransportError | ExecutionFailed | SubmissionUnknown | NotApplied, Sui>;
|
|
3109
|
+
readonly recorded: (digest: Digest) => Effect.Effect<Option.Option<JournalEntry>, JournalError, never>;
|
|
3310
3110
|
readonly run: (recipe: Transaction | Recipe, opts: {
|
|
3311
3111
|
readonly signer: Signer;
|
|
3312
3112
|
readonly gasOwner?: SuiAddress;
|
|
@@ -3315,8 +3115,42 @@ declare const Tx: {
|
|
|
3315
3115
|
* the bytes name a gas owner that is not the sender.
|
|
3316
3116
|
*/
|
|
3317
3117
|
readonly sponsor?: Signer;
|
|
3118
|
+
/**
|
|
3119
|
+
* Called with the signed bytes **after every signature is on them and
|
|
3120
|
+
* before the first `executeTransaction`**, which is the one moment a
|
|
3121
|
+
* consumer's own record has to be written: the digest is final from here
|
|
3122
|
+
* on, and anything that happens next may have reached the network.
|
|
3123
|
+
*
|
|
3124
|
+
* `Tx.submit` already writes its `Signed` journal entry at this point; this
|
|
3125
|
+
* is for the record the journal does not hold — a domain row joining the
|
|
3126
|
+
* digest to a batch, an outbox, a log line an operator greps. It runs
|
|
3127
|
+
* inside the sender lock, so it is ordered with the submission it belongs
|
|
3128
|
+
* to.
|
|
3129
|
+
*
|
|
3130
|
+
* Failing it fails the run **before anything is sent**, which is why its
|
|
3131
|
+
* error is a `JournalError`: that is the taxonomy's "the record could not
|
|
3132
|
+
* be written and nothing has gone out yet", it is already in `Tx.run`'s
|
|
3133
|
+
* union, and it is `not_applied`, so the documented retry idiom is correct.
|
|
3134
|
+
* Map your own persistence failure into it
|
|
3135
|
+
* (`Effect.mapError((cause) => new JournalError({ cause }))`).
|
|
3136
|
+
*
|
|
3137
|
+
* @since 0.1.2
|
|
3138
|
+
*/
|
|
3139
|
+
readonly onSigned?: (signed: Signed) => Effect.Effect<void, JournalError>;
|
|
3318
3140
|
}) => Effect.Effect<Executed, TransportError | SimulationFailed | ExecutionFailed | SubmissionUnknown | NotApplied | SigningError | BuildError | PolicyDenied | JournalError, Sui>;
|
|
3319
|
-
readonly reconcileAll: () => Effect.Effect<readonly
|
|
3141
|
+
readonly reconcileAll: () => Effect.Effect<readonly ({
|
|
3142
|
+
readonly _tag: "ExecutionFailed";
|
|
3143
|
+
readonly error: ExecutionFailed;
|
|
3144
|
+
} | {
|
|
3145
|
+
readonly _tag: "SubmissionUnknown";
|
|
3146
|
+
readonly error: SubmissionUnknown;
|
|
3147
|
+
} | {
|
|
3148
|
+
readonly _tag: "NotApplied";
|
|
3149
|
+
readonly error: NotApplied;
|
|
3150
|
+
} | {
|
|
3151
|
+
readonly _tag: "Executed";
|
|
3152
|
+
readonly executed: Executed;
|
|
3153
|
+
})[], TransportError | JournalError, Sui>;
|
|
3320
3154
|
}
|
|
3321
3155
|
```
|
|
3322
3156
|
|
|
@@ -3338,44 +3172,7 @@ The tags whose entries still need an answer from the network.
|
|
|
3338
3172
|
declare const build: (input: Transaction | Recipe, opts: {
|
|
3339
3173
|
readonly sender: SuiAddress;
|
|
3340
3174
|
readonly gasOwner?: SuiAddress;
|
|
3341
|
-
}) => Effect.Effect<
|
|
3342
|
-
readonly digest: Digest;
|
|
3343
|
-
readonly sender: SuiAddress;
|
|
3344
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
3345
|
-
readonly chain?: string | undefined;
|
|
3346
|
-
readonly expiration?: {
|
|
3347
|
-
readonly $kind: "None";
|
|
3348
|
-
readonly None: true;
|
|
3349
|
-
} | {
|
|
3350
|
-
readonly $kind: "Epoch";
|
|
3351
|
-
readonly Epoch: bigint;
|
|
3352
|
-
} | {
|
|
3353
|
-
readonly $kind: "ValidDuring";
|
|
3354
|
-
readonly ValidDuring: {
|
|
3355
|
-
readonly minEpoch: bigint | null;
|
|
3356
|
-
readonly maxEpoch: bigint | null;
|
|
3357
|
-
readonly minTimestamp: bigint | null;
|
|
3358
|
-
readonly maxTimestamp: bigint | null;
|
|
3359
|
-
readonly chain: string;
|
|
3360
|
-
readonly nonce: number;
|
|
3361
|
-
};
|
|
3362
|
-
} | {
|
|
3363
|
-
readonly $kind: "Validity";
|
|
3364
|
-
readonly Validity: {
|
|
3365
|
-
readonly allowedProposers: {
|
|
3366
|
-
readonly epoch: bigint;
|
|
3367
|
-
readonly proposers: readonly number[];
|
|
3368
|
-
} | null;
|
|
3369
|
-
readonly minEpoch: bigint | null;
|
|
3370
|
-
readonly maxEpoch: bigint | null;
|
|
3371
|
-
readonly minTimestamp: bigint | null;
|
|
3372
|
-
readonly maxTimestamp: bigint | null;
|
|
3373
|
-
readonly chain: string;
|
|
3374
|
-
readonly nonce: number;
|
|
3375
|
-
};
|
|
3376
|
-
} | undefined;
|
|
3377
|
-
readonly gasOwner?: SuiAddress | undefined;
|
|
3378
|
-
}, TransportError | SimulationFailed | BuildError, Sui>
|
|
3175
|
+
}) => Effect.Effect<Built, TransportError | SimulationFailed | BuildError, Sui>
|
|
3379
3176
|
```
|
|
3380
3177
|
|
|
3381
3178
|
Builds a transaction into signable bytes.
|
|
@@ -3416,81 +3213,7 @@ Re-exported from `@unconfirmed/sui-effect`.
|
|
|
3416
3213
|
### `cosign` (const)
|
|
3417
3214
|
|
|
3418
3215
|
```ts
|
|
3419
|
-
declare const cosign: (signed:
|
|
3420
|
-
readonly digest: Digest;
|
|
3421
|
-
readonly sender: SuiAddress;
|
|
3422
|
-
readonly signatures: readonly Signature[];
|
|
3423
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
3424
|
-
readonly chain?: string | undefined;
|
|
3425
|
-
readonly expiration?: {
|
|
3426
|
-
readonly $kind: "None";
|
|
3427
|
-
readonly None: true;
|
|
3428
|
-
} | {
|
|
3429
|
-
readonly $kind: "Epoch";
|
|
3430
|
-
readonly Epoch: bigint;
|
|
3431
|
-
} | {
|
|
3432
|
-
readonly $kind: "ValidDuring";
|
|
3433
|
-
readonly ValidDuring: {
|
|
3434
|
-
readonly minEpoch: bigint | null;
|
|
3435
|
-
readonly maxEpoch: bigint | null;
|
|
3436
|
-
readonly minTimestamp: bigint | null;
|
|
3437
|
-
readonly maxTimestamp: bigint | null;
|
|
3438
|
-
readonly chain: string;
|
|
3439
|
-
readonly nonce: number;
|
|
3440
|
-
};
|
|
3441
|
-
} | {
|
|
3442
|
-
readonly $kind: "Validity";
|
|
3443
|
-
readonly Validity: {
|
|
3444
|
-
readonly allowedProposers: {
|
|
3445
|
-
readonly epoch: bigint;
|
|
3446
|
-
readonly proposers: readonly number[];
|
|
3447
|
-
} | null;
|
|
3448
|
-
readonly minEpoch: bigint | null;
|
|
3449
|
-
readonly maxEpoch: bigint | null;
|
|
3450
|
-
readonly minTimestamp: bigint | null;
|
|
3451
|
-
readonly maxTimestamp: bigint | null;
|
|
3452
|
-
readonly chain: string;
|
|
3453
|
-
readonly nonce: number;
|
|
3454
|
-
};
|
|
3455
|
-
} | undefined;
|
|
3456
|
-
}, signer: Signer) => Effect.Effect<{
|
|
3457
|
-
readonly digest: Digest;
|
|
3458
|
-
readonly sender: SuiAddress;
|
|
3459
|
-
readonly signatures: readonly Signature[];
|
|
3460
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
3461
|
-
readonly chain?: string | undefined;
|
|
3462
|
-
readonly expiration?: {
|
|
3463
|
-
readonly $kind: "None";
|
|
3464
|
-
readonly None: true;
|
|
3465
|
-
} | {
|
|
3466
|
-
readonly $kind: "Epoch";
|
|
3467
|
-
readonly Epoch: bigint;
|
|
3468
|
-
} | {
|
|
3469
|
-
readonly $kind: "ValidDuring";
|
|
3470
|
-
readonly ValidDuring: {
|
|
3471
|
-
readonly minEpoch: bigint | null;
|
|
3472
|
-
readonly maxEpoch: bigint | null;
|
|
3473
|
-
readonly minTimestamp: bigint | null;
|
|
3474
|
-
readonly maxTimestamp: bigint | null;
|
|
3475
|
-
readonly chain: string;
|
|
3476
|
-
readonly nonce: number;
|
|
3477
|
-
};
|
|
3478
|
-
} | {
|
|
3479
|
-
readonly $kind: "Validity";
|
|
3480
|
-
readonly Validity: {
|
|
3481
|
-
readonly allowedProposers: {
|
|
3482
|
-
readonly epoch: bigint;
|
|
3483
|
-
readonly proposers: readonly number[];
|
|
3484
|
-
} | null;
|
|
3485
|
-
readonly minEpoch: bigint | null;
|
|
3486
|
-
readonly maxEpoch: bigint | null;
|
|
3487
|
-
readonly minTimestamp: bigint | null;
|
|
3488
|
-
readonly maxTimestamp: bigint | null;
|
|
3489
|
-
readonly chain: string;
|
|
3490
|
-
readonly nonce: number;
|
|
3491
|
-
};
|
|
3492
|
-
} | undefined;
|
|
3493
|
-
}, SigningError, never>
|
|
3216
|
+
declare const cosign: (signed: Signed, signer: Signer) => Effect.Effect<Signed, SigningError, never>
|
|
3494
3217
|
```
|
|
3495
3218
|
|
|
3496
3219
|
Adds one more signature to already signed bytes, for a sponsored or
|
|
@@ -3526,15 +3249,23 @@ be a security bug, not a convenience.
|
|
|
3526
3249
|
declare const fromConfig: (name?: string) => Effect.Effect<Signer, Config.ConfigError>
|
|
3527
3250
|
```
|
|
3528
3251
|
|
|
3529
|
-
Reads a
|
|
3530
|
-
|
|
3252
|
+
Reads a secret key from configuration and builds its signer.
|
|
3253
|
+
|
|
3254
|
+
Two spellings, told apart by the text itself:
|
|
3255
|
+
|
|
3256
|
+
- a **Bech32 `suiprivkey1…`**, whose flag names one of the three schemes;
|
|
3257
|
+
- a **32-byte hex seed** (64 hex characters, `0x` optional), which carries no
|
|
3258
|
+
scheme and is read as **Ed25519** — the default every Sui tool uses for a
|
|
3259
|
+
raw seed. This is what a secret manager or another language's SDK hands
|
|
3260
|
+
over, and reading it here is what keeps `fromHex` and the decoded bytes out
|
|
3261
|
+
of application code.
|
|
3531
3262
|
|
|
3532
3263
|
The key is read with `Config.redacted`, and the decoded bytes never leave
|
|
3533
3264
|
this function. Neither does anything derived from them: the failure carries
|
|
3534
3265
|
one fixed sentence and no `cause`, because the decoder's own message quotes
|
|
3535
3266
|
the input it rejected.
|
|
3536
3267
|
|
|
3537
|
-
**Fails with: `ConfigError` when the variable is missing, is
|
|
3268
|
+
**Fails with: `ConfigError` when the variable is missing, is neither spelling, or names a scheme that has no keypair class (`MultiSig`, `ZkLogin`, `Passkey` — use {@link remote} for those).**
|
|
3538
3269
|
|
|
3539
3270
|
### `fromKeypair` (const)
|
|
3540
3271
|
|
|
@@ -3563,12 +3294,29 @@ and `signPersonalMessage`. Nothing here needs the secret, so nothing here
|
|
|
3563
3294
|
needs a keypair, and the `Signer` this returns exposes no secret material
|
|
3564
3295
|
either.
|
|
3565
3296
|
|
|
3297
|
+
**`toSuiAddress()` and `getKeyScheme()` are read here, synchronously**, and
|
|
3298
|
+
the address and scheme of the returned `Signer` are whatever they answered at
|
|
3299
|
+
this moment: a credential that changes accounts later is a different
|
|
3300
|
+
`Signer`, built again. A test double therefore needs both of those methods,
|
|
3301
|
+
not only `signTransaction` — a double without `getKeyScheme` used to produce
|
|
3302
|
+
`scheme: undefined` and nothing complained until a validator did.
|
|
3303
|
+
|
|
3304
|
+
**Clear-signing inputs are the SDK signer's own concern.** The Ledger signer
|
|
3305
|
+
takes `signTransaction(bytes, bcsObjects?, resolution?)` and resolves those
|
|
3306
|
+
extra arguments through the client it was constructed with; this passes only
|
|
3307
|
+
the bytes, which is the whole of the base `Signer` contract. A device that
|
|
3308
|
+
needs more than the bytes gets it from its own client, or from
|
|
3309
|
+
`remote`.
|
|
3310
|
+
|
|
3566
3311
|
For a credential that is not an SDK `Signer` at all — a remote service, a
|
|
3567
3312
|
hardware device behind your own protocol — use `remote`, which takes
|
|
3568
3313
|
Effects and the address to sign as.
|
|
3569
3314
|
|
|
3570
|
-
|
|
3571
|
-
|
|
3315
|
+
**Throws** a `TypeError` naming the missing member when the argument is not
|
|
3316
|
+
an SDK signer — that is a wiring mistake in the caller, not a runtime
|
|
3317
|
+
failure a program recovers from. Otherwise never fails: a bad address or
|
|
3318
|
+
signature surfaces as a `SigningError` from the member that produced it, not
|
|
3319
|
+
from construction.
|
|
3572
3320
|
|
|
3573
3321
|
### `isUnresolved` (const)
|
|
3574
3322
|
|
|
@@ -3909,12 +3657,29 @@ always `SubmissionUnknown`. Pass the `Signed` bytes (or the
|
|
|
3909
3657
|
### `reconcileAll` (const)
|
|
3910
3658
|
|
|
3911
3659
|
```ts
|
|
3912
|
-
declare const reconcileAll: () => Effect.Effect<readonly
|
|
3660
|
+
declare const reconcileAll: () => Effect.Effect<readonly ({
|
|
3661
|
+
readonly _tag: "ExecutionFailed";
|
|
3662
|
+
readonly error: ExecutionFailed;
|
|
3663
|
+
} | {
|
|
3664
|
+
readonly _tag: "SubmissionUnknown";
|
|
3665
|
+
readonly error: SubmissionUnknown;
|
|
3666
|
+
} | {
|
|
3667
|
+
readonly _tag: "NotApplied";
|
|
3668
|
+
readonly error: NotApplied;
|
|
3669
|
+
} | {
|
|
3670
|
+
readonly _tag: "Executed";
|
|
3671
|
+
readonly executed: Executed;
|
|
3672
|
+
})[], TransportError | JournalError, Sui>
|
|
3913
3673
|
```
|
|
3914
3674
|
|
|
3915
3675
|
Settles every unresolved entry in the journal: the explicit startup call a
|
|
3916
3676
|
long-lived application makes after building a durable `Journal`.
|
|
3917
3677
|
|
|
3678
|
+
**Only unresolved entries come back.** `Signed` and `Unknown` are the tags
|
|
3679
|
+
that still need an answer; a digest that already settled is not in the
|
|
3680
|
+
journal's unresolved index and is not in this array. Ask about one of those
|
|
3681
|
+
with `recorded`.
|
|
3682
|
+
|
|
3918
3683
|
Nothing here fails per entry: each one settles to an `Executed`, an
|
|
3919
3684
|
`ExecutionFailed`, a `NotApplied` or a `SubmissionUnknown`, in the order the
|
|
3920
3685
|
journal listed them, and the journal is updated to match. Every settled entry
|
|
@@ -3930,6 +3695,28 @@ the same rule `Tx.submit` follows.
|
|
|
3930
3695
|
|
|
3931
3696
|
**Fails with: `JournalError`, `TransportError`.**
|
|
3932
3697
|
|
|
3698
|
+
### `recorded` (const)
|
|
3699
|
+
|
|
3700
|
+
```ts
|
|
3701
|
+
declare const recorded: (digest: Digest) => Effect.Effect<Option.Option<JournalEntry>, JournalError, never>
|
|
3702
|
+
```
|
|
3703
|
+
|
|
3704
|
+
What the journal recorded for one digest, if anything.
|
|
3705
|
+
|
|
3706
|
+
`Tx.reconcileAll` returns **only the entries that were still unresolved**,
|
|
3707
|
+
because those are the ones it had work to do about; a transaction that had
|
|
3708
|
+
already settled — executed, failed, or proven never applied — is not in its
|
|
3709
|
+
answer and never will be. This is how to ask about one of those: the entry is
|
|
3710
|
+
`Executed`, `Failed` or `NotApplied` for a settled digest, `Signed` or
|
|
3711
|
+
`Unknown` for one still in flight, and `None` for a digest this journal has
|
|
3712
|
+
never seen (including every digest at all, when the journal is the in-memory
|
|
3713
|
+
default and the process restarted).
|
|
3714
|
+
|
|
3715
|
+
It is exactly `(yield* Journal).get(digest)`, named so that the recovery path
|
|
3716
|
+
does not have to reach for the reference.
|
|
3717
|
+
|
|
3718
|
+
**Fails with: `JournalError`.**
|
|
3719
|
+
|
|
3933
3720
|
### `remote` (const)
|
|
3934
3721
|
|
|
3935
3722
|
```ts
|
|
@@ -3957,6 +3744,28 @@ declare const run: (recipe: Transaction | Recipe, opts: {
|
|
|
3957
3744
|
* the bytes name a gas owner that is not the sender.
|
|
3958
3745
|
*/
|
|
3959
3746
|
readonly sponsor?: Signer;
|
|
3747
|
+
/**
|
|
3748
|
+
* Called with the signed bytes **after every signature is on them and
|
|
3749
|
+
* before the first `executeTransaction`**, which is the one moment a
|
|
3750
|
+
* consumer's own record has to be written: the digest is final from here
|
|
3751
|
+
* on, and anything that happens next may have reached the network.
|
|
3752
|
+
*
|
|
3753
|
+
* `Tx.submit` already writes its `Signed` journal entry at this point; this
|
|
3754
|
+
* is for the record the journal does not hold — a domain row joining the
|
|
3755
|
+
* digest to a batch, an outbox, a log line an operator greps. It runs
|
|
3756
|
+
* inside the sender lock, so it is ordered with the submission it belongs
|
|
3757
|
+
* to.
|
|
3758
|
+
*
|
|
3759
|
+
* Failing it fails the run **before anything is sent**, which is why its
|
|
3760
|
+
* error is a `JournalError`: that is the taxonomy's "the record could not
|
|
3761
|
+
* be written and nothing has gone out yet", it is already in `Tx.run`'s
|
|
3762
|
+
* union, and it is `not_applied`, so the documented retry idiom is correct.
|
|
3763
|
+
* Map your own persistence failure into it
|
|
3764
|
+
* (`Effect.mapError((cause) => new JournalError({ cause }))`).
|
|
3765
|
+
*
|
|
3766
|
+
* @since 0.1.2
|
|
3767
|
+
*/
|
|
3768
|
+
readonly onSigned?: (signed: Signed) => Effect.Effect<void, JournalError>;
|
|
3960
3769
|
}) => Effect.Effect<Executed, TransportError | SimulationFailed | ExecutionFailed | SubmissionUnknown | NotApplied | SigningError | BuildError | PolicyDenied | JournalError, Sui>
|
|
3961
3770
|
```
|
|
3962
3771
|
|
|
@@ -3989,86 +3798,20 @@ and immediately after the build when it came out of the recipe. Use the
|
|
|
3989
3798
|
explicit lifecycle (`Tx.build`, `Tx.sign`, `Tx.cosign`, `Tx.submit`) when the
|
|
3990
3799
|
two parties cannot both sign in one process.
|
|
3991
3800
|
|
|
3801
|
+
**`onSigned` is the hook between signing and sending.** A program with its
|
|
3802
|
+
own record to keep — a batch row, an outbox, an idempotency key — has to
|
|
3803
|
+
write the digest before the first send, and that used to mean giving up
|
|
3804
|
+
`Tx.run` and reassembling `withSenderLock(build → sign → record → submit)` by
|
|
3805
|
+
hand. Pass `onSigned` instead: it runs inside the sender lock, after the last
|
|
3806
|
+
signature and before `Tx.submit`'s first `executeTransaction`, and failing it
|
|
3807
|
+
fails the run with nothing sent.
|
|
3808
|
+
|
|
3992
3809
|
**Fails with: `BuildError`, `SimulationFailed`, `PolicyDenied`, `SigningError`, `ExecutionFailed`, `NotApplied`, `SubmissionUnknown`, `JournalError`, `TransportError` (from the build reads; once bytes are sent, transport failures become `SubmissionUnknown`).**
|
|
3993
3810
|
|
|
3994
3811
|
### `sign` (const)
|
|
3995
3812
|
|
|
3996
3813
|
```ts
|
|
3997
|
-
declare const sign: (built:
|
|
3998
|
-
readonly digest: Digest;
|
|
3999
|
-
readonly sender: SuiAddress;
|
|
4000
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
4001
|
-
readonly chain?: string | undefined;
|
|
4002
|
-
readonly expiration?: {
|
|
4003
|
-
readonly $kind: "None";
|
|
4004
|
-
readonly None: true;
|
|
4005
|
-
} | {
|
|
4006
|
-
readonly $kind: "Epoch";
|
|
4007
|
-
readonly Epoch: bigint;
|
|
4008
|
-
} | {
|
|
4009
|
-
readonly $kind: "ValidDuring";
|
|
4010
|
-
readonly ValidDuring: {
|
|
4011
|
-
readonly minEpoch: bigint | null;
|
|
4012
|
-
readonly maxEpoch: bigint | null;
|
|
4013
|
-
readonly minTimestamp: bigint | null;
|
|
4014
|
-
readonly maxTimestamp: bigint | null;
|
|
4015
|
-
readonly chain: string;
|
|
4016
|
-
readonly nonce: number;
|
|
4017
|
-
};
|
|
4018
|
-
} | {
|
|
4019
|
-
readonly $kind: "Validity";
|
|
4020
|
-
readonly Validity: {
|
|
4021
|
-
readonly allowedProposers: {
|
|
4022
|
-
readonly epoch: bigint;
|
|
4023
|
-
readonly proposers: readonly number[];
|
|
4024
|
-
} | null;
|
|
4025
|
-
readonly minEpoch: bigint | null;
|
|
4026
|
-
readonly maxEpoch: bigint | null;
|
|
4027
|
-
readonly minTimestamp: bigint | null;
|
|
4028
|
-
readonly maxTimestamp: bigint | null;
|
|
4029
|
-
readonly chain: string;
|
|
4030
|
-
readonly nonce: number;
|
|
4031
|
-
};
|
|
4032
|
-
} | undefined;
|
|
4033
|
-
readonly gasOwner?: SuiAddress | undefined;
|
|
4034
|
-
}, signer: Signer) => Effect.Effect<{
|
|
4035
|
-
readonly digest: Digest;
|
|
4036
|
-
readonly sender: SuiAddress;
|
|
4037
|
-
readonly signatures: readonly Signature[];
|
|
4038
|
-
readonly bytes: Uint8Array<ArrayBufferLike>;
|
|
4039
|
-
readonly chain?: string | undefined;
|
|
4040
|
-
readonly expiration?: {
|
|
4041
|
-
readonly $kind: "None";
|
|
4042
|
-
readonly None: true;
|
|
4043
|
-
} | {
|
|
4044
|
-
readonly $kind: "Epoch";
|
|
4045
|
-
readonly Epoch: bigint;
|
|
4046
|
-
} | {
|
|
4047
|
-
readonly $kind: "ValidDuring";
|
|
4048
|
-
readonly ValidDuring: {
|
|
4049
|
-
readonly minEpoch: bigint | null;
|
|
4050
|
-
readonly maxEpoch: bigint | null;
|
|
4051
|
-
readonly minTimestamp: bigint | null;
|
|
4052
|
-
readonly maxTimestamp: bigint | null;
|
|
4053
|
-
readonly chain: string;
|
|
4054
|
-
readonly nonce: number;
|
|
4055
|
-
};
|
|
4056
|
-
} | {
|
|
4057
|
-
readonly $kind: "Validity";
|
|
4058
|
-
readonly Validity: {
|
|
4059
|
-
readonly allowedProposers: {
|
|
4060
|
-
readonly epoch: bigint;
|
|
4061
|
-
readonly proposers: readonly number[];
|
|
4062
|
-
} | null;
|
|
4063
|
-
readonly minEpoch: bigint | null;
|
|
4064
|
-
readonly maxEpoch: bigint | null;
|
|
4065
|
-
readonly minTimestamp: bigint | null;
|
|
4066
|
-
readonly maxTimestamp: bigint | null;
|
|
4067
|
-
readonly chain: string;
|
|
4068
|
-
readonly nonce: number;
|
|
4069
|
-
};
|
|
4070
|
-
} | undefined;
|
|
4071
|
-
}, SigningError, never>
|
|
3814
|
+
declare const sign: (built: Built, signer: Signer) => Effect.Effect<Signed, SigningError, never>
|
|
4072
3815
|
```
|
|
4073
3816
|
|
|
4074
3817
|
Signs built bytes.
|
|
@@ -4113,9 +3856,16 @@ the transaction that was already signed. When the retries run out it runs
|
|
|
4113
3856
|
`Tx.reconcile`, which either finds the transaction, proves it never applied,
|
|
4114
3857
|
or says it does not know.
|
|
4115
3858
|
|
|
4116
|
-
`TransportError` never escapes: once bytes may have been sent, "the
|
|
4117
|
-
was unreachable" is not an answer a caller can act on, so it becomes
|
|
4118
|
-
`SubmissionUnknown` carrying the signed bytes.
|
|
3859
|
+
`TransportError` almost never escapes: once bytes may have been sent, "the
|
|
3860
|
+
network was unreachable" is not an answer a caller can act on, so it becomes
|
|
3861
|
+
`SubmissionUnknown` carrying the signed bytes. **The one exception is a node
|
|
3862
|
+
that refused the request outright** — gRPC `INVALID_ARGUMENT`, which is what
|
|
3863
|
+
a validator answers for malformed bytes or for a sponsored transaction
|
|
3864
|
+
carrying one signature. That answer came from the node, it is final, and
|
|
3865
|
+
nothing was executed, so it is reported as the `TransportError` it is rather
|
|
3866
|
+
than reconciled: a reconcile would go on to ask "is this digest on chain?",
|
|
3867
|
+
a question about a transaction that was never sent, and a lagging or scripted
|
|
3868
|
+
node can answer it yes.
|
|
4119
3869
|
|
|
4120
3870
|
`JournalError` can only come from the `Signed` write, before anything has
|
|
4121
3871
|
been sent. Once the network has answered, a journal write that fails is
|
|
@@ -4123,7 +3873,40 @@ logged with `Effect.logError` and the answer stands, because "the journal is
|
|
|
4123
3873
|
broken" is not a thing a caller can act on and reporting it in place of a
|
|
4124
3874
|
charged `ExecutionFailed` would invite a second submission.
|
|
4125
3875
|
|
|
4126
|
-
**Fails with: `ExecutionFailed` (applied on chain and failed; gas was charged), `NotApplied` (provably never applied), `SubmissionUnknown` (the outcome is not known and the bytes are in the error), `JournalError` (only before the first send).**
|
|
3876
|
+
**Fails with: `ExecutionFailed` (applied on chain and failed; gas was charged), `NotApplied` (provably never applied), `SubmissionUnknown` (the outcome is not known and the bytes are in the error), `JournalError` (only before the first send), `TransportError` (only `INVALID_ARGUMENT`: the node refused the submission and nothing was executed).**
|
|
3877
|
+
|
|
3878
|
+
### `submitVia` (const)
|
|
3879
|
+
|
|
3880
|
+
```ts
|
|
3881
|
+
declare const submitVia: <E, R>(signed: Signed, send: (bytes: Uint8Array, signatures: ReadonlyArray<Signature>) => Effect.Effect<SubmitViaReply, E, R>) => Effect.Effect<Executed, SubmitViaError | E, Sui | R>
|
|
3882
|
+
```
|
|
3883
|
+
|
|
3884
|
+
Submits through **someone else** — a relay, a sponsorship service, a backend
|
|
3885
|
+
that holds the only key allowed to talk to the node — and keeps the journal
|
|
3886
|
+
and the evidence rules that `Tx.submit` would have kept.
|
|
3887
|
+
|
|
3888
|
+
The bytes never reach `executeTransaction` here; `send` does whatever the
|
|
3889
|
+
service needs (an HTTP POST, a queue, another process) and answers with
|
|
3890
|
+
whatever the service returns. What this owns is everything around it:
|
|
3891
|
+
|
|
3892
|
+
- a `Signed` journal entry is written **before** `send` is called, so a crash
|
|
3893
|
+
between here and the service leaves the same record a direct submit leaves;
|
|
3894
|
+
- `send` is called **once**. A third party's submit is not known to be
|
|
3895
|
+
idempotent and re-sending is not this function's decision;
|
|
3896
|
+
- the reply is turned into an `Executed` when it carries one (see
|
|
3897
|
+
`SubmitViaReply`), and otherwise the chain is asked — by the digest
|
|
3898
|
+
of the bytes that were handed over, which a co-signature does not change;
|
|
3899
|
+
- a failure from `send` is **ambiguous** unless it says otherwise, so it ends
|
|
3900
|
+
in `Tx.reconcile` with the full evidence rules: the ordered expiry check,
|
|
3901
|
+
the chain-identity guard, the versioned consumer check. A sender error that
|
|
3902
|
+
**declares** `outcome: "not_applied"` on the instance — a 400 from the
|
|
3903
|
+
service, a refusal before anything went out — is taken at its word and
|
|
3904
|
+
fails straight through without spending a reconcile. A `TransportError` is
|
|
3905
|
+
not that: the taxonomy calls it `not_applied`, but a transport failure
|
|
3906
|
+
*talking to the relay* is exactly the ambiguous case, so it reconciles;
|
|
3907
|
+
- every terminal answer is journalled, exactly as `Tx.submit` journals it.
|
|
3908
|
+
|
|
3909
|
+
**Fails with: `ExecutionFailed`, `NotApplied`, `SubmissionUnknown` (carrying the signed bytes, with the sender's failure as its `cause`), `JournalError` (only from the write before `send`), and `E` — whatever `send` fails with — when that error declares `outcome: "not_applied"`.**
|
|
4127
3910
|
|
|
4128
3911
|
## `@unconfirmed/sui-effect/journal`
|
|
4129
3912
|
|
|
@@ -4488,7 +4271,28 @@ added to the value itself.
|
|
|
4488
4271
|
## `@unconfirmed/sui-effect/script`
|
|
4489
4272
|
|
|
4490
4273
|
|
|
4491
|
-
|
|
4274
|
+
11 exported symbols.
|
|
4275
|
+
|
|
4276
|
+
### `ReportOptions` (interface)
|
|
4277
|
+
|
|
4278
|
+
```ts
|
|
4279
|
+
export interface ReportOptions {
|
|
4280
|
+
/** Where the lines go, one at a time. Defaults to `process.stderr`. */
|
|
4281
|
+
readonly stderr?: (line: string) => void;
|
|
4282
|
+
/**
|
|
4283
|
+
* The journal the program ran with, for the unresolved entries.
|
|
4284
|
+
*
|
|
4285
|
+
* A program with its own `ManagedRuntime` has to hand it over — reading the
|
|
4286
|
+
* bare `Journal` reference here would look in the process-wide in-memory
|
|
4287
|
+
* default and find nothing, which is precisely wrong for the program that
|
|
4288
|
+
* provided a durable one. Left out, the default reference is read, which is
|
|
4289
|
+
* right for a program that never provided a journal at all.
|
|
4290
|
+
*/
|
|
4291
|
+
readonly journal?: JournalService;
|
|
4292
|
+
}
|
|
4293
|
+
```
|
|
4294
|
+
|
|
4295
|
+
What `report` needs beyond the `Exit`.
|
|
4492
4296
|
|
|
4493
4297
|
### `Script` (class)
|
|
4494
4298
|
|
|
@@ -4537,6 +4341,8 @@ export declare class Script extends Script_base {
|
|
|
4537
4341
|
static readonly exitCode: <A, E>(exit: Exit.Exit<A, E>, options?: ExitCodeOptions) => number;
|
|
4538
4342
|
/** See {@link run}. */
|
|
4539
4343
|
static readonly run: <A, E>(effect: Effect.Effect<A, E, Script | Sui | SuiCore>, options?: ScriptRunOptions) => Promise<number>;
|
|
4344
|
+
/** See {@link report}. */
|
|
4345
|
+
static readonly report: <A, E>(exit: Exit.Exit<A, E>, options?: ReportOptions) => Promise<number>;
|
|
4540
4346
|
}
|
|
4541
4347
|
```
|
|
4542
4348
|
|
|
@@ -4663,6 +4469,26 @@ script that means mainnet has to say so twice, in `SUI_NETWORK` and in
|
|
|
4663
4469
|
|
|
4664
4470
|
**Fails with: `ConfigError`.**
|
|
4665
4471
|
|
|
4472
|
+
### `report` (const)
|
|
4473
|
+
|
|
4474
|
+
```ts
|
|
4475
|
+
declare const report: <A, E>(exit: Exit.Exit<A, E>, options?: ReportOptions) => Promise<number>
|
|
4476
|
+
```
|
|
4477
|
+
|
|
4478
|
+
Prints what `run` prints, and answers the exit code, for a program that
|
|
4479
|
+
owns its own process.
|
|
4480
|
+
|
|
4481
|
+
`Script.run` is a whole entrypoint: it builds the layer, forks the root
|
|
4482
|
+
fiber, installs signal handlers and exits. A CLI with its own argv parser and
|
|
4483
|
+
twenty subcommands has all of that already and still wants the two things
|
|
4484
|
+
`run` does at the end — one diagnostic line per failure (with the bytes of a
|
|
4485
|
+
`SubmissionUnknown`), and every unresolved journal entry on a non-zero exit —
|
|
4486
|
+
plus the code itself. That is this: hand it the `Exit` of whatever you ran,
|
|
4487
|
+
get the lines on stderr and the number back, and call `process.exitCode = …`
|
|
4488
|
+
yourself rather than `process.exit`, so buffered output still flushes.
|
|
4489
|
+
|
|
4490
|
+
**Never fails.**
|
|
4491
|
+
|
|
4666
4492
|
### `run` (const)
|
|
4667
4493
|
|
|
4668
4494
|
```ts
|
|
@@ -4699,7 +4525,7 @@ Returns the exit code as well as passing it to `exit`, so a test can inject
|
|
|
4699
4525
|
## `@unconfirmed/sui-effect/testing`
|
|
4700
4526
|
|
|
4701
4527
|
|
|
4702
|
-
|
|
4528
|
+
17 exported symbols.
|
|
4703
4529
|
|
|
4704
4530
|
### `CLOCK_TYPE` (const)
|
|
4705
4531
|
|
|
@@ -4728,6 +4554,19 @@ declare const DEFAULT_EPOCH = 100n
|
|
|
4728
4554
|
|
|
4729
4555
|
The epoch the fake reports when a script does not set one.
|
|
4730
4556
|
|
|
4557
|
+
### `FakeBalance` (interface)
|
|
4558
|
+
|
|
4559
|
+
```ts
|
|
4560
|
+
export interface FakeBalance extends SuiClientTypes.Balance {
|
|
4561
|
+
readonly owner?: string;
|
|
4562
|
+
}
|
|
4563
|
+
```
|
|
4564
|
+
|
|
4565
|
+
A balance the fake serves, optionally for one owner.
|
|
4566
|
+
|
|
4567
|
+
`owner` is the address this balance belongs to. Left out, the entry answers
|
|
4568
|
+
for **any** owner, which is what every script written before 0.1.2 assumed.
|
|
4569
|
+
|
|
4731
4570
|
### `FakeChange` (interface)
|
|
4732
4571
|
|
|
4733
4572
|
```ts
|
|
@@ -4860,7 +4699,29 @@ export interface FakeScript {
|
|
|
4860
4699
|
readonly coins?: ReadonlyArray<SuiClientTypes.Coin>;
|
|
4861
4700
|
/** The gas budget the resolve plugin sets when a transaction has none. */
|
|
4862
4701
|
readonly gasBudget?: bigint;
|
|
4863
|
-
|
|
4702
|
+
/**
|
|
4703
|
+
* The balances `getBalance` and `listBalances` serve.
|
|
4704
|
+
*
|
|
4705
|
+
* Keyed by **owner and coin type**: an entry with an `owner` answers only for
|
|
4706
|
+
* that address, and one without answers for any, which is what a script
|
|
4707
|
+
* written before 0.1.2 meant. A `getBalance` for an owner and coin type no
|
|
4708
|
+
* entry names answers zero, the way a node does for an address that holds
|
|
4709
|
+
* none of that coin.
|
|
4710
|
+
*/
|
|
4711
|
+
readonly balances?: ReadonlyArray<FakeBalance>;
|
|
4712
|
+
/**
|
|
4713
|
+
* Scripted outcomes for `getObject`, oldest first; the last repeats forever.
|
|
4714
|
+
*
|
|
4715
|
+
* This is transport-error injection on a **read**: `FakeOutcome.transportError`
|
|
4716
|
+
* and `FakeOutcome.timeoutThen` are what it is for, and they are how a test
|
|
4717
|
+
* drives `SuiCore`'s read retry policy or an extension's own fallback.
|
|
4718
|
+
* `FakeOutcome.notFound` answers the way a missing object does
|
|
4719
|
+
* (`ObjectNotFound`). A `succeed` entry — and an empty or exhausted script —
|
|
4720
|
+
* means "serve the object map", which is the normal behaviour.
|
|
4721
|
+
*
|
|
4722
|
+
* @since 0.1.2
|
|
4723
|
+
*/
|
|
4724
|
+
readonly getObject?: ReadonlyArray<FakeOutcome>;
|
|
4864
4725
|
/**
|
|
4865
4726
|
* What `getCoinMetadata` answers, keyed by coin type.
|
|
4866
4727
|
*
|
|
@@ -5021,7 +4882,7 @@ export interface SuiCoreFakeState {
|
|
|
5021
4882
|
*/
|
|
5022
4883
|
readonly recordTransaction: (digest: string, outcome: FakeOutcome) => Effect.Effect<void>;
|
|
5023
4884
|
/** Replaces the remaining scripted outcomes of a method. */
|
|
5024
|
-
readonly setOutcomes: (method: "simulate" | "execute" | "getTransaction" | "buildSimulate", outcomes: ReadonlyArray<FakeOutcome>) => Effect.Effect<void>;
|
|
4885
|
+
readonly setOutcomes: (method: "simulate" | "execute" | "getTransaction" | "buildSimulate" | "getObject", outcomes: ReadonlyArray<FakeOutcome>) => Effect.Effect<void>;
|
|
5025
4886
|
}
|
|
5026
4887
|
```
|
|
5027
4888
|
|
|
@@ -5043,6 +4904,7 @@ declare const SuiTest: {
|
|
|
5043
4904
|
readonly scriptExecute: (outcomes: ReadonlyArray<FakeOutcome>) => Effect.Effect<void, never, SuiCoreFake>;
|
|
5044
4905
|
readonly scriptSimulate: (outcomes: ReadonlyArray<FakeOutcome>) => Effect.Effect<void, never, SuiCoreFake>;
|
|
5045
4906
|
readonly scriptGetTransaction: (outcomes: ReadonlyArray<FakeOutcome>) => Effect.Effect<void, never, SuiCoreFake>;
|
|
4907
|
+
readonly scriptGetObject: (outcomes: ReadonlyArray<FakeOutcome>) => Effect.Effect<void, never, SuiCoreFake>;
|
|
5046
4908
|
readonly calls: (method?: string) => Effect.Effect<ReadonlyArray<RecordedCall>, never, SuiCoreFake>;
|
|
5047
4909
|
}
|
|
5048
4910
|
```
|
|
@@ -5774,22 +5636,12 @@ const SettlementBcs = bcs.struct("Settlement", {
|
|
|
5774
5636
|
* needs a real `BcsType` so it can re-serialize what it parsed and reject
|
|
5775
5637
|
* trailing bytes, and a domain type is not a BCS layout.
|
|
5776
5638
|
*/
|
|
5777
|
-
export class Settlement extends Schema.Class<Settlement>("Settlement")({
|
|
5639
|
+
export class Settlement extends Schema.Class<Settlement>("escrow/Settlement")({
|
|
5778
5640
|
escrowId: ObjectId,
|
|
5779
5641
|
settledAt: Schema.DateTimeUtc,
|
|
5780
5642
|
claimedBy: SuiAddress
|
|
5781
5643
|
}) {}
|
|
5782
5644
|
|
|
5783
|
-
/**
|
|
5784
|
-
* The halfway shape the transformation produces: the domain field names, before
|
|
5785
|
-
* `Settlement`'s own schema brands the ids.
|
|
5786
|
-
*/
|
|
5787
|
-
interface SettlementParts {
|
|
5788
|
-
readonly escrowId: string
|
|
5789
|
-
readonly settledAt: DateTime.Utc
|
|
5790
|
-
readonly claimedBy: string
|
|
5791
|
-
}
|
|
5792
|
-
|
|
5793
5645
|
/**
|
|
5794
5646
|
* The composed codec: BCS bytes to `Settlement`, and back.
|
|
5795
5647
|
*
|
|
@@ -5803,10 +5655,11 @@ interface SettlementParts {
|
|
|
5803
5655
|
*
|
|
5804
5656
|
* Two details worth copying:
|
|
5805
5657
|
*
|
|
5806
|
-
* - **`decode` produces the target's
|
|
5807
|
-
*
|
|
5808
|
-
*
|
|
5809
|
-
*
|
|
5658
|
+
* - **`decode` produces the target's `Encoded` side, not an instance.**
|
|
5659
|
+
* `typeof Settlement.Encoded` is exactly that shape, so nothing has to be
|
|
5660
|
+
* written out by hand and nothing can drift. `decodeTo` sits between the
|
|
5661
|
+
* source type and the target schema, which is what lets the target's own
|
|
5662
|
+
* checks — the `ObjectId` and `SuiAddress` brands here — run afterwards.
|
|
5810
5663
|
* - **`encode` is the inverse mapper and is not optional.** A codec that cannot
|
|
5811
5664
|
* encode is one `Schema.encodeUnknownEffect` fails on, and the compiler asks
|
|
5812
5665
|
* for it here rather than at the call site.
|
|
@@ -5826,7 +5679,7 @@ export const SettlementContent = (typeOrigin: string) =>
|
|
|
5826
5679
|
).pipe(
|
|
5827
5680
|
Schema.decodeTo(
|
|
5828
5681
|
Settlement,
|
|
5829
|
-
SchemaTransformation.transformOrFail<
|
|
5682
|
+
SchemaTransformation.transformOrFail<typeof Settlement.Encoded, typeof SettlementBcs.$inferType>({
|
|
5830
5683
|
decode: (fields, options) =>
|
|
5831
5684
|
// `transformOrFail`, not `transform`, because one of these mappings can
|
|
5832
5685
|
// fail: a `u64` of milliseconds is not necessarily a time. A `transform`
|
|
@@ -5843,7 +5696,7 @@ export const SettlementContent = (typeOrigin: string) =>
|
|
|
5843
5696
|
options
|
|
5844
5697
|
)
|
|
5845
5698
|
),
|
|
5846
|
-
(settledAt):
|
|
5699
|
+
(settledAt): typeof Settlement.Encoded => ({
|
|
5847
5700
|
escrowId: fields.escrow_id,
|
|
5848
5701
|
settledAt,
|
|
5849
5702
|
claimedBy: fields.claimed_by
|
|
@@ -5875,6 +5728,14 @@ export const SettlementContent = (typeOrigin: string) =>
|
|
|
5875
5728
|
*
|
|
5876
5729
|
* The tags are prefixed with the package name because `EscrowNotFound` is a
|
|
5877
5730
|
* name two packages could plausibly both want.
|
|
5731
|
+
*
|
|
5732
|
+
* And every one of them has a real `.message`. `Schema.TaggedError` leaves it
|
|
5733
|
+
* empty, so an error that supplies neither an `override get message()` nor a
|
|
5734
|
+
* `message` schema field surfaces an empty string everywhere a consumer
|
|
5735
|
+
* catches it, and `SuiError.toJson` emits no `message` key at all. The getter
|
|
5736
|
+
* is the usual answer — it stays out of the encoding, so it costs nothing at
|
|
5737
|
+
* the constructor — and a `message` schema field is for the case where the
|
|
5738
|
+
* sentence comes from somewhere else, as `EscrowSettlementUnknown`'s does.
|
|
5878
5739
|
*/
|
|
5879
5740
|
import { Schema } from "effect"
|
|
5880
5741
|
import { Digest, type Outcome, ObjectId } from "@unconfirmed/sui-effect"
|
|
@@ -5890,6 +5751,18 @@ export class EscrowNotFound extends Schema.TaggedError<EscrowNotFound>()(
|
|
|
5890
5751
|
{ escrowId: ObjectId }
|
|
5891
5752
|
) {
|
|
5892
5753
|
readonly outcome: Outcome = "not_applied"
|
|
5754
|
+
|
|
5755
|
+
/**
|
|
5756
|
+
* `Schema.TaggedError` leaves `.message` empty, so anything surfacing
|
|
5757
|
+
* `error.message` — a log line, a `catch` in a consumer's UI,
|
|
5758
|
+
* `SuiError.toJson` — shows nothing unless the class supplies one. This is
|
|
5759
|
+
* the idiom sui-effect's own errors use, and the reason every error here has
|
|
5760
|
+
* one: define a getter over the fields, never a `message` schema field you
|
|
5761
|
+
* then have to pass to every constructor.
|
|
5762
|
+
*/
|
|
5763
|
+
override get message(): string {
|
|
5764
|
+
return `no escrow ${this.escrowId}`
|
|
5765
|
+
}
|
|
5893
5766
|
}
|
|
5894
5767
|
|
|
5895
5768
|
/**
|
|
@@ -5899,6 +5772,10 @@ export class EscrowNotFound extends Schema.TaggedError<EscrowNotFound>()(
|
|
|
5899
5772
|
* This is the case the `outcome` field exists for: the transaction applied, the
|
|
5900
5773
|
* operation as a whole did not finish, and the only safe next step is to
|
|
5901
5774
|
* reconcile rather than to retry. A script that fails with this exits 3.
|
|
5775
|
+
*
|
|
5776
|
+
* Its `message` is a **schema field** rather than a getter, because the
|
|
5777
|
+
* sentence comes from the settlement service rather than from these fields.
|
|
5778
|
+
* Either way `.message` is a real string and `SuiError.toJson` carries it.
|
|
5902
5779
|
*/
|
|
5903
5780
|
export class EscrowSettlementUnknown extends Schema.TaggedError<EscrowSettlementUnknown>()(
|
|
5904
5781
|
"escrow/EscrowSettlementUnknown",
|
|
@@ -5923,6 +5800,11 @@ export class EscrowUnsupportedNetwork extends Schema.TaggedError<EscrowUnsupport
|
|
|
5923
5800
|
{ network: Schema.String }
|
|
5924
5801
|
) {
|
|
5925
5802
|
readonly outcome: Outcome = "not_applied"
|
|
5803
|
+
|
|
5804
|
+
/** See {@link EscrowNotFound.message}: a getter, not a schema field. */
|
|
5805
|
+
override get message(): string {
|
|
5806
|
+
return `this release bundles no escrow deployment for ${this.network}`
|
|
5807
|
+
}
|
|
5926
5808
|
}
|
|
5927
5809
|
```
|
|
5928
5810
|
|
|
@@ -6144,7 +6026,7 @@ const make = (
|
|
|
6144
6026
|
Effect.flatMap((raw) =>
|
|
6145
6027
|
decodeAddress(raw).pipe(
|
|
6146
6028
|
Effect.mapError((issue) =>
|
|
6147
|
-
new DecodeError({ expectedType: "SuiAddress", issue: issue.message })
|
|
6029
|
+
new DecodeError({ expectedType: "SuiAddress", kind: "shape", issue: issue.message })
|
|
6148
6030
|
)
|
|
6149
6031
|
)
|
|
6150
6032
|
),
|
|
@@ -6788,6 +6670,15 @@ describe("Settlement: a domain class over the BCS bridge", () => {
|
|
|
6788
6670
|
claimed_by: bcs.Address
|
|
6789
6671
|
})
|
|
6790
6672
|
|
|
6673
|
+
// The identifier is the class's stable runtime marker and its JSON-Schema
|
|
6674
|
+
// `$ref` key, so it follows the guide's `"<package>/<Name>"` rule: two
|
|
6675
|
+
// extensions with a `Settlement` class must not collide in one document.
|
|
6676
|
+
test("the class identifier is scoped to the package", () => {
|
|
6677
|
+
expect(JSON.stringify(Schema.toJsonSchemaDocument(Settlement))).toContain(
|
|
6678
|
+
"escrow/Settlement"
|
|
6679
|
+
)
|
|
6680
|
+
})
|
|
6681
|
+
|
|
6791
6682
|
test("snake_case Move fields decode into the camelCase domain class", async () => {
|
|
6792
6683
|
const bytes = SettlementBcs.serialize({
|
|
6793
6684
|
escrow_id: ESCROW_ID,
|
|
@@ -7165,6 +7056,41 @@ describe("the errors", () => {
|
|
|
7165
7056
|
expect(json["outcome"]).toBe("unknown")
|
|
7166
7057
|
expect(json["outcome"]).toBe(SuiError.outcome(error))
|
|
7167
7058
|
})
|
|
7059
|
+
|
|
7060
|
+
/**
|
|
7061
|
+
* `Schema.TaggedError` leaves `.message` empty, so an error that defines
|
|
7062
|
+
* neither a getter nor a `message` schema field logs as an empty string and
|
|
7063
|
+
* `SuiError.toJson` emits no `message` key at all. Every error here defines
|
|
7064
|
+
* one, and the guide promises a reader that they will.
|
|
7065
|
+
*/
|
|
7066
|
+
test("every error has a real message, and toJson carries it", () => {
|
|
7067
|
+
const errors = [
|
|
7068
|
+
new EscrowNotFound({ escrowId: ESCROW_ID }),
|
|
7069
|
+
new EscrowSettlementUnknown({
|
|
7070
|
+
escrowId: ESCROW_ID,
|
|
7071
|
+
digest: "1".repeat(32) as never,
|
|
7072
|
+
message: "the operator never confirmed"
|
|
7073
|
+
}),
|
|
7074
|
+
new EscrowUnsupportedNetwork({ network: "devnet" })
|
|
7075
|
+
]
|
|
7076
|
+
for (const error of errors) {
|
|
7077
|
+
expect([error._tag, error.message.length > 0]).toEqual([error._tag, true])
|
|
7078
|
+
expect([error._tag, SuiError.toJson(error)["message"]]).toEqual([
|
|
7079
|
+
error._tag,
|
|
7080
|
+
error.message
|
|
7081
|
+
])
|
|
7082
|
+
}
|
|
7083
|
+
// The getter reads the error's own fields, so the sentence names the thing
|
|
7084
|
+
// that failed rather than repeating the tag.
|
|
7085
|
+
expect(new EscrowNotFound({ escrowId: ESCROW_ID }).message).toBe(`no escrow ${ESCROW_ID}`)
|
|
7086
|
+
expect(new EscrowUnsupportedNetwork({ network: "devnet" }).message).toBe(
|
|
7087
|
+
"this release bundles no escrow deployment for devnet"
|
|
7088
|
+
)
|
|
7089
|
+
// And a getter stays out of the encoding, so it is not a constructor
|
|
7090
|
+
// argument: only `EscrowSettlementUnknown` takes a `message`.
|
|
7091
|
+
expect(Object.keys(SuiError.toJson(new EscrowUnsupportedNetwork({ network: "devnet" }))))
|
|
7092
|
+
.toEqual(["_tag", "network", "outcome", "message"])
|
|
7093
|
+
})
|
|
7168
7094
|
})
|
|
7169
7095
|
```
|
|
7170
7096
|
|