@misofm/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +248 -0
  3. package/dist/catalog.d.ts +31 -0
  4. package/dist/catalog.d.ts.map +1 -0
  5. package/dist/catalog.js +45 -0
  6. package/dist/catalog.js.map +1 -0
  7. package/dist/client.d.ts +134 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +113 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/contracts/miso_pressing/certificate.d.ts +78 -0
  12. package/dist/contracts/miso_pressing/certificate.d.ts.map +1 -0
  13. package/dist/contracts/miso_pressing/certificate.js +91 -0
  14. package/dist/contracts/miso_pressing/certificate.js.map +1 -0
  15. package/dist/contracts/miso_pressing/deps/std/type_name.d.ts +18 -0
  16. package/dist/contracts/miso_pressing/deps/std/type_name.d.ts.map +1 -0
  17. package/dist/contracts/miso_pressing/deps/std/type_name.js +20 -0
  18. package/dist/contracts/miso_pressing/deps/std/type_name.js.map +1 -0
  19. package/dist/contracts/miso_pressing/listing.d.ts +449 -0
  20. package/dist/contracts/miso_pressing/listing.d.ts.map +1 -0
  21. package/dist/contracts/miso_pressing/listing.js +416 -0
  22. package/dist/contracts/miso_pressing/listing.js.map +1 -0
  23. package/dist/contracts/miso_pressing/pressing.d.ts +365 -0
  24. package/dist/contracts/miso_pressing/pressing.d.ts.map +1 -0
  25. package/dist/contracts/miso_pressing/pressing.js +335 -0
  26. package/dist/contracts/miso_pressing/pressing.js.map +1 -0
  27. package/dist/contracts/utils/index.d.ts +31 -0
  28. package/dist/contracts/utils/index.d.ts.map +1 -0
  29. package/dist/contracts/utils/index.js +162 -0
  30. package/dist/contracts/utils/index.js.map +1 -0
  31. package/dist/execute.d.ts +17 -0
  32. package/dist/execute.d.ts.map +1 -0
  33. package/dist/execute.js +21 -0
  34. package/dist/execute.js.map +1 -0
  35. package/dist/index.d.ts +10 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +27 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/pressing.d.ts +223 -0
  40. package/dist/pressing.d.ts.map +1 -0
  41. package/dist/pressing.js +280 -0
  42. package/dist/pressing.js.map +1 -0
  43. package/dist/queries.d.ts +2 -0
  44. package/dist/queries.d.ts.map +1 -0
  45. package/dist/queries.js +8 -0
  46. package/dist/queries.js.map +1 -0
  47. package/dist/release-graph.d.ts +93 -0
  48. package/dist/release-graph.d.ts.map +1 -0
  49. package/dist/release-graph.js +143 -0
  50. package/dist/release-graph.js.map +1 -0
  51. package/dist/share-template.d.ts +3 -0
  52. package/dist/share-template.d.ts.map +1 -0
  53. package/dist/share-template.js +46 -0
  54. package/dist/share-template.js.map +1 -0
  55. package/dist/share.d.ts +66 -0
  56. package/dist/share.d.ts.map +1 -0
  57. package/dist/share.js +156 -0
  58. package/dist/share.js.map +1 -0
  59. package/dist/transactions.d.ts +177 -0
  60. package/dist/transactions.d.ts.map +1 -0
  61. package/dist/transactions.js +237 -0
  62. package/dist/transactions.js.map +1 -0
  63. package/package.json +99 -0
  64. package/src/catalog.ts +77 -0
  65. package/src/client.ts +249 -0
  66. package/src/contracts/miso_pressing/certificate.ts +129 -0
  67. package/src/contracts/miso_pressing/deps/std/type_name.ts +22 -0
  68. package/src/contracts/miso_pressing/listing.ts +621 -0
  69. package/src/contracts/miso_pressing/pressing.ts +454 -0
  70. package/src/contracts/utils/index.ts +229 -0
  71. package/src/execute.ts +34 -0
  72. package/src/index.ts +29 -0
  73. package/src/pressing.ts +497 -0
  74. package/src/queries.ts +9 -0
  75. package/src/release-graph.ts +279 -0
  76. package/src/share-template.ts +55 -0
  77. package/src/share.ts +258 -0
  78. package/src/transactions.ts +440 -0
@@ -0,0 +1,454 @@
1
+ /**************************************************************
2
+ * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
3
+ **************************************************************/
4
+
5
+
6
+ /**
7
+ * A release's record production — its _Pressing_.
8
+ *
9
+ * A release has exactly one pressing, and the pressing is one uncapped run of
10
+ * records: every copy ever made draws its number from this single counter,
11
+ * forever. There are no editions, no supply caps, and no sold-out state — scarcity
12
+ * on Miso is what a record _accrues_ (playtime above all), not how few of it were
13
+ * printed. The pressing owns two things and only two things: the **run** the
14
+ * records number against, and the **switch** that stops it.
15
+ *
16
+ * ```text
17
+ * Release
18
+ * └─ Pressing the run, and when it sells at all PressingKey()
19
+ * ├─ PressingAdminCap authority over price and state PressingAdminCapKey()
20
+ * ├─ Listing<SUI> what it costs in one currency ListingKey<SUI>()
21
+ * └─ Listing<USDC>
22
+ * ```
23
+ *
24
+ * # Everything is address math
25
+ *
26
+ * A pressing's UID is derived off its release's UID at a singleton key, its admin
27
+ * cap's and each listing's off the pressing's, and records off the pressing's at
28
+ * their number. So every object in the tree is reachable from the release id
29
+ * alone, by pure computation — no registry, no pointer that has to be maintained,
30
+ * and no stored set of listings: a listing either exists at its derived address or
31
+ * it does not (`listing::has_listing`), and `ListingOpenedEvent<Currency>`
32
+ * enumerates them for an indexer. It also makes the number sequence gap-free for
33
+ * free, and every record verifiable against its pressing from chain state alone
34
+ * (`verify_record`).
35
+ *
36
+ * # Starting and stopping is state, never teardown
37
+ *
38
+ * Nothing here is ever destroyed, sealed, or wound down — deleting a pressing
39
+ * would strand its whole derived subtree, so there is no destructor at all. The
40
+ * run's lifecycle is `Scheduled → Active → Paused → Active`: it opens itself at
41
+ * its drop moment (no artist transaction, and nobody can buy early), and after
42
+ * that the artist stops and starts it at will. The first transition is real, not
43
+ * computed — the first sale past the start rewrites `Scheduled` to `Active` inside
44
+ * `mint_next`, which is why `Scheduled` only ever describes a run still waiting.
45
+ * Below it, each listing's `Enabled | Disabled` governs one currency. A run that
46
+ * is paused or not yet open sells in no currency, whatever the listings say.
47
+ *
48
+ * There is no end state and no expiry: an uncapped, permanent run has nothing to
49
+ * count down to, and a time-limited sale is scarcity theater this design rejects.
50
+ * An artist ending a campaign pauses it.
51
+ *
52
+ * # Authority
53
+ *
54
+ * Opening a pressing needs the release's `ReleaseAdminCap`, enforced by the
55
+ * protocol's `release::uid_mut`, and hands back a `PressingAdminCap`. Everything
56
+ * after that — pricing, pausing, opening listings — authorizes against the
57
+ * pressing cap alone.
58
+ *
59
+ * The split is deliberate and it is about money, not tidiness. `ReleaseAdminCap`
60
+ * yields `release::uid_mut`, and `balance::withdraw_funds_from_object` is gated on
61
+ * `&mut UID` alone — so the release cap can withdraw the sales revenue that `buy`
62
+ * forwards to the release's address. Under one cap, "may reprice a listing" and
63
+ * "may take the money" would be the same grant. The pressing cap is the routine
64
+ * one, safe to delegate to whoever runs the shop; the release cap stays with the
65
+ * rightsholder.
66
+ */
67
+
68
+ import { MoveTuple, MoveStruct, MoveEnum, normalizeMoveArguments, type RawTransactionArgument } from '../utils/index.js';
69
+ import { bcs } from '@mysten/sui/bcs';
70
+ import { type Transaction, type TransactionArgument } from '@mysten/sui/transactions';
71
+ const $moduleName = '@local-pkg/miso_pressing::pressing';
72
+ export const PressingKey = new MoveTuple({ name: `${$moduleName}::PressingKey`, fields: [bcs.bool()] });
73
+ export const PressingAdminCapKey = new MoveTuple({ name: `${$moduleName}::PressingAdminCapKey`, fields: [bcs.bool()] });
74
+ export const MintWitness = new MoveStruct({ name: `${$moduleName}::MintWitness`, fields: {
75
+ dummy_field: bcs.bool()
76
+ } });
77
+ /**
78
+ * Whether the run sells, over every currency at once. The lifecycle runs
79
+ * `Scheduled → Active → Paused → Active`: a pressing opens itself at its drop
80
+ * moment, then the artist stops and starts it at will.
81
+ */
82
+ export const PressingState = new MoveEnum({ name: `${$moduleName}::PressingState`, fields: {
83
+ /**
84
+ * Opens the moment the clock passes `start_timestamp_ms` (Unix ms), with no
85
+ * further action from anyone. A start already in the past sells now.
86
+ *
87
+ * This is a _transitional_ state: the first sale past the start rewrites it to
88
+ * `Active` (in `mint_next`, before any sales logic), so a run reads `Scheduled`
89
+ * only while it is still waiting. Between the start and that first sale the run
90
+ * already sells — `is_selling` answers against the clock — so nobody has to go
91
+ * first for the drop to be open.
92
+ *
93
+ * Consequence worth knowing: once the transition fires the start time is gone from
94
+ * the object. `PressingOpenedEvent` and `PressingStateChangedEvent` carry it, so
95
+ * "when was this run scheduled for" is an event-log question, not an object read.
96
+ */
97
+ Scheduled: new MoveStruct({ name: `PressingState.Scheduled`, fields: {
98
+ start_timestamp_ms: bcs.u64()
99
+ } }),
100
+ /** Selling, subject to each listing's own state. */
101
+ Active: null,
102
+ /** Selling in no currency, whatever the listings say. */
103
+ Paused: null
104
+ } });
105
+ export const Pressing = new MoveStruct({ name: `${$moduleName}::Pressing`, fields: {
106
+ id: bcs.Address,
107
+ /** The release these records are copies of. */
108
+ release_id: bcs.Address,
109
+ /** Whether the run sells at all, in any currency. */
110
+ state: PressingState,
111
+ /**
112
+ * Records pressed so far; also the most recent number. Read on every mint — this
113
+ * is the sequence itself, not a statistic.
114
+ */
115
+ supply: bcs.u64()
116
+ } });
117
+ export const PressingAdminCap = new MoveStruct({ name: `${$moduleName}::PressingAdminCap`, fields: {
118
+ id: bcs.Address,
119
+ /** The pressing this cap controls. Every mutator asserts against it. */
120
+ pressing_id: bcs.Address
121
+ } });
122
+ export const PressingOpenedEvent = new MoveStruct({ name: `${$moduleName}::PressingOpenedEvent`, fields: {
123
+ pressing_id: bcs.Address,
124
+ release_id: bcs.Address,
125
+ state: PressingState
126
+ } });
127
+ export const PressingStateChangedEvent = new MoveStruct({ name: `${$moduleName}::PressingStateChangedEvent`, fields: {
128
+ pressing_id: bcs.Address,
129
+ state: PressingState
130
+ } });
131
+ export interface NewScheduledStateArguments {
132
+ startTimestampMs: RawTransactionArgument<number | bigint>;
133
+ }
134
+ export interface NewScheduledStateOptions {
135
+ package?: string;
136
+ arguments: NewScheduledStateArguments | [
137
+ startTimestampMs: RawTransactionArgument<number | bigint>
138
+ ];
139
+ }
140
+ /** The scheduled state: the run opens itself at `start_timestamp_ms` (Unix ms). */
141
+ export function newScheduledState(options: NewScheduledStateOptions) {
142
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
143
+ const argumentsTypes = [
144
+ 'u64'
145
+ ] satisfies (string | null)[];
146
+ const parameterNames = ["startTimestampMs"];
147
+ return (tx: Transaction) => tx.moveCall({
148
+ package: packageAddress,
149
+ module: 'pressing',
150
+ function: 'new_scheduled_state',
151
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
152
+ });
153
+ }
154
+ export interface NewActiveStateOptions {
155
+ package?: string;
156
+ arguments?: [
157
+ ];
158
+ }
159
+ /** The active state: the run sells, subject to each listing's own state. */
160
+ export function newActiveState(options: NewActiveStateOptions = {}) {
161
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
162
+ return (tx: Transaction) => tx.moveCall({
163
+ package: packageAddress,
164
+ module: 'pressing',
165
+ function: 'new_active_state',
166
+ });
167
+ }
168
+ export interface NewPausedStateOptions {
169
+ package?: string;
170
+ arguments?: [
171
+ ];
172
+ }
173
+ /** The paused state: the run sells in no currency. */
174
+ export function newPausedState(options: NewPausedStateOptions = {}) {
175
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
176
+ return (tx: Transaction) => tx.moveCall({
177
+ package: packageAddress,
178
+ module: 'pressing',
179
+ function: 'new_paused_state',
180
+ });
181
+ }
182
+ export interface NewArguments {
183
+ release: RawTransactionArgument<string>;
184
+ cap: RawTransactionArgument<string>;
185
+ state: TransactionArgument;
186
+ }
187
+ export interface NewOptions {
188
+ package?: string;
189
+ arguments: NewArguments | [
190
+ release: RawTransactionArgument<string>,
191
+ cap: RawTransactionArgument<string>,
192
+ state: TransactionArgument
193
+ ];
194
+ }
195
+ /**
196
+ * Open a release's pressing in `state` — `Scheduled` for a drop moment, `Active`
197
+ * to sell immediately, `Paused` to set it up quietly. Returns it unshared, so the
198
+ * same transaction can list it (`listing::new`) before `share` puts it on chain,
199
+ * plus the cap that governs it from here on. Neither value has `drop`, so neither
200
+ * can be lost by forgetting.
201
+ *
202
+ * Claim-once on `PressingKey()` means a release's pressing can only ever be opened
203
+ * here, exactly once; calling this twice for the same release aborts.
204
+ */
205
+ export function _new(options: NewOptions) {
206
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
207
+ const argumentsTypes = [
208
+ null,
209
+ null,
210
+ null
211
+ ] satisfies (string | null)[];
212
+ const parameterNames = ["release", "cap", "state"];
213
+ return (tx: Transaction) => tx.moveCall({
214
+ package: packageAddress,
215
+ module: 'pressing',
216
+ function: 'new',
217
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
218
+ });
219
+ }
220
+ export interface ShareArguments {
221
+ self: RawTransactionArgument<string>;
222
+ }
223
+ export interface ShareOptions {
224
+ package?: string;
225
+ arguments: ShareArguments | [
226
+ self: RawTransactionArgument<string>
227
+ ];
228
+ }
229
+ /**
230
+ * Put the pressing on chain. `new` hands back an unshared `Pressing` so the same
231
+ * transaction can list it first; this is the last call in that sequence.
232
+ */
233
+ export function share(options: ShareOptions) {
234
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
235
+ const argumentsTypes = [
236
+ null
237
+ ] satisfies (string | null)[];
238
+ const parameterNames = ["self"];
239
+ return (tx: Transaction) => tx.moveCall({
240
+ package: packageAddress,
241
+ module: 'pressing',
242
+ function: 'share',
243
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
244
+ });
245
+ }
246
+ export interface SetStateArguments {
247
+ self: RawTransactionArgument<string>;
248
+ cap: RawTransactionArgument<string>;
249
+ state: TransactionArgument;
250
+ }
251
+ export interface SetStateOptions {
252
+ package?: string;
253
+ arguments: SetStateArguments | [
254
+ self: RawTransactionArgument<string>,
255
+ cap: RawTransactionArgument<string>,
256
+ state: TransactionArgument
257
+ ];
258
+ }
259
+ /**
260
+ * Move the run between its three modes — schedule it, open it, stop it. Takes
261
+ * effect across every currency at once, regardless of any listing's own state.
262
+ */
263
+ export function setState(options: SetStateOptions) {
264
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
265
+ const argumentsTypes = [
266
+ null,
267
+ null,
268
+ null
269
+ ] satisfies (string | null)[];
270
+ const parameterNames = ["self", "cap", "state"];
271
+ return (tx: Transaction) => tx.moveCall({
272
+ package: packageAddress,
273
+ module: 'pressing',
274
+ function: 'set_state',
275
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
276
+ });
277
+ }
278
+ export interface DeriveIdArguments {
279
+ releaseId: RawTransactionArgument<string>;
280
+ }
281
+ export interface DeriveIdOptions {
282
+ package?: string;
283
+ arguments: DeriveIdArguments | [
284
+ releaseId: RawTransactionArgument<string>
285
+ ];
286
+ }
287
+ /**
288
+ * The address `release_id`'s pressing occupies — pure address math, computable
289
+ * before the pressing has been opened.
290
+ */
291
+ export function deriveId(options: DeriveIdOptions) {
292
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
293
+ const argumentsTypes = [
294
+ '0x2::object::ID'
295
+ ] satisfies (string | null)[];
296
+ const parameterNames = ["releaseId"];
297
+ return (tx: Transaction) => tx.moveCall({
298
+ package: packageAddress,
299
+ module: 'pressing',
300
+ function: 'derive_id',
301
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
302
+ });
303
+ }
304
+ export interface IdArguments {
305
+ self: RawTransactionArgument<string>;
306
+ }
307
+ export interface IdOptions {
308
+ package?: string;
309
+ arguments: IdArguments | [
310
+ self: RawTransactionArgument<string>
311
+ ];
312
+ }
313
+ export function id(options: IdOptions) {
314
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
315
+ const argumentsTypes = [
316
+ null
317
+ ] satisfies (string | null)[];
318
+ const parameterNames = ["self"];
319
+ return (tx: Transaction) => tx.moveCall({
320
+ package: packageAddress,
321
+ module: 'pressing',
322
+ function: 'id',
323
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
324
+ });
325
+ }
326
+ export interface ReleaseIdArguments {
327
+ self: RawTransactionArgument<string>;
328
+ }
329
+ export interface ReleaseIdOptions {
330
+ package?: string;
331
+ arguments: ReleaseIdArguments | [
332
+ self: RawTransactionArgument<string>
333
+ ];
334
+ }
335
+ export function releaseId(options: ReleaseIdOptions) {
336
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
337
+ const argumentsTypes = [
338
+ null
339
+ ] satisfies (string | null)[];
340
+ const parameterNames = ["self"];
341
+ return (tx: Transaction) => tx.moveCall({
342
+ package: packageAddress,
343
+ module: 'pressing',
344
+ function: 'release_id',
345
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
346
+ });
347
+ }
348
+ export interface SupplyArguments {
349
+ self: RawTransactionArgument<string>;
350
+ }
351
+ export interface SupplyOptions {
352
+ package?: string;
353
+ arguments: SupplyArguments | [
354
+ self: RawTransactionArgument<string>
355
+ ];
356
+ }
357
+ /** Records pressed so far; also the most recent number. */
358
+ export function supply(options: SupplyOptions) {
359
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
360
+ const argumentsTypes = [
361
+ null
362
+ ] satisfies (string | null)[];
363
+ const parameterNames = ["self"];
364
+ return (tx: Transaction) => tx.moveCall({
365
+ package: packageAddress,
366
+ module: 'pressing',
367
+ function: 'supply',
368
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
369
+ });
370
+ }
371
+ export interface IsSellingArguments {
372
+ self: RawTransactionArgument<string>;
373
+ }
374
+ export interface IsSellingOptions {
375
+ package?: string;
376
+ arguments: IsSellingArguments | [
377
+ self: RawTransactionArgument<string>
378
+ ];
379
+ }
380
+ /**
381
+ * Whether the run sells _right now_ — the question `buy` actually asks.
382
+ * `Scheduled` answers it against the clock, so a run past its start that has not
383
+ * yet had a sale to settle it reads as selling, which it is.
384
+ */
385
+ export function isSelling(options: IsSellingOptions) {
386
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
387
+ const argumentsTypes = [
388
+ null,
389
+ '0x2::clock::Clock'
390
+ ] satisfies (string | null)[];
391
+ const parameterNames = ["self"];
392
+ return (tx: Transaction) => tx.moveCall({
393
+ package: packageAddress,
394
+ module: 'pressing',
395
+ function: 'is_selling',
396
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
397
+ });
398
+ }
399
+ export interface PressingAdminCapPressingIdArguments {
400
+ cap: RawTransactionArgument<string>;
401
+ }
402
+ export interface PressingAdminCapPressingIdOptions {
403
+ package?: string;
404
+ arguments: PressingAdminCapPressingIdArguments | [
405
+ cap: RawTransactionArgument<string>
406
+ ];
407
+ }
408
+ /**
409
+ * The pressing this cap controls. Public so a custody layer holding the cap can
410
+ * tell what it governs without the `Pressing` object.
411
+ */
412
+ export function pressingAdminCapPressingId(options: PressingAdminCapPressingIdOptions) {
413
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
414
+ const argumentsTypes = [
415
+ null
416
+ ] satisfies (string | null)[];
417
+ const parameterNames = ["cap"];
418
+ return (tx: Transaction) => tx.moveCall({
419
+ package: packageAddress,
420
+ module: 'pressing',
421
+ function: 'pressing_admin_cap_pressing_id',
422
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
423
+ });
424
+ }
425
+ export interface VerifyRecordArguments {
426
+ record: RawTransactionArgument<string>;
427
+ }
428
+ export interface VerifyRecordOptions {
429
+ package?: string;
430
+ arguments: VerifyRecordArguments | [
431
+ record: RawTransactionArgument<string>
432
+ ];
433
+ }
434
+ /**
435
+ * Whether `record` is genuinely the copy its certificate claims it is, checked
436
+ * from chain state alone and without needing the `Pressing` object.
437
+ *
438
+ * The record must sit at exactly the address its certificate number derives to off
439
+ * its release's pressing. The certificate is the readable form of what the address
440
+ * already proves.
441
+ */
442
+ export function verifyRecord(options: VerifyRecordOptions) {
443
+ const packageAddress = options.package ?? '@local-pkg/miso_pressing';
444
+ const argumentsTypes = [
445
+ null
446
+ ] satisfies (string | null)[];
447
+ const parameterNames = ["record"];
448
+ return (tx: Transaction) => tx.moveCall({
449
+ package: packageAddress,
450
+ module: 'pressing',
451
+ function: 'verify_record',
452
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
453
+ });
454
+ }
@@ -0,0 +1,229 @@
1
+
2
+ import {
3
+ bcs,
4
+ type BcsType,
5
+ type TypeTag,
6
+ TypeTagSerializer,
7
+ BcsStruct,
8
+ BcsEnum,
9
+ BcsTuple,
10
+ } from '@mysten/sui/bcs';
11
+ import { normalizeSuiAddress } from '@mysten/sui/utils';
12
+ import { type TransactionArgument, isArgument } from '@mysten/sui/transactions';
13
+ import { type ClientWithCoreApi, type SuiClientTypes } from '@mysten/sui/client';
14
+
15
+ const MOVE_STDLIB_ADDRESS = normalizeSuiAddress('0x1');
16
+ const SUI_FRAMEWORK_ADDRESS = normalizeSuiAddress('0x2');
17
+
18
+ export type RawTransactionArgument<T> = T | TransactionArgument;
19
+
20
+ export type GetOptions<Include extends Omit<SuiClientTypes.ObjectInclude, 'content'> = {}> =
21
+ SuiClientTypes.GetObjectOptions<Include> & { client: ClientWithCoreApi };
22
+
23
+ export type GetManyOptions<Include extends Omit<SuiClientTypes.ObjectInclude, 'content'> = {}> =
24
+ SuiClientTypes.GetObjectsOptions<Include> & { client: ClientWithCoreApi };
25
+
26
+ export function getPureBcsSchema(typeTag: string | TypeTag): BcsType<any> | null {
27
+ const parsedTag = typeof typeTag === 'string' ? TypeTagSerializer.parseFromStr(typeTag) : typeTag;
28
+
29
+ if ('u8' in parsedTag) {
30
+ return bcs.U8;
31
+ } else if ('u16' in parsedTag) {
32
+ return bcs.U16;
33
+ } else if ('u32' in parsedTag) {
34
+ return bcs.U32;
35
+ } else if ('u64' in parsedTag) {
36
+ return bcs.U64;
37
+ } else if ('u128' in parsedTag) {
38
+ return bcs.U128;
39
+ } else if ('u256' in parsedTag) {
40
+ return bcs.U256;
41
+ } else if ('address' in parsedTag) {
42
+ return bcs.Address;
43
+ } else if ('bool' in parsedTag) {
44
+ return bcs.Bool;
45
+ } else if ('vector' in parsedTag) {
46
+ const type = getPureBcsSchema(parsedTag.vector);
47
+ return type ? bcs.vector(type) : null;
48
+ } else if ('struct' in parsedTag) {
49
+ const structTag = parsedTag.struct;
50
+ const pkg = normalizeSuiAddress(structTag.address);
51
+
52
+ if (pkg === MOVE_STDLIB_ADDRESS) {
53
+ if (
54
+ (structTag.module === 'ascii' || structTag.module === 'string') &&
55
+ structTag.name === 'String'
56
+ ) {
57
+ return bcs.String;
58
+ }
59
+
60
+ if (structTag.module === 'option' && structTag.name === 'Option') {
61
+ const inner = structTag.typeParams[0];
62
+ const type = inner ? getPureBcsSchema(inner) : null;
63
+ return type ? bcs.option(type) : null;
64
+ }
65
+ }
66
+
67
+ if (
68
+ pkg === SUI_FRAMEWORK_ADDRESS &&
69
+ structTag.module === 'object' &&
70
+ (structTag.name === 'ID' || structTag.name === 'UID')
71
+ ) {
72
+ return bcs.Address;
73
+ }
74
+ }
75
+
76
+ return null;
77
+ }
78
+
79
+ export function normalizeMoveArguments(
80
+ args: unknown[] | object,
81
+ argTypes: readonly (string | null)[],
82
+ parameterNames?: string[],
83
+ ) {
84
+ const argLen = Array.isArray(args) ? args.length : Object.keys(args).length;
85
+ if (parameterNames && argLen !== parameterNames.length) {
86
+ throw new Error(
87
+ `Invalid number of arguments, expected ${parameterNames.length}, got ${argLen}`,
88
+ );
89
+ }
90
+
91
+ const normalizedArgs: TransactionArgument[] = [];
92
+
93
+ let index = 0;
94
+ for (const argType of argTypes) {
95
+ if (argType === '0x2::clock::Clock') {
96
+ normalizedArgs.push((tx) => tx.object.clock());
97
+ continue;
98
+ }
99
+
100
+ if (argType === '0x2::random::Random') {
101
+ normalizedArgs.push((tx) => tx.object.random());
102
+ continue;
103
+ }
104
+
105
+ if (argType === '0x2::deny_list::DenyList') {
106
+ normalizedArgs.push((tx) => tx.object.denyList());
107
+ continue;
108
+ }
109
+
110
+ if (argType === '0x3::sui_system::SuiSystemState') {
111
+ normalizedArgs.push((tx) => tx.object.system());
112
+ continue;
113
+ }
114
+
115
+ let arg;
116
+ if (Array.isArray(args)) {
117
+ if (index >= args.length) {
118
+ throw new Error(
119
+ `Invalid number of arguments, expected at least ${index + 1}, got ${args.length}`,
120
+ );
121
+ }
122
+ arg = args[index];
123
+ } else {
124
+ if (!parameterNames) {
125
+ throw new Error(`Expected arguments to be passed as an array`);
126
+ }
127
+ const name = parameterNames[index];
128
+ arg = args[name as keyof typeof args];
129
+
130
+ if (arg === undefined) {
131
+ throw new Error(`Parameter ${name} is required`);
132
+ }
133
+ }
134
+
135
+ index += 1;
136
+
137
+ if (typeof arg === 'function' || isArgument(arg)) {
138
+ normalizedArgs.push(arg as TransactionArgument);
139
+ continue;
140
+ }
141
+
142
+ const bcsType = argType === null ? null : getPureBcsSchema(argType);
143
+
144
+ if (bcsType) {
145
+ const bytes = bcsType.serialize(arg as never);
146
+ normalizedArgs.push((tx) => tx.pure(bytes));
147
+ continue;
148
+ }
149
+
150
+ if (typeof arg === 'string') {
151
+ normalizedArgs.push((tx) => tx.object(arg));
152
+ continue;
153
+ }
154
+
155
+ throw new Error(`Invalid argument ${stringify(arg)} for type ${argType}`);
156
+ }
157
+
158
+ return normalizedArgs;
159
+ }
160
+
161
+ export class MoveStruct<
162
+ T extends Record<string, BcsType<any>>,
163
+ const Name extends string = string,
164
+ > extends BcsStruct<T, Name> {
165
+ async get<Include extends Omit<SuiClientTypes.ObjectInclude, 'content' | 'json'> = {}>({
166
+ objectId,
167
+ ...options
168
+ }: GetOptions<Include>): Promise<
169
+ SuiClientTypes.Object<Include & { content: true, json: true }> & { json: BcsStruct<T>['$inferType'] }
170
+ > {
171
+ const [res] = await this.getMany<Include>({
172
+ ...options,
173
+ objectIds: [objectId],
174
+ });
175
+
176
+ if (!res) {
177
+ throw new Error(`No object found for id ${objectId}`);
178
+ }
179
+
180
+ return res;
181
+ }
182
+
183
+ async getMany<Include extends Omit<SuiClientTypes.ObjectInclude, 'content' | 'json'> = {}>({
184
+ client,
185
+ ...options
186
+ }: GetManyOptions<Include>): Promise<
187
+ Array<SuiClientTypes.Object<Include & { content: true, json: true }> & { json: BcsStruct<T>['$inferType'] }>
188
+ > {
189
+ const response = (await client.core.getObjects({
190
+ ...options,
191
+ include: {
192
+ ...options.include,
193
+ content: true,
194
+ },
195
+ })) as SuiClientTypes.GetObjectsResponse<Include & { content: true }>;
196
+
197
+ return response.objects.map((obj) => {
198
+ if (obj instanceof Error) {
199
+ throw obj;
200
+ }
201
+
202
+ return {
203
+ ...obj,
204
+ json: this.parse(obj.content),
205
+ };
206
+ });
207
+ }
208
+ }
209
+
210
+ export class MoveEnum<
211
+ T extends Record<string, BcsType<any> | null>,
212
+ const Name extends string,
213
+ > extends BcsEnum<T, Name> {}
214
+
215
+ export class MoveTuple<
216
+ const T extends readonly BcsType<any>[],
217
+ const Name extends string,
218
+ > extends BcsTuple<T, Name> {}
219
+
220
+ function stringify(val: unknown) {
221
+ if (typeof val === 'object') {
222
+ return JSON.stringify(val, (val: unknown) => val);
223
+ }
224
+ if (typeof val === 'bigint') {
225
+ return val.toString();
226
+ }
227
+
228
+ return val;
229
+ }