@misonetwork/sdk 0.3.1 → 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 +6 -55
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +7 -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 +31 -5
  31. package/dist/queries.d.ts.map +1 -1
  32. package/dist/queries.js +179 -56
  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 +82 -89
  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 +357 -83
  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
package/README.md CHANGED
@@ -1,17 +1,13 @@
1
1
  # @misonetwork/sdk
2
2
 
3
- TypeScript SDK for the [Miso](https://github.com/misonetwork/miso-protocol) protocol on [Sui](https://sui.io).
3
+ TypeScript SDK for the [Miso](https://github.com/misonetwork/protocol) protocol
4
+ core on [Sui](https://sui.io). Bindings are regenerated from the local
5
+ `misonetwork/protocol` Move source with `bun run codegen`.
4
6
 
5
- This package mirrors the on-chain ABI of the [`misonetwork/miso-protocol`](https://github.com/misonetwork/miso-protocol) Move package — the protocol core, and nothing else — regenerated from the live Move source via `bun run codegen`.
6
-
7
- Miso is a permissionless on-chain music protocol that models compositions, recordings, and releases — and their associated rights and royalties — as Sui objects. This SDK provides typed queries, composable transaction builders, BCS event parsers, and a client extension.
8
-
9
- Helpers for the first-party **extensions** — credits, cover art, royalty pools —
10
- live in [`@misofm/sdk`](https://github.com/misofm/sdk), not here. An extension is
11
- opinionated business logic hung off the protocol's `&mut UID` hook (which roles
12
- exist and what they are called, what a cover is, how royalties accumulate), so it
13
- ships with the platform layer. The protocol package stays the open thing anyone
14
- can build on without adopting Miso's opinions.
7
+ Miso models compositions, recordings, releases, their rights, and royalties as
8
+ Sui objects. This package provides core queries, PTB primitives, generated BCS
9
+ bindings, event parsers, and a client extension. First-party policy and
10
+ extension helpers live in [`@misofm/sdk`](https://github.com/misofm/sdk).
15
11
 
16
12
  ## Installation
17
13
 
@@ -19,555 +15,153 @@ can build on without adopting Miso's opinions.
19
15
  bun add @misonetwork/sdk @mysten/sui
20
16
  ```
21
17
 
22
- ## Quick Start
18
+ ## Client extension
23
19
 
24
20
  ```ts
25
21
  import { SuiGrpcClient } from "@mysten/sui/grpc";
26
22
  import { miso } from "@misonetwork/sdk";
27
23
 
28
- const client = new SuiGrpcClient({ network: "testnet" })
24
+ const client = new SuiGrpcClient({
25
+ network: "testnet",
26
+ baseUrl: "https://fullnode.testnet.sui.io:443",
27
+ })
29
28
  .$extend(miso({ misoPackageId: "0x..." }));
30
29
 
31
- // Fetch a recording
32
30
  const recording = await client.miso.getRecordingById("0x...");
33
- console.log(recording.state); // display title comes from the parent composition
34
-
35
- // Derive an admin cap ID (pure, no network call)
36
31
  const adminCapId = client.miso.deriveRecordingAdminCapId("0x...");
37
32
  ```
38
33
 
39
- ## Client Extension
40
-
41
- The SDK provides a `miso()` client extension that works with any Sui client implementing the Core API:
42
-
43
- ```ts
44
- import { SuiGrpcClient } from "@mysten/sui/grpc";
45
- import { SuiGraphQLClient } from "@mysten/sui/graphql";
46
- import { miso } from "@misonetwork/sdk";
47
-
48
- const graphqlClient = new SuiGraphQLClient({
49
- url: "https://sui-testnet.mystenlabs.com/graphql",
50
- network: "testnet",
51
- });
52
-
53
- const client = new SuiGrpcClient({ network: "testnet" })
54
- .$extend(miso({
55
- misoPackageId: "0x...",
56
- graphqlClient, // Required for generic type-based queries (getByShareType, getOwnedCompositionAdminCaps, getOwnedRecordingAdminCaps, getReleaseRegistry, getAdministeredRecordings)
57
- }));
58
- ```
59
-
60
- ### API Priority
61
-
62
- Methods use the most efficient transport available:
34
+ Pass a `SuiGraphQLClient` as `graphqlClient` only for generic type discovery,
35
+ such as `getCompositionByShareType` and `getRecordingByShareType`. ID reads and
36
+ owned-cap queries use the Core API.
63
37
 
64
- | Transport | When Used | Examples |
65
- |-----------|-----------|----------|
66
- | **Core API** | Single-object fetch by ID, derivation | `getRecordingById`, `deriveCompositionAdminCapId` |
67
- | **Core API** | Non-generic type queries | `getOwnedReleaseAdminCaps` |
68
- | **GraphQL** | Generic type queries (partial type matching) | `getOwnedCompositionAdminCaps`, `getRecordingByShareType` |
38
+ ## Data model
69
39
 
70
- ## Data Model
40
+ - `Composition`: the written work, with a share currency and royalty rate.
41
+ - `Recording`: an audio performance of a composition, with its own share currency.
42
+ - `Track`: a recording admin's consent to an exact target release ID and split.
43
+ - `Release`: a flat ordered sequence of tracks. Disc/side grouping is extension
44
+ presentation data, not core state.
71
45
 
72
- Miso stores only protocol-verifiable state. Each entity follows a build-then-freeze
73
- lifecycle (`Initialized Published`) and is immutable once published.
74
-
75
- - **Composition** — the underlying written work. Earns an immutable-floored `royaltyRate` from each recording. Backed by its own share currency.
76
- - **Recording** — an audio performance of a composition. Backed by its own share currency. Carries no name of its own — its display title is its composition's title; richer naming lives in the metadata extension.
77
- - **Release** — a flat, ordered tracklist of `Track`s (album, EP, or single), assembled from `Deal`s. Display grouping (discs/sides) lives in extensions.
78
- - **Deal** — a recording admin's transferable authorization to include the recording on one exact release id.
79
-
80
- Everything else — credits, cover art, royalty pools, masters, descriptive
81
- metadata — attaches to the frozen core objects as dynamic fields through
82
- extension packages (see [Extensions](#extensions)).
83
-
84
- On publish, each entity emits a single lean pointer event carrying just its identity;
85
- indexers subscribe to that pointer and fetch the immutable object by ID.
46
+ Core objects are built then published. Credits, cover art, royalty pools, and
47
+ release coordination are extension-layer concerns in `@misofm/sdk`.
86
48
 
87
49
  ## Queries
88
50
 
89
- All client methods are also available as standalone functions (taking the client
90
- explicitly) from the package root.
91
-
92
- ### Compositions
93
-
94
- ```ts
95
- // Core API (by ID)
96
- const comp = await client.miso.getCompositionById("0x...");
97
- const comps = await client.miso.getCompositionsByIds(["0x...", "0x..."]);
98
- const capId = client.miso.deriveCompositionAdminCapId("0x...");
99
- const cap = await client.miso.getCompositionAdminCapById(capId);
100
- const shareType = await client.miso.getCompositionShareType("0x...");
101
-
102
- // GraphQL (by type or owner)
103
- const comp2 = await client.miso.getCompositionByShareType("0x...::share::Share");
104
- const caps = await client.miso.getOwnedCompositionAdminCaps(ownerAddress);
105
- ```
106
-
107
- ### Recordings
51
+ All client methods are also exported as standalone functions.
108
52
 
109
53
  ```ts
110
- // Core API (by ID)
111
- const rec = await client.miso.getRecordingById("0x...");
112
- const recs = await client.miso.getRecordingsByIds(["0x...", "0x..."]);
113
- const recCapId = client.miso.deriveRecordingAdminCapId("0x...");
114
- const recCap = await client.miso.getRecordingAdminCapById(recCapId);
115
-
116
- // A Recording is generic over two phantoms — Recording<RecordingShare, CompositionShare>.
117
- const recShareType = await client.miso.getRecordingShareType("0x..."); // the recording's OWN share type
118
- const [recShare, compShare] = await getRecordingShareTypes(client, "0x..."); // both, in that order
119
-
120
- // GraphQL (by type or owner)
121
- const rec2 = await client.miso.getRecordingByShareType("0x...::share::Share");
122
- const recCaps = await client.miso.getOwnedRecordingAdminCaps(ownerAddress);
123
- const administered = await client.miso.getAdministeredRecordings(ownerAddress);
124
- ```
125
-
126
- `getRecordingShareType` returns the recording's own share type
127
- (`RecordingShare`) and is bound on the client. `getRecordingShareTypes` is the
128
- standalone query that returns both as `[RecordingShare, CompositionShare]` —
129
- reach for it when building anything generic over the pair, which is most of the
130
- protocol: `deal::new`, `track::new`, `recording::publish`, and the recording
131
- credit/royalty-pool extensions all take the two phantoms in exactly that order.
132
-
133
- ### Deals
134
-
135
- ```ts
136
- // Share types are read from the object's `Deal<RecordingShare, CompositionShare>` type parameters.
137
- const deal = await client.miso.getDealById("0x...");
138
- // { id, releaseId, trackSplitBps, recordingShareType, compositionShareType }
139
- ```
140
-
141
- ### Releases
142
-
143
- ```ts
144
- // Core API (by ID)
145
54
  const release = await client.miso.getReleaseById("0x...");
146
- const releases = await client.miso.getReleasesByIds(["0x...", "0x..."]);
147
- const relCapId = client.miso.deriveReleaseAdminCapId("0x...");
148
- const relCap = await client.miso.getReleaseAdminCapById(relCapId);
149
- const relCaps = await client.miso.getOwnedReleaseAdminCaps(ownerAddress);
150
-
151
- // GraphQL
152
- const registryId = await client.miso.getReleaseRegistry();
153
- ```
154
-
155
- ### Share currencies
156
-
157
- ```ts
158
- const shareType = await client.miso.getShareCurrencyType("0x..."); // Currency<T> object id → T
159
- // Takes the share TYPE (which builders already thread around), not the Currency
160
- // object id — so this is one call, not two.
161
- const treasuryCapId = await client.miso.getShareCurrencyTreasuryCap(shareType, ownerAddress);
55
+ const caps = await client.miso.getOwnedReleaseAdminCaps(ownerAddress);
56
+ const [recordingShare, compositionShare] = await getRecordingShareTypes(
57
+ client,
58
+ "0x...",
59
+ );
162
60
  ```
163
61
 
164
- ### Missing objects: null vs throw
165
-
166
- Core-object getters (`getCompositionById`, `getDealById`, …) **throw** when the
167
- object is missing — a miss means a broken reference. Extension readers
168
- (`getCompositionCredits`, `getReleaseCover`, … — now in `@misofm/sdk`) return
169
- **`null`** instead, because extension data is optional by design. The exported
170
- `isNotFound(e)` helper distinguishes a missing-object error from a transport
171
- failure across all Sui client transports, and `@misofm/sdk` re-exports it so
172
- both packages share one not-found taxonomy:
173
-
174
- ```ts
175
- import { isNotFound } from "@misonetwork/sdk";
176
-
177
- try {
178
- await client.miso.getReleaseById(id);
179
- } catch (e) {
180
- if (isNotFound(e)) { /* no such object */ } else throw e;
181
- }
182
- ```
183
-
184
- Also exported: `extractTypeParam("p::m::T<A>")` → `"A"` and
185
- `extractTypeParams2("p::m::T<A, B>")` → `["A", "B"]` for reading share types
186
- out of object type tags.
187
-
188
- ## Transaction Builders
189
-
190
- This module exports five builders, in two shapes:
191
-
192
- | Builder | Shape |
193
- |---------|-------|
194
- | `createComposition(tx, params)` | takes the `Transaction` first, returns `CompositionParts` |
195
- | `createRecording(tx, params)` | takes the `Transaction` first, returns `RecordingParts` |
196
- | `createDeal(tx, params)` | takes the `Transaction` first, returns a `TransactionObjectArgument` |
197
- | `createRelease(tx, params, trackVec)` | takes the `Transaction` first, returns `ReleaseParts` |
198
- | `rejectDeal(params)` | returns a `TxThunk` |
199
-
200
- Only `rejectDeal` follows the thunk pattern — it returns a `TxThunk`
201
- (`(tx: Transaction) => void | Promise<void>`) that appends commands to a
202
- caller-owned `Transaction`. The four `create*` primitives take the
203
- `Transaction` as their **first argument** and return their by-value results, so
204
- those results can be threaded into later commands. Either way, everything
205
- composes inside a single caller-owned PTB.
206
-
207
- The client binds exactly one builder — `client.miso.tx.rejectDeal` — which
208
- injects the client's `misoPackageId`. The `create*` primitives have no thunk to
209
- bind, so they stay free functions: import them from the package root and pass
210
- `misoPackageId` explicitly.
211
-
212
- This SDK keeps the bare protocol primitives only. The four `create*` functions
213
- each append a single `::new` and hand back its by-value results — never
214
- dispersing a share supply, publishing (sharing) the object, or routing an admin
215
- cap. The opinionated layers — the finish (disperse via minato, publish,
216
- transfer), track assembly, cap disposition, and the share-currency lifecycle —
217
- live in [`@misofm/sdk`](https://github.com/misofm/sdk) as **free functions that
218
- take `misoPackageId` explicitly** (they are not bound onto any client's `tx`
219
- namespace): `finalizeComposition`/`finalizeRecording`/`finalizeRelease`,
220
- `publishComposition`/`publishRecording`/`publishCompositionAndRecording`,
221
- `publishRelease`/`publishReleaseFromDeals`/`publishReleaseGraph`,
222
- `disperseShares`, share-currency provisioning, and `executeViaExecutor`. Those
223
- import the primitives from here and build on top.
224
-
225
- Execute any thunk (from this SDK or composed with another) with `buildTx` +
226
- `signAndExecute` — see [Execution](#execution-executets):
227
-
228
- ```ts
229
- import { buildTx, signAndExecute } from "@misonetwork/sdk";
62
+ Core object getters throw for a missing object. The exported `isNotFound(error)`
63
+ helper distinguishes that condition from transport failures.
230
64
 
231
- const tx = await buildTx(client.miso.tx.rejectDeal({ /* … */ }));
232
- await signAndExecute(client, signer, tx);
233
- ```
65
+ ## Transaction primitives
234
66
 
235
- ### Deals
67
+ The core exports these synchronous builders, each operating on the caller's
68
+ `Transaction`:
236
69
 
237
- `createDeal` is a primitive: it appends `deal::new` and returns the `Deal` for
238
- you to route. It is a free function (not on `client.tx`) because it takes the
239
- `Transaction` directly, so pass `misoPackageId` explicitly.
70
+ | Builder | Result |
71
+ | --- | --- |
72
+ | `createComposition(tx, params)` | `CompositionParts` |
73
+ | `createRecording(tx, params)` | `RecordingParts` |
74
+ | `createTrack(tx, params)` | `TransactionObjectArgument` |
240
75
 
241
- The returned `Deal` MUST be consumed in the same transaction — it is
242
- `key, store` with no `drop` but it can go to either of two places, which is
243
- why the SDK does not choose for you:
76
+ `createTrack` adds cap-gated `track::new`; it accepts either an on-chain
77
+ `recordingAdminCapId` or a PTB-local `recordingAdminCap` result. A `Track` has
78
+ `drop, store`, so leaving it unconsumed is valid. To create a release, collect
79
+ tracks with `tx.makeMoveVec({ type: `${misoPackageId}::track::Track`, elements })`
80
+ and call the extension's `release_registry::new_release` via `@misofm/sdk`.
244
81
 
245
82
  ```ts
246
- import { createDeal } from "@misonetwork/sdk";
83
+ import { createTrack } from "@misonetwork/sdk";
247
84
 
248
- const deal = createDeal(tx, {
85
+ const track = createTrack(tx, {
249
86
  recordingId: "0x...",
250
- recordingAdminCapId: "0x...", // or `recordingAdminCap` as an in-PTB argument
87
+ recordingAdminCapId: "0x...",
251
88
  recordingShareType: "0x...::share::Share",
252
89
  compositionShareType: "0x...::share::Share",
253
- releaseId: "0x...", // pre-derived to match release::new — see view.deriveReleaseId
90
+ targetReleaseId: "0x...",
254
91
  trackSplitBps: 5000,
255
92
  misoPackageId,
256
93
  });
257
-
258
- // (1) cross-party: send it to whoever assembles the release, to redeem later
259
- tx.transferObjects([deal], releaseCreator);
260
-
261
- // (2) same-party: spend it immediately as authorization for a track
262
- // tx.add(contracts.track._new({ package: misoPackageId, typeArguments, arguments: [deal, recording] }));
263
- ```
264
-
265
- `rejectDeal` is the one builder bound on the client. It destroys a deal without
266
- including it in a release, and emits `DealRejectedEvent`:
267
-
268
- ```ts
269
- client.miso.tx.rejectDeal({
270
- dealId: "0x...",
271
- recordingShareType: "0x...::share::Share",
272
- compositionShareType: "0x...::share::Share",
273
- });
274
- ```
275
-
276
- ### Releases
277
-
278
- The end-to-end release publishers are **not** on `client.miso.tx` — they are free
279
- functions in [`@misofm/sdk`](https://github.com/misofm/sdk) that take
280
- `misoPackageId` explicitly:
281
-
282
- ```ts
283
- import { publishRelease, publishReleaseFromDeals } from "@misofm/sdk";
284
-
285
- // Sender holds every recording's admin cap (a deal is created inline per track).
286
- await buildTx(publishRelease({ title, tracks, releaseRegistryId, releaseId, releaseNonce, adminAddress, misoPackageId }));
287
-
288
- // Or assemble from pre-made Deals the sender already holds.
289
- await buildTx(publishReleaseFromDeals({ title, deals, releaseRegistryId, releaseNonce, adminAddress, misoPackageId }));
290
94
  ```
291
95
 
292
- `releaseId` is a field on `PublishReleaseParams` only pre-derive it (see
293
- [Deriving the release id](#deriving-the-release-id-view)) so the inline deals
294
- pin the right release. `PublishReleaseFromDealsParams` has no `releaseId`: each
295
- pre-made deal already embeds it, so the from-deals variant derives it from them.
96
+ `createComposition` and `createRecording` return their by-value components so
97
+ they can be composed in the same PTB. `recording::new` borrows its composition,
98
+ so a fresh composition can be passed directly into `createRecording` before it
99
+ is published.
296
100
 
297
- This package supplies the primitive underneath both: `createRelease(tx, params,
298
- trackVec)`, which appends `release::new` over a caller-built `vector<Track>` and
299
- returns the release plus its admin cap.
101
+ ### Release IDs
300
102
 
301
- ### Deriving the release id (`view`)
302
-
303
- Deals embed the exact release id, which the chain derives from the full
304
- tracklist + nonce. Compute it up front via `simulateTransaction`:
103
+ Release IDs are derived on chain by simulation. `parentId` is a pure object ID,
104
+ not an object input—for example, the shared `ReleaseRegistry` owned by the
105
+ extension package.
305
106
 
306
107
  ```ts
307
- const releaseId = await client.miso.view.deriveReleaseId({
308
- sender: ownerAddress, // any address; not charged
309
- recordingIds: ["0x...", "0x..."], // in track order
310
- splitBps: [5000, 5000], // aligned to recordingIds
108
+ const targetReleaseId = await client.miso.view.deriveTargetReleaseId({
109
+ sender: ownerAddress,
110
+ recordingIds: ["0x...", "0x..."],
111
+ splitBps: [5000, 5000],
311
112
  nonce: "42",
312
- releaseRegistryId: "0x...",
113
+ parentId: releaseRegistryId,
313
114
  });
314
115
  ```
315
116
 
316
- ### Creating works (`createComposition` / `createRecording` / `createRelease`)
317
-
318
- Each `create*` appends a single `::new` and returns its by-value parts — the
319
- object, its admin cap, and for a work its freshly-minted share `Balance`. The
320
- caller decides what happens next.
321
-
322
- The key move is **borrow-before-share**: `recording::new` takes the parent
323
- composition by immutable reference, so you can pass a `createComposition(...)`
324
- result straight into `createRecording`'s `composition` param while it is still an
325
- unshared, transaction-local value. That is what lets a composition and its first
326
- recording be minted in one PTB.
327
-
328
- ```ts
329
- import { Transaction } from "@mysten/sui/transactions";
330
- import { createComposition, createRecording } from "@misonetwork/sdk";
331
-
332
- const tx = new Transaction();
333
-
334
- // 1. Composition — returns { composition, adminCap, balance }.
335
- const comp = createComposition(tx, {
336
- title: "Song Title",
337
- royaltyRateBps: 1000,
338
- shareType: compositionShareType, // `${sharePkg}::share::Share`
339
- shareCurrencyId: "0x...", // Currency<Share>
340
- shareTreasuryCapId: "0x...", // TreasuryCap<Share>, consumed by `new`
341
- misoPackageId,
342
- });
343
-
344
- // 2. Recording — borrow-before-share: hand the still-unshared composition
345
- // straight in. No on-chain object id is needed for it.
346
- const rec = createRecording(tx, {
347
- composition: comp.composition, // or `tx.object(compositionId)` if already on chain
348
- compositionShareType,
349
- shareType: recordingShareType,
350
- shareCurrencyId: "0x...",
351
- shareTreasuryCapId: "0x...",
352
- maxRoyaltyRateBps: 1000, // slippage guard — see below
353
- misoPackageId,
354
- });
117
+ Generated `contracts.release._new` is intentionally exposed because codegen
118
+ mirrors the ABI, but it is not PTB-callable: its final parameter is `&mut UID`.
119
+ Release construction therefore belongs in `@misofm/sdk`, whose
120
+ `release_registry::new_release` already owns that UID.
355
121
 
356
- // 3. Both objects MUST still be consumed by their `publish` in THIS transaction
357
- // — e.g. `finalizeComposition(tx, { ...comp, ... })` / `finalizeRecording(tx,
358
- // { ...rec, ... })` from `@misofm/sdk`, which disperse the balances, publish
359
- // the works, and route the admin caps.
360
- ```
122
+ ### Generated bindings
361
123
 
362
- `createRelease` takes the `vector<Track>` as an argument, because track assembly
363
- is the part that genuinely varies between flows from recording admin caps,
364
- from pre-made deals, or from a mix of fresh and existing recordings:
124
+ `contracts` and `client.miso.call` expose generated `composition`, `recording`,
125
+ `release`, and `track` modules. Do not edit `src/contracts/`; run `bun run
126
+ codegen` after updating protocol source.
365
127
 
366
128
  ```ts
367
- import { createRelease } from "@misonetwork/sdk";
368
-
369
- const trackVec = tx.makeMoveVec({ type: `${misoPackageId}::track::Track`, elements: trackArgs });
370
- const rel = createRelease(tx, { title: "Album Title", nonce: "42", releaseRegistryId, misoPackageId }, trackVec);
371
- // rel.release must be consumed by `release::publish` in this same tx.
129
+ tx.add(client.miso.call.track._new({
130
+ typeArguments: [recordingShareType, compositionShareType],
131
+ arguments: [adminCap, tx.object(recordingId), tx.pure.id(targetReleaseId), tx.pure.u16(5000)],
132
+ }));
372
133
  ```
373
134
 
374
- #### Royalty-rate slippage (`maxRoyaltyRateBps`)
375
-
376
- A composition's royalty rate is floored but can be **raised** by its admin. If it
377
- goes up between the moment you read it and the moment your transaction lands, a
378
- recording you thought owed 10% could land owing more. `CreateRecordingParams.maxRoyaltyRateBps`
379
- is the guard: it is the maximum composition royalty rate (in bps) the recorder is
380
- willing to grant, and `recording::new` aborts with `ERoyaltyRateAboveMax` if the
381
- composition's live rate exceeds it. Pass the rate you actually observed.
382
-
383
- It is optional, and defaults to the exported `PROTOCOL_MAX_ROYALTY_RATE_BPS`
384
- (`2000`, the protocol's `MAX_ROYALTY_RATE_BPS`) — which accepts any legal rate,
385
- i.e. no slippage protection. Set it explicitly whenever you are recording someone
386
- else's composition.
387
-
388
- ```ts
389
- import { PROTOCOL_MAX_ROYALTY_RATE_BPS } from "@misonetwork/sdk";
390
-
391
- const comp = await client.miso.getCompositionById(compositionId);
392
- createRecording(tx, { /* … */ maxRoyaltyRateBps: comp.royaltyRate.value });
393
- ```
394
-
395
- #### Result shapes
396
-
397
- ```ts
398
- import type {
399
- CompositionParts, RecordingParts, ReleaseParts, ShareCurrencyBinding,
400
- } from "@misonetwork/sdk";
401
-
402
- // CompositionParts { composition, adminCap, balance } — balance is the creator's
403
- // freshly-minted share supply
404
- // RecordingParts { recording, adminCap, balance } — balance is what remains
405
- // after the composition's cut
406
- // ReleaseParts { release, adminCap }
407
- // All fields are `TransactionObjectArgument`s, for threading onward in the PTB.
408
- ```
409
-
410
- `ShareCurrencyBinding` is the trio every work-creating builder needs, extended by
411
- both `CreateCompositionParams` and `CreateRecordingParams`: `shareType` (the
412
- `${packageId}::share::Share` type), `shareCurrencyId` (the `Currency<Share>`
413
- object), and `shareTreasuryCapId` (the `TreasuryCap<Share>`, consumed by `new`).
414
- All three are passed explicitly rather than read from chain, which keeps the
415
- builders synchronous — no RPC inside the transaction build.
416
-
417
- **Lifecycle requirement.** `Composition`, `Recording`, and `Release` are all
418
- `key`-only with no `drop`, so each created object MUST be consumed by its
419
- `publish` in the same transaction — none can be transferred, wrapped, shared, or
420
- discarded, and none can outlive its creating PTB. That is a same-**transaction**
421
- requirement, not a same-**function** one: pairing a `create*` here with a
422
- `finalize*` from `@misofm/sdk` on the same `tx` satisfies it. Keeping them apart
423
- is what makes the intermediate value useful at all — borrowing a still-unshared
424
- composition into `recording::new`, attaching a royalty pool via `uid_mut`, or
425
- routing an admin cap somewhere other than a plain address (every admin cap is
426
- `key, store`, hence freely routable).
427
-
428
- Whole-graph orchestration lives in `@misofm/sdk` too: `publishReleaseGraph`
429
- mints every composition and recording, attaches optional royalty pools, builds
430
- the deals/tracks, and publishes the release — with the release id derived
431
- on-chain — all in one PTB, importing the primitives from here.
432
-
433
- ```ts
434
- import { publishReleaseGraph } from "@misofm/sdk";
435
- ```
436
-
437
- ## Extensions (moved to `@misofm/sdk`)
438
-
439
- Extension helpers are no longer part of this package. As of **0.3.0**, credits,
440
- cover art, and royalty pools ship from [`@misofm/sdk`](https://github.com/misofm/sdk):
441
-
442
- | Was `@misonetwork/sdk` | Now `@misofm/sdk` |
443
- |---|---|
444
- | `attachCompositionCredit`, `attachRecordingCredit`, `addReleaseCredit`, `addRecordingPrimaryArtist`, `addRecordingFeaturedArtist`, `getCompositionCredits`, `getRecordingCredits`, `getReleaseCredits` | same names |
445
- | `setReleaseCover`, `getReleaseCover` | same names |
446
- | `attachCompositionRoyaltyPool`, `attachRecordingRoyaltyPool` | same names |
447
- | `contracts.compositionCredits`, `.recordingCredits`, `.releaseCredits`, `.compositionPartyRole`, `.recordingPartyRole`, `.releasePartyRole`, `.royaltyPool`, `.royaltyPoolStake`, `.compositionRoyaltyPool`, `.recordingRoyaltyPool`, `.coverArt`, `.releaseCoverArt` | `contracts.*`, same names |
448
- | types `CreditView`, `RecordingCreditsView`, `CompositionRole`, `RecordingRole`, `RecordingRoleLevel`, `RecordingLeveledRoleType`, `ReleaseRole`, `ReleaseCoverView`, `CoverImageRef` | same names |
135
+ ## Event parsers
449
136
 
450
- Signatures are unchanged only the import specifier moves:
137
+ Core emits only publish/royalty events. Parse them with
138
+ `client.miso.parse.compositionPublishedEvent`,
139
+ `compositionRoyaltySetEvent`, `recordingPublishedEvent`, and
140
+ `releasePublishedEvent`. Track creation has no core event; pre-publish
141
+ observability is an extension concern.
451
142
 
452
- ```diff
453
- -import { attachRecordingCredit, setReleaseCover } from "@misonetwork/sdk";
454
- +import { attachRecordingCredit, setReleaseCover } from "@misofm/sdk";
455
- ```
456
-
457
- The reasoning is the split this package exists to hold. An extension is not part
458
- of what a Composition or Recording *is*; it is a choice about how to describe one
459
- — which roles exist and what they are called, what counts as a cover, whether
460
- royalties accumulate in a pool. The protocol offers a cap-gated `&mut UID` hook
461
- and takes no position on what hangs off it. Everything that *does* take a
462
- position is business logic, and business logic ships from the platform package.
463
-
464
- Share-currency provisioning (`createShareCurrency`, `publishShareCurrencies`,
465
- `initializeShareCurrencies`) moved to `@misofm/sdk` earlier for the same reason —
466
- every composition and recording is backed by its own fixed-supply share currency,
467
- and provisioning one is part of the opinionated publish flow, not a protocol
468
- primitive.
469
-
470
- ## Execution (`execute.ts`)
471
-
472
- Builders only append to a `Transaction`; this module submits:
473
-
474
- ```ts
475
- import { buildTx, signAndExecute, execThunks, publishedPackageId, createdByType, balanceDelta } from "@misonetwork/sdk";
476
-
477
- const result = await execThunks(client, signer, thunkA, thunkB); // build + sign + execute + wait
478
- // ExecResult: { digest, changedObjects, objectTypes, balanceChanges, gasUsed }
479
-
480
- // Object-change extractors:
481
- const pkgId = publishedPackageId(result);
482
- const currencyId = createdByType(result, "::coin_registry::Currency<");
483
- const delta = balanceDelta(result, address, "0x2::sui::SUI");
484
- ```
485
-
486
- `@misofm/sdk` builds `executeViaExecutor(executor, ...thunks)` on top of this
487
- module's `buildTx`/`toExecResult` — it submits a non-idempotent PTB through a
488
- `ParallelTransactionExecutor` exactly once (no auto-retry), for its batched
489
- share-currency provisioning.
490
-
491
- ## Event Parsers
492
-
493
- Miso uses a lean publish-only event model: published objects emit a single pointer event,
494
- and indexers fetch the immutable object by ID. Parse the BCS-encoded events from transaction
495
- results:
496
-
497
- ```ts
498
- // Pointer events (carry only identities)
499
- const comp = client.miso.parse.compositionPublishedEvent(bcsBytes); // { compositionId }
500
- const rec = client.miso.parse.recordingPublishedEvent(bcsBytes); // { recordingId }
501
- const rel = client.miso.parse.releasePublishedEvent(bcsBytes); // { releaseId }
502
-
503
- // Non-pointer events
504
- const royalty = client.miso.parse.compositionRoyaltySetEvent(bcsBytes); // { royaltyRateBps }
505
- const created = client.miso.parse.dealCreatedEvent(bcsBytes); // { dealId, releaseId, trackSplitBps }
506
- const accepted = client.miso.parse.dealAcceptedEvent(bcsBytes); // { dealId, releaseId }
507
- const rejected = client.miso.parse.dealRejectedEvent(bcsBytes); // { dealId, releaseId }
508
- ```
509
-
510
- The same functions are exported standalone as `parseCompositionPublishedEvent`, etc.
511
-
512
- ## Types
513
-
514
- All Miso domain types are exported:
515
-
516
- ```ts
517
- import type {
518
- // Core entities
519
- Composition, Recording, Release, Deal, Track, BPS,
520
- // Admin caps
521
- CompositionAdminCap, RecordingAdminCap, ReleaseAdminCap,
522
- // State machines
523
- CompositionState, RecordingState, ReleaseState, TrackState,
524
- // Events
525
- CompositionPublishedEvent, CompositionRoyaltySetEvent,
526
- RecordingPublishedEvent, ReleasePublishedEvent,
527
- DealCreatedEvent, DealAcceptedEvent, DealRejectedEvent,
528
- // Transaction builder inputs & results (from ./transactions)
529
- TxThunk, ShareCurrencyBinding,
530
- CompositionParts, RecordingParts, ReleaseParts,
531
- CreateCompositionParams, CreateRecordingParams, CreateDealParams,
532
- CreateReleaseParams, RejectDealParams,
533
- } from "@misonetwork/sdk";
534
- ```
535
-
536
- The credit and cover types (`CreditView`, `RecordingCreditsView`,
537
- `CompositionRole`, `RecordingRole`, `RecordingRoleLevel`,
538
- `RecordingLeveledRoleType`, `ReleaseRole`, `ReleaseCoverView`, `CoverImageRef`)
539
- moved to `@misofm/sdk` in 0.3.0 — see [Extensions](#extensions-moved-to-misofmsdk).
540
-
541
- The non-type value export `PROTOCOL_MAX_ROYALTY_RATE_BPS` (`2000`) is documented
542
- under [royalty-rate slippage](#royalty-rate-slippage-maxroyaltyratebps).
543
-
544
- ## Generated Bindings (`contracts`)
545
-
546
- The codegen-generated, ABI-bound bindings (BCS structs + type-safe Move calls)
547
- are exported under the `contracts` namespace — the core protocol modules
548
- `composition`, `recording`, `release`, `deal`, and `track`. Bindings for the
549
- extension packages are in `@misofm/sdk`'s own `contracts` namespace:
550
-
551
- ```ts
552
- import { contracts } from "@misonetwork/sdk";
553
-
554
- const parsed = contracts.composition.Composition.parse(bcsBytes);
555
- tx.add(contracts.deal.reject({ package: misoPackageId, typeArguments, arguments: [dealId] }));
556
- ```
143
+ ## 0.4.0 → 0.5.0 migration
557
144
 
558
- On the client, `client.miso.call.*` exposes the core modules with the package
559
- id pre-bound, and `client.miso.bcs.*` the core BCS structs.
145
+ | Previous API | 0.5.0 |
146
+ | --- | --- |
147
+ | `createDeal` | `createTrack`; use `targetReleaseId` rather than `releaseId` |
148
+ | `rejectDeal`, `getDealById`, Deal event parsers/types, `contracts.deal` | removed; offer/withdrawal policy is extension-layer |
149
+ | `createRelease` | removed; use `@misofm/sdk` `release_registry::new_release` |
150
+ | `deriveReleaseId({ releaseRegistryId })` | `deriveTargetReleaseId({ parentId })`; the parent is pure |
151
+ | `getReleaseRegistry`, `MisoOptions.releaseRegistryId` | removed; extension registry is a different package type |
152
+ | `client.miso.tx` | removed; no core thunk builders remain |
153
+ | deployed disc-shaped release fallback | removed; reads parse only canonical flat `Release.tracks` |
560
154
 
561
- ## Derived Objects
155
+ Update `@misofm/sdk` in the same release window: it owns release-registry
156
+ bindings and the callable release-construction flow.
562
157
 
563
- Miso uses Sui's derived object pattern for admin caps. The SDK provides pure derivation
564
- functions that compute object IDs without network calls:
158
+ ## Derived admin caps
565
159
 
566
- | Function | Derivation Key | Parent Object |
567
- |----------|---------------|---------------|
568
- | `deriveCompositionAdminCapId` | `CompositionAdminCapKey()` | Composition |
569
- | `deriveRecordingAdminCapId` | `RecordingAdminCapKey()` | Recording |
570
- | `deriveReleaseAdminCapId` | `ReleaseAdminCapKey()` | Release |
160
+ | Function | Parent |
161
+ | --- | --- |
162
+ | `deriveCompositionAdminCapId` | Composition |
163
+ | `deriveRecordingAdminCapId` | Recording |
164
+ | `deriveReleaseAdminCapId` | Release |
571
165
 
572
166
  ## License
573
167