@misonetwork/sdk 0.4.0 → 0.6.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 (70) hide show
  1. package/README.md +101 -503
  2. package/dist/client.d.ts +21 -59
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +26 -58
  5. package/dist/client.js.map +1 -1
  6. package/dist/contracts/miso/release.d.ts +34 -31
  7. package/dist/contracts/miso/release.d.ts.map +1 -1
  8. package/dist/contracts/miso/release.js +32 -29
  9. package/dist/contracts/miso/release.js.map +1 -1
  10. package/dist/contracts/miso/track.d.ts +66 -22
  11. package/dist/contracts/miso/track.d.ts.map +1 -1
  12. package/dist/contracts/miso/track.js +65 -20
  13. package/dist/contracts/miso/track.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 +0 -1
  19. package/dist/contracts.d.ts.map +1 -1
  20. package/dist/contracts.js +0 -1
  21. package/dist/contracts.js.map +1 -1
  22. package/dist/deployments.d.ts +21 -0
  23. package/dist/deployments.d.ts.map +1 -0
  24. package/dist/deployments.js +17 -0
  25. package/dist/deployments.js.map +1 -0
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +1 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/internal.d.ts +0 -7
  31. package/dist/internal.d.ts.map +1 -1
  32. package/dist/internal.js +0 -22
  33. package/dist/internal.js.map +1 -1
  34. package/dist/parsers.d.ts +1 -4
  35. package/dist/parsers.d.ts.map +1 -1
  36. package/dist/parsers.js +0 -24
  37. package/dist/parsers.js.map +1 -1
  38. package/dist/queries.d.ts +2 -5
  39. package/dist/queries.d.ts.map +1 -1
  40. package/dist/queries.js +8 -45
  41. package/dist/queries.js.map +1 -1
  42. package/dist/transactions.d.ts +10 -71
  43. package/dist/transactions.d.ts.map +1 -1
  44. package/dist/transactions.js +15 -72
  45. package/dist/transactions.js.map +1 -1
  46. package/dist/types.d.ts +3 -40
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/view.d.ts +7 -7
  49. package/dist/view.d.ts.map +1 -1
  50. package/dist/view.js +9 -9
  51. package/dist/view.js.map +1 -1
  52. package/package.json +8 -4
  53. package/src/client.ts +47 -86
  54. package/src/contracts/miso/release.ts +39 -36
  55. package/src/contracts/miso/track.ts +81 -23
  56. package/src/contracts/utils/index.ts +156 -4
  57. package/src/contracts.ts +0 -1
  58. package/src/deployments.ts +42 -0
  59. package/src/index.ts +1 -0
  60. package/src/internal.ts +0 -24
  61. package/src/parsers.ts +0 -35
  62. package/src/queries.ts +11 -59
  63. package/src/transactions.ts +20 -112
  64. package/src/types.ts +3 -53
  65. package/src/view.ts +13 -13
  66. package/dist/contracts/miso/deal.d.ts +0 -184
  67. package/dist/contracts/miso/deal.d.ts.map +0 -1
  68. package/dist/contracts/miso/deal.js +0 -184
  69. package/dist/contracts/miso/deal.js.map +0 -1
  70. package/src/contracts/miso/deal.ts +0 -257
package/src/client.ts CHANGED
@@ -6,15 +6,16 @@ import type {
6
6
  SuiClientRegistration,
7
7
  } from "@mysten/sui/client";
8
8
  import type { SuiGraphQLClient } from "@mysten/sui/graphql";
9
- import type { TxThunk } from "./transactions.ts";
9
+ import {
10
+ getMisoProtocolDeployment,
11
+ type MisoProtocolDeployment,
12
+ } from "./deployments.ts";
10
13
  import * as parsers from "./parsers.ts";
11
14
  import * as queries from "./queries.ts";
12
- import * as transactions from "./transactions.ts";
13
15
  import * as view from "./view.ts";
14
16
  import type {
15
17
  Composition,
16
18
  CompositionAdminCap,
17
- Deal,
18
19
  Recording,
19
20
  RecordingAdminCap,
20
21
  Release,
@@ -25,46 +26,27 @@ import type {
25
26
  import * as composition from "./contracts/miso/composition.ts";
26
27
  import * as recording from "./contracts/miso/recording.ts";
27
28
  import * as release from "./contracts/miso/release.ts";
28
- import * as deal from "./contracts/miso/deal.ts";
29
29
  import * as track from "./contracts/miso/track.ts";
30
30
 
31
31
  export interface MisoOptions<Name extends string = "miso"> {
32
32
  /** Name for the client extension. Defaults to "miso". */
33
33
  name?: Name;
34
- /** The Miso package ID. Required for type-based queries and derivation. */
35
- misoPackageId: string;
36
34
  /**
37
- * The `ReleaseRegistry` object ID for this deployment.
38
- *
39
- * Created once in `release::init` and shared, so it is FIXED for the lifetime
40
- * of a published package — deployment config, not runtime state. Supply it
41
- * (alongside `misoPackageId`, from the same deployment manifest) and
42
- * `getReleaseRegistry()` needs no network call at all. Omit it and the SDK
43
- * falls back to a GraphQL scan, which is why this is worth configuring.
35
+ * Complete custom deployment. Omit for bundled Mainnet/Testnet addresses,
36
+ * selected from the Sui client's `network`.
44
37
  */
45
- releaseRegistryId?: string;
38
+ deployment?: MisoProtocolDeployment;
39
+ /** @deprecated Use `deployment`. Retained for compatibility with pre-0.4 callers. */
40
+ misoPackageId?: string;
46
41
  /**
47
42
  * Optional GraphQL client, required ONLY for the global type-discovery reads
48
43
  * the Core API cannot express: `getCompositionByShareType`,
49
- * `getRecordingByShareType`, and `getReleaseRegistry` when
50
- * `releaseRegistryId` is not configured. Everything else — including every
44
+ * `getRecordingByShareType`. Everything else — including every
51
45
  * `getOwned*AdminCaps` — goes over the Core API.
52
46
  */
53
47
  graphqlClient?: SuiGraphQLClient;
54
48
  }
55
49
 
56
- /**
57
- * Wraps a builder so the client's `misoPackageId` is injected, dropping it from
58
- * the caller's params. Explicit call-sites (the free functions in
59
- * `./transactions`) remain available for full control.
60
- */
61
- function bindPackages<P extends { misoPackageId: string }>(
62
- fn: (params: P) => TxThunk,
63
- misoPackageId: string,
64
- ): (params: Omit<P, "misoPackageId">) => TxThunk {
65
- return (params) => fn({ misoPackageId, ...params } as unknown as P);
66
- }
67
-
68
50
  /** Defaults `options.package` to `pkg` for every call-function in a generated module. */
69
51
  function bindModulePackage<M extends object>(mod: M, pkg: string): M {
70
52
  const out: Record<string, unknown> = {};
@@ -84,31 +66,53 @@ function bindModulePackage<M extends object>(mod: M, pkg: string): M {
84
66
  * @example
85
67
  * ```ts
86
68
  * const client = new SuiGrpcClient({ network: 'testnet' })
87
- * .$extend(miso({ misoPackageId: '0x...' }));
69
+ * .$extend(miso());
88
70
  * const composition = await client.miso.getCompositionById('0x...');
89
71
  * ```
90
72
  */
91
73
  export function miso<const Name extends string = "miso">(
92
- options: MisoOptions<Name>,
93
- ): SuiClientRegistration<ClientWithCoreApi, Name, MisoClient> {
74
+ options: MisoOptions<Name> = {},
75
+ ): SuiClientRegistration<ClientWithCoreApi, Name, MisoProtocolClient> {
94
76
  const name = (options.name ?? "miso") as Name;
95
77
  return {
96
78
  name,
97
- register: (client) => new MisoClient(client, options),
79
+ register: (client) => {
80
+ const deployment =
81
+ options.deployment ??
82
+ (options.misoPackageId
83
+ ? { packageId: options.misoPackageId }
84
+ : getMisoProtocolDeployment(client.network));
85
+ return new MisoProtocolClient(client, {
86
+ deployment,
87
+ graphqlClient: options.graphqlClient,
88
+ });
89
+ },
98
90
  };
99
91
  }
100
92
 
101
- export class MisoClient {
93
+ export interface MisoProtocolClientOptions {
94
+ deployment: MisoProtocolDeployment;
95
+ graphqlClient?: SuiGraphQLClient;
96
+ }
97
+
98
+ export class MisoProtocolClient {
102
99
  #client: ClientWithCoreApi;
103
100
  #graphqlClient?: SuiGraphQLClient;
104
- #misoPackageId: string;
105
- #releaseRegistryId?: string;
101
+ #deployment: MisoProtocolDeployment;
106
102
 
107
- constructor(client: ClientWithCoreApi, options: Omit<MisoOptions, "name">) {
103
+ constructor(client: ClientWithCoreApi, options: MisoProtocolClientOptions) {
108
104
  this.#client = client;
109
105
  this.#graphqlClient = options.graphqlClient;
110
- this.#misoPackageId = options.misoPackageId;
111
- this.#releaseRegistryId = options.releaseRegistryId;
106
+ this.#deployment = options.deployment;
107
+ }
108
+
109
+ /** The exact deployment selected for this client. */
110
+ get deployment(): MisoProtocolDeployment {
111
+ return this.#deployment;
112
+ }
113
+
114
+ get #misoPackageId(): string {
115
+ return this.#deployment.packageId;
112
116
  }
113
117
 
114
118
  // === Composition ===
@@ -202,12 +206,6 @@ export class MisoClient {
202
206
  return queries.deriveRecordingAdminCapId(recordingId, this.#misoPackageId);
203
207
  }
204
208
 
205
- // === Deal ===
206
-
207
- async getDealById(dealId: string): Promise<Deal> {
208
- return queries.getDealById(this.#client, dealId);
209
- }
210
-
211
209
  // === Release ===
212
210
 
213
211
  async getReleaseById(releaseId: string): Promise<Release> {
@@ -229,23 +227,6 @@ export class MisoClient {
229
227
  this.#misoPackageId,
230
228
  );
231
229
  }
232
- /**
233
- * The deployment's `ReleaseRegistry` object ID.
234
- *
235
- * Returns the configured `releaseRegistryId` with no network call. Only when
236
- * it was not configured does this fall back to a GraphQL scan — a one-time
237
- * bootstrap for a fresh deployment whose id you have not recorded yet. Prefer
238
- * configuring it: the registry is created once in `release::init` and never
239
- * changes, so scanning for it on every call is pure overhead.
240
- */
241
- async getReleaseRegistry(): Promise<string> {
242
- if (this.#releaseRegistryId) return this.#releaseRegistryId;
243
- return queries.getReleaseRegistry(
244
- this.#requireGraphQL(),
245
- this.#misoPackageId,
246
- );
247
- }
248
-
249
230
  // === Share Currency ===
250
231
 
251
232
  async getShareCurrencyType(shareCurrencyId: string): Promise<string> {
@@ -263,29 +244,14 @@ export class MisoClient {
263
244
  return queries.getShareCurrencyTreasuryCap(this.#client, shareType, owner);
264
245
  }
265
246
 
266
- // === Transaction builders (thunks) ===
267
-
268
- // Only the `(params) => TxThunk` builders bind here. The primitives that take
269
- // a `Transaction` directly and return values (`createComposition`,
270
- // `createRecording`, `createRelease`, `createDeal`) are free functions by
271
- // design — they thread results into a caller-owned PTB, so there is nothing
272
- // to bind. Import them from the package root and pass `misoPackageId`
273
- // explicitly.
274
- get tx() {
275
- const miso = this.#misoPackageId;
276
- return {
277
- rejectDeal: bindPackages(transactions.rejectDeal, miso),
278
- };
279
- }
280
-
281
247
  // === Simulate-based reads (view) ===
282
248
 
283
249
  get view() {
284
250
  const client = this.#client;
285
251
  const misoPackageId = this.#misoPackageId;
286
252
  return {
287
- deriveReleaseId: (params: view.DeriveReleaseIdParams) =>
288
- view.deriveReleaseId(client, misoPackageId, params),
253
+ deriveTargetReleaseId: (params: view.DeriveTargetReleaseIdParams) =>
254
+ view.deriveTargetReleaseId(client, misoPackageId, params),
289
255
  };
290
256
  }
291
257
 
@@ -297,7 +263,6 @@ export class MisoClient {
297
263
  composition: bindModulePackage(composition, pkg),
298
264
  recording: bindModulePackage(recording, pkg),
299
265
  release: bindModulePackage(release, pkg),
300
- deal: bindModulePackage(deal, pkg),
301
266
  track: bindModulePackage(track, pkg),
302
267
  };
303
268
  }
@@ -309,15 +274,11 @@ export class MisoClient {
309
274
  Composition: composition.Composition,
310
275
  Recording: recording.Recording,
311
276
  Release: release.Release,
312
- Deal: deal.Deal,
313
277
  Track: track.Track,
314
278
  CompositionPublishedEvent: composition.CompositionPublishedEvent,
315
279
  CompositionRoyaltySetEvent: composition.CompositionRoyaltySetEvent,
316
280
  RecordingPublishedEvent: recording.RecordingPublishedEvent,
317
281
  ReleasePublishedEvent: release.ReleasePublishedEvent,
318
- DealCreatedEvent: deal.DealCreatedEvent,
319
- DealAcceptedEvent: deal.DealAcceptedEvent,
320
- DealRejectedEvent: deal.DealRejectedEvent,
321
282
  };
322
283
  }
323
284
 
@@ -329,9 +290,6 @@ export class MisoClient {
329
290
  compositionRoyaltySetEvent: parsers.parseCompositionRoyaltySetEvent,
330
291
  recordingPublishedEvent: parsers.parseRecordingPublishedEvent,
331
292
  releasePublishedEvent: parsers.parseReleasePublishedEvent,
332
- dealCreatedEvent: parsers.parseDealCreatedEvent,
333
- dealAcceptedEvent: parsers.parseDealAcceptedEvent,
334
- dealRejectedEvent: parsers.parseDealRejectedEvent,
335
293
  };
336
294
  }
337
295
 
@@ -344,3 +302,6 @@ export class MisoClient {
344
302
  return this.#graphqlClient;
345
303
  }
346
304
  }
305
+
306
+ /** @deprecated Prefer the layer-specific `MisoProtocolClient` name. */
307
+ export { MisoProtocolClient as MisoClient };
@@ -38,14 +38,22 @@
38
38
  *
39
39
  * ### Consent scope
40
40
  *
41
- * The release digest — and therefore the derived release id every `Deal` commits
42
- * to — binds the economics and membership of the release: the ordered list of
43
- * `(recording, split)` pairs and the creator's nonce. It deliberately binds
44
- * nothing else. The title — the one embedded field outside the digest — and
41
+ * The release digest — and therefore the derived release id every `Track` commits
42
+ * to at creation — binds the economics and membership of the release: the ordered
43
+ * list of `(recording, split)` pairs and the creator's nonce. It deliberately
44
+ * binds nothing else. The title — the one embedded field outside the digest — and
45
45
  * everything in the extension layer (artwork, credits, display grouping) are
46
- * chosen by the release creator, before or after deals are signed, and are trusted
47
- * and publicly attributable rather than cryptographically committed. See
48
- * `deal::new` for the signer-side statement of this boundary.
46
+ * chosen by the release creator, before or after tracks are created, and are
47
+ * trusted and publicly attributable rather than cryptographically committed. See
48
+ * `track::new` for the signer-side statement of this boundary.
49
+ *
50
+ * The derived id commits to a `(parent, digest)` pair, not the digest alone — so
51
+ * targeting an id also consents to that namespace's liveness. If the parent object
52
+ * is deleted, or its `&mut UID` becomes permanently unreachable, the release can
53
+ * never exist and every track or offer targeting it is stranded — the same
54
+ * blast-radius class as a release that simply never publishes. A coordinator meant
55
+ * to serve as the default parent namespace should therefore be shared and
56
+ * undeletable.
49
57
  *
50
58
  * ### Lifecycle and trust model
51
59
  *
@@ -65,12 +73,11 @@
65
73
  * holder as able to mutate or delete any extension data, forever.
66
74
  */
67
75
 
68
- import { MoveTuple, MoveEnum, MoveStruct, normalizeMoveArguments, type RawTransactionArgument } from '../utils/index.js';
76
+ import { MoveEnum, MoveStruct, MoveTuple, normalizeMoveArguments, type RawTransactionArgument } from '../utils/index.js';
69
77
  import { bcs } from '@mysten/sui/bcs';
70
78
  import { type Transaction, type TransactionArgument } from '@mysten/sui/transactions';
71
79
  import * as track from './track.js';
72
80
  const $moduleName = '@local-pkg/miso::release';
73
- export const RELEASE = new MoveTuple({ name: `${$moduleName}::RELEASE`, fields: [bcs.bool()] });
74
81
  /** Lifecycle state of a release. */
75
82
  export const ReleaseState = new MoveEnum({ name: `${$moduleName}::ReleaseState`, fields: {
76
83
  /** Release is initialized but not yet published. */
@@ -86,15 +93,12 @@ export const Release = new MoveStruct({ name: `${$moduleName}::Release`, fields:
86
93
  /** Title of the release. */
87
94
  title: bcs.string(),
88
95
  /**
89
- * The ordered tracklist. Same shape as the digest pre-image every deal consented
90
- * to; display grouping lives in the metadata extension.
96
+ * The ordered tracklist. Same shape as the digest pre-image every track's creator
97
+ * consented to; display grouping lives in the metadata extension.
91
98
  */
92
99
  tracks: bcs.vector(track.Track)
93
100
  } });
94
101
  export const ReleaseKey = new MoveTuple({ name: `${$moduleName}::ReleaseKey`, fields: [bcs.vector(bcs.u8())] });
95
- export const ReleaseRegistry = new MoveStruct({ name: `${$moduleName}::ReleaseRegistry`, fields: {
96
- id: bcs.Address
97
- } });
98
102
  export const ReleaseAdminCap = new MoveStruct({ name: `${$moduleName}::ReleaseAdminCap`, fields: {
99
103
  /** Unique identifier for this capability. */
100
104
  id: bcs.Address,
@@ -102,10 +106,6 @@ export const ReleaseAdminCap = new MoveStruct({ name: `${$moduleName}::ReleaseAd
102
106
  release_id: bcs.Address
103
107
  } });
104
108
  export const ReleaseAdminCapKey = new MoveTuple({ name: `${$moduleName}::ReleaseAdminCapKey`, fields: [bcs.bool()] });
105
- export const ReleaseRegistryCreatedEvent = new MoveStruct({ name: `${$moduleName}::ReleaseRegistryCreatedEvent`, fields: {
106
- registry_id: bcs.Address,
107
- created_by: bcs.Address
108
- } });
109
109
  export const ReleasePublishedEvent = new MoveStruct({ name: `${$moduleName}::ReleasePublishedEvent`, fields: {
110
110
  release_id: bcs.Address
111
111
  } });
@@ -113,7 +113,7 @@ export interface NewArguments {
113
113
  title: RawTransactionArgument<string>;
114
114
  tracks: TransactionArgument;
115
115
  nonce: RawTransactionArgument<number | bigint>;
116
- registry: RawTransactionArgument<string>;
116
+ parent: RawTransactionArgument<string>;
117
117
  }
118
118
  export interface NewOptions {
119
119
  package?: string;
@@ -121,12 +121,15 @@ export interface NewOptions {
121
121
  title: RawTransactionArgument<string>,
122
122
  tracks: TransactionArgument,
123
123
  nonce: RawTransactionArgument<number | bigint>,
124
- registry: RawTransactionArgument<string>
124
+ parent: RawTransactionArgument<string>
125
125
  ];
126
126
  }
127
127
  /**
128
- * Creates a new release with the given configuration. Returns the release and
129
- * admin capability.
128
+ * Creates a new release with the given configuration. Claims the release's UID as
129
+ * a derived child of `parent`, keyed by the release digest (see the module doc's
130
+ * "Consent scope" section) — so contention is per-parent, and which object serves
131
+ * as parent is entirely the caller's choice. Returns the release and admin
132
+ * capability.
130
133
  */
131
134
  export function _new(options: NewOptions) {
132
135
  const packageAddress = options.package ?? '@local-pkg/miso';
@@ -134,9 +137,9 @@ export function _new(options: NewOptions) {
134
137
  '0x1::string::String',
135
138
  'vector<null>',
136
139
  'u256',
137
- null
140
+ '0x2::object::ID'
138
141
  ] satisfies (string | null)[];
139
- const parameterNames = ["title", "tracks", "nonce", "registry"];
142
+ const parameterNames = ["title", "tracks", "nonce", "parent"];
140
143
  return (tx: Transaction) => tx.moveCall({
141
144
  package: packageAddress,
142
145
  module: 'release',
@@ -203,39 +206,39 @@ export function authorize(options: AuthorizeOptions) {
203
206
  arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
204
207
  });
205
208
  }
206
- export interface DeriveReleaseIdArguments {
209
+ export interface DeriveTargetReleaseIdArguments {
207
210
  recordingIds: RawTransactionArgument<Array<string>>;
208
211
  trackSplitValues: RawTransactionArgument<Array<number | bigint>>;
209
212
  nonce: RawTransactionArgument<number | bigint>;
210
- registry: RawTransactionArgument<string>;
213
+ parent: RawTransactionArgument<string>;
211
214
  }
212
- export interface DeriveReleaseIdOptions {
215
+ export interface DeriveTargetReleaseIdOptions {
213
216
  package?: string;
214
- arguments: DeriveReleaseIdArguments | [
217
+ arguments: DeriveTargetReleaseIdArguments | [
215
218
  recordingIds: RawTransactionArgument<Array<string>>,
216
219
  trackSplitValues: RawTransactionArgument<Array<number | bigint>>,
217
220
  nonce: RawTransactionArgument<number | bigint>,
218
- registry: RawTransactionArgument<string>
221
+ parent: RawTransactionArgument<string>
219
222
  ];
220
223
  }
221
224
  /**
222
- * Derives the release ID that `new()` would produce for the given inputs, without
223
- * creating the object. This is the on-chain equivalent of the client-side
224
- * `deriveReleaseId()` function.
225
+ * Derives the target release ID that `new()` would produce for the given inputs
226
+ * and parent, without creating the object. This is the on-chain equivalent of the
227
+ * client-side `deriveReleaseId()` function.
225
228
  */
226
- export function deriveReleaseId(options: DeriveReleaseIdOptions) {
229
+ export function deriveTargetReleaseId(options: DeriveTargetReleaseIdOptions) {
227
230
  const packageAddress = options.package ?? '@local-pkg/miso';
228
231
  const argumentsTypes = [
229
232
  'vector<0x2::object::ID>',
230
233
  'vector<u64>',
231
234
  'u256',
232
- null
235
+ '0x2::object::ID'
233
236
  ] satisfies (string | null)[];
234
- const parameterNames = ["recordingIds", "trackSplitValues", "nonce", "registry"];
237
+ const parameterNames = ["recordingIds", "trackSplitValues", "nonce", "parent"];
235
238
  return (tx: Transaction) => tx.moveCall({
236
239
  package: packageAddress,
237
240
  module: 'release',
238
- function: 'derive_release_id',
241
+ function: 'derive_target_release_id',
239
242
  arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
240
243
  });
241
244
  }
@@ -14,8 +14,8 @@
14
14
  * recording/composition share-type identities) is reached.
15
15
  * - `split_bps` — this track's share of the release's revenue; genuinely
16
16
  * release-specific and not derivable from the recording.
17
- * - `state` — the assign-once lifecycle that carries (then sheds) each deal's
18
- * target release commitment; see `TrackState`.
17
+ * - `state` — the assign-once lifecycle that carries (then sheds) the recording
18
+ * admin's target release commitment, made at creation; see `TrackState`.
19
19
  *
20
20
  * `Track` is intentionally monomorphic: a `Release` holds a `vector<Track>` of
21
21
  * tracks from many different recordings/compositions, so it cannot be generic over
@@ -30,16 +30,16 @@ import * as bps from './deps/bps/bps.js';
30
30
  const $moduleName = '@local-pkg/miso::track';
31
31
  /**
32
32
  * Lifecycle state of a track within a release. A track is born `Unassigned`,
33
- * carrying the target `release_id` its originating `Deal` committed to (the
34
- * release id is a digest of the whole tracklist, so this is the recording owner's
35
- * consent to the exact release configuration). At publish the release verifies the
36
- * match and transitions the track to `Assigned`, which carries no id — shedding
37
- * the 32-byte commitment once it has served its purpose.
33
+ * carrying the target release id the consent committed to at creation (the release
34
+ * id is a digest of the whole tracklist, so this is the recording owner's consent
35
+ * to the exact release configuration). At publish the release verifies the match
36
+ * and transitions the track to `Assigned`, which carries no id — shedding the
37
+ * 32-byte commitment once it has served its purpose.
38
38
  */
39
39
  export const TrackState = new MoveEnum({ name: `${$moduleName}::TrackState`, fields: {
40
40
  /**
41
41
  * Track has been created but not yet assigned to a release. Carries the target
42
- * release id the originating deal committed to.
42
+ * release id the consent committed to at creation.
43
43
  */
44
44
  Unassigned: bcs.Address,
45
45
  /** Track has been assigned to its target release. */
@@ -63,14 +63,18 @@ export const Track = new MoveStruct({ name: `${$moduleName}::Track`, fields: {
63
63
  split_bps: bps.BPS
64
64
  } });
65
65
  export interface NewArguments {
66
- deal: RawTransactionArgument<string>;
66
+ _: RawTransactionArgument<string>;
67
67
  recording: RawTransactionArgument<string>;
68
+ targetReleaseId: RawTransactionArgument<string>;
69
+ trackSplitBpsValue: RawTransactionArgument<number>;
68
70
  }
69
71
  export interface NewOptions {
70
72
  package?: string;
71
73
  arguments: NewArguments | [
72
- deal: RawTransactionArgument<string>,
73
- recording: RawTransactionArgument<string>
74
+ _: RawTransactionArgument<string>,
75
+ recording: RawTransactionArgument<string>,
76
+ targetReleaseId: RawTransactionArgument<string>,
77
+ trackSplitBpsValue: RawTransactionArgument<number>
74
78
  ];
75
79
  typeArguments: [
76
80
  string,
@@ -78,25 +82,52 @@ export interface NewOptions {
78
82
  ];
79
83
  }
80
84
  /**
81
- * Creates a new track by accepting a deal. The deal is the authorization — created
82
- * by the recording's admin, carrying the target release and the agreed split.
83
- * Emits a `DealAcceptedEvent`.
85
+ * Creates a new track: the recording admin's consent to that recording's inclusion
86
+ * in a specific future release with an agreed split. Requires the recording admin
87
+ * capability. No event: a `Track` has `drop` and is not an object, so a creation
88
+ * event could announce a consent that is then silently discarded, and indexers
89
+ * would be unable to distinguish pending from dead. Pre-publish observability is
90
+ * the responsibility of whatever wraps the track (see below).
84
91
  *
85
- * The deal's `RecordingShare`/`CompositionShare` phantoms are erased here: a
86
- * `Track` is monomorphic so it can live in a release's heterogeneous
87
- * `vector<Track>`. Identity rides on those phantoms up to this point, but the
88
- * monomorphic `Track` must store the recording's _address_ for revenue routing —
89
- * and an address can't come from a phantom. So the matching `Recording` is passed
90
- * in (the deal's phantoms force it to be the right one) purely to read its id; the
91
- * deal no longer stores it.
92
+ * The composition is identified by the recording's `CompositionShare` phantom, so
93
+ * the recording↔composition pairing is compile-time enforced there is no
94
+ * `Composition` argument and no runtime ID check.
95
+ *
96
+ * ### What creating a track consents to
97
+ *
98
+ * `target_release_id` is derived from the release digest, so targeting it consents
99
+ * to that release's exact economics and membership: the ordered list of
100
+ * `(recording, split)` pairs and the creator's nonce, nothing more. The release's
101
+ * title, artwork, credits, and display grouping are chosen by the release creator
102
+ * — before or after this track is created — and are not bound by the digest.
103
+ * Presentation is trusted and publicly attributable, not cryptographically
104
+ * committed.
105
+ *
106
+ * The recording need not be `Published`: its admin can create tracks inside the
107
+ * recording's own creating transaction (an `Initialized` recording cannot escape
108
+ * that transaction, so across transactions tracks always reference `Published`,
109
+ * shared recordings).
110
+ *
111
+ * A `Track` has `store`, not `key`: it carries no identity of its own, so it may
112
+ * be exercised synchronously in the same transaction that creates it, or handed to
113
+ * an offer extension that wraps it in a real object with its own identity.
114
+ * Withdrawal, expiry, and rejection are then whatever that wrapping extension
115
+ * encodes — visible in its type, not in core.
116
+ *
117
+ * `recording` compile-time-binds the `RecordingShare`/`CompositionShare` phantom
118
+ * pairing, and is read for its id: the monomorphic `Track` must store the
119
+ * recording's _address_ for revenue routing, and an address cannot come from a
120
+ * phantom.
92
121
  */
93
122
  export function _new(options: NewOptions) {
94
123
  const packageAddress = options.package ?? '@local-pkg/miso';
95
124
  const argumentsTypes = [
96
125
  null,
97
- null
126
+ null,
127
+ '0x2::object::ID',
128
+ 'u16'
98
129
  ] satisfies (string | null)[];
99
- const parameterNames = ["deal", "recording"];
130
+ const parameterNames = ["_", "recording", "targetReleaseId", "trackSplitBpsValue"];
100
131
  return (tx: Transaction) => tx.moveCall({
101
132
  package: packageAddress,
102
133
  module: 'track',
@@ -150,4 +181,31 @@ export function splitBps(options: SplitBpsOptions) {
150
181
  function: 'split_bps',
151
182
  arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
152
183
  });
184
+ }
185
+ export interface TargetReleaseIdArguments {
186
+ self: TransactionArgument;
187
+ }
188
+ export interface TargetReleaseIdOptions {
189
+ package?: string;
190
+ arguments: TargetReleaseIdArguments | [
191
+ self: TransactionArgument
192
+ ];
193
+ }
194
+ /**
195
+ * Returns the target release id this track's creator consented to. Aborts if the
196
+ * track is `Assigned`: an assigned track only exists inside a published release,
197
+ * so its release is the object you fetched it from.
198
+ */
199
+ export function targetReleaseId(options: TargetReleaseIdOptions) {
200
+ const packageAddress = options.package ?? '@local-pkg/miso';
201
+ const argumentsTypes = [
202
+ null
203
+ ] satisfies (string | null)[];
204
+ const parameterNames = ["self"];
205
+ return (tx: Transaction) => tx.moveCall({
206
+ package: packageAddress,
207
+ module: 'track',
208
+ function: 'target_release_id',
209
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
210
+ });
153
211
  }