@misofm/sdk 0.12.4 → 0.14.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 (60) hide show
  1. package/README.md +50 -3
  2. package/dist/contracts/genre/genre.d.ts +8 -15
  3. package/dist/contracts/genre/genre.d.ts.map +1 -1
  4. package/dist/contracts/genre/genre.js +9 -15
  5. package/dist/contracts/genre/genre.js.map +1 -1
  6. package/dist/cover.d.ts +2 -2
  7. package/dist/cover.d.ts.map +1 -1
  8. package/dist/cover.js +5 -2
  9. package/dist/cover.js.map +1 -1
  10. package/dist/credits.d.ts +9 -9
  11. package/dist/credits.d.ts.map +1 -1
  12. package/dist/credits.js +8 -5
  13. package/dist/credits.js.map +1 -1
  14. package/dist/deployments.d.ts +8 -8
  15. package/dist/deployments.js +4 -4
  16. package/dist/execute.d.ts +13 -1
  17. package/dist/execute.d.ts.map +1 -1
  18. package/dist/execute.js +8 -2
  19. package/dist/execute.js.map +1 -1
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/publication.d.ts +207 -0
  25. package/dist/publication.d.ts.map +1 -0
  26. package/dist/publication.js +666 -0
  27. package/dist/publication.js.map +1 -0
  28. package/dist/recording-extensions.d.ts +2 -2
  29. package/dist/recording-extensions.d.ts.map +1 -1
  30. package/dist/recording-extensions.js +8 -5
  31. package/dist/recording-extensions.js.map +1 -1
  32. package/dist/release-extensions.d.ts +2 -2
  33. package/dist/release-extensions.d.ts.map +1 -1
  34. package/dist/release-extensions.js +10 -7
  35. package/dist/release-extensions.js.map +1 -1
  36. package/dist/share.d.ts +4 -3
  37. package/dist/share.d.ts.map +1 -1
  38. package/dist/share.js +4 -3
  39. package/dist/share.js.map +1 -1
  40. package/dist/transactions.d.ts +1 -0
  41. package/dist/transactions.d.ts.map +1 -1
  42. package/dist/transactions.js +1 -0
  43. package/dist/transactions.js.map +1 -1
  44. package/dist/vault.d.ts +7 -1
  45. package/dist/vault.d.ts.map +1 -1
  46. package/dist/vault.js +8 -0
  47. package/dist/vault.js.map +1 -1
  48. package/package.json +7 -3
  49. package/src/contracts/genre/genre.ts +9 -17
  50. package/src/cover.ts +9 -4
  51. package/src/credits.ts +18 -14
  52. package/src/deployments.ts +4 -4
  53. package/src/execute.ts +17 -4
  54. package/src/index.ts +1 -0
  55. package/src/publication.ts +949 -0
  56. package/src/recording-extensions.ts +12 -8
  57. package/src/release-extensions.ts +14 -9
  58. package/src/share.ts +7 -4
  59. package/src/transactions.ts +1 -0
  60. package/src/vault.ts +20 -2
@@ -0,0 +1,666 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Opinionated, atomic Miso catalog publication.
5
+ *
6
+ * Share packages and their registered Currency objects must already exist. This
7
+ * builder then creates every declared Party, Composition, Recording, Track,
8
+ * Release, extension, Vault plugin, Pressing, and Listing in one PTB. Fresh raw
9
+ * protocol capabilities never leave the transaction: data extensions use them
10
+ * directly, Vault-only plugins are configured while each new Vault is still
11
+ * owned, and only the selected direct cap or VaultAdminCap is delivered.
12
+ */
13
+ import { Transaction } from "@mysten/sui/transactions";
14
+ import { contracts as protocolContracts, deriveCompositionAdminCapId, deriveRecordingAdminCapId, deriveReleaseAdminCapId, } from "@misonetwork/sdk";
15
+ import { derivePartyAdminCapId } from "@misonetwork/sdk/party";
16
+ import { disperseShares, requiredCommandResult } from "./transactions.js";
17
+ import { addRecordingPrimaryArtist, addReleaseCredit, attachCompositionCredit, attachRecordingCredit, } from "./credits.js";
18
+ import { setRecordingAdvisory, setRecordingInstrumental, setRecordingLanguages, setRecordingMasterReference, setRecordingPreview, } from "./recording-extensions.js";
19
+ import { setReleaseDescription, setReleaseDspLinks, setReleaseGenres, setReleaseKind, } from "./release-extensions.js";
20
+ import { setReleaseCover, setReleaseTrackCover } from "./cover.js";
21
+ import { custodyNewAdminCap, directAdminCap, disposeNewAdminCap, initializeCompositionRoyaltyPool, initializeRecordingRoyaltyPool, installCompositionRoutedStakePlugin, installCompositionRoyaltyPoolPlugin, installPartyWalletPlugin, installRecordingRoyaltyPoolPlugin, installReleaseRevenueDistributorPlugin, invokeWithAdminCap, parseVaultCreatedEvent, } from "./vault.js";
22
+ import { derivePressingAdminCapId, derivePressingId, } from "./pressing.js";
23
+ import { allCreatedByType, createdByExactType } from "./execute.js";
24
+ import * as pressingContract from "./contracts/miso_pressing/pressing.js";
25
+ import * as listingContract from "./contracts/miso_pressing/listing.js";
26
+ const { composition, recording, release, track, party } = protocolContracts;
27
+ export const MAX_ATOMIC_PUBLICATION_COMMANDS = 900;
28
+ export const MAX_ATOMIC_PUBLICATION_INPUTS = 2048;
29
+ function requiredAt(items, index, description) {
30
+ const value = items[index];
31
+ if (value === undefined)
32
+ throw new Error(`${description} index ${index} is out of range`);
33
+ return value;
34
+ }
35
+ function partyCapType(p) {
36
+ return `${p.deployment.protocol.misoParty}::party::PartyAdminCap`;
37
+ }
38
+ function compositionCapType(p, shareType) {
39
+ return `${p.deployment.protocol.miso}::composition::CompositionAdminCap<${shareType}>`;
40
+ }
41
+ function recordingCapType(p, shareType) {
42
+ return `${p.deployment.protocol.miso}::recording::RecordingAdminCap<${shareType}>`;
43
+ }
44
+ function releaseCapType(p) {
45
+ return `${p.deployment.protocol.miso}::release::ReleaseAdminCap`;
46
+ }
47
+ function pressingCapType(p) {
48
+ return `${p.deployment.packages.pressing}::pressing::PressingAdminCap`;
49
+ }
50
+ function custody(p, selected, capType, configure) {
51
+ if (selected.kind === "direct")
52
+ return { kind: "direct", owner: selected.owner };
53
+ return {
54
+ kind: "vault",
55
+ owner: selected.owner,
56
+ capType,
57
+ vaultPackageId: p.deployment.packages.vault,
58
+ configure,
59
+ };
60
+ }
61
+ function partyByRef(parties, ref) {
62
+ const value = parties.get(ref);
63
+ if (!value)
64
+ throw new Error(`Unknown publication party ref ${JSON.stringify(ref)}`);
65
+ return value;
66
+ }
67
+ function languageVector(tx, p, codes) {
68
+ const values = codes.map((code) => tx.moveCall({
69
+ target: `${p.deployment.protocol.languageCode}::language_code::new`,
70
+ arguments: [tx.pure.string(code)],
71
+ }));
72
+ return tx.makeMoveVec({
73
+ type: `${p.deployment.protocol.languageCode}::language_code::LanguageCode`,
74
+ elements: values,
75
+ });
76
+ }
77
+ function walrusBlob(tx, p, blobId) {
78
+ return tx.moveCall({
79
+ target: `${p.deployment.packages.ori}::walrus_data::new_blob`,
80
+ arguments: [tx.pure.u256(blobId)],
81
+ });
82
+ }
83
+ function pressingState(tx, p, state) {
84
+ const pkg = p.deployment.packages.pressing;
85
+ if (state.kind === "scheduled") {
86
+ return tx.add(pressingContract.newScheduledState({
87
+ package: pkg,
88
+ arguments: [BigInt(state.startTimestampMs)],
89
+ }));
90
+ }
91
+ if (state.kind === "paused")
92
+ return tx.add(pressingContract.newPausedState({ package: pkg }));
93
+ return tx.add(pressingContract.newActiveState({ package: pkg }));
94
+ }
95
+ function listingPrice(tx, p, price) {
96
+ const pkg = p.deployment.packages.pressing;
97
+ const args = { package: pkg, arguments: [BigInt(price.amount)] };
98
+ return tx.add(price.kind === "fixed"
99
+ ? listingContract.newFixedPrice(args)
100
+ : listingContract.newFloorPrice(args));
101
+ }
102
+ function publishComposition(tx, p, node, parts) {
103
+ disperseShares(tx, p.deployment.packages.minato, node.shareType, parts.balance, node.shareRecipients);
104
+ const typeArguments = [node.shareType];
105
+ if (node.custody.kind === "direct") {
106
+ tx.add(composition.publish({
107
+ package: p.deployment.protocol.miso,
108
+ typeArguments,
109
+ arguments: [parts.work, parts.adminCap],
110
+ }));
111
+ disposeNewAdminCap(tx, parts.adminCap, custody(p, node.custody, compositionCapType(p, node.shareType)));
112
+ return;
113
+ }
114
+ custodyNewAdminCap(tx, {
115
+ adminCap: parts.adminCap,
116
+ capType: compositionCapType(p, node.shareType),
117
+ vaultPackageId: p.deployment.packages.vault,
118
+ owner: node.custody.owner,
119
+ configure: (vault, vaultAdminCap) => {
120
+ if (node.royaltyPool) {
121
+ installCompositionRoyaltyPoolPlugin(tx, {
122
+ vault, vaultAdminCap, compositionShareType: node.shareType,
123
+ pluginPackageId: p.deployment.packages.compositionRoyaltyPoolPlugin,
124
+ });
125
+ initializeCompositionRoyaltyPool(tx, {
126
+ vault, vaultAdminCap, composition: parts.work,
127
+ compositionShareType: node.shareType,
128
+ currencyType: node.royaltyPool.currencyType,
129
+ pluginPackageId: p.deployment.packages.compositionRoyaltyPoolPlugin,
130
+ });
131
+ }
132
+ if (node.routedStake) {
133
+ installCompositionRoutedStakePlugin(tx, {
134
+ vault, vaultAdminCap, compositionShareType: node.shareType,
135
+ pluginPackageId: p.deployment.packages.compositionRoutedStakePlugin,
136
+ });
137
+ }
138
+ invokeWithAdminCap(tx, {
139
+ kind: "vault", vault, vaultAdminCap,
140
+ capType: compositionCapType(p, node.shareType),
141
+ vaultPackageId: p.deployment.packages.vault,
142
+ }, {
143
+ target: `${p.deployment.protocol.miso}::composition::publish`,
144
+ typeArguments,
145
+ arguments: [parts.work, tx.object.clock()],
146
+ adminCapIndex: 1,
147
+ });
148
+ },
149
+ });
150
+ }
151
+ function publishRecording(tx, p, node, parts) {
152
+ const typeArguments = [node.shareType, node.compositionShareType];
153
+ disperseShares(tx, p.deployment.packages.minato, node.shareType, parts.balance, node.shareRecipients);
154
+ if (node.custody.kind === "direct") {
155
+ tx.add(recording.publish({
156
+ package: p.deployment.protocol.miso,
157
+ typeArguments,
158
+ arguments: [parts.work, parts.adminCap],
159
+ }));
160
+ disposeNewAdminCap(tx, parts.adminCap, custody(p, node.custody, recordingCapType(p, node.shareType)));
161
+ return;
162
+ }
163
+ custodyNewAdminCap(tx, {
164
+ adminCap: parts.adminCap,
165
+ capType: recordingCapType(p, node.shareType),
166
+ vaultPackageId: p.deployment.packages.vault,
167
+ owner: node.custody.owner,
168
+ configure: (vault, vaultAdminCap) => {
169
+ if (node.royaltyPool) {
170
+ installRecordingRoyaltyPoolPlugin(tx, {
171
+ vault, vaultAdminCap,
172
+ recordingShareType: node.shareType,
173
+ compositionShareType: node.compositionShareType,
174
+ pluginPackageId: p.deployment.packages.recordingRoyaltyPoolPlugin,
175
+ });
176
+ initializeRecordingRoyaltyPool(tx, {
177
+ vault, vaultAdminCap, recording: parts.work,
178
+ recordingShareType: node.shareType,
179
+ compositionShareType: node.compositionShareType,
180
+ currencyType: node.royaltyPool.currencyType,
181
+ pluginPackageId: p.deployment.packages.recordingRoyaltyPoolPlugin,
182
+ });
183
+ }
184
+ invokeWithAdminCap(tx, {
185
+ kind: "vault", vault, vaultAdminCap,
186
+ capType: recordingCapType(p, node.shareType),
187
+ vaultPackageId: p.deployment.packages.vault,
188
+ }, {
189
+ target: `${p.deployment.protocol.miso}::recording::publish`,
190
+ typeArguments,
191
+ arguments: [parts.work, tx.object.clock()],
192
+ adminCapIndex: 1,
193
+ });
194
+ },
195
+ });
196
+ }
197
+ function publishReleaseObject(tx, p, node, releaseObject, adminCap) {
198
+ if (node.custody.kind === "direct") {
199
+ tx.add(release.publish({
200
+ package: p.deployment.protocol.miso,
201
+ arguments: [releaseObject, adminCap],
202
+ }));
203
+ disposeNewAdminCap(tx, adminCap, custody(p, node.custody, releaseCapType(p)));
204
+ return;
205
+ }
206
+ custodyNewAdminCap(tx, {
207
+ adminCap,
208
+ capType: releaseCapType(p),
209
+ vaultPackageId: p.deployment.packages.vault,
210
+ owner: node.custody.owner,
211
+ configure: (vault, vaultAdminCap) => {
212
+ if (node.revenueDistribution) {
213
+ installReleaseRevenueDistributorPlugin(tx, {
214
+ vault, vaultAdminCap,
215
+ pluginPackageId: p.deployment.packages.releaseRevenueDistributorPlugin,
216
+ });
217
+ }
218
+ invokeWithAdminCap(tx, {
219
+ kind: "vault", vault, vaultAdminCap,
220
+ capType: releaseCapType(p),
221
+ vaultPackageId: p.deployment.packages.vault,
222
+ }, {
223
+ target: `${p.deployment.protocol.miso}::release::publish`,
224
+ arguments: [releaseObject, tx.object.clock()],
225
+ adminCapIndex: 1,
226
+ });
227
+ },
228
+ });
229
+ }
230
+ /** Build the complete post-share catalog graph as one atomic PTB. */
231
+ export function publishAtomicCatalog(p) {
232
+ if (p.pressing && !p.release)
233
+ throw new Error("A pressing requires a release");
234
+ for (const node of [...p.compositions, ...p.recordings]) {
235
+ if ((node.royaltyPool || ("routedStake" in node && node.routedStake)) && node.custody.kind !== "vault") {
236
+ throw new Error(`${node.ref}: Vault-only plugins require Vault custody`);
237
+ }
238
+ }
239
+ if (p.release?.revenueDistribution && p.release.custody.kind !== "vault") {
240
+ throw new Error("Release revenue distribution requires Vault custody");
241
+ }
242
+ return (tx) => {
243
+ const createdParties = new Map();
244
+ const parties = new Map();
245
+ for (const node of p.parties) {
246
+ if ("id" in node) {
247
+ parties.set(node.ref, tx.object(node.id));
248
+ continue;
249
+ }
250
+ const kind = tx.add(node.create === "group"
251
+ ? party.newGroupKind({ package: p.deployment.protocol.misoParty })
252
+ : party.newIndividualKind({ package: p.deployment.protocol.misoParty }));
253
+ const created = tx.add(party._new({
254
+ package: p.deployment.protocol.misoParty,
255
+ arguments: [kind, node.name],
256
+ }));
257
+ const parts = {
258
+ party: requiredCommandResult(created, 0, "party::new"),
259
+ adminCap: requiredCommandResult(created, 1, "party::new"),
260
+ };
261
+ createdParties.set(node.ref, parts);
262
+ parties.set(node.ref, parts.party);
263
+ }
264
+ const compositions = p.compositions.map((node) => {
265
+ const created = tx.add(composition._new({
266
+ package: p.deployment.protocol.miso,
267
+ typeArguments: [node.shareType],
268
+ arguments: [node.title, node.royaltyRateBps, node.shareCurrencyId, node.shareTreasuryCapId],
269
+ }));
270
+ return {
271
+ work: requiredCommandResult(created, 0, "composition::new"),
272
+ adminCap: requiredCommandResult(created, 1, "composition::new"),
273
+ balance: requiredCommandResult(created, 2, "composition::new"),
274
+ };
275
+ });
276
+ const recordings = p.recordings.map((node) => {
277
+ const parent = node.parentCompositionIndex !== undefined
278
+ ? requiredAt(compositions, node.parentCompositionIndex, "parent composition").work
279
+ : tx.object(node.parentCompositionId);
280
+ const created = tx.add(recording._new({
281
+ package: p.deployment.protocol.miso,
282
+ typeArguments: [node.shareType, node.compositionShareType],
283
+ arguments: [parent, node.shareCurrencyId, node.shareTreasuryCapId],
284
+ }));
285
+ return {
286
+ work: requiredCommandResult(created, 0, "recording::new"),
287
+ adminCap: requiredCommandResult(created, 1, "recording::new"),
288
+ balance: requiredCommandResult(created, 2, "recording::new"),
289
+ };
290
+ });
291
+ let releaseObject;
292
+ let releaseAdminCap;
293
+ if (p.release) {
294
+ const ids = p.release.tracks.map((node) => "recordingIndex" in node
295
+ ? tx.moveCall({
296
+ target: "0x2::object::id",
297
+ typeArguments: [`${p.deployment.protocol.miso}::recording::Recording<${p.recordings[node.recordingIndex].shareType},${p.recordings[node.recordingIndex].compositionShareType}>`],
298
+ arguments: [requiredAt(recordings, node.recordingIndex, "fresh recording").work],
299
+ })
300
+ : tx.pure.id(node.recordingId));
301
+ const targetReleaseId = tx.moveCall({
302
+ target: `${p.deployment.protocol.miso}::release::derive_target_release_id`,
303
+ arguments: [
304
+ tx.object(p.deployment.objects.releaseRegistry),
305
+ tx.makeMoveVec({ type: "0x2::object::ID", elements: ids }),
306
+ tx.makeMoveVec({ type: "u64", elements: p.release.tracks.map((node) => tx.pure.u64(node.splitBps)) }),
307
+ tx.pure.u256(BigInt(p.release.nonce)),
308
+ ],
309
+ });
310
+ const tracks = p.release.tracks.map((node) => {
311
+ if ("recordingIndex" in node) {
312
+ const recNode = requiredAt(p.recordings, node.recordingIndex, "fresh recording");
313
+ const rec = requiredAt(recordings, node.recordingIndex, "fresh recording");
314
+ return tx.add(track._new({
315
+ package: p.deployment.protocol.miso,
316
+ typeArguments: [recNode.shareType, recNode.compositionShareType],
317
+ arguments: [rec.adminCap, rec.work, targetReleaseId, node.splitBps],
318
+ }));
319
+ }
320
+ return invokeWithAdminCap(tx, node.authority, {
321
+ target: `${p.deployment.protocol.miso}::track::new`,
322
+ typeArguments: [node.recordingShareType, node.compositionShareType],
323
+ arguments: [tx.object(node.recordingId), targetReleaseId, tx.pure.u16(node.splitBps)],
324
+ adminCapIndex: 0,
325
+ });
326
+ });
327
+ const created = tx.moveCall({
328
+ target: `${p.deployment.protocol.miso}::release::new`,
329
+ arguments: [
330
+ tx.object(p.deployment.objects.releaseRegistry),
331
+ tx.pure.string(p.release.title),
332
+ tx.makeMoveVec({ type: `${p.deployment.protocol.miso}::track::Track`, elements: tracks }),
333
+ tx.pure.u256(BigInt(p.release.nonce)),
334
+ ],
335
+ });
336
+ releaseObject = requiredCommandResult(created, 0, "release::new");
337
+ releaseAdminCap = requiredCommandResult(created, 1, "release::new");
338
+ }
339
+ p.compositions.forEach((node, index) => {
340
+ const parts = requiredAt(compositions, index, "composition");
341
+ for (const credit of node.credits ?? []) {
342
+ attachCompositionCredit({
343
+ compositionId: parts.work,
344
+ authority: directAdminCap(parts.adminCap),
345
+ partyId: partyByRef(parties, credit.party),
346
+ displayName: credit.displayName,
347
+ roles: credit.roles,
348
+ compositionShareType: node.shareType,
349
+ compositionCreditsPackageId: p.deployment.packages.compositionCredits,
350
+ misoCreditPackageId: p.deployment.packages.credit,
351
+ })(tx);
352
+ }
353
+ });
354
+ p.recordings.forEach((node, index) => {
355
+ const parts = requiredAt(recordings, index, "recording");
356
+ const authority = directAdminCap(parts.adminCap);
357
+ for (const credit of node.credits ?? []) {
358
+ const target = partyByRef(parties, credit.party);
359
+ attachRecordingCredit({
360
+ recordingId: parts.work, authority, partyId: target,
361
+ displayName: credit.displayName, roles: credit.roles,
362
+ recordingShareType: node.shareType,
363
+ compositionShareType: node.compositionShareType,
364
+ recordingCreditsPackageId: p.deployment.packages.recordingCredits,
365
+ misoCreditPackageId: p.deployment.packages.credit,
366
+ })(tx);
367
+ if (credit.primaryArtist) {
368
+ addRecordingPrimaryArtist({
369
+ recordingId: parts.work, authority, partyId: target,
370
+ recordingShareType: node.shareType,
371
+ compositionShareType: node.compositionShareType,
372
+ recordingCreditsPackageId: p.deployment.packages.recordingCredits,
373
+ })(tx);
374
+ }
375
+ }
376
+ if (node.advisory)
377
+ setRecordingAdvisory({
378
+ recordingId: parts.work, authority,
379
+ recordingShareType: node.shareType,
380
+ compositionShareType: node.compositionShareType,
381
+ recordingAdvisoryPackageId: p.deployment.packages.recordingAdvisory,
382
+ rating: node.advisory,
383
+ })(tx);
384
+ if (node.languages?.kind === "instrumental")
385
+ setRecordingInstrumental({
386
+ recordingId: parts.work, authority,
387
+ recordingShareType: node.shareType,
388
+ compositionShareType: node.compositionShareType,
389
+ recordingLanguagePackageId: p.deployment.packages.recordingLanguage,
390
+ })(tx);
391
+ if (node.languages?.kind === "languages")
392
+ setRecordingLanguages({
393
+ recordingId: parts.work, authority,
394
+ recordingShareType: node.shareType,
395
+ compositionShareType: node.compositionShareType,
396
+ recordingLanguagePackageId: p.deployment.packages.recordingLanguage,
397
+ languages: languageVector(tx, p, node.languages.codes),
398
+ })(tx);
399
+ if (node.masterReferenceBlobId !== undefined)
400
+ setRecordingMasterReference({
401
+ recordingId: parts.work, authority,
402
+ recordingShareType: node.shareType,
403
+ compositionShareType: node.compositionShareType,
404
+ recordingMasterReferencePackageId: p.deployment.packages.recordingMasterReference,
405
+ reference: walrusBlob(tx, p, node.masterReferenceBlobId),
406
+ })(tx);
407
+ if (node.previewBlobId !== undefined)
408
+ setRecordingPreview({
409
+ recordingId: parts.work, authority,
410
+ recordingShareType: node.shareType,
411
+ compositionShareType: node.compositionShareType,
412
+ recordingPreviewPackageId: p.deployment.packages.recordingPreview,
413
+ reference: walrusBlob(tx, p, node.previewBlobId),
414
+ })(tx);
415
+ });
416
+ if (p.release && releaseObject && releaseAdminCap) {
417
+ const authority = directAdminCap(releaseAdminCap);
418
+ for (const credit of p.release.credits ?? [])
419
+ addReleaseCredit({
420
+ releaseId: releaseObject, authority,
421
+ partyId: partyByRef(parties, credit.party),
422
+ displayName: credit.displayName, role: credit.role,
423
+ releaseCreditsPackageId: p.deployment.packages.releaseCredits,
424
+ misoCreditPackageId: p.deployment.packages.credit,
425
+ })(tx);
426
+ if (p.release.kind)
427
+ setReleaseKind({
428
+ releaseId: releaseObject, authority, kind: p.release.kind,
429
+ releaseKindPackageId: p.deployment.packages.releaseKind,
430
+ })(tx);
431
+ if (p.release.description)
432
+ setReleaseDescription({
433
+ releaseId: releaseObject, authority, description: p.release.description,
434
+ releaseDescriptionPackageId: p.deployment.packages.releaseDescription,
435
+ })(tx);
436
+ if (p.release.genres)
437
+ setReleaseGenres({
438
+ releaseId: releaseObject, authority,
439
+ primaryGenreId: p.release.genres.primaryGenreId,
440
+ secondaryGenreIds: p.release.genres.secondaryGenreIds ?? [],
441
+ trackPrimaryGenres: p.release.genres.tracks ?? [],
442
+ releaseGenrePackageId: p.deployment.packages.releaseGenre,
443
+ })(tx);
444
+ if (p.release.dspLinks)
445
+ setReleaseDspLinks({
446
+ releaseId: releaseObject, authority,
447
+ releaseLinks: p.release.dspLinks.release ?? [],
448
+ trackLinks: p.release.dspLinks.tracks ?? [],
449
+ releaseDspLinkPackageId: p.deployment.packages.releaseDspLink,
450
+ })(tx);
451
+ if (p.release.cover?.stillBlobId !== undefined)
452
+ setReleaseCover({
453
+ releaseId: releaseObject, authority,
454
+ stillBlobId: p.release.cover.stillBlobId,
455
+ animatedBlobId: p.release.cover.animatedBlobId,
456
+ coverArtPackageId: p.deployment.packages.coverArt,
457
+ releaseCoverArtPackageId: p.deployment.packages.releaseCoverArt,
458
+ oriPackageId: p.deployment.packages.ori,
459
+ })(tx);
460
+ for (const cover of p.release.cover?.tracks ?? [])
461
+ setReleaseTrackCover({
462
+ releaseId: releaseObject, authority,
463
+ trackIndex: cover.trackIndex,
464
+ stillBlobId: cover.stillBlobId,
465
+ animatedBlobId: cover.animatedBlobId,
466
+ coverArtPackageId: p.deployment.packages.coverArt,
467
+ releaseCoverArtPackageId: p.deployment.packages.releaseCoverArt,
468
+ oriPackageId: p.deployment.packages.ori,
469
+ })(tx);
470
+ }
471
+ let pressingParts;
472
+ if (p.pressing && releaseObject && releaseAdminCap) {
473
+ const created = tx.add(pressingContract._new({
474
+ package: p.deployment.packages.pressing,
475
+ arguments: [
476
+ releaseObject,
477
+ releaseAdminCap,
478
+ pressingState(tx, p, p.pressing.state ?? { kind: "active" }),
479
+ ],
480
+ }));
481
+ pressingParts = {
482
+ pressing: requiredCommandResult(created, 0, "pressing::new"),
483
+ adminCap: requiredCommandResult(created, 1, "pressing::new"),
484
+ };
485
+ for (const listing of p.pressing.listings) {
486
+ tx.add(listingContract._new({
487
+ package: p.deployment.packages.pressing,
488
+ typeArguments: [listing.currencyType],
489
+ arguments: [
490
+ pressingParts.pressing,
491
+ pressingParts.adminCap,
492
+ listingPrice(tx, p, listing.price),
493
+ tx.add(listing.enabled === false
494
+ ? listingContract.newDisabledState({ package: p.deployment.packages.pressing })
495
+ : listingContract.newEnabledState({ package: p.deployment.packages.pressing })),
496
+ ],
497
+ }));
498
+ }
499
+ }
500
+ p.compositions.forEach((node, index) => publishComposition(tx, p, node, requiredAt(compositions, index, "composition")));
501
+ p.recordings.forEach((node, index) => publishRecording(tx, p, node, requiredAt(recordings, index, "recording")));
502
+ if (p.release && releaseObject && releaseAdminCap) {
503
+ publishReleaseObject(tx, p, p.release, releaseObject, releaseAdminCap);
504
+ }
505
+ for (const node of p.parties) {
506
+ if ("id" in node)
507
+ continue;
508
+ const parts = createdParties.get(node.ref);
509
+ tx.add(party.share({
510
+ package: p.deployment.protocol.misoParty,
511
+ arguments: [parts.party, parts.adminCap],
512
+ }));
513
+ disposeNewAdminCap(tx, parts.adminCap, custody(p, node.custody, partyCapType(p), node.custody.kind === "vault" && node.installWallet !== false
514
+ ? (vault, vaultAdminCap) => installPartyWalletPlugin(tx, {
515
+ vault, vaultAdminCap,
516
+ pluginPackageId: p.deployment.packages.partyWalletPlugin,
517
+ })
518
+ : undefined));
519
+ }
520
+ if (p.pressing && pressingParts) {
521
+ tx.add(pressingContract.share({
522
+ package: p.deployment.packages.pressing,
523
+ arguments: [pressingParts.pressing],
524
+ }));
525
+ disposeNewAdminCap(tx, pressingParts.adminCap, custody(p, p.pressing.custody, pressingCapType(p)));
526
+ }
527
+ };
528
+ }
529
+ /** Assemble without RPC access so callers can fail before publishing share packages. */
530
+ export function inspectAtomicPublication(p) {
531
+ const tx = new Transaction();
532
+ publishAtomicCatalog(p)(tx);
533
+ const data = tx.getData();
534
+ return { commands: data.commands.length, inputs: data.inputs.length };
535
+ }
536
+ export function assertAtomicPublicationBounds(p) {
537
+ const inspection = inspectAtomicPublication(p);
538
+ if (inspection.commands > MAX_ATOMIC_PUBLICATION_COMMANDS) {
539
+ throw new Error(`Atomic publication requires ${inspection.commands} commands; the SDK safety cap is ` +
540
+ `${MAX_ATOMIC_PUBLICATION_COMMANDS} (Sui permits at most 1024).`);
541
+ }
542
+ if (inspection.inputs > MAX_ATOMIC_PUBLICATION_INPUTS) {
543
+ throw new Error(`Atomic publication requires ${inspection.inputs} inputs; Sui permits at most ` +
544
+ `${MAX_ATOMIC_PUBLICATION_INPUTS}.`);
545
+ }
546
+ return inspection;
547
+ }
548
+ function compactType(type) {
549
+ return type.replace(/\s+/g, "");
550
+ }
551
+ function findByShareType(created, shareType, description) {
552
+ const wanted = compactType(shareType);
553
+ const matches = created.filter((item) => compactType(item.objectType).includes(wanted));
554
+ if (matches.length !== 1)
555
+ throw new Error(`Expected one ${description} for ${shareType}; found ${matches.length}`);
556
+ return matches[0].objectId;
557
+ }
558
+ function vaultsByWrappedCap(result) {
559
+ const out = new Map();
560
+ for (const event of result.events) {
561
+ if (!event.eventType.includes("::vault::VaultCreatedEvent<"))
562
+ continue;
563
+ const parsed = parseVaultCreatedEvent(event.bcs);
564
+ out.set(parsed.wrapped_cap_id, {
565
+ vaultId: parsed.vault_id,
566
+ vaultAdminCapId: parsed.vault_admin_cap_id,
567
+ });
568
+ }
569
+ return out;
570
+ }
571
+ function authorityOut(result, vaults, selected, adminCapId, capType, vaultPackageId) {
572
+ if (selected.kind === "direct")
573
+ return { kind: "direct", adminCapId };
574
+ const found = vaults.get(adminCapId);
575
+ if (!found)
576
+ throw new Error(`No VaultCreatedEvent wrapped admin cap ${adminCapId} in ${result.digest}`);
577
+ return { kind: "vault", ...found, capType, vaultPackageId };
578
+ }
579
+ /** Parse one atomic publication using type identity plus lifecycle event payloads. */
580
+ export function parseAtomicPublicationResult(p, result) {
581
+ const vaults = vaultsByWrappedCap(result);
582
+ const createdCompositions = allCreatedByType(result, "::composition::Composition<");
583
+ const createdRecordings = allCreatedByType(result, "::recording::Recording<");
584
+ const createdPools = allCreatedByType(result, "::pool::RoyaltyPool<");
585
+ const createdPartyNodes = p.parties.filter((node) => "create" in node);
586
+ const partyEvents = result.events.filter((event) => event.eventType.endsWith("::party::PartyCreatedEvent"));
587
+ if (partyEvents.length !== createdPartyNodes.length) {
588
+ throw new Error(`Expected ${createdPartyNodes.length} PartyCreatedEvent values; found ${partyEvents.length}`);
589
+ }
590
+ const parties = {};
591
+ for (const node of p.parties) {
592
+ if ("id" in node) {
593
+ parties[node.ref] = {
594
+ id: node.id,
595
+ adminCapId: derivePartyAdminCapId(node.id, p.deployment.protocol.misoParty),
596
+ created: false,
597
+ };
598
+ }
599
+ }
600
+ createdPartyNodes.forEach((node, index) => {
601
+ const event = partyEvents[index];
602
+ const parsed = protocolContracts.party.PartyCreatedEvent.parse(event.bcs);
603
+ const adminCapId = derivePartyAdminCapId(parsed.party_id, p.deployment.protocol.misoParty);
604
+ parties[node.ref] = {
605
+ id: parsed.party_id,
606
+ adminCapId,
607
+ created: true,
608
+ authority: authorityOut(result, vaults, node.custody, adminCapId, partyCapType(p), p.deployment.packages.vault),
609
+ };
610
+ });
611
+ const compositions = {};
612
+ p.compositions.forEach((node) => {
613
+ const id = findByShareType(createdCompositions, node.shareType, "Composition");
614
+ const adminCapId = deriveCompositionAdminCapId(id, p.deployment.protocol.miso);
615
+ compositions[node.ref] = {
616
+ id,
617
+ adminCapId,
618
+ shareType: node.shareType,
619
+ authority: authorityOut(result, vaults, node.custody, adminCapId, compositionCapType(p, node.shareType), p.deployment.packages.vault),
620
+ royaltyPoolId: node.royaltyPool ? findByShareType(createdPools, node.shareType, "Composition RoyaltyPool") : undefined,
621
+ };
622
+ });
623
+ const recordings = {};
624
+ p.recordings.forEach((node) => {
625
+ const id = findByShareType(createdRecordings, node.shareType, "Recording");
626
+ const adminCapId = deriveRecordingAdminCapId(id, p.deployment.protocol.miso);
627
+ recordings[node.ref] = {
628
+ id,
629
+ adminCapId,
630
+ shareType: node.shareType,
631
+ compositionShareType: node.compositionShareType,
632
+ authority: authorityOut(result, vaults, node.custody, adminCapId, recordingCapType(p, node.shareType), p.deployment.packages.vault),
633
+ royaltyPoolId: node.royaltyPool ? findByShareType(createdPools, node.shareType, "Recording RoyaltyPool") : undefined,
634
+ };
635
+ });
636
+ let releaseOut;
637
+ if (p.release) {
638
+ const id = createdByExactType(result, `${p.deployment.protocol.miso}::release::Release`);
639
+ const adminCapId = deriveReleaseAdminCapId(id, p.deployment.protocol.miso);
640
+ releaseOut = {
641
+ id,
642
+ adminCapId,
643
+ authority: authorityOut(result, vaults, p.release.custody, adminCapId, releaseCapType(p), p.deployment.packages.vault),
644
+ };
645
+ }
646
+ let pressingOut;
647
+ if (p.pressing && releaseOut) {
648
+ const id = derivePressingId(releaseOut.id, p.deployment.packages.pressing);
649
+ const adminCapId = derivePressingAdminCapId(id, p.deployment.packages.pressing);
650
+ pressingOut = {
651
+ id,
652
+ adminCapId,
653
+ authority: authorityOut(result, vaults, p.pressing.custody, adminCapId, pressingCapType(p), p.deployment.packages.vault),
654
+ };
655
+ }
656
+ return {
657
+ digest: result.digest,
658
+ gasUsed: result.gasUsed,
659
+ parties,
660
+ compositions,
661
+ recordings,
662
+ release: releaseOut,
663
+ pressing: pressingOut,
664
+ };
665
+ }
666
+ //# sourceMappingURL=publication.js.map