@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,440 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // Transaction builders follow the Sui SDK thunk pattern: a builder returns a
5
+ // `(tx: Transaction) => …` thunk that adds commands to a caller-owned
6
+ // `Transaction`, so a platform call composes with protocol calls and anything
7
+ // else in the same PTB.
8
+ //
9
+ // This module holds the OPINIONATED publish flows. `@misonetwork/sdk` does the
10
+ // minimum the Move semantics FORCE and returns anything a caller could
11
+ // legitimately route elsewhere; deciding where those values GO is the
12
+ // platform-layer call that lives here:
13
+ //
14
+ // - minting a work's share supply is a protocol primitive
15
+ // (`createComposition`/`createRecording`) — dispersing it to recipients via
16
+ // minato, publishing (sharing) the work, and transferring its admin cap is
17
+ // an opinion about economics;
18
+ // - minting a release is likewise a primitive (`createRelease`) — choosing a
19
+ // track-assembly strategy, publishing (sharing) it, and picking a recipient
20
+ // for its `ReleaseAdminCap` is the opinion, so `finalizeRelease` /
21
+ // `publishRelease` / `publishReleaseFromDeals` live here.
22
+ //
23
+ // Every `finalize*` here MUST run in the same PTB as the `create*` that produced
24
+ // its parts — `Composition`, `Recording`, and `Release` are all `key`-only with
25
+ // no `drop`, so none can outlive its creating transaction. That is a same-PTB
26
+ // constraint, not a same-function one, which is exactly what makes this split
27
+ // possible.
28
+ //
29
+ // Composes with `@misonetwork/sdk`'s calls in the same PTB (the
30
+ // transaction-thunk composition pattern, just crossing a package boundary now).
31
+
32
+ import { Transaction, type TransactionObjectArgument } from "@mysten/sui/transactions";
33
+ import {
34
+ contracts,
35
+ createComposition,
36
+ createRecording,
37
+ createRelease,
38
+ type CompositionParts,
39
+ type CreateCompositionParams,
40
+ type CreateRecordingParams,
41
+ type RecordingParts,
42
+ type ReleaseParts,
43
+ type ShareCurrencyBinding,
44
+ type TxThunk,
45
+ } from "@misonetwork/sdk";
46
+
47
+ const { deal, track, release } = contracts;
48
+
49
+ // `TxThunk` is the protocol SDK's type, re-exported so platform consumers get
50
+ // the same nominal shape rather than a structurally-identical twin.
51
+ export type { TxThunk };
52
+
53
+ // ============================================================================
54
+ // Share dispersal (minato)
55
+ // ============================================================================
56
+
57
+ export interface ShareRecipient {
58
+ address: string;
59
+ value: number;
60
+ }
61
+
62
+ /**
63
+ * Splits a share `Balance` across `recipients` via `minato::disperse_balance`, then
64
+ * destroys the emptied balance. Exposed for consumers assembling custom share
65
+ * distributions in their own PTBs.
66
+ */
67
+ export function disperseShares(
68
+ tx: Transaction,
69
+ minatoPackageId: string,
70
+ shareType: string,
71
+ balance: TransactionObjectArgument,
72
+ recipients: ShareRecipient[],
73
+ ) {
74
+ tx.moveCall({
75
+ target: `${minatoPackageId}::minato::disperse_balance`,
76
+ typeArguments: [shareType],
77
+ arguments: [
78
+ balance,
79
+ tx.makeMoveVec({ type: "u64", elements: recipients.map((r) => tx.pure.u64(r.value)) }),
80
+ tx.makeMoveVec({ type: "address", elements: recipients.map((r) => tx.pure.address(r.address)) }),
81
+ ],
82
+ });
83
+ tx.moveCall({ target: "0x2::balance::destroy_zero", typeArguments: [shareType], arguments: [balance] });
84
+ }
85
+
86
+ // ============================================================================
87
+ // Share currency (external share / framework)
88
+ // ============================================================================
89
+
90
+ export interface PackageBytecode {
91
+ modules: string[];
92
+ dependencies: string[];
93
+ digest: number[];
94
+ }
95
+
96
+ export function publishShareCurrency(bytecode: PackageBytecode): TxThunk {
97
+ return (tx) => {
98
+ const upgradeCap = tx.publish(bytecode);
99
+ tx.moveCall({ target: "0x2::package::make_immutable", arguments: [upgradeCap] });
100
+ };
101
+ }
102
+
103
+ const SUI_COIN_REGISTRY_ID = "0xc";
104
+
105
+ export interface InitializeShareCurrencyParams {
106
+ shareCurrencyPackageId: string;
107
+ name: string;
108
+ description: string;
109
+ iconUrl: string;
110
+ treasuryCapRecipient: string;
111
+ }
112
+
113
+ export function initializeShareCurrency(params: InitializeShareCurrencyParams): TxThunk {
114
+ const { shareCurrencyPackageId, name, description, iconUrl, treasuryCapRecipient } = params;
115
+ return (tx) => {
116
+ const treasuryCap = tx.moveCall({
117
+ target: `${shareCurrencyPackageId}::share::initialize`,
118
+ arguments: [tx.pure.string(name), tx.pure.string(description), tx.pure.string(iconUrl), tx.object(SUI_COIN_REGISTRY_ID)],
119
+ });
120
+ tx.transferObjects([treasuryCap], treasuryCapRecipient);
121
+ };
122
+ }
123
+
124
+ // ============================================================================
125
+ // Composition
126
+ // ============================================================================
127
+
128
+ export interface FinalizeCompositionParams extends CompositionParts {
129
+ /** The composition's `share::Share` type. */
130
+ shareType: string;
131
+ shareRecipients: ShareRecipient[];
132
+ adminAddress: string;
133
+ misoPackageId: string;
134
+ minatoPackageId: string;
135
+ }
136
+
137
+ /**
138
+ * The opinionated finish for a composition: disperse its share supply to
139
+ * `shareRecipients`, publish (share) it, and transfer its admin cap to
140
+ * `adminAddress`. Consumers that want different economics skip this and act on
141
+ * the `CompositionParts` from `@misonetwork/sdk`'s `createComposition` directly.
142
+ */
143
+ export function finalizeComposition(tx: Transaction, params: FinalizeCompositionParams): void {
144
+ disperseShares(tx, params.minatoPackageId, params.shareType, params.balance, params.shareRecipients);
145
+ tx.add(contracts.composition.publish({ package: params.misoPackageId, typeArguments: [params.shareType], arguments: [params.composition, params.adminCap] }));
146
+ tx.transferObjects([params.adminCap], params.adminAddress);
147
+ }
148
+
149
+ export interface PublishCompositionParams extends ShareCurrencyBinding {
150
+ title: string;
151
+ royaltyRateBps: number;
152
+ shareRecipients: ShareRecipient[];
153
+ /** Sole owner of the shares + CompositionAdminCap (the zkLogin address). */
154
+ adminAddress: string;
155
+ misoPackageId: string;
156
+ minatoPackageId: string;
157
+ }
158
+
159
+ /** Convenience: publish a composition end-to-end (createComposition → finalizeComposition). */
160
+ export function publishComposition(params: PublishCompositionParams): TxThunk {
161
+ return (tx) => {
162
+ const parts = createComposition(tx, {
163
+ shareType: params.shareType,
164
+ shareCurrencyId: params.shareCurrencyId,
165
+ shareTreasuryCapId: params.shareTreasuryCapId,
166
+ title: params.title,
167
+ royaltyRateBps: params.royaltyRateBps,
168
+ misoPackageId: params.misoPackageId,
169
+ } satisfies CreateCompositionParams);
170
+ finalizeComposition(tx, {
171
+ ...parts,
172
+ shareType: params.shareType,
173
+ shareRecipients: params.shareRecipients,
174
+ adminAddress: params.adminAddress,
175
+ misoPackageId: params.misoPackageId,
176
+ minatoPackageId: params.minatoPackageId,
177
+ });
178
+ };
179
+ }
180
+
181
+ // ============================================================================
182
+ // Recording
183
+ // ============================================================================
184
+
185
+ export interface FinalizeRecordingParams extends RecordingParts {
186
+ /** The recording's own `share::Share` type. */
187
+ recordingShareType: string;
188
+ /** Share type of the parent composition. */
189
+ compositionShareType: string;
190
+ shareRecipients: ShareRecipient[];
191
+ adminAddress: string;
192
+ misoPackageId: string;
193
+ minatoPackageId: string;
194
+ }
195
+
196
+ /**
197
+ * The opinionated finish for a recording: publish (share) it, disperse its
198
+ * share supply, and transfer its admin cap to `adminAddress`. A recording has
199
+ * no embedded metadata to set — naming lives in the metadata extension.
200
+ */
201
+ export function finalizeRecording(tx: Transaction, params: FinalizeRecordingParams): void {
202
+ const typeArguments: [string, string] = [params.recordingShareType, params.compositionShareType];
203
+ tx.add(contracts.recording.publish({ package: params.misoPackageId, typeArguments, arguments: [params.recording, params.adminCap] }));
204
+ disperseShares(tx, params.minatoPackageId, params.recordingShareType, params.balance, params.shareRecipients);
205
+ tx.transferObjects([params.adminCap], params.adminAddress);
206
+ }
207
+
208
+ export interface PublishRecordingParams extends ShareCurrencyBinding {
209
+ /**
210
+ * Parent composition, referenced as an on-chain object. Read-only at
211
+ * `recording::new` (only its royalty rate and id are read).
212
+ */
213
+ compositionId: string;
214
+ /** Share type of the parent composition (the recording's `CompositionShare` phantom). */
215
+ compositionShareType: string;
216
+ shareRecipients: ShareRecipient[];
217
+ adminAddress: string;
218
+ /** Slippage guard for `recording::new` — pass the composition rate you observed (default: protocol max). */
219
+ maxRoyaltyRateBps?: number;
220
+ misoPackageId: string;
221
+ minatoPackageId: string;
222
+ }
223
+
224
+ /** Convenience: publish a recording against an already-on-chain composition. */
225
+ export function publishRecording(params: PublishRecordingParams): TxThunk {
226
+ return (tx) => {
227
+ const parts = createRecording(tx, {
228
+ shareType: params.shareType,
229
+ shareCurrencyId: params.shareCurrencyId,
230
+ shareTreasuryCapId: params.shareTreasuryCapId,
231
+ compositionShareType: params.compositionShareType,
232
+ composition: tx.object(params.compositionId),
233
+ maxRoyaltyRateBps: params.maxRoyaltyRateBps,
234
+ misoPackageId: params.misoPackageId,
235
+ } satisfies CreateRecordingParams);
236
+ finalizeRecording(tx, {
237
+ ...parts,
238
+ recordingShareType: params.shareType,
239
+ compositionShareType: params.compositionShareType,
240
+ shareRecipients: params.shareRecipients,
241
+ adminAddress: params.adminAddress,
242
+ misoPackageId: params.misoPackageId,
243
+ minatoPackageId: params.minatoPackageId,
244
+ });
245
+ };
246
+ }
247
+
248
+ // ============================================================================
249
+ // Composition + Recording (single PTB)
250
+ // ============================================================================
251
+
252
+ export interface PublishCompositionAndRecordingParams {
253
+ title: string;
254
+ royaltyRateBps: number;
255
+ /** Share-currency binding for the composition. */
256
+ composition: ShareCurrencyBinding & { shareRecipients: ShareRecipient[]; adminAddress: string };
257
+ /** Share-currency binding for the recording. */
258
+ recording: ShareCurrencyBinding & { shareRecipients: ShareRecipient[]; adminAddress: string };
259
+ misoPackageId: string;
260
+ minatoPackageId: string;
261
+ }
262
+
263
+ /**
264
+ * Publishes a composition and its recording in a single atomic PTB.
265
+ *
266
+ * The ordering is load-bearing: `recording::new` borrows the composition by
267
+ * immutable reference, so it must run while the composition is still an unshared,
268
+ * transaction-local value — i.e. AFTER `composition::new` but BEFORE
269
+ * `composition::publish` (which moves the composition into `share_object`). Hence:
270
+ * `composition::new` → `recording::new(&comp)` → finalize composition (publish) →
271
+ * finalize recording (publish).
272
+ */
273
+ export function publishCompositionAndRecording(params: PublishCompositionAndRecordingParams): TxThunk {
274
+ return (tx) => {
275
+ const comp = createComposition(tx, {
276
+ shareType: params.composition.shareType,
277
+ shareCurrencyId: params.composition.shareCurrencyId,
278
+ shareTreasuryCapId: params.composition.shareTreasuryCapId,
279
+ title: params.title,
280
+ royaltyRateBps: params.royaltyRateBps,
281
+ misoPackageId: params.misoPackageId,
282
+ } satisfies CreateCompositionParams);
283
+
284
+ // Borrow the still-unshared composition into recording::new before publishing it.
285
+ // The composition is created in this PTB with a known rate, so the slippage
286
+ // guard pins that exact value — front-running is structurally impossible here.
287
+ const rec = createRecording(tx, {
288
+ shareType: params.recording.shareType,
289
+ shareCurrencyId: params.recording.shareCurrencyId,
290
+ shareTreasuryCapId: params.recording.shareTreasuryCapId,
291
+ compositionShareType: params.composition.shareType,
292
+ composition: comp.composition,
293
+ maxRoyaltyRateBps: params.royaltyRateBps,
294
+ misoPackageId: params.misoPackageId,
295
+ } satisfies CreateRecordingParams);
296
+
297
+ finalizeComposition(tx, {
298
+ ...comp,
299
+ shareType: params.composition.shareType,
300
+ shareRecipients: params.composition.shareRecipients,
301
+ adminAddress: params.composition.adminAddress,
302
+ misoPackageId: params.misoPackageId,
303
+ minatoPackageId: params.minatoPackageId,
304
+ });
305
+
306
+ finalizeRecording(tx, {
307
+ ...rec,
308
+ recordingShareType: params.recording.shareType,
309
+ compositionShareType: params.composition.shareType,
310
+ shareRecipients: params.recording.shareRecipients,
311
+ adminAddress: params.recording.adminAddress,
312
+ misoPackageId: params.misoPackageId,
313
+ minatoPackageId: params.minatoPackageId,
314
+ });
315
+ };
316
+ }
317
+
318
+ // ============================================================================
319
+ // Release
320
+ // ============================================================================
321
+
322
+ export interface FinalizeReleaseParams extends ReleaseParts {
323
+ /** Recipient of the `ReleaseAdminCap`. */
324
+ adminAddress: string;
325
+ misoPackageId: string;
326
+ }
327
+
328
+ /**
329
+ * The opinionated finish for a release: publish (share) it and transfer its
330
+ * admin cap to `adminAddress`.
331
+ *
332
+ * MUST run in the same PTB as the `createRelease` that produced these parts —
333
+ * `Release` is `key`-only with no `drop`, so an unpublished release cannot
334
+ * outlive its transaction. Splitting create from finalize is what lets a caller
335
+ * do something else with the cap (route it to a vault, hand it to another
336
+ * package, keep it for later commands) instead of a plain address transfer.
337
+ */
338
+ export function finalizeRelease(tx: Transaction, params: FinalizeReleaseParams): void {
339
+ tx.add(release.publish({ package: params.misoPackageId, arguments: [params.release, params.adminCap] }));
340
+ tx.transferObjects([params.adminCap], tx.pure.address(params.adminAddress));
341
+ }
342
+
343
+ export interface TrackInput {
344
+ recordingId: string;
345
+ recordingAdminCapId: string;
346
+ /** Share type of the recording (the deal/track `RecordingShare` phantom). */
347
+ recordingShareType: string;
348
+ /** Share type of the parent composition (the deal/track `CompositionShare` phantom). */
349
+ compositionShareType: string;
350
+ splitBps: number;
351
+ }
352
+
353
+ export interface PublishReleaseParams {
354
+ title: string;
355
+ /** The ordered tracklist. Display grouping (discs/sides) is extension data. */
356
+ tracks: TrackInput[];
357
+ releaseRegistryId: string;
358
+ releaseId: string;
359
+ releaseNonce: string;
360
+ misoPackageId: string;
361
+ adminAddress: string;
362
+ }
363
+
364
+ function buildTrackVec(
365
+ tx: Transaction,
366
+ misoPackageId: string,
367
+ trackArgs: TransactionObjectArgument[],
368
+ ) {
369
+ return tx.makeMoveVec({ type: `${misoPackageId}::track::Track`, elements: trackArgs });
370
+ }
371
+
372
+ /**
373
+ * Convenience: publish a release end-to-end, assembling its tracklist from
374
+ * recording admin caps held by the sender (a deal is created inline per track).
375
+ */
376
+ export function publishRelease(params: PublishReleaseParams): TxThunk {
377
+ return (tx) => {
378
+ const { misoPackageId } = params;
379
+ const trackArgs = params.tracks.map((t) => {
380
+ const typeArguments: [string, string] = [t.recordingShareType, t.compositionShareType];
381
+ const dealArg = tx.add(
382
+ deal._new({
383
+ package: misoPackageId,
384
+ typeArguments,
385
+ arguments: [tx.object(t.recordingAdminCapId), tx.object(t.recordingId), tx.pure.id(params.releaseId), tx.pure.u16(t.splitBps)],
386
+ }),
387
+ );
388
+ return tx.add(track._new({ package: misoPackageId, typeArguments, arguments: [dealArg, tx.object(t.recordingId)] }));
389
+ });
390
+ const parts = createRelease(
391
+ tx,
392
+ { title: params.title, nonce: params.releaseNonce, releaseRegistryId: params.releaseRegistryId, misoPackageId },
393
+ buildTrackVec(tx, misoPackageId, trackArgs),
394
+ );
395
+ finalizeRelease(tx, { ...parts, adminAddress: params.adminAddress, misoPackageId });
396
+ };
397
+ }
398
+
399
+ export interface DealInput {
400
+ dealId: string;
401
+ /** The recording the deal is for — `track::new` takes `&Recording` alongside the deal. */
402
+ recordingId: string;
403
+ /** Share type of the recording (the deal/track `RecordingShare` phantom). */
404
+ recordingShareType: string;
405
+ /** Share type of the parent composition (the deal/track `CompositionShare` phantom). */
406
+ compositionShareType: string;
407
+ }
408
+
409
+ export interface PublishReleaseFromDealsParams {
410
+ title: string;
411
+ /** The ordered tracklist, one pre-made deal per track. */
412
+ deals: DealInput[];
413
+ releaseRegistryId: string;
414
+ releaseNonce: string;
415
+ misoPackageId: string;
416
+ adminAddress: string;
417
+ }
418
+
419
+ /**
420
+ * Convenience: publish a release end-to-end from pre-made `Deal`s held by the
421
+ * sender (each deal already pins this release's id).
422
+ */
423
+ export function publishReleaseFromDeals(params: PublishReleaseFromDealsParams): TxThunk {
424
+ return (tx) => {
425
+ const { misoPackageId } = params;
426
+ const trackArgs = params.deals.map((dl) =>
427
+ tx.add(track._new({
428
+ package: misoPackageId,
429
+ typeArguments: [dl.recordingShareType, dl.compositionShareType],
430
+ arguments: [tx.object(dl.dealId), tx.object(dl.recordingId)],
431
+ })),
432
+ );
433
+ const parts = createRelease(
434
+ tx,
435
+ { title: params.title, nonce: params.releaseNonce, releaseRegistryId: params.releaseRegistryId, misoPackageId },
436
+ buildTrackVec(tx, misoPackageId, trackArgs),
437
+ );
438
+ finalizeRelease(tx, { ...parts, adminAddress: params.adminAddress, misoPackageId });
439
+ };
440
+ }