@misonetwork/sdk 0.4.0 → 0.5.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 +97 -503
  2. package/dist/client.d.ts +3 -55
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +1 -52
  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/internal.d.ts +0 -7
  23. package/dist/internal.d.ts.map +1 -1
  24. package/dist/internal.js +0 -22
  25. package/dist/internal.js.map +1 -1
  26. package/dist/parsers.d.ts +1 -4
  27. package/dist/parsers.d.ts.map +1 -1
  28. package/dist/parsers.js +0 -24
  29. package/dist/parsers.js.map +1 -1
  30. package/dist/queries.d.ts +2 -5
  31. package/dist/queries.d.ts.map +1 -1
  32. package/dist/queries.js +8 -45
  33. package/dist/queries.js.map +1 -1
  34. package/dist/transactions.d.ts +10 -71
  35. package/dist/transactions.d.ts.map +1 -1
  36. package/dist/transactions.js +15 -72
  37. package/dist/transactions.js.map +1 -1
  38. package/dist/types.d.ts +3 -40
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/view.d.ts +7 -7
  41. package/dist/view.d.ts.map +1 -1
  42. package/dist/view.js +9 -9
  43. package/dist/view.js.map +1 -1
  44. package/package.json +4 -4
  45. package/src/client.ts +3 -78
  46. package/src/contracts/miso/release.ts +39 -36
  47. package/src/contracts/miso/track.ts +81 -23
  48. package/src/contracts/utils/index.ts +156 -4
  49. package/src/contracts.ts +0 -1
  50. package/src/internal.ts +0 -24
  51. package/src/parsers.ts +0 -35
  52. package/src/queries.ts +11 -59
  53. package/src/transactions.ts +20 -112
  54. package/src/types.ts +3 -53
  55. package/src/view.ts +13 -13
  56. package/dist/contracts/miso/deal.d.ts +0 -184
  57. package/dist/contracts/miso/deal.d.ts.map +0 -1
  58. package/dist/contracts/miso/deal.js +0 -184
  59. package/dist/contracts/miso/deal.js.map +0 -1
  60. package/src/contracts/miso/deal.ts +0 -257
@@ -8,7 +8,7 @@ import {
8
8
  BcsEnum,
9
9
  BcsTuple,
10
10
  } from '@mysten/sui/bcs';
11
- import { normalizeSuiAddress } from '@mysten/sui/utils';
11
+ import { normalizeStructTag, normalizeSuiAddress } from '@mysten/sui/utils';
12
12
  import { type TransactionArgument, isArgument } from '@mysten/sui/transactions';
13
13
  import { type ClientWithCoreApi, type SuiClientTypes } from '@mysten/sui/client';
14
14
 
@@ -158,10 +158,140 @@ export function normalizeMoveArguments(
158
158
  return normalizedArgs;
159
159
  }
160
160
 
161
+ /* -------------------------- Move type tags -------------------------- */
162
+
163
+ /** A type argument: a type tag string, or a BCS type whose name is a Move type. */
164
+ export type TypeArgument = string | BcsType<any>;
165
+
166
+ export interface TypeTagOptions {
167
+ package?: string;
168
+ typeArguments?: readonly TypeArgument[];
169
+ }
170
+
171
+ /**
172
+ * `typeArguments` is required when the type's name contains unfilled
173
+ * `phantom X` parameters (at any depth). Everything else — argument arity,
174
+ * position contents, and tag validity — is validated at runtime.
175
+ */
176
+ type TypeTagParams<Name extends string> = Name extends `${string}phantom ${string}`
177
+ ? [options: TypeTagOptions & { typeArguments: readonly TypeArgument[] }]
178
+ : [options?: TypeTagOptions];
179
+
180
+ type ResolveTypeTagOptions<Name extends string> = { client: ClientWithCoreApi } & (
181
+ Name extends `${string}phantom ${string}`
182
+ ? TypeTagOptions & { typeArguments: readonly TypeArgument[] }
183
+ : TypeTagOptions
184
+ );
185
+
186
+ const HAS_PHANTOM_REGEX = /phantom [A-Za-z_$][A-Za-z0-9_$]*/;
187
+
188
+ function splitTopLevelTypeArgs(inner: string): string[] {
189
+ const parts: string[] = [];
190
+ let depth = 0;
191
+ let current = '';
192
+ for (const char of inner) {
193
+ if (char === ',' && depth === 0) {
194
+ parts.push(current.trim());
195
+ current = '';
196
+ continue;
197
+ }
198
+ if (char === '<') depth++;
199
+ if (char === '>') depth--;
200
+ current += char;
201
+ }
202
+ if (current) parts.push(current.trim());
203
+ return parts;
204
+ }
205
+
206
+ function buildTypeTag(name: string, options: TypeTagOptions | undefined): string {
207
+ const lt = name.indexOf('<');
208
+ const base = lt === -1 ? name : name.slice(0, lt);
209
+
210
+ if (base.split('::').length !== 3) {
211
+ throw new Error(`${name} is not a top-level Move type`);
212
+ }
213
+
214
+ let result = name;
215
+
216
+ if (options?.typeArguments) {
217
+ const baked = lt === -1 ? [] : splitTopLevelTypeArgs(name.slice(lt + 1, -1));
218
+ const supplied = options.typeArguments.map((arg) => {
219
+ if (typeof arg === 'string') {
220
+ return arg;
221
+ }
222
+ if (arg && typeof arg.serialize === 'function' && typeof arg.name === 'string') {
223
+ return arg.name;
224
+ }
225
+ throw new Error(`Invalid type argument ${stringify(arg)}`);
226
+ });
227
+
228
+ if (supplied.length !== baked.length) {
229
+ throw new Error(
230
+ `Expected ${baked.length} type arguments for ${base}, got ${supplied.length}`,
231
+ );
232
+ }
233
+
234
+ result = supplied.length === 0 ? base : `${base}<${supplied.join(', ')}>`;
235
+ }
236
+
237
+ if (HAS_PHANTOM_REGEX.test(result)) {
238
+ throw new Error(
239
+ options?.typeArguments
240
+ ? `A type argument contains an unfilled phantom parameter in ${result}`
241
+ : `Missing type arguments for ${result}`,
242
+ );
243
+ }
244
+
245
+ if (options?.package) {
246
+ const [, ...rest] = result.split('::');
247
+ result = [options.package, ...rest].join('::');
248
+ }
249
+
250
+ // fully validate address-only tags (MVR names can't be parsed as type tags)
251
+ if (!HAS_PHANTOM_REGEX.test(result) && !/[@/]/.test(result)) {
252
+ TypeTagSerializer.parseFromStr(result);
253
+ }
254
+
255
+ return result;
256
+ }
257
+
258
+ async function resolveBuiltTypeTag(
259
+ name: string,
260
+ options: { client: ClientWithCoreApi } & TypeTagOptions,
261
+ ): Promise<string> {
262
+ const { client, ...rest } = options;
263
+ const { type } = await client.core.mvr.resolveType({
264
+ type: buildTypeTag(name, rest),
265
+ });
266
+ return normalizeStructTag(type);
267
+ }
268
+
161
269
  export class MoveStruct<
162
270
  T extends Record<string, BcsType<any>>,
163
271
  const Name extends string = string,
164
272
  > extends BcsStruct<T, Name> {
273
+ /**
274
+ * Build the type tag for this struct.
275
+ *
276
+ * `typeArguments` is the full positional list, in Move declaration order, and
277
+ * is required when the struct has unfilled phantom parameters. The result may
278
+ * contain MVR names: those are valid in transaction `typeArguments`, but for
279
+ * queries or comparisons against on-chain data use `resolveTypeTag` instead.
280
+ */
281
+ typeTag(...args: TypeTagParams<Name>): string {
282
+ return buildTypeTag(this.name, args[0] as TypeTagOptions | undefined);
283
+ }
284
+
285
+ /**
286
+ * Build the type tag for this struct, then resolve any MVR names through the
287
+ * client (using its configured overrides and the MVR API) and return the
288
+ * normalized, address-only form suitable for queries and comparisons against
289
+ * on-chain data.
290
+ */
291
+ async resolveTypeTag(options: ResolveTypeTagOptions<Name>): Promise<string> {
292
+ return resolveBuiltTypeTag(this.name, options as { client: ClientWithCoreApi } & TypeTagOptions);
293
+ }
294
+
165
295
  async get<Include extends Omit<SuiClientTypes.ObjectInclude, 'content' | 'json'> = {}>({
166
296
  objectId,
167
297
  ...options
@@ -210,16 +340,38 @@ export class MoveStruct<
210
340
  export class MoveEnum<
211
341
  T extends Record<string, BcsType<any> | null>,
212
342
  const Name extends string,
213
- > extends BcsEnum<T, Name> {}
343
+ > extends BcsEnum<T, Name> {
344
+ /** Build the type tag for this enum. See `MoveStruct.typeTag` for semantics. */
345
+ typeTag(...args: TypeTagParams<Name>): string {
346
+ return buildTypeTag(this.name, args[0] as TypeTagOptions | undefined);
347
+ }
348
+
349
+ /** Build and resolve the type tag for this enum. See `MoveStruct.resolveTypeTag`. */
350
+ async resolveTypeTag(options: ResolveTypeTagOptions<Name>): Promise<string> {
351
+ return resolveBuiltTypeTag(this.name, options as { client: ClientWithCoreApi } & TypeTagOptions);
352
+ }
353
+ }
214
354
 
215
355
  export class MoveTuple<
216
356
  const T extends readonly BcsType<any>[],
217
357
  const Name extends string,
218
- > extends BcsTuple<T, Name> {}
358
+ > extends BcsTuple<T, Name> {
359
+ /** Build the type tag for this struct. See `MoveStruct.typeTag` for semantics. */
360
+ typeTag(...args: TypeTagParams<Name>): string {
361
+ return buildTypeTag(this.name, args[0] as TypeTagOptions | undefined);
362
+ }
363
+
364
+ /** Build and resolve the type tag for this struct. See `MoveStruct.resolveTypeTag`. */
365
+ async resolveTypeTag(options: ResolveTypeTagOptions<Name>): Promise<string> {
366
+ return resolveBuiltTypeTag(this.name, options as { client: ClientWithCoreApi } & TypeTagOptions);
367
+ }
368
+ }
219
369
 
220
370
  function stringify(val: unknown) {
221
371
  if (typeof val === 'object') {
222
- return JSON.stringify(val, (val: unknown) => val);
372
+ return JSON.stringify(val, (_key, value) =>
373
+ typeof value === 'bigint' ? value.toString() : value,
374
+ );
223
375
  }
224
376
  if (typeof val === 'bigint') {
225
377
  return val.toString();
package/src/contracts.ts CHANGED
@@ -10,5 +10,4 @@
10
10
  export * as composition from "./contracts/miso/composition.ts";
11
11
  export * as recording from "./contracts/miso/recording.ts";
12
12
  export * as release from "./contracts/miso/release.ts";
13
- export * as deal from "./contracts/miso/deal.ts";
14
13
  export * as track from "./contracts/miso/track.ts";
package/src/internal.ts CHANGED
@@ -78,27 +78,3 @@ export function mapRelease(id: string, d: Parsed): ReleaseType {
78
78
  tracks: (d.tracks ?? []).map(mapTrack),
79
79
  };
80
80
  }
81
-
82
- /**
83
- * Maps the deployed disc-based Release JSON shape to the SDK's flat Release
84
- * view. The current protocol source stores `tracks` directly, while the
85
- * existing testnet package stores `discs`; both represent one ordered
86
- * tracklist to SDK consumers.
87
- */
88
- export function mapDiscReleaseJson(id: string, d: Parsed): ReleaseType {
89
- const tracks = (d.discs ?? []).flatMap((disc: Parsed) => disc.tracks ?? []);
90
- const publishedAt = d.state?.["@variant"] === "Published" ? d.state.pos0 : null;
91
- return {
92
- id,
93
- state:
94
- publishedAt == null
95
- ? { type: "Initialized" }
96
- : { type: "Published", timestampMs: Number(publishedAt) },
97
- title: d.title,
98
- tracks: tracks.map((track: Parsed) => ({
99
- state: (track.state?.["@variant"] ?? "Unassigned") as TrackState,
100
- recordingId: track.recording_id,
101
- splitBps: { value: Number(track.split_bps?.pos0 ?? track.split_bps) },
102
- })),
103
- };
104
- }
package/src/parsers.ts CHANGED
@@ -11,19 +11,11 @@ import {
11
11
  } from "./contracts/miso/composition.ts";
12
12
  import { RecordingPublishedEvent as RecordingPublishedEventBcs } from "./contracts/miso/recording.ts";
13
13
  import { ReleasePublishedEvent as ReleasePublishedEventBcs } from "./contracts/miso/release.ts";
14
- import {
15
- DealCreatedEvent as DealCreatedEventBcs,
16
- DealAcceptedEvent as DealAcceptedEventBcs,
17
- DealRejectedEvent as DealRejectedEventBcs,
18
- } from "./contracts/miso/deal.ts";
19
14
  import type {
20
15
  CompositionPublishedEvent,
21
16
  CompositionRoyaltySetEvent,
22
17
  RecordingPublishedEvent,
23
18
  ReleasePublishedEvent,
24
- DealCreatedEvent,
25
- DealAcceptedEvent,
26
- DealRejectedEvent,
27
19
  } from "./types.ts";
28
20
 
29
21
  // === Composition ===
@@ -51,30 +43,3 @@ export function parseReleasePublishedEvent(bytes: Uint8Array): ReleasePublishedE
51
43
  const e = ReleasePublishedEventBcs.parse(bytes);
52
44
  return { releaseId: e.release_id };
53
45
  }
54
-
55
- // === Deal ===
56
-
57
- export function parseDealCreatedEvent(bytes: Uint8Array): DealCreatedEvent {
58
- const e = DealCreatedEventBcs.parse(bytes);
59
- return {
60
- dealId: e.deal_id,
61
- releaseId: e.release_id,
62
- trackSplitBps: { value: e.track_split_bps_value },
63
- };
64
- }
65
-
66
- export function parseDealAcceptedEvent(bytes: Uint8Array): DealAcceptedEvent {
67
- const e = DealAcceptedEventBcs.parse(bytes);
68
- return {
69
- dealId: e.deal_id,
70
- releaseId: e.release_id,
71
- };
72
- }
73
-
74
- export function parseDealRejectedEvent(bytes: Uint8Array): DealRejectedEvent {
75
- const e = DealRejectedEventBcs.parse(bytes);
76
- return {
77
- dealId: e.deal_id,
78
- releaseId: e.release_id,
79
- };
80
- }
package/src/queries.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  // uses GraphQL to find object addresses, then reads them through the Core path.
8
8
  //
9
9
  // Missing-object convention (null vs throw):
10
- // - Core-object getters in this module (`getCompositionById`, `getDealById`,
10
+ // - Core-object getters in this module (`getCompositionById`,
11
11
  // `get*AdminCapById`, …) THROW when the object is missing. Callers pass ids
12
12
  // they obtained from the chain, so a miss means a broken reference — an
13
13
  // exceptional state, not a normal one.
@@ -25,20 +25,17 @@ import { graphql } from "@mysten/sui/graphql/schema";
25
25
  import { deriveObjectID, normalizeSuiAddress } from "@mysten/sui/utils";
26
26
 
27
27
  import { Composition as CompositionBcs } from "./contracts/miso/composition.ts";
28
- import { Deal as DealBcs } from "./contracts/miso/deal.ts";
29
28
  import { Recording as RecordingBcs } from "./contracts/miso/recording.ts";
30
29
  import { Release as ReleaseBcs } from "./contracts/miso/release.ts";
31
30
  import {
32
31
  mapBps,
33
32
  mapComposition,
34
- mapDiscReleaseJson,
35
33
  mapRecording,
36
34
  mapRelease,
37
35
  } from "./internal.ts";
38
36
  import type {
39
37
  Composition,
40
38
  CompositionAdminCap,
41
- Deal,
42
39
  Recording,
43
40
  RecordingAdminCap,
44
41
  Release,
@@ -345,7 +342,7 @@ export async function getWorksByIds(
345
342
 
346
343
  const { objects } = await client.core.getObjects({
347
344
  objectIds: [...kinds.keys()],
348
- include: { content: true, json: true },
345
+ include: { content: true },
349
346
  });
350
347
  for (const obj of objects) {
351
348
  if (obj instanceof Error || !obj.content) continue;
@@ -361,10 +358,10 @@ export async function getWorksByIds(
361
358
  RecordingBcs.parse(obj.content),
362
359
  );
363
360
  } else if (kind === "releases") {
364
- const json = obj.json as { discs?: unknown[] } | null;
365
- out.releases[obj.objectId] = json?.discs
366
- ? mapDiscReleaseJson(obj.objectId, json)
367
- : mapRelease(obj.objectId, ReleaseBcs.parse(obj.content));
361
+ out.releases[obj.objectId] = mapRelease(
362
+ obj.objectId,
363
+ ReleaseBcs.parse(obj.content),
364
+ );
368
365
  }
369
366
  }
370
367
  return out;
@@ -543,7 +540,7 @@ export async function getRecordingShareType(
543
540
 
544
541
  /**
545
542
  * Both of a recording's share types, as `[RecordingShare, CompositionShare]`.
546
- * Most builders need the pair — `deal::new`, `track::new`, `recording::publish`
543
+ * Most builders need the pair — `track::new`, `recording::publish`
547
544
  * and the recording credit/pool extensions are all generic over both, in this
548
545
  * order.
549
546
  */
@@ -616,33 +613,6 @@ export function deriveRecordingAdminCapId(
616
613
  );
617
614
  }
618
615
 
619
- // ============================================================================
620
- // Deal
621
- // ============================================================================
622
-
623
- /** Fetches a deal by its object ID (share types read from the type parameters). */
624
- export async function getDealById(
625
- client: ClientWithCoreApi,
626
- dealId: string,
627
- ): Promise<Deal> {
628
- const { object } = await client.core.getObject({
629
- objectId: dealId,
630
- include: { content: true },
631
- });
632
- if (!object.content) throw new Error(`Deal not found: ${dealId}`);
633
- const d = DealBcs.parse(object.content);
634
- const [recordingShareType, compositionShareType] = extractTypeParams2(
635
- object.type,
636
- );
637
- return {
638
- id: dealId,
639
- releaseId: d.release_id,
640
- trackSplitBps: mapBps(d.track_split_bps),
641
- recordingShareType,
642
- compositionShareType,
643
- };
644
- }
645
-
646
616
  // ============================================================================
647
617
  // Release
648
618
  // ============================================================================
@@ -654,15 +624,12 @@ export async function getReleasesByIds(
654
624
  if (releaseIds.length === 0) return {};
655
625
  const { objects } = await client.core.getObjects({
656
626
  objectIds: releaseIds,
657
- include: { content: true, json: true },
627
+ include: { content: true },
658
628
  });
659
629
  const out: Record<string, Release> = {};
660
630
  for (const obj of objects) {
661
631
  if (obj instanceof Error || !obj.content) continue;
662
- const json = obj.json as { discs?: unknown[] } | null;
663
- out[obj.objectId] = json?.discs
664
- ? mapDiscReleaseJson(obj.objectId, json)
665
- : mapRelease(obj.objectId, ReleaseBcs.parse(obj.content));
632
+ out[obj.objectId] = mapRelease(obj.objectId, ReleaseBcs.parse(obj.content));
666
633
  }
667
634
  return out;
668
635
  }
@@ -673,25 +640,10 @@ export async function getReleaseById(
673
640
  ): Promise<Release> {
674
641
  const { object } = await client.core.getObject({
675
642
  objectId: releaseId,
676
- include: { content: true, json: true },
643
+ include: { content: true },
677
644
  });
678
645
  if (!object.content) throw new Error(`Release not found: ${releaseId}`);
679
- const json = object.json as { discs?: unknown[] } | null;
680
- return json?.discs
681
- ? mapDiscReleaseJson(releaseId, json)
682
- : mapRelease(releaseId, ReleaseBcs.parse(object.content));
683
- }
684
-
685
- export async function getReleaseRegistry(
686
- client: SuiGraphQLClient,
687
- misoPackageId: string,
688
- ): Promise<string> {
689
- const address = await firstAddressOfType(
690
- client,
691
- `${misoPackageId}::release::ReleaseRegistry`,
692
- );
693
- if (!address) throw new Error("ReleaseRegistry not found");
694
- return address;
646
+ return mapRelease(releaseId, ReleaseBcs.parse(object.content));
695
647
  }
696
648
 
697
649
  export async function getReleaseAdminCapById(
@@ -2,18 +2,17 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  // Transaction builders. Every builder adds commands to a caller-owned
5
- // `Transaction`, so flows compose in a single PTB, but they come in two shapes.
5
+ // `Transaction`, so flows compose in a single PTB.
6
6
  // The `create*` primitives take the `Transaction` as their FIRST argument and
7
7
  // return their by-value results, so those results can be threaded into later
8
- // commands. `rejectDeal` has nothing to hand back, so it keeps the Sui SDK
9
- // thunk shape: `(params) => (tx: Transaction) => …`. Miso calls go through the
10
- // codegen-generated, type-safe call functions.
8
+ // commands. Miso calls go through the codegen-generated, type-safe call
9
+ // functions.
11
10
  //
12
11
  // This module keeps the bare protocol PRIMITIVES only. The rule is: do the
13
12
  // minimum the Move semantics FORCE, and return anything the caller could
14
13
  // legitimately route elsewhere.
15
14
  //
16
- // `createComposition`, `createRecording`, and `createRelease` each append a
15
+ // `createComposition` and `createRecording` each append a
17
16
  // single `::new` and hand back its by-value results — never dispersing a share
18
17
  // supply, publishing (sharing) the object, or routing an admin cap.
19
18
  //
@@ -28,7 +27,7 @@
28
27
  //
29
28
  // The opinionated layers — track assembly, cap disposition, minato dispersal,
30
29
  // the share-currency lifecycle — live in `@misofm/sdk`
31
- // (`publishRelease`/`publishReleaseFromDeals`/`publishReleaseGraph`,
30
+ // (`release_registry::new_release`, `publishRelease`/`publishReleaseGraph`,
32
31
  // `finalizeComposition`/`finalizeRecording`/`finalizeRelease`,
33
32
  // `publishComposition`/`publishRecording`/`publishCompositionAndRecording`,
34
33
  // `share.ts`) as free functions taking `misoPackageId` explicitly. Those import
@@ -39,8 +38,7 @@ import { Transaction, type TransactionObjectArgument } from "@mysten/sui/transac
39
38
 
40
39
  import * as composition from "./contracts/miso/composition.ts";
41
40
  import * as recording from "./contracts/miso/recording.ts";
42
- import * as deal from "./contracts/miso/deal.ts";
43
- import * as release from "./contracts/miso/release.ts";
41
+ import * as track from "./contracts/miso/track.ts";
44
42
 
45
43
  /** A thunk that adds commands to a transaction. May be async (resolves at build time). */
46
44
  export type TxThunk = (tx: Transaction) => void | Promise<void>;
@@ -153,138 +151,48 @@ export function createRecording(tx: Transaction, params: CreateRecordingParams):
153
151
  }
154
152
 
155
153
  // ============================================================================
156
- // Deal
154
+ // Track
157
155
  // ============================================================================
158
156
 
159
- export interface CreateDealParams {
157
+ export interface CreateTrackParams {
160
158
  recordingId: string;
161
159
  recordingAdminCapId?: string;
162
160
  recordingAdminCap?: TransactionObjectArgument;
163
- /** Share type of the recording (the deal's `RecordingShare` phantom). */
161
+ /** Share type of the recording (the track's `RecordingShare` phantom). */
164
162
  recordingShareType: string;
165
- /** Share type of the parent composition (the deal's `CompositionShare` phantom). */
163
+ /** Share type of the parent composition (the track's `CompositionShare` phantom). */
166
164
  compositionShareType: string;
167
- releaseId: string;
165
+ targetReleaseId: string;
168
166
  trackSplitBps: number;
169
167
  misoPackageId: string;
170
168
  }
171
169
 
172
170
  /**
173
- * PRIMITIVE. Appends `deal::new` and returns the `Deal` by value without routing
174
- * it anywhere the caller decides what happens next.
175
- *
176
- * LIFECYCLE NOTE the returned `Deal` MUST be consumed in this same
177
- * transaction. It is `key, store` with no `drop`, so it cannot be discarded, but
178
- * it CAN go to either of two places, which is exactly why this does not choose:
179
- *
180
- * 1. `tx.transferObjects([deal], recipient)` — send it to whoever is
181
- * assembling the release, for them to redeem later. This is the
182
- * cross-party flow: a recording owner signs a deal for someone else's
183
- * release.
184
- * 2. straight into `track::new(deal, &recording)` in this same PTB — the
185
- * same-party flow, where the deal is a transient authorization rather than
186
- * something anyone holds. `@misofm/sdk`'s `publishReleaseGraph` does this.
187
- *
188
- * Both are legitimate, and picking one for the caller would make the other
189
- * awkward, so the disposition stays with the caller. `@misofm/sdk` layers the
190
- * opinionated flows on top.
171
+ * PRIMITIVE. Appends `track::new` and returns its by-value `Track`. A track has
172
+ * `drop, store`, so callers may leave it unused; to assemble a release, pass
173
+ * returned tracks to `tx.makeMoveVec({ type: `${misoPackageId}::track::Track`,
174
+ * elements })` and then call `release_registry::new_release` from `@misofm/sdk`.
191
175
  *
192
176
  * The `recordingAdminCap` may be passed as an on-chain object id
193
177
  * (`recordingAdminCapId`) or as a PTB-local argument (`recordingAdminCap`) —
194
- * the latter lets a deal be signed against a recording created earlier in the
178
+ * the latter lets a track be created against a recording created earlier in the
195
179
  * same transaction, before its cap has been transferred anywhere.
196
180
  */
197
- export function createDeal(tx: Transaction, params: CreateDealParams): TransactionObjectArgument {
181
+ export function createTrack(tx: Transaction, params: CreateTrackParams): TransactionObjectArgument {
198
182
  if (!params.recordingAdminCap && !params.recordingAdminCapId) {
199
- throw new Error("createDeal: recordingAdminCapId or recordingAdminCap required");
183
+ throw new Error("createTrack: recordingAdminCapId or recordingAdminCap required");
200
184
  }
201
185
  const adminCapArg = params.recordingAdminCap ?? tx.object(params.recordingAdminCapId!);
202
186
  return tx.add(
203
- deal._new({
187
+ track._new({
204
188
  package: params.misoPackageId,
205
189
  typeArguments: [params.recordingShareType, params.compositionShareType],
206
190
  arguments: [
207
191
  adminCapArg,
208
192
  tx.object(params.recordingId),
209
- tx.pure.id(params.releaseId),
193
+ tx.pure.id(params.targetReleaseId),
210
194
  tx.pure.u16(params.trackSplitBps),
211
195
  ],
212
196
  }),
213
197
  );
214
198
  }
215
-
216
- export interface RejectDealParams {
217
- dealId: string;
218
- /** Share type of the recording (the deal's `RecordingShare` phantom). */
219
- recordingShareType: string;
220
- /** Share type of the parent composition (the deal's `CompositionShare` phantom). */
221
- compositionShareType: string;
222
- misoPackageId: string;
223
- }
224
-
225
- /** Rejects (destroys) a deal without including it in a release. Emits `DealRejectedEvent`. */
226
- export function rejectDeal(params: RejectDealParams): TxThunk {
227
- return (tx) => {
228
- tx.add(deal.reject({
229
- package: params.misoPackageId,
230
- typeArguments: [params.recordingShareType, params.compositionShareType],
231
- arguments: [tx.object(params.dealId)],
232
- }));
233
- };
234
- }
235
-
236
- // ============================================================================
237
- // Release
238
- // ============================================================================
239
-
240
- /** The two by-value results of `release::new`, for threading onward in a PTB. */
241
- export interface ReleaseParts {
242
- release: TransactionObjectArgument;
243
- adminCap: TransactionObjectArgument;
244
- }
245
-
246
- export interface CreateReleaseParams {
247
- title: string;
248
- /** u256 nonce as a decimal string (deterministic release id). */
249
- nonce: string;
250
- releaseRegistryId: string;
251
- misoPackageId: string;
252
- }
253
-
254
- /**
255
- * PRIMITIVE. Appends `release::new` over a caller-built `vector<Track>` and
256
- * returns its by-value results without publishing (sharing) the release or
257
- * routing the admin cap — the caller decides what happens next. Mirrors
258
- * {@link createComposition}/{@link createRecording}.
259
- *
260
- * `trackVec` is supplied by the caller because track assembly is the part that
261
- * genuinely varies between release flows: from recording admin caps, from
262
- * pre-made deals, or from a mix of fresh and existing recordings (see
263
- * `@misofm/sdk`'s `publishRelease`/`publishReleaseFromDeals`/
264
- * `publishReleaseGraph`).
265
- *
266
- * LIFECYCLE NOTE — the returned `Release` MUST be consumed by
267
- * `release::publish` in this same transaction. `Release` is `key`-only with no
268
- * `drop`, and `publish` is its only by-value consumer, so an `Initialized`
269
- * release cannot be transferred, wrapped, shared, or discarded, and cannot
270
- * outlive its creating transaction; the protocol deliberately provides no keep
271
- * function. That is a same-PTB requirement, NOT a same-function one — pairing
272
- * this with a later `finalizeRelease` command in the same `tx` satisfies it.
273
- * (`Composition` and `Recording` carry the identical requirement, which is why
274
- * all three primitives have the same shape.) The admin cap has no such
275
- * constraint: `ReleaseAdminCap` is `key, store` and `publish` only borrows it,
276
- * so it is an ordinary transferable value the caller routes as it sees fit.
277
- */
278
- export function createRelease(
279
- tx: Transaction,
280
- params: CreateReleaseParams,
281
- trackVec: TransactionObjectArgument,
282
- ): ReleaseParts {
283
- const result = tx.add(
284
- release._new({
285
- package: params.misoPackageId,
286
- arguments: [tx.pure.string(params.title), trackVec, tx.pure.u256(BigInt(params.nonce)), tx.object(params.releaseRegistryId)],
287
- }),
288
- );
289
- return { release: result[0]!, adminCap: result[1]! };
290
- }