@misofm/sdk 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +13 -9
  2. package/dist/client.d.ts +17 -1
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +22 -3
  5. package/dist/client.js.map +1 -1
  6. package/dist/contracts/release_registry/release_registry.d.ts +114 -0
  7. package/dist/contracts/release_registry/release_registry.d.ts.map +1 -0
  8. package/dist/contracts/release_registry/release_registry.js +119 -0
  9. package/dist/contracts/release_registry/release_registry.js.map +1 -0
  10. package/dist/contracts/royalty_pool/pool.d.ts +28 -2
  11. package/dist/contracts/royalty_pool/pool.d.ts.map +1 -1
  12. package/dist/contracts/royalty_pool/pool.js +28 -2
  13. package/dist/contracts/royalty_pool/pool.js.map +1 -1
  14. package/dist/contracts/utils/index.d.ts +44 -0
  15. package/dist/contracts/utils/index.d.ts.map +1 -1
  16. package/dist/contracts/utils/index.js +104 -2
  17. package/dist/contracts/utils/index.js.map +1 -1
  18. package/dist/contracts.d.ts +1 -0
  19. package/dist/contracts.d.ts.map +1 -1
  20. package/dist/contracts.js +4 -1
  21. package/dist/contracts.js.map +1 -1
  22. package/dist/cover.d.ts +3 -6
  23. package/dist/cover.d.ts.map +1 -1
  24. package/dist/cover.js +7 -16
  25. package/dist/cover.js.map +1 -1
  26. package/dist/credits.d.ts.map +1 -1
  27. package/dist/credits.js +17 -43
  28. package/dist/credits.js.map +1 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +3 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/read/catalog.d.ts +2 -12
  33. package/dist/read/catalog.d.ts.map +1 -1
  34. package/dist/read/catalog.js +9 -24
  35. package/dist/read/catalog.js.map +1 -1
  36. package/dist/read/config.d.ts +3 -8
  37. package/dist/read/config.d.ts.map +1 -1
  38. package/dist/read/config.js +15 -50
  39. package/dist/read/config.js.map +1 -1
  40. package/dist/read/index.d.ts +1 -1
  41. package/dist/read/index.d.ts.map +1 -1
  42. package/dist/read/index.js +1 -1
  43. package/dist/read/index.js.map +1 -1
  44. package/dist/read/types.d.ts +1 -1
  45. package/dist/read/types.d.ts.map +1 -1
  46. package/dist/read/wallet.d.ts +3 -7
  47. package/dist/read/wallet.d.ts.map +1 -1
  48. package/dist/read/wallet.js +11 -38
  49. package/dist/read/wallet.js.map +1 -1
  50. package/dist/read/works.d.ts +2 -5
  51. package/dist/read/works.d.ts.map +1 -1
  52. package/dist/read/works.js +7 -37
  53. package/dist/read/works.js.map +1 -1
  54. package/dist/release-graph.d.ts +6 -19
  55. package/dist/release-graph.d.ts.map +1 -1
  56. package/dist/release-graph.js +29 -43
  57. package/dist/release-graph.js.map +1 -1
  58. package/dist/transactions.d.ts +12 -28
  59. package/dist/transactions.d.ts.map +1 -1
  60. package/dist/transactions.js +23 -28
  61. package/dist/transactions.js.map +1 -1
  62. package/package.json +3 -3
  63. package/src/client.ts +33 -2
  64. package/src/contracts/release_registry/release_registry.ts +160 -0
  65. package/src/contracts/royalty_pool/pool.ts +28 -2
  66. package/src/contracts/utils/index.ts +156 -4
  67. package/src/contracts.ts +5 -1
  68. package/src/cover.ts +8 -19
  69. package/src/credits.ts +23 -63
  70. package/src/index.ts +3 -1
  71. package/src/read/catalog.ts +9 -29
  72. package/src/read/config.ts +18 -58
  73. package/src/read/index.ts +0 -1
  74. package/src/read/types.ts +1 -1
  75. package/src/read/wallet.ts +11 -37
  76. package/src/read/works.ts +5 -42
  77. package/src/release-graph.ts +40 -75
  78. package/src/transactions.ts +33 -62
@@ -3,35 +3,33 @@
3
3
 
4
4
  // Single-PTB publisher for a whole release graph: creates every composition and
5
5
  // recording, optionally attaches royalty pools, derives the release id ON-CHAIN
6
- // (so recordings need not be shared first), builds the deals/tracks/release,
6
+ // (so recordings need not be shared first), builds the tracks/release,
7
7
  // then shares everything and transfers the admin caps — all in ONE transaction.
8
8
  //
9
9
  // Share currencies must already be published + initialized (their Currency objects
10
10
  // shared on-chain); their ids/types are passed in. Ordering is load-bearing:
11
11
  // 1. composition::new → recording::new(&comp) (borrow-before-share) + pool attach
12
- // 2. release::derive_release_id(<recording::id results>) → deal::new(cap, &rec,
13
- // derivedId, split) → track::new → release::new
12
+ // 2. release::derive_target_release_id(<recording::id results>) →
13
+ // track::new(cap, &rec, derivedId, split) → release_registry::new_release
14
14
  // 3. publish (share) comps + recs + release, disperse supply, transfer caps
15
15
  // Steps 1–2 borrow the works; step 3 consumes them into share_object.
16
16
  //
17
- // Release tracks come in three shapes (see TrackNode): recordings created in
18
- // THIS PTB, existing recordings authorized by their admin cap (deal created
19
- // inline), and existing recordings authorized by a pre-made Deal in hand.
20
- // Pre-made deals pin the release id, so they cannot coexist with fresh
21
- // recordings — the builder rejects that mix up front.
17
+ // Release tracks come in two shapes (see TrackNode): recordings created in THIS
18
+ // PTB, and existing recordings authorized by their admin cap.
22
19
  //
23
20
  // This is the whole-graph orchestration half of the opinionated publish flow —
24
- // it composes `@misonetwork/sdk`'s bare `composition`/`recording`/`deal`/`track`/
25
- // `release` call bindings and its `createRelease` primitive with this package's
21
+ // it composes `@misonetwork/sdk`'s bare `composition`/`recording`/`track`/
22
+ // `release` call bindings and this package's `release_registry` binding with its
26
23
  // own `disperseShares`/`finalizeRelease` and royalty-pool extension helpers, into
27
24
  // one PTB.
28
25
 
29
26
  import { Transaction, type TransactionObjectArgument } from "@mysten/sui/transactions";
30
- import { contracts, createRelease, PROTOCOL_MAX_ROYALTY_RATE_BPS } from "@misonetwork/sdk";
27
+ import { contracts, PROTOCOL_MAX_ROYALTY_RATE_BPS } from "@misonetwork/sdk";
31
28
  import { attachCompositionRoyaltyPool, attachRecordingRoyaltyPool } from "./extensions/royalty-pool.ts";
32
29
  import { disperseShares, finalizeRelease, type ShareRecipient } from "./transactions.ts";
30
+ import * as releaseRegistry from "./contracts/release_registry/release_registry.ts";
33
31
 
34
- const { composition, recording, deal, track, release } = contracts;
32
+ const { composition, recording, track, release } = contracts;
35
33
 
36
34
  /** A royalty pool to attach to a work, in the same PTB. */
37
35
  export interface RoyaltyPoolNode {
@@ -75,7 +73,7 @@ export interface RecordingNode {
75
73
  royaltyPool?: RoyaltyPoolNode;
76
74
  }
77
75
 
78
- /** A track whose recording is created in THIS PTB (its deal is created inline). */
76
+ /** A track whose recording is created in THIS PTB. */
79
77
  export interface FreshTrackNode {
80
78
  /** Index into `recordings[]`. */
81
79
  recordingIndex: number;
@@ -83,9 +81,8 @@ export interface FreshTrackNode {
83
81
  }
84
82
 
85
83
  /**
86
- * A track over an EXISTING recording, authorized by its admin cap (held by the
87
- * sender) the deal is created inline against the on-chain-derived release id.
88
- * This is the only way to mix existing recordings with ones created in this PTB.
84
+ * A track over an EXISTING recording, authorized by its admin cap held by the
85
+ * sender. This can coexist with recordings created in this PTB.
89
86
  */
90
87
  export interface CapTrackNode {
91
88
  recordingId: string;
@@ -95,25 +92,9 @@ export interface CapTrackNode {
95
92
  splitBps: number;
96
93
  }
97
94
 
98
- /**
99
- * A track over an EXISTING recording, authorized by a pre-made `Deal` held by
100
- * the sender. A deal pins the exact release id — a digest over ALL track
101
- * recording ids — so deal-backed tracks cannot coexist with `FreshTrackNode`s
102
- * (a fresh recording's id is unknowable when the deal was created).
103
- * `splitBps` must be the value stored in the deal (read it from the object).
104
- */
105
- export interface DealTrackNode {
106
- dealId: string;
107
- recordingId: string;
108
- recordingShareType: string;
109
- compositionShareType: string;
110
- splitBps: number;
111
- }
112
-
113
- export type TrackNode = FreshTrackNode | CapTrackNode | DealTrackNode;
95
+ export type TrackNode = FreshTrackNode | CapTrackNode;
114
96
 
115
97
  const isFresh = (t: TrackNode): t is FreshTrackNode => "recordingIndex" in t;
116
- const isDealBacked = (t: TrackNode): t is DealTrackNode => "dealId" in t;
117
98
 
118
99
  export interface ReleaseNode {
119
100
  title: string;
@@ -131,6 +112,8 @@ export interface PublishReleaseGraphParams {
131
112
  release?: ReleaseNode;
132
113
  misoPackageId: string;
133
114
  minatoPackageId: string;
115
+ /** `release_registry` extension package, distinct from its shared object id. */
116
+ releaseRegistryPackageId: string;
134
117
  }
135
118
 
136
119
  interface Parts {
@@ -141,7 +124,7 @@ interface Parts {
141
124
 
142
125
  /** Builds the entire graph in a single transaction (see file header for ordering). */
143
126
  export function publishReleaseGraph(params: PublishReleaseGraphParams): (tx: Transaction) => void {
144
- const { misoPackageId: pkg, minatoPackageId } = params;
127
+ const { misoPackageId: pkg, minatoPackageId, releaseRegistryPackageId } = params;
145
128
  return (tx) => {
146
129
  // ── 1) Create every composition, then every recording (borrow-before-share) ──
147
130
  const comps: Parts[] = params.compositions.map((c) => {
@@ -199,61 +182,43 @@ export function publishReleaseGraph(params: PublishReleaseGraphParams): (tx: Tra
199
182
  return parts;
200
183
  });
201
184
 
202
- // ── 2) Release: derive the id on-chain, then deals → tracks → release ──
185
+ // ── 2) Release: derive the id on-chain, then tracks → release ──────────
203
186
  if (params.release) {
204
187
  const rel = params.release;
205
188
  const ordered = rel.tracks;
206
- if (ordered.some(isDealBacked) && ordered.some(isFresh)) {
207
- throw new Error(
208
- "A release cannot mix pre-made deals with recordings created in this transaction: " +
209
- "a deal pins the exact release id, whose digest includes every track's recording id, " +
210
- "and a fresh recording's id is unknowable when the deal was created. " +
211
- "Authorize the existing recordings with their admin caps instead.",
212
- );
213
- }
214
-
215
- // The derived id feeds the deals created inline (fresh/cap-backed tracks).
216
- // Pre-made deals already store it, so an all-deal release skips the derive.
217
- let releaseId: TransactionObjectArgument | undefined;
218
- if (!ordered.every(isDealBacked)) {
219
- const idVec = tx.makeMoveVec({
220
- type: "0x2::object::ID",
221
- elements: ordered.map((t) =>
222
- isFresh(t)
223
- ? tx.add(recording.id({ package: pkg, typeArguments: recTypeArgs(t.recordingIndex), arguments: [recs[t.recordingIndex]!.work] }))
224
- : tx.pure.id(t.recordingId),
225
- ),
226
- });
227
- const splitVec = tx.makeMoveVec({ type: "u64", elements: ordered.map((t) => tx.pure.u64(t.splitBps)) });
228
- releaseId = tx.add(
229
- release.deriveReleaseId({ package: pkg, arguments: [idVec, splitVec, tx.pure.u256(BigInt(rel.nonce)), tx.object(rel.releaseRegistryId)] }),
230
- );
231
- }
189
+ const idVec = tx.makeMoveVec({
190
+ type: "0x2::object::ID",
191
+ elements: ordered.map((t) =>
192
+ isFresh(t)
193
+ ? tx.add(recording.id({ package: pkg, typeArguments: recTypeArgs(t.recordingIndex), arguments: [recs[t.recordingIndex]!.work] }))
194
+ : tx.pure.id(t.recordingId),
195
+ ),
196
+ });
197
+ const splitVec = tx.makeMoveVec({ type: "u64", elements: ordered.map((t) => tx.pure.u64(t.splitBps)) });
198
+ // This returns an ID value (not an object); pass the result straight to
199
+ // `track::new` so every track consents to this exact release target.
200
+ const releaseId = tx.add(
201
+ release.deriveTargetReleaseId({ package: pkg, arguments: [idVec, splitVec, tx.pure.u256(BigInt(rel.nonce)), tx.pure.id(rel.releaseRegistryId)] }),
202
+ );
232
203
 
233
204
  const trackArgs = ordered.map((t) => {
234
- if (isDealBacked(t)) {
235
- const typeArgs: [string, string] = [t.recordingShareType, t.compositionShareType];
236
- return tx.add(track._new({ package: pkg, typeArguments: typeArgs, arguments: [tx.object(t.dealId), tx.object(t.recordingId)] }));
237
- }
238
205
  if (isFresh(t)) {
239
206
  const typeArgs = recTypeArgs(t.recordingIndex);
240
207
  const parts = recs[t.recordingIndex]!;
241
- const dealArg = tx.add(deal._new({ package: pkg, typeArguments: typeArgs, arguments: [parts.adminCap, parts.work, releaseId!, tx.pure.u16(t.splitBps)] }));
242
- return tx.add(track._new({ package: pkg, typeArguments: typeArgs, arguments: [dealArg, parts.work] }));
208
+ return tx.add(track._new({ package: pkg, typeArguments: typeArgs, arguments: [parts.adminCap, parts.work, releaseId, tx.pure.u16(t.splitBps)] }));
243
209
  }
244
210
  const typeArgs: [string, string] = [t.recordingShareType, t.compositionShareType];
245
211
  const rec = tx.object(t.recordingId);
246
- const dealArg = tx.add(
247
- deal._new({ package: pkg, typeArguments: typeArgs, arguments: [tx.object(t.recordingAdminCapId), rec, releaseId!, tx.pure.u16(t.splitBps)] }),
248
- );
249
- return tx.add(track._new({ package: pkg, typeArguments: typeArgs, arguments: [dealArg, rec] }));
212
+ return tx.add(track._new({ package: pkg, typeArguments: typeArgs, arguments: [tx.object(t.recordingAdminCapId), rec, releaseId, tx.pure.u16(t.splitBps)] }));
250
213
  });
251
214
  const trackVec = tx.makeMoveVec({ type: `${pkg}::track::Track`, elements: trackArgs });
252
- const releaseParts = createRelease(
253
- tx,
254
- { title: rel.title, nonce: rel.nonce, releaseRegistryId: rel.releaseRegistryId, misoPackageId: pkg },
255
- trackVec,
215
+ const created = tx.add(
216
+ releaseRegistry.newRelease({
217
+ package: releaseRegistryPackageId,
218
+ arguments: [tx.object(rel.releaseRegistryId), tx.pure.string(rel.title), trackVec, tx.pure.u256(BigInt(rel.nonce))],
219
+ }),
256
220
  );
221
+ const releaseParts = { release: created[0]!, adminCap: created[1]! };
257
222
  finalizeRelease(tx, { ...releaseParts, adminAddress: rel.adminAddress, misoPackageId: pkg });
258
223
  }
259
224
 
@@ -15,10 +15,11 @@
15
15
  // (`createComposition`/`createRecording`) — dispersing it to recipients via
16
16
  // minato, publishing (sharing) the work, and transferring its admin cap is
17
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.
18
+ // - minting a release is a platform primitive: core's `release::new` takes an
19
+ // unconstructible PTB `&mut UID`, so `release_registry::new_release` is the
20
+ // canonical client path. Choosing a track-assembly strategy, publishing
21
+ // (sharing) it, and picking a recipient for its `ReleaseAdminCap` is the
22
+ // opinion, so `finalizeRelease` / `publishRelease` live here.
22
23
  //
23
24
  // Every `finalize*` here MUST run in the same PTB as the `create*` that produced
24
25
  // its parts — `Composition`, `Recording`, and `Release` are all `key`-only with
@@ -34,17 +35,21 @@ import {
34
35
  contracts,
35
36
  createComposition,
36
37
  createRecording,
37
- createRelease,
38
38
  type CompositionParts,
39
39
  type CreateCompositionParams,
40
40
  type CreateRecordingParams,
41
41
  type RecordingParts,
42
- type ReleaseParts,
43
42
  type ShareCurrencyBinding,
44
43
  type TxThunk,
45
44
  } from "@misonetwork/sdk";
45
+ import * as releaseRegistry from "./contracts/release_registry/release_registry.ts";
46
46
 
47
- const { deal, track, release } = contracts;
47
+ const { track, release } = contracts;
48
+
49
+ interface ReleaseParts {
50
+ release: TransactionObjectArgument;
51
+ adminCap: TransactionObjectArgument;
52
+ }
48
53
 
49
54
  // `TxThunk` is the protocol SDK's type, re-exported so platform consumers get
50
55
  // the same nominal shape rather than a structurally-identical twin.
@@ -329,7 +334,8 @@ export interface FinalizeReleaseParams extends ReleaseParts {
329
334
  * The opinionated finish for a release: publish (share) it and transfer its
330
335
  * admin cap to `adminAddress`.
331
336
  *
332
- * MUST run in the same PTB as the `createRelease` that produced these parts —
337
+ * MUST run in the same PTB as the `release_registry::new_release` that produced
338
+ * these parts —
333
339
  * `Release` is `key`-only with no `drop`, so an unpublished release cannot
334
340
  * outlive its transaction. Splitting create from finalize is what lets a caller
335
341
  * do something else with the cap (route it to a vault, hand it to another
@@ -343,9 +349,9 @@ export function finalizeRelease(tx: Transaction, params: FinalizeReleaseParams):
343
349
  export interface TrackInput {
344
350
  recordingId: string;
345
351
  recordingAdminCapId: string;
346
- /** Share type of the recording (the deal/track `RecordingShare` phantom). */
352
+ /** Share type of the recording (the track `RecordingShare` phantom). */
347
353
  recordingShareType: string;
348
- /** Share type of the parent composition (the deal/track `CompositionShare` phantom). */
354
+ /** Share type of the parent composition (the track `CompositionShare` phantom). */
349
355
  compositionShareType: string;
350
356
  splitBps: number;
351
357
  }
@@ -354,6 +360,8 @@ export interface PublishReleaseParams {
354
360
  title: string;
355
361
  /** The ordered tracklist. Display grouping (discs/sides) is extension data. */
356
362
  tracks: TrackInput[];
363
+ /** `release_registry` extension package, distinct from its shared object id. */
364
+ releaseRegistryPackageId: string;
357
365
  releaseRegistryId: string;
358
366
  releaseId: string;
359
367
  releaseNonce: string;
@@ -371,70 +379,33 @@ function buildTrackVec(
371
379
 
372
380
  /**
373
381
  * 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).
382
+ * recording admin caps held by the sender.
375
383
  */
376
384
  export function publishRelease(params: PublishReleaseParams): TxThunk {
377
385
  return (tx) => {
378
- const { misoPackageId } = params;
386
+ const { misoPackageId, releaseRegistryPackageId } = params;
379
387
  const trackArgs = params.tracks.map((t) => {
380
388
  const typeArguments: [string, string] = [t.recordingShareType, t.compositionShareType];
381
- const dealArg = tx.add(
382
- deal._new({
389
+ return tx.add(
390
+ track._new({
383
391
  package: misoPackageId,
384
392
  typeArguments,
385
393
  arguments: [tx.object(t.recordingAdminCapId), tx.object(t.recordingId), tx.pure.id(params.releaseId), tx.pure.u16(t.splitBps)],
386
394
  }),
387
395
  );
388
- return tx.add(track._new({ package: misoPackageId, typeArguments, arguments: [dealArg, tx.object(t.recordingId)] }));
389
396
  });
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),
397
+ const created = tx.add(
398
+ releaseRegistry.newRelease({
399
+ package: releaseRegistryPackageId,
400
+ arguments: [
401
+ tx.object(params.releaseRegistryId),
402
+ tx.pure.string(params.title),
403
+ buildTrackVec(tx, misoPackageId, trackArgs),
404
+ tx.pure.u256(BigInt(params.releaseNonce)),
405
+ ],
406
+ }),
437
407
  );
408
+ const parts: ReleaseParts = { release: created[0]!, adminCap: created[1]! };
438
409
  finalizeRelease(tx, { ...parts, adminAddress: params.adminAddress, misoPackageId });
439
410
  };
440
411
  }