@misonetwork/sdk 0.5.0 → 0.7.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 (51) hide show
  1. package/README.md +23 -4
  2. package/dist/client.d.ts +24 -13
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +25 -8
  5. package/dist/client.js.map +1 -1
  6. package/dist/contracts/miso/composition.d.ts +16 -38
  7. package/dist/contracts/miso/composition.d.ts.map +1 -1
  8. package/dist/contracts/miso/composition.js +16 -37
  9. package/dist/contracts/miso/composition.js.map +1 -1
  10. package/dist/contracts/miso/recording.d.ts +43 -18
  11. package/dist/contracts/miso/recording.d.ts.map +1 -1
  12. package/dist/contracts/miso/recording.js +45 -19
  13. package/dist/contracts/miso/recording.js.map +1 -1
  14. package/dist/contracts/miso/release.d.ts +2 -0
  15. package/dist/contracts/miso/release.d.ts.map +1 -1
  16. package/dist/contracts/miso/track.d.ts +39 -8
  17. package/dist/contracts/miso/track.d.ts.map +1 -1
  18. package/dist/contracts/miso/track.js +42 -8
  19. package/dist/contracts/miso/track.js.map +1 -1
  20. package/dist/deployments.d.ts +21 -0
  21. package/dist/deployments.d.ts.map +1 -0
  22. package/dist/deployments.js +17 -0
  23. package/dist/deployments.js.map +1 -0
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/internal.d.ts.map +1 -1
  29. package/dist/internal.js +2 -0
  30. package/dist/internal.js.map +1 -1
  31. package/dist/parsers.d.ts +1 -2
  32. package/dist/parsers.d.ts.map +1 -1
  33. package/dist/parsers.js +1 -5
  34. package/dist/parsers.js.map +1 -1
  35. package/dist/transactions.d.ts +0 -9
  36. package/dist/transactions.d.ts.map +1 -1
  37. package/dist/transactions.js +1 -3
  38. package/dist/transactions.js.map +1 -1
  39. package/dist/types.d.ts +17 -8
  40. package/dist/types.d.ts.map +1 -1
  41. package/package.json +5 -1
  42. package/src/client.ts +46 -12
  43. package/src/contracts/miso/composition.ts +16 -53
  44. package/src/contracts/miso/recording.ts +59 -22
  45. package/src/contracts/miso/track.ts +51 -8
  46. package/src/deployments.ts +42 -0
  47. package/src/index.ts +1 -0
  48. package/src/internal.ts +2 -0
  49. package/src/parsers.ts +1 -10
  50. package/src/transactions.ts +1 -11
  51. package/src/types.ts +17 -9
package/dist/types.d.ts CHANGED
@@ -25,7 +25,10 @@ export interface Composition {
25
25
  state: CompositionState;
26
26
  /** Primary title of the composition. */
27
27
  title: string;
28
- /** Royalty rate this composition earns from each recording's revenue (basis points, 0-2000). */
28
+ /**
29
+ * Royalty rate this composition earns from each recording's revenue (basis
30
+ * points, 0-10000). Immutable for the composition's lifetime.
31
+ */
29
32
  royaltyRate: BPS;
30
33
  }
31
34
  /**
@@ -36,13 +39,6 @@ export interface Composition {
36
39
  export interface CompositionPublishedEvent {
37
40
  compositionId: string;
38
41
  }
39
- /**
40
- * Emitted when a composition's royalty rate is set or changed. The composition
41
- * is identified by the event's `CompositionShare` phantom type, not a field.
42
- */
43
- export interface CompositionRoyaltySetEvent {
44
- royaltyRateBps: number;
45
- }
46
42
  /**
47
43
  * Admin cap for a Composition, derived deterministically from the Composition object ID.
48
44
  *
@@ -80,6 +76,12 @@ export interface Recording {
80
76
  id: string;
81
77
  /** Current lifecycle state. */
82
78
  state: RecordingState;
79
+ /**
80
+ * Object ID of the parent composition. An identity/membership handle — not a
81
+ * revenue routing target: the composition is paid via its recording-share
82
+ * ownership, settled at recording creation. Immutable.
83
+ */
84
+ compositionId: string;
83
85
  }
84
86
  /**
85
87
  * Emitted once when a recording is published. A pure pointer carrying only the
@@ -112,6 +114,13 @@ export type TrackState = "Unassigned" | "Assigned";
112
114
  export interface Track {
113
115
  /** Current state of the track (Unassigned until the release claims it, then Assigned). */
114
116
  state: TrackState;
117
+ /**
118
+ * ID of the composition underlying this track's recording. An identity/
119
+ * membership handle — not a revenue routing target: the composition is paid
120
+ * via its recording-share ownership, and a track routes its full split to the
121
+ * recording.
122
+ */
123
+ compositionId: string;
115
124
  /** ID of the recording on this track. */
116
125
  recordingId: string;
117
126
  /** Revenue split for this track within the release (in basis points). */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAOA,wDAAwD;AACxD,MAAM,WAAW,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,wCAAwC;AACxC,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,EAAE,EAAE,MAAM,CAAC;IACX,+BAA+B;IAC/B,KAAK,EAAE,gBAAgB,CAAC;IACxB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,WAAW,EAAE,GAAG,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,sCAAsC;AACtC,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,+BAA+B;IAC/B,KAAK,EAAE,cAAc,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,+CAA+C;AAC/C,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,WAAW,KAAK;IACpB,0FAA0F;IAC1F,KAAK,EAAE,UAAU,CAAC;IAClB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,QAAQ,EAAE,GAAG,CAAC;CACf;AAMD,oCAAoC;AACpC,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C;;;;;;;;;GASG;AACH,MAAM,WAAW,OAAO;IACtB,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,+BAA+B;IAC/B,KAAK,EAAE,YAAY,CAAC;IACpB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAOA,wDAAwD;AACxD,MAAM,WAAW,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,wCAAwC;AACxC,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,EAAE,EAAE,MAAM,CAAC;IACX,+BAA+B;IAC/B,KAAK,EAAE,gBAAgB,CAAC;IACxB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,EAAE,GAAG,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,sCAAsC;AACtC,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,+BAA+B;IAC/B,KAAK,EAAE,cAAc,CAAC;IACtB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,+CAA+C;AAC/C,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,WAAW,KAAK;IACpB,0FAA0F;IAC1F,KAAK,EAAE,UAAU,CAAC;IAClB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,QAAQ,EAAE,GAAG,CAAC;CACf;AAMD,oCAAoC;AACpC,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C;;;;;;;;;GASG;AACH,MAAM,WAAW,OAAO;IACtB,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,+BAA+B;IAC/B,KAAK,EAAE,YAAY,CAAC;IACpB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;CACnB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@misonetwork/sdk",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Typed query helpers and transaction builders for the Miso protocol core on Sui.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -44,6 +44,10 @@
44
44
  "types": "./dist/client.d.ts",
45
45
  "default": "./dist/client.js"
46
46
  },
47
+ "./deployments": {
48
+ "types": "./dist/deployments.d.ts",
49
+ "default": "./dist/deployments.js"
50
+ },
47
51
  "./queries": {
48
52
  "types": "./dist/queries.d.ts",
49
53
  "default": "./dist/queries.js"
package/src/client.ts CHANGED
@@ -6,6 +6,10 @@ import type {
6
6
  SuiClientRegistration,
7
7
  } from "@mysten/sui/client";
8
8
  import type { SuiGraphQLClient } from "@mysten/sui/graphql";
9
+ import {
10
+ getMisoProtocolDeployment,
11
+ type MisoProtocolDeployment,
12
+ } from "./deployments.ts";
9
13
  import * as parsers from "./parsers.ts";
10
14
  import * as queries from "./queries.ts";
11
15
  import * as view from "./view.ts";
@@ -27,8 +31,13 @@ import * as track from "./contracts/miso/track.ts";
27
31
  export interface MisoOptions<Name extends string = "miso"> {
28
32
  /** Name for the client extension. Defaults to "miso". */
29
33
  name?: Name;
30
- /** The Miso package ID. Required for type-based queries and derivation. */
31
- misoPackageId: string;
34
+ /**
35
+ * Complete custom deployment. Omit for bundled Mainnet/Testnet addresses,
36
+ * selected from the Sui client's `network`.
37
+ */
38
+ deployment?: MisoProtocolDeployment;
39
+ /** @deprecated Use `deployment`. Retained for compatibility with pre-0.4 callers. */
40
+ misoPackageId?: string;
32
41
  /**
33
42
  * Optional GraphQL client, required ONLY for the global type-discovery reads
34
43
  * the Core API cannot express: `getCompositionByShareType`,
@@ -57,29 +66,53 @@ function bindModulePackage<M extends object>(mod: M, pkg: string): M {
57
66
  * @example
58
67
  * ```ts
59
68
  * const client = new SuiGrpcClient({ network: 'testnet' })
60
- * .$extend(miso({ misoPackageId: '0x...' }));
69
+ * .$extend(miso());
61
70
  * const composition = await client.miso.getCompositionById('0x...');
62
71
  * ```
63
72
  */
64
73
  export function miso<const Name extends string = "miso">(
65
- options: MisoOptions<Name>,
66
- ): SuiClientRegistration<ClientWithCoreApi, Name, MisoClient> {
74
+ options: MisoOptions<Name> = {},
75
+ ): SuiClientRegistration<ClientWithCoreApi, Name, MisoProtocolClient> {
67
76
  const name = (options.name ?? "miso") as Name;
68
77
  return {
69
78
  name,
70
- 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
+ },
71
90
  };
72
91
  }
73
92
 
74
- export class MisoClient {
93
+ export interface MisoProtocolClientOptions {
94
+ deployment: MisoProtocolDeployment;
95
+ graphqlClient?: SuiGraphQLClient;
96
+ }
97
+
98
+ export class MisoProtocolClient {
75
99
  #client: ClientWithCoreApi;
76
100
  #graphqlClient?: SuiGraphQLClient;
77
- #misoPackageId: string;
101
+ #deployment: MisoProtocolDeployment;
78
102
 
79
- constructor(client: ClientWithCoreApi, options: Omit<MisoOptions, "name">) {
103
+ constructor(client: ClientWithCoreApi, options: MisoProtocolClientOptions) {
80
104
  this.#client = client;
81
105
  this.#graphqlClient = options.graphqlClient;
82
- this.#misoPackageId = options.misoPackageId;
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;
83
116
  }
84
117
 
85
118
  // === Composition ===
@@ -243,7 +276,6 @@ export class MisoClient {
243
276
  Release: release.Release,
244
277
  Track: track.Track,
245
278
  CompositionPublishedEvent: composition.CompositionPublishedEvent,
246
- CompositionRoyaltySetEvent: composition.CompositionRoyaltySetEvent,
247
279
  RecordingPublishedEvent: recording.RecordingPublishedEvent,
248
280
  ReleasePublishedEvent: release.ReleasePublishedEvent,
249
281
  };
@@ -254,7 +286,6 @@ export class MisoClient {
254
286
  get parse() {
255
287
  return {
256
288
  compositionPublishedEvent: parsers.parseCompositionPublishedEvent,
257
- compositionRoyaltySetEvent: parsers.parseCompositionRoyaltySetEvent,
258
289
  recordingPublishedEvent: parsers.parseRecordingPublishedEvent,
259
290
  releasePublishedEvent: parsers.parseReleasePublishedEvent,
260
291
  };
@@ -269,3 +300,6 @@ export class MisoClient {
269
300
  return this.#graphqlClient;
270
301
  }
271
302
  }
303
+
304
+ /** @deprecated Prefer the layer-specific `MisoProtocolClient` name. */
305
+ export { MisoProtocolClient as MisoClient };
@@ -67,12 +67,6 @@ export const CompositionAdminCapKey = new MoveTuple({ name: `${$moduleName}::Com
67
67
  export const CompositionPublishedEvent = new MoveStruct({ name: `${$moduleName}::CompositionPublishedEvent<phantom CompositionShare>`, fields: {
68
68
  composition_id: bcs.Address
69
69
  } });
70
- export const CompositionRoyaltySetEvent = new MoveStruct({ name: `${$moduleName}::CompositionRoyaltySetEvent<phantom CompositionShare>`, fields: {
71
- composition_id: bcs.Address,
72
- previous_royalty_rate_bps: bcs.u16(),
73
- royalty_rate_bps: bcs.u16(),
74
- changed_by: bcs.Address
75
- } });
76
70
  export interface NewArguments {
77
71
  title: RawTransactionArgument<string>;
78
72
  royaltyRateBps: RawTransactionArgument<number>;
@@ -92,10 +86,17 @@ export interface NewOptions {
92
86
  ];
93
87
  }
94
88
  /**
95
- * Creates a new composition with the given title and royalty rate. The royalty
96
- * rate must not exceed `MAX_ROYALTY_RATE_BPS`; there is no floor, so 0% is
97
- * permitted (e.g. a generative recording with no authored composition).
98
- * Initializes share tokens (10M supply, 6 decimals) and returns:
89
+ * Creates a new composition with the given title and royalty rate.
90
+ *
91
+ * The rate is set once, here, and is immutable for the composition's lifetime: it
92
+ * is a permanent standing offer that recorders and share buyers can price against
93
+ * without trusting the admin. The protocol imposes no opinion on it beyond the
94
+ * arithmetic bound of 100% (10000 bps, enforced by `bps::new`). There is no floor
95
+ * — 0% is permitted (e.g. a generative recording with no authored composition) —
96
+ * and no protocol ceiling: an uncompetitive rate simply attracts no recordings.
97
+ * What rate is reasonable is a client-side concern; per-deal deviations settle as
98
+ * voluntary share transfers after recording creation. Initializes share tokens
99
+ * (10M supply, 6 decimals) and returns:
99
100
  *
100
101
  * - The composition object
101
102
  * - Admin capability for the owner
@@ -155,48 +156,6 @@ export function publish(options: PublishOptions) {
155
156
  typeArguments: options.typeArguments
156
157
  });
157
158
  }
158
- export interface SetRoyaltyRateArguments {
159
- self: RawTransactionArgument<string>;
160
- _: RawTransactionArgument<string>;
161
- royaltyRateBps: RawTransactionArgument<number>;
162
- }
163
- export interface SetRoyaltyRateOptions {
164
- package?: string;
165
- arguments: SetRoyaltyRateArguments | [
166
- self: RawTransactionArgument<string>,
167
- _: RawTransactionArgument<string>,
168
- royaltyRateBps: RawTransactionArgument<number>
169
- ];
170
- typeArguments: [
171
- string
172
- ];
173
- }
174
- /**
175
- * Sets the royalty rate this composition earns from each recording. Must not
176
- * exceed `MAX_ROYALTY_RATE_BPS` (there is no floor; 0% is allowed). The rate can
177
- * be changed in any lifecycle state, including after publishing, and takes effect
178
- * immediately. There is deliberately no rate-change cooldown: a change cannot
179
- * surprise anyone, because each recording snapshots the rate when it is created
180
- * (existing recordings keep the rate they captured) and `recording::new`'s
181
- * `max_royalty_rate_bps` slippage guard means no future recorder can be charged a
182
- * rate they did not consent to.
183
- */
184
- export function setRoyaltyRate(options: SetRoyaltyRateOptions) {
185
- const packageAddress = options.package ?? '@local-pkg/miso';
186
- const argumentsTypes = [
187
- null,
188
- null,
189
- 'u16'
190
- ] satisfies (string | null)[];
191
- const parameterNames = ["self", "_", "royaltyRateBps"];
192
- return (tx: Transaction) => tx.moveCall({
193
- package: packageAddress,
194
- module: 'composition',
195
- function: 'set_royalty_rate',
196
- arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
197
- typeArguments: options.typeArguments
198
- });
199
- }
200
159
  export interface IdArguments {
201
160
  self: RawTransactionArgument<string>;
202
161
  }
@@ -263,7 +222,11 @@ export interface RoyaltyRateOptions {
263
222
  string
264
223
  ];
265
224
  }
266
- /** Returns the royalty rate this composition earns from each recording. */
225
+ /**
226
+ * Returns the royalty rate this composition earns from each recording. Immutable
227
+ * for the composition's lifetime — the value read here is, by construction, the
228
+ * value `recording::new` will apply.
229
+ */
267
230
  export function royaltyRate(options: RoyaltyRateOptions) {
268
231
  const packageAddress = options.package ?? '@local-pkg/miso';
269
232
  const argumentsTypes = [
@@ -45,14 +45,15 @@
45
45
  * the one trust assumption that never expires: integrators should model the cap
46
46
  * holder as able to mutate or delete any extension data, forever.
47
47
  *
48
- * The recording carries its parent composition's identity as the
49
- * `CompositionShare` phantom type parameter the composition's share type is its
50
- * durable identity (a share currency is published independently of miso and
51
- * survives a fresh republish, whereas an object ID does not). This makes the
52
- * recording↔composition lineage compile-time enforced wherever the two meet, and
53
- * it is the sole link: the composition's object id is not stored on the recording.
54
- * Off-chain consumers that need the composition object resolve its share type to
55
- * an id via `composition::CompositionPublishedEvent`, which binds the two.
48
+ * The recording carries its parent composition's identity two ways. The
49
+ * `CompositionShare` phantom type parameter is the durable identity (a share
50
+ * currency is published independently of miso and survives a fresh republish,
51
+ * whereas an object ID does not) and makes the recording↔composition lineage
52
+ * compile-time enforced wherever the two meet. The embedded `composition_id` is
53
+ * the address-level handle: Move cannot chase a type (or an ID) to an object, so
54
+ * on-chain consumers holding only `&Recording` or a bare `Track` could not
55
+ * otherwise reach the composition at all. Both are set at creation and immutable,
56
+ * so they cannot diverge.
56
57
  *
57
58
  * A recording is its own freshly-created object (`object::new`), not a derived
58
59
  * child of its composition: `recording::new` takes a read-only `&Composition`
@@ -76,7 +77,15 @@ export const Recording = new MoveStruct({ name: `${$moduleName}::Recording<phant
76
77
  /** Unique identifier for this recording. */
77
78
  id: bcs.Address,
78
79
  /** Current lifecycle state. */
79
- state: RecordingState
80
+ state: RecordingState,
81
+ /**
82
+ * Object ID of the parent composition. The address-level counterpart of the
83
+ * `CompositionShare` phantom, set from the `&Composition` passed to `new` (the
84
+ * shared phantom proves the pairing). An identity handle — not a revenue routing
85
+ * target: the composition is paid through its recording-share ownership, settled
86
+ * at creation.
87
+ */
88
+ composition_id: bcs.Address
80
89
  } });
81
90
  export const RecordingAdminCap = new MoveStruct({ name: `${$moduleName}::RecordingAdminCap<phantom RecordingShare>`, fields: {
82
91
  /** Unique identifier for this capability. */
@@ -99,15 +108,13 @@ export interface NewArguments {
99
108
  composition: RawTransactionArgument<string>;
100
109
  shareCurrency: RawTransactionArgument<string>;
101
110
  shareTreasuryCap: RawTransactionArgument<string>;
102
- maxRoyaltyRateBps: RawTransactionArgument<number>;
103
111
  }
104
112
  export interface NewOptions {
105
113
  package?: string;
106
114
  arguments: NewArguments | [
107
115
  composition: RawTransactionArgument<string>,
108
116
  shareCurrency: RawTransactionArgument<string>,
109
- shareTreasuryCap: RawTransactionArgument<string>,
110
- maxRoyaltyRateBps: RawTransactionArgument<number>
117
+ shareTreasuryCap: RawTransactionArgument<string>
111
118
  ];
112
119
  typeArguments: [
113
120
  string,
@@ -126,13 +133,11 @@ export interface NewOptions {
126
133
  * composition owner then does with the shares (hold, stake, sell) is outside the
127
134
  * protocol's scope.
128
135
  *
129
- * `max_royalty_rate_bps` is a slippage guard: `new` reads the composition's
130
- * royalty rate live off a shared object, so a composition owner could land a rate
131
- * increase in a transaction ordered just before this one and capture more of the
132
- * recording's shares than the recorder saw. The call aborts if the composition's
133
- * current rate exceeds `max_royalty_rate_bps`, so the recorder pins the most they
134
- * will grant (pass the rate they observed, or `2000` to accept up to the protocol
135
- * maximum).
136
+ * The composition's royalty rate is immutable, so the rate a recorder's client
137
+ * displayed is exactly the rate applied here no slippage protection is needed or
138
+ * possible. Whether that rate is acceptable is the recorder's decision to make
139
+ * before calling; per-deal deviations settle as voluntary share transfers after
140
+ * creation.
136
141
  *
137
142
  * The composition need not be `Published`: within the composition's own creating
138
143
  * transaction its creator can already mint recordings against it. Third parties
@@ -153,10 +158,9 @@ export function _new(options: NewOptions) {
153
158
  const argumentsTypes = [
154
159
  null,
155
160
  null,
156
- null,
157
- 'u16'
161
+ null
158
162
  ] satisfies (string | null)[];
159
- const parameterNames = ["composition", "shareCurrency", "shareTreasuryCap", "maxRoyaltyRateBps"];
163
+ const parameterNames = ["composition", "shareCurrency", "shareTreasuryCap"];
160
164
  return (tx: Transaction) => tx.moveCall({
161
165
  package: packageAddress,
162
166
  module: 'recording',
@@ -203,6 +207,39 @@ export function publish(options: PublishOptions) {
203
207
  typeArguments: options.typeArguments
204
208
  });
205
209
  }
210
+ export interface CompositionIdArguments {
211
+ self: RawTransactionArgument<string>;
212
+ }
213
+ export interface CompositionIdOptions {
214
+ package?: string;
215
+ arguments: CompositionIdArguments | [
216
+ self: RawTransactionArgument<string>
217
+ ];
218
+ typeArguments: [
219
+ string,
220
+ string
221
+ ];
222
+ }
223
+ /**
224
+ * Returns the object ID of the parent composition. An identity/membership handle
225
+ * (the address-level counterpart of the `CompositionShare` phantom) — not a
226
+ * revenue routing target: the composition is paid via its recording-share
227
+ * ownership.
228
+ */
229
+ export function compositionId(options: CompositionIdOptions) {
230
+ const packageAddress = options.package ?? '@local-pkg/miso';
231
+ const argumentsTypes = [
232
+ null
233
+ ] satisfies (string | null)[];
234
+ const parameterNames = ["self"];
235
+ return (tx: Transaction) => tx.moveCall({
236
+ package: packageAddress,
237
+ module: 'recording',
238
+ function: 'composition_id',
239
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
240
+ typeArguments: options.typeArguments
241
+ });
242
+ }
206
243
  export interface IdArguments {
207
244
  self: RawTransactionArgument<string>;
208
245
  }
@@ -12,6 +12,10 @@
12
12
  * - `recording_id` — the routing target for the track's revenue, and the handle
13
13
  * through which all other metadata (title, cover art, and the
14
14
  * recording/composition share-type identities) is reached.
15
+ * - `composition_id` — the identity of the recording's underlying work, so the
16
+ * composition–recording–release graph is walkable on-chain from the release
17
+ * alone. Move cannot chase an ID to an object, so this edge is unreachable in a
18
+ * track loop unless embedded here.
15
19
  * - `split_bps` — this track's share of the release's revenue; genuinely
16
20
  * release-specific and not derivable from the recording.
17
21
  * - `state` — the assign-once lifecycle that carries (then sheds) the recording
@@ -19,8 +23,9 @@
19
23
  *
20
24
  * `Track` is intentionally monomorphic: a `Release` holds a `vector<Track>` of
21
25
  * tracks from many different recordings/compositions, so it cannot be generic over
22
- * their share types. It stores no title, cover art, or share-type — all derived
23
- * from the recording via `recording_id`.
26
+ * their share types. It stores no title, cover art, or share-type — those are
27
+ * consumed off-chain and derived from the recording via `recording_id`; a `Track`
28
+ * embeds exactly the facts on-chain consumers cannot reach any other way.
24
29
  */
25
30
 
26
31
  import { MoveEnum, MoveStruct, normalizeMoveArguments, type RawTransactionArgument } from '../utils/index.js';
@@ -48,6 +53,14 @@ export const TrackState = new MoveEnum({ name: `${$moduleName}::TrackState`, fie
48
53
  export const Track = new MoveStruct({ name: `${$moduleName}::Track`, fields: {
49
54
  /** Current state of the track. */
50
55
  state: TrackState,
56
+ /**
57
+ * ID of the composition underlying this track's recording. An identity and
58
+ * membership handle — NOT a revenue routing target: the composition is paid
59
+ * through its recording-share ownership (settled at `recording::new`), so a track
60
+ * routes its full split to the recording. Immutable and safe to denormalize: the
61
+ * recording↔composition pairing is fixed at recording creation.
62
+ */
63
+ composition_id: bcs.Address,
51
64
  /**
52
65
  * ID of the recording on this track. The routing target for the track's revenue;
53
66
  * also the handle a consumer uses to fetch the recording (whose type carries the
@@ -89,9 +102,10 @@ export interface NewOptions {
89
102
  * would be unable to distinguish pending from dead. Pre-publish observability is
90
103
  * the responsibility of whatever wraps the track (see below).
91
104
  *
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.
105
+ * The recording↔composition pairing is compile-time enforced by the recording's
106
+ * `CompositionShare` phantom, and its address-level counterpart is embedded on the
107
+ * recording at creation so the composition id is copied from the `&Recording`
108
+ * argument with no `Composition` argument and no runtime check needed.
95
109
  *
96
110
  * ### What creating a track consents to
97
111
  *
@@ -115,9 +129,10 @@ export interface NewOptions {
115
129
  * encodes — visible in its type, not in core.
116
130
  *
117
131
  * `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.
132
+ * pairing, and is read for its own id and its embedded composition id: the
133
+ * monomorphic `Track` must store both _addresses_ the recording's for revenue
134
+ * routing, the composition's for graph reachability — and an address cannot come
135
+ * from a phantom.
121
136
  */
122
137
  export function _new(options: NewOptions) {
123
138
  const packageAddress = options.package ?? '@local-pkg/miso';
@@ -159,6 +174,34 @@ export function recordingId(options: RecordingIdOptions) {
159
174
  arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
160
175
  });
161
176
  }
177
+ export interface CompositionIdArguments {
178
+ self: TransactionArgument;
179
+ }
180
+ export interface CompositionIdOptions {
181
+ package?: string;
182
+ arguments: CompositionIdArguments | [
183
+ self: TransactionArgument
184
+ ];
185
+ }
186
+ /**
187
+ * Returns the ID of the composition underlying this track's recording. An
188
+ * identity/membership handle (e.g. "is this composition on this release?") — not a
189
+ * revenue routing target: the composition is paid via its recording-share
190
+ * ownership, and a track routes its full split to the recording.
191
+ */
192
+ export function compositionId(options: CompositionIdOptions) {
193
+ const packageAddress = options.package ?? '@local-pkg/miso';
194
+ const argumentsTypes = [
195
+ null
196
+ ] satisfies (string | null)[];
197
+ const parameterNames = ["self"];
198
+ return (tx: Transaction) => tx.moveCall({
199
+ package: packageAddress,
200
+ module: 'track',
201
+ function: 'composition_id',
202
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
203
+ });
204
+ }
162
205
  export interface SplitBpsArguments {
163
206
  self: TransactionArgument;
164
207
  }
@@ -0,0 +1,42 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ /** Sui networks with a protocol deployment bundled into this SDK release. */
5
+ export type MisoNetwork = "mainnet" | "testnet";
6
+
7
+ /**
8
+ * On-chain identity for one Miso protocol deployment.
9
+ *
10
+ * Package deployments are immutable. A new publish is represented by a new SDK
11
+ * release with updated values here, keeping the ABI bindings and addresses in
12
+ * the same versioned artifact.
13
+ */
14
+ export interface MisoProtocolDeployment {
15
+ /** The published `miso` package used for calls, types, and derivation. */
16
+ readonly packageId: string;
17
+ }
18
+
19
+ export const MISO_PROTOCOL_DEPLOYMENTS = {
20
+ testnet: {
21
+ packageId:
22
+ "0x974d453e82b09ac90d29cf65d981d3cf3cabe1e5ca9c6348f42860226ef9b5c4",
23
+ },
24
+ } as const satisfies Partial<Record<MisoNetwork, MisoProtocolDeployment>>;
25
+
26
+ /** Resolve a bundled deployment, failing closed for devnet/localnet/custom names. */
27
+ export function getMisoProtocolDeployment(
28
+ network: string,
29
+ ): MisoProtocolDeployment {
30
+ const deployment = (
31
+ MISO_PROTOCOL_DEPLOYMENTS as Partial<
32
+ Record<string, MisoProtocolDeployment>
33
+ >
34
+ )[network];
35
+ if (!deployment) {
36
+ throw new Error(
37
+ `@misonetwork/sdk: no bundled Miso protocol deployment for network "${network}". ` +
38
+ "Pass an explicit deployment to miso() for custom networks.",
39
+ );
40
+ }
41
+ return deployment;
42
+ }
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@ export * from "./queries.ts";
11
11
  export * from "./parsers.ts";
12
12
  export * from "./view.ts";
13
13
  export * from "./client.ts";
14
+ export * from "./deployments.ts";
14
15
 
15
16
  // Generated, ABI-bound bindings (BCS structs + type-safe Move calls).
16
17
  export * as contracts from "./contracts.ts";
package/src/internal.ts CHANGED
@@ -59,12 +59,14 @@ export function mapRecording(id: string, d: Parsed): Recording {
59
59
  return {
60
60
  id,
61
61
  state: mapState(d.state),
62
+ compositionId: d.composition_id,
62
63
  };
63
64
  }
64
65
 
65
66
  export function mapTrack(d: Parsed): Track {
66
67
  return {
67
68
  state: (d.state?.$kind ?? "Unassigned") as TrackState,
69
+ compositionId: d.composition_id,
68
70
  recordingId: d.recording_id,
69
71
  splitBps: mapBps(d.split_bps),
70
72
  };
package/src/parsers.ts CHANGED
@@ -5,15 +5,11 @@
5
5
  // they track the on-chain ABI automatically); these functions parse raw event
6
6
  // bytes and map them to the public camelCase event types.
7
7
 
8
- import {
9
- CompositionPublishedEvent as CompositionPublishedEventBcs,
10
- CompositionRoyaltySetEvent as CompositionRoyaltySetEventBcs,
11
- } from "./contracts/miso/composition.ts";
8
+ import { CompositionPublishedEvent as CompositionPublishedEventBcs } from "./contracts/miso/composition.ts";
12
9
  import { RecordingPublishedEvent as RecordingPublishedEventBcs } from "./contracts/miso/recording.ts";
13
10
  import { ReleasePublishedEvent as ReleasePublishedEventBcs } from "./contracts/miso/release.ts";
14
11
  import type {
15
12
  CompositionPublishedEvent,
16
- CompositionRoyaltySetEvent,
17
13
  RecordingPublishedEvent,
18
14
  ReleasePublishedEvent,
19
15
  } from "./types.ts";
@@ -25,11 +21,6 @@ export function parseCompositionPublishedEvent(bytes: Uint8Array): CompositionPu
25
21
  return { compositionId: e.composition_id };
26
22
  }
27
23
 
28
- export function parseCompositionRoyaltySetEvent(bytes: Uint8Array): CompositionRoyaltySetEvent {
29
- const e = CompositionRoyaltySetEventBcs.parse(bytes);
30
- return { royaltyRateBps: e.royalty_rate_bps };
31
- }
32
-
33
24
  // === Recording ===
34
25
 
35
26
  export function parseRecordingPublishedEvent(bytes: Uint8Array): RecordingPublishedEvent {
@@ -110,9 +110,6 @@ export interface RecordingParts {
110
110
  balance: TransactionObjectArgument;
111
111
  }
112
112
 
113
- /** The protocol's maximum composition royalty rate (`MAX_ROYALTY_RATE_BPS`). */
114
- export const PROTOCOL_MAX_ROYALTY_RATE_BPS = 2000;
115
-
116
113
  export interface CreateRecordingParams extends ShareCurrencyBinding {
117
114
  /** Share type of the parent composition (the recording's `CompositionShare` phantom). */
118
115
  compositionShareType: string;
@@ -122,13 +119,6 @@ export interface CreateRecordingParams extends ShareCurrencyBinding {
122
119
  * unshared, transaction-local `createComposition(...).composition` result.
123
120
  */
124
121
  composition: TransactionObjectArgument;
125
- /**
126
- * Slippage guard: the maximum composition royalty rate (bps) the recorder will
127
- * grant — `recording::new` aborts if the composition's live rate exceeds it.
128
- * Pass the rate you observed. Defaults to the protocol maximum (2000), which
129
- * accepts any legal rate.
130
- */
131
- maxRoyaltyRateBps?: number;
132
122
  misoPackageId: string;
133
123
  }
134
124
 
@@ -144,7 +134,7 @@ export function createRecording(tx: Transaction, params: CreateRecordingParams):
144
134
  recording._new({
145
135
  package: params.misoPackageId,
146
136
  typeArguments: [params.shareType, params.compositionShareType],
147
- arguments: [params.composition, tx.object(params.shareCurrencyId), tx.object(params.shareTreasuryCapId), tx.pure.u16(params.maxRoyaltyRateBps ?? PROTOCOL_MAX_ROYALTY_RATE_BPS)],
137
+ arguments: [params.composition, tx.object(params.shareCurrencyId), tx.object(params.shareTreasuryCapId)],
148
138
  }),
149
139
  );
150
140
  return { recording: result[0]!, adminCap: result[1]!, balance: result[2]! };