@misofm/musicos 0.1.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.
- package/LICENSE +201 -0
- package/README.md +75 -0
- package/dist/client.d.ts +309 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +216 -0
- package/dist/client.js.map +1 -0
- package/dist/contracts/musicos/composition.d.ts +195 -0
- package/dist/contracts/musicos/composition.d.ts.map +1 -0
- package/dist/contracts/musicos/composition.js +195 -0
- package/dist/contracts/musicos/composition.js.map +1 -0
- package/dist/contracts/musicos/deps/bps/bps.d.ts +17 -0
- package/dist/contracts/musicos/deps/bps/bps.d.ts.map +1 -0
- package/dist/contracts/musicos/deps/bps/bps.js +19 -0
- package/dist/contracts/musicos/deps/bps/bps.js.map +1 -0
- package/dist/contracts/musicos/recording.d.ts +238 -0
- package/dist/contracts/musicos/recording.d.ts.map +1 -0
- package/dist/contracts/musicos/recording.js +232 -0
- package/dist/contracts/musicos/recording.js.map +1 -0
- package/dist/contracts/musicos/release.d.ts +298 -0
- package/dist/contracts/musicos/release.d.ts.map +1 -0
- package/dist/contracts/musicos/release.js +298 -0
- package/dist/contracts/musicos/release.js.map +1 -0
- package/dist/contracts/musicos/track.d.ts +193 -0
- package/dist/contracts/musicos/track.d.ts.map +1 -0
- package/dist/contracts/musicos/track.js +197 -0
- package/dist/contracts/musicos/track.js.map +1 -0
- package/dist/contracts/utils/index.d.ts +104 -0
- package/dist/contracts/utils/index.d.ts.map +1 -0
- package/dist/contracts/utils/index.js +272 -0
- package/dist/contracts/utils/index.js.map +1 -0
- package/dist/contracts.d.ts +9 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +14 -0
- package/dist/contracts.js.map +1 -0
- package/dist/deployments.d.ts +60 -0
- package/dist/deployments.d.ts.map +1 -0
- package/dist/deployments.js +109 -0
- package/dist/deployments.js.map +1 -0
- package/dist/events.d.ts +16 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +25 -0
- package/dist/events.js.map +1 -0
- package/dist/execute.d.ts +49 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +110 -0
- package/dist/execute.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +17 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +46 -0
- package/dist/internal.js.map +1 -0
- package/dist/numeric.d.ts +5 -0
- package/dist/numeric.d.ts.map +1 -0
- package/dist/numeric.js +21 -0
- package/dist/numeric.js.map +1 -0
- package/dist/packages.d.ts +67 -0
- package/dist/packages.d.ts.map +1 -0
- package/dist/packages.js +85 -0
- package/dist/packages.js.map +1 -0
- package/dist/parsers.d.ts +9 -0
- package/dist/parsers.d.ts.map +1 -0
- package/dist/parsers.js +40 -0
- package/dist/parsers.js.map +1 -0
- package/dist/queries.d.ts +178 -0
- package/dist/queries.d.ts.map +1 -0
- package/dist/queries.js +611 -0
- package/dist/queries.js.map +1 -0
- package/dist/transactions.d.ts +136 -0
- package/dist/transactions.d.ts.map +1 -0
- package/dist/transactions.js +145 -0
- package/dist/transactions.js.map +1 -0
- package/dist/types.d.ts +194 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/view.d.ts +22 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +42 -0
- package/dist/view.js.map +1 -0
- package/package.json +119 -0
- package/src/client.ts +341 -0
- package/src/contracts/musicos/composition.ts +280 -0
- package/src/contracts/musicos/deps/bps/bps.ts +22 -0
- package/src/contracts/musicos/recording.ts +308 -0
- package/src/contracts/musicos/release.ts +409 -0
- package/src/contracts/musicos/track.ts +255 -0
- package/src/contracts/utils/index.ts +428 -0
- package/src/contracts.ts +29 -0
- package/src/deployments.ts +166 -0
- package/src/events.ts +30 -0
- package/src/execute.ts +137 -0
- package/src/index.ts +21 -0
- package/src/internal.ts +78 -0
- package/src/numeric.ts +25 -0
- package/src/packages.ts +117 -0
- package/src/parsers.ts +66 -0
- package/src/queries.ts +928 -0
- package/src/transactions.ts +305 -0
- package/src/types.ts +222 -0
- package/src/view.ts +65 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// Copyright (c) Miso Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
// Transaction builders. Every builder adds commands to a caller-owned
|
|
5
|
+
// `Transaction`, so flows compose in a single PTB.
|
|
6
|
+
// The `create*` primitives take the `Transaction` as their FIRST argument and
|
|
7
|
+
// return their by-value results, so those results can be threaded into later
|
|
8
|
+
// commands. Miso calls go through the codegen-generated, type-safe call
|
|
9
|
+
// functions.
|
|
10
|
+
//
|
|
11
|
+
// This module keeps the bare protocol PRIMITIVES only. The rule is: do the
|
|
12
|
+
// minimum the Move semantics FORCE, and return anything the caller could
|
|
13
|
+
// legitimately route elsewhere.
|
|
14
|
+
//
|
|
15
|
+
// `createComposition` and `createRecording` each append a
|
|
16
|
+
// single `::new` and hand back its by-value results — never dispersing a share
|
|
17
|
+
// supply, publishing (sharing) the object, or routing an admin cap.
|
|
18
|
+
//
|
|
19
|
+
// Each created object MUST still be consumed by its `publish` in the same PTB
|
|
20
|
+
// (`Composition`, `Recording`, and `Release` are all `key`-only with no `drop`),
|
|
21
|
+
// but that is a same-TRANSACTION requirement, not a same-FUNCTION one: a later
|
|
22
|
+
// `finalize*` command on the same `tx` satisfies it. Keeping them apart is what
|
|
23
|
+
// lets the intermediate value be used at all — borrowing a still-unshared
|
|
24
|
+
// composition into `recording::new`, attaching a royalty pool via `uid_mut`, or
|
|
25
|
+
// sending an admin cap somewhere other than a plain address (every admin cap is
|
|
26
|
+
// `key, store`, so it is freely routable).
|
|
27
|
+
//
|
|
28
|
+
// This package exposes the complete low-level current ABI. The platform SDK
|
|
29
|
+
// should own product-specific orchestration (cap disposition, currency
|
|
30
|
+
// lifecycle, authority-package workflows) on top of these composable calls.
|
|
31
|
+
|
|
32
|
+
import {
|
|
33
|
+
Transaction,
|
|
34
|
+
type TransactionObjectArgument,
|
|
35
|
+
} from "@mysten/sui/transactions";
|
|
36
|
+
|
|
37
|
+
import * as composition from "./contracts/musicos/composition.ts";
|
|
38
|
+
import * as recording from "./contracts/musicos/recording.ts";
|
|
39
|
+
import * as release from "./contracts/musicos/release.ts";
|
|
40
|
+
import { asU256, type UnsignedInput } from "./numeric.ts";
|
|
41
|
+
import * as track from "./contracts/musicos/track.ts";
|
|
42
|
+
|
|
43
|
+
/** A thunk that adds commands to a transaction. May be async (resolves at build time). */
|
|
44
|
+
export type TxThunk = (tx: Transaction) => void | Promise<void>;
|
|
45
|
+
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Shared inputs
|
|
48
|
+
// ============================================================================
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Share-currency binding for a work: the fully-qualified `share::Share` type, the
|
|
52
|
+
* `Currency<Share>` object, and the `TreasuryCap<Share>`. All three are known once
|
|
53
|
+
* the currency has been published + initialized, so builders take them explicitly
|
|
54
|
+
* rather than reading them from chain — keeping the thunks synchronous and
|
|
55
|
+
* composable (no RPC inside the transaction build).
|
|
56
|
+
*/
|
|
57
|
+
export interface ShareCurrencyBinding {
|
|
58
|
+
/** The `${packageId}::share::Share` type. */
|
|
59
|
+
shareType: string;
|
|
60
|
+
/** The `Currency<Share>` object id. */
|
|
61
|
+
shareCurrencyId: string;
|
|
62
|
+
/** The `TreasuryCap<Share>` object id (held by the caller, consumed by `new`). */
|
|
63
|
+
shareTreasuryCapId: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// Composition
|
|
68
|
+
// ============================================================================
|
|
69
|
+
|
|
70
|
+
/** The three by-value results of `composition::new`, for threading onward in a PTB. */
|
|
71
|
+
export interface CompositionParts {
|
|
72
|
+
composition: TransactionObjectArgument;
|
|
73
|
+
adminCap: TransactionObjectArgument;
|
|
74
|
+
/** The creator's freshly-minted share supply (a `Balance<Share>`). */
|
|
75
|
+
balance: TransactionObjectArgument;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface CreateCompositionParams extends ShareCurrencyBinding {
|
|
79
|
+
title: string;
|
|
80
|
+
royaltyRateBps: number;
|
|
81
|
+
misoPackageId: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* PRIMITIVE. Appends `composition::new` and returns its by-value results without
|
|
86
|
+
* dispersing, sharing, or transferring anything — the caller decides what happens
|
|
87
|
+
* next (share it, keep it unshared to bundle with a recording, attach a dynamic
|
|
88
|
+
* field via `uid_mut`, …). Composes with anything in the same PTB.
|
|
89
|
+
*/
|
|
90
|
+
export function createComposition(tx: Transaction, params: CreateCompositionParams): CompositionParts {
|
|
91
|
+
const result = tx.add(
|
|
92
|
+
composition._new({
|
|
93
|
+
package: params.misoPackageId,
|
|
94
|
+
typeArguments: [params.shareType],
|
|
95
|
+
arguments: [tx.pure.string(params.title), tx.pure.u16(params.royaltyRateBps), tx.object(params.shareCurrencyId), tx.object(params.shareTreasuryCapId)],
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
98
|
+
return { composition: result[0]!, adminCap: result[1]!, balance: result[2]! };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// Recording
|
|
103
|
+
// ============================================================================
|
|
104
|
+
|
|
105
|
+
/** The three by-value results of `recording::new`, for threading onward in a PTB. */
|
|
106
|
+
export interface RecordingParts {
|
|
107
|
+
recording: TransactionObjectArgument;
|
|
108
|
+
adminCap: TransactionObjectArgument;
|
|
109
|
+
/** The creator's remaining share supply after the composition's cut is split off. */
|
|
110
|
+
balance: TransactionObjectArgument;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface CreateRecordingParams extends ShareCurrencyBinding {
|
|
114
|
+
/** Share type of the parent composition (the recording's `CompositionShare` phantom). */
|
|
115
|
+
compositionShareType: string;
|
|
116
|
+
/**
|
|
117
|
+
* Parent `Composition`, passed by immutable reference (`recording::new` reads only
|
|
118
|
+
* its id + royalty rate). May be an on-chain object (`tx.object(id)`) or a still-
|
|
119
|
+
* unshared, transaction-local `createComposition(...).composition` result.
|
|
120
|
+
*/
|
|
121
|
+
composition: TransactionObjectArgument;
|
|
122
|
+
misoPackageId: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* PRIMITIVE. Appends `recording::new` and returns its by-value results without
|
|
127
|
+
* publishing/dispersing/transferring. Because it borrows the composition by
|
|
128
|
+
* reference, it can run against a composition that is still an unshared PTB-local
|
|
129
|
+
* value — the borrow-before-share pattern that lets a composition + recording share
|
|
130
|
+
* one PTB.
|
|
131
|
+
*/
|
|
132
|
+
export function createRecording(tx: Transaction, params: CreateRecordingParams): RecordingParts {
|
|
133
|
+
const result = tx.add(
|
|
134
|
+
recording._new({
|
|
135
|
+
package: params.misoPackageId,
|
|
136
|
+
typeArguments: [params.shareType, params.compositionShareType],
|
|
137
|
+
arguments: [params.composition, tx.object(params.shareCurrencyId), tx.object(params.shareTreasuryCapId)],
|
|
138
|
+
}),
|
|
139
|
+
);
|
|
140
|
+
return { recording: result[0]!, adminCap: result[1]!, balance: result[2]! };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ============================================================================
|
|
144
|
+
// Track
|
|
145
|
+
// ============================================================================
|
|
146
|
+
|
|
147
|
+
export interface CreateTrackParams {
|
|
148
|
+
/** Shared recording object ID, unless `recording` is PTB-local. */
|
|
149
|
+
recordingId?: string;
|
|
150
|
+
/** A recording returned by `createRecording` earlier in this same PTB. */
|
|
151
|
+
recording?: TransactionObjectArgument;
|
|
152
|
+
recordingAdminCapId?: string;
|
|
153
|
+
recordingAdminCap?: TransactionObjectArgument;
|
|
154
|
+
/** Share type of the recording (the track's `RecordingShare` phantom). */
|
|
155
|
+
recordingShareType: string;
|
|
156
|
+
/** Share type of the parent composition (the track's `CompositionShare` phantom). */
|
|
157
|
+
compositionShareType: string;
|
|
158
|
+
targetReleaseId: string;
|
|
159
|
+
trackSplitBps: number;
|
|
160
|
+
misoPackageId: string;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* PRIMITIVE. Appends `track::new` and returns its by-value `Track`. A track has
|
|
165
|
+
* `drop, store`, so callers may leave it unused; to assemble a release, pass
|
|
166
|
+
* returned tracks to `tx.makeMoveVec({ type: `${misoPackageId}::track::Track`,
|
|
167
|
+
* elements })` and then pass that vector to `createRelease` with its shared
|
|
168
|
+
* `ReleaseRegistry` object.
|
|
169
|
+
*
|
|
170
|
+
* The `recordingAdminCap` may be passed as an on-chain object id
|
|
171
|
+
* (`recordingAdminCapId`) or as a PTB-local argument (`recordingAdminCap`) —
|
|
172
|
+
* the latter lets a track be created against a recording created earlier in the
|
|
173
|
+
* same transaction, before its cap has been transferred anywhere.
|
|
174
|
+
*/
|
|
175
|
+
export function createTrack(tx: Transaction, params: CreateTrackParams): TransactionObjectArgument {
|
|
176
|
+
if (!params.recordingAdminCap && !params.recordingAdminCapId) {
|
|
177
|
+
throw new Error("createTrack: recordingAdminCapId or recordingAdminCap required");
|
|
178
|
+
}
|
|
179
|
+
if (!params.recording && !params.recordingId) {
|
|
180
|
+
throw new Error("createTrack: recordingId or recording required");
|
|
181
|
+
}
|
|
182
|
+
const adminCapArg = params.recordingAdminCap ?? tx.object(params.recordingAdminCapId!);
|
|
183
|
+
const recordingArg = params.recording ?? tx.object(params.recordingId!);
|
|
184
|
+
return tx.add(
|
|
185
|
+
track._new({
|
|
186
|
+
package: params.misoPackageId,
|
|
187
|
+
typeArguments: [params.recordingShareType, params.compositionShareType],
|
|
188
|
+
arguments: [
|
|
189
|
+
adminCapArg,
|
|
190
|
+
recordingArg,
|
|
191
|
+
tx.pure.id(params.targetReleaseId),
|
|
192
|
+
tx.pure.u16(params.trackSplitBps),
|
|
193
|
+
],
|
|
194
|
+
}),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ============================================================================
|
|
199
|
+
// Publish finalizers
|
|
200
|
+
// ============================================================================
|
|
201
|
+
|
|
202
|
+
/** Consume and share an initialized composition. The generated call supplies Clock. */
|
|
203
|
+
export function publishComposition(
|
|
204
|
+
tx: Transaction,
|
|
205
|
+
params: {
|
|
206
|
+
composition: TransactionObjectArgument;
|
|
207
|
+
adminCap: TransactionObjectArgument;
|
|
208
|
+
shareType: string;
|
|
209
|
+
misoPackageId: string;
|
|
210
|
+
},
|
|
211
|
+
): void {
|
|
212
|
+
tx.add(
|
|
213
|
+
composition.publish({
|
|
214
|
+
package: params.misoPackageId,
|
|
215
|
+
typeArguments: [params.shareType],
|
|
216
|
+
arguments: [params.composition, params.adminCap],
|
|
217
|
+
}),
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Consume and share an initialized recording. The generated call supplies Clock. */
|
|
222
|
+
export function publishRecording(
|
|
223
|
+
tx: Transaction,
|
|
224
|
+
params: {
|
|
225
|
+
recording: TransactionObjectArgument;
|
|
226
|
+
adminCap: TransactionObjectArgument;
|
|
227
|
+
recordingShareType: string;
|
|
228
|
+
compositionShareType: string;
|
|
229
|
+
misoPackageId: string;
|
|
230
|
+
},
|
|
231
|
+
): void {
|
|
232
|
+
tx.add(
|
|
233
|
+
recording.publish({
|
|
234
|
+
package: params.misoPackageId,
|
|
235
|
+
typeArguments: [params.recordingShareType, params.compositionShareType],
|
|
236
|
+
arguments: [params.recording, params.adminCap],
|
|
237
|
+
}),
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Consume and share an initialized release. The generated call supplies Clock. */
|
|
242
|
+
export function publishRelease(
|
|
243
|
+
tx: Transaction,
|
|
244
|
+
params: {
|
|
245
|
+
release: TransactionObjectArgument;
|
|
246
|
+
adminCap: TransactionObjectArgument;
|
|
247
|
+
misoPackageId: string;
|
|
248
|
+
},
|
|
249
|
+
): void {
|
|
250
|
+
tx.add(
|
|
251
|
+
release.publish({
|
|
252
|
+
package: params.misoPackageId,
|
|
253
|
+
arguments: [params.release, params.adminCap],
|
|
254
|
+
}),
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// ============================================================================
|
|
259
|
+
// Core release registry
|
|
260
|
+
// ============================================================================
|
|
261
|
+
|
|
262
|
+
/** The by-value result of core `release::new`. Publish it in this PTB. */
|
|
263
|
+
export interface ReleaseParts {
|
|
264
|
+
release: TransactionObjectArgument;
|
|
265
|
+
adminCap: TransactionObjectArgument;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface CreateReleaseParams {
|
|
269
|
+
/** Shared, canonical `miso::release::ReleaseRegistry` object ID. */
|
|
270
|
+
releaseRegistryId: string;
|
|
271
|
+
title: string;
|
|
272
|
+
/** `Track` values returned by {@link createTrack}; all are consumed. */
|
|
273
|
+
tracks: readonly TransactionObjectArgument[];
|
|
274
|
+
nonce: UnsignedInput;
|
|
275
|
+
/** Freshly published core `miso` package ID. */
|
|
276
|
+
misoPackageId: string;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Assemble a release through core `miso::release::new`. The registry is the
|
|
281
|
+
* first object argument; there is no arbitrary-parent or utility-package path.
|
|
282
|
+
* Both returned values are non-drop and must be published or otherwise consumed
|
|
283
|
+
* in this PTB.
|
|
284
|
+
*/
|
|
285
|
+
export function createRelease(
|
|
286
|
+
tx: Transaction,
|
|
287
|
+
params: CreateReleaseParams,
|
|
288
|
+
): ReleaseParts {
|
|
289
|
+
const tracks = tx.makeMoveVec({
|
|
290
|
+
type: `${params.misoPackageId}::track::Track`,
|
|
291
|
+
elements: [...params.tracks],
|
|
292
|
+
});
|
|
293
|
+
const result = tx.add(
|
|
294
|
+
release._new({
|
|
295
|
+
package: params.misoPackageId,
|
|
296
|
+
arguments: [
|
|
297
|
+
tx.object(params.releaseRegistryId),
|
|
298
|
+
tx.pure.string(params.title),
|
|
299
|
+
tracks,
|
|
300
|
+
tx.pure.u256(asU256("release nonce", params.nonce)),
|
|
301
|
+
],
|
|
302
|
+
}),
|
|
303
|
+
);
|
|
304
|
+
return { release: result[0]!, adminCap: result[1]! };
|
|
305
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// Copyright (c) Miso Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Common
|
|
6
|
+
// ============================================================================
|
|
7
|
+
|
|
8
|
+
/** Basis points value (0-10000, where 10000 = 100%). */
|
|
9
|
+
export interface BPS {
|
|
10
|
+
value: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Composition
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
/** Lifecycle state of a composition. */
|
|
18
|
+
export type CompositionState =
|
|
19
|
+
| { type: "Initialized" }
|
|
20
|
+
| { type: "Published"; timestampMs: number };
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A musical composition representing the underlying written work.
|
|
24
|
+
*
|
|
25
|
+
* Compositions are the written musical works (songs, instrumentals) that
|
|
26
|
+
* recordings are based on. Each composition has its own share token for
|
|
27
|
+
* ownership distribution.
|
|
28
|
+
*
|
|
29
|
+
* State machine: Initialized -> Published (immutable after publish)
|
|
30
|
+
*/
|
|
31
|
+
export interface Composition {
|
|
32
|
+
/** Unique identifier for this composition. */
|
|
33
|
+
id: string;
|
|
34
|
+
/** Current lifecycle state. */
|
|
35
|
+
state: CompositionState;
|
|
36
|
+
/** Primary title of the composition. */
|
|
37
|
+
title: string;
|
|
38
|
+
/**
|
|
39
|
+
* Royalty rate this composition earns from each recording's revenue (basis
|
|
40
|
+
* points, 0-10000). Immutable for the composition's lifetime.
|
|
41
|
+
*/
|
|
42
|
+
royaltyRate: BPS;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Emitted once when a composition is published. A pure pointer carrying only the
|
|
47
|
+
* composition's identity — an indexer fetches the full immutable object by
|
|
48
|
+
* `compositionId`.
|
|
49
|
+
*/
|
|
50
|
+
export interface CompositionPublishedEvent {
|
|
51
|
+
compositionId: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Admin cap for a Composition, derived deterministically from the Composition object ID.
|
|
56
|
+
*
|
|
57
|
+
* The share type parameter T is extracted from the on-chain type
|
|
58
|
+
* `CompositionAdminCap<T>` where T is the composition's share token type.
|
|
59
|
+
*/
|
|
60
|
+
export interface CompositionAdminCap {
|
|
61
|
+
/** The object ID of the admin cap. */
|
|
62
|
+
id: string;
|
|
63
|
+
/** The share type parameter T from CompositionAdminCap<T>. */
|
|
64
|
+
shareType: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// Recording
|
|
69
|
+
// ============================================================================
|
|
70
|
+
|
|
71
|
+
/** Lifecycle state of a recording. */
|
|
72
|
+
export type RecordingState =
|
|
73
|
+
| { type: "Initialized" }
|
|
74
|
+
| { type: "Published"; timestampMs: number };
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* An audio recording of a composition.
|
|
78
|
+
*
|
|
79
|
+
* Recordings are the audio performances that are distributed and played.
|
|
80
|
+
* Each recording has its own share token for ownership distribution.
|
|
81
|
+
*
|
|
82
|
+
* A recording carries no name of its own: its display title is its
|
|
83
|
+
* composition's title, resolved through the recording's `CompositionShare`
|
|
84
|
+
* type parameter. Richer naming ("(Live)", localized titles) lives in the
|
|
85
|
+
* metadata extension.
|
|
86
|
+
*
|
|
87
|
+
* State machine: Initialized -> Published (immutable after publish)
|
|
88
|
+
*/
|
|
89
|
+
export interface Recording {
|
|
90
|
+
/** Unique identifier for this recording. */
|
|
91
|
+
id: string;
|
|
92
|
+
/** Current lifecycle state. */
|
|
93
|
+
state: RecordingState;
|
|
94
|
+
/**
|
|
95
|
+
* Object ID of the parent composition. An identity/membership handle — not a
|
|
96
|
+
* revenue routing target: the composition is paid via its recording-share
|
|
97
|
+
* ownership, settled at recording creation. Immutable.
|
|
98
|
+
*/
|
|
99
|
+
compositionId: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Emitted once when a recording is published. A pure pointer carrying only the
|
|
104
|
+
* recording's identity — an indexer fetches the full immutable object by
|
|
105
|
+
* `recordingId`.
|
|
106
|
+
*/
|
|
107
|
+
export interface RecordingPublishedEvent {
|
|
108
|
+
recordingId: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Emitted when recording creation grants the composition its immutable royalty
|
|
113
|
+
* rate's share of the new recording currency.
|
|
114
|
+
*/
|
|
115
|
+
export interface CompositionSharesGrantedEvent {
|
|
116
|
+
recordingId: string;
|
|
117
|
+
compositionId: string;
|
|
118
|
+
/** Recording-share base units sent to the composition address. */
|
|
119
|
+
value: string;
|
|
120
|
+
/** The immutable composition royalty rate applied at recording creation. */
|
|
121
|
+
rateBps: number;
|
|
122
|
+
grantedBy: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Admin cap for a Recording, derived deterministically from the Recording object ID.
|
|
127
|
+
*
|
|
128
|
+
* The share type parameter T is extracted from the on-chain type
|
|
129
|
+
* `RecordingAdminCap<T>` where T is the recording's share token type.
|
|
130
|
+
*/
|
|
131
|
+
export interface RecordingAdminCap {
|
|
132
|
+
/** The object ID of the admin cap. */
|
|
133
|
+
id: string;
|
|
134
|
+
/** The share type parameter T from RecordingAdminCap<T>. */
|
|
135
|
+
shareType: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Track
|
|
139
|
+
// ============================================================================
|
|
140
|
+
|
|
141
|
+
/** Lifecycle state of a track on a release. */
|
|
142
|
+
export type TrackState = "Unassigned" | "Assigned";
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* A track on a release, linking a recording to its position in the tracklist.
|
|
146
|
+
* The recording is the handle through which all other metadata (share types,
|
|
147
|
+
* composition lineage, and — via the composition — the display title) is
|
|
148
|
+
* reached.
|
|
149
|
+
*/
|
|
150
|
+
export interface Track {
|
|
151
|
+
/** Current state of the track (Unassigned until the release claims it, then Assigned). */
|
|
152
|
+
state: TrackState;
|
|
153
|
+
/**
|
|
154
|
+
* ID of the composition underlying this track's recording. An identity/
|
|
155
|
+
* membership handle — not a revenue routing target: the composition is paid
|
|
156
|
+
* via its recording-share ownership, and a track routes its full split to the
|
|
157
|
+
* recording.
|
|
158
|
+
*/
|
|
159
|
+
compositionId: string;
|
|
160
|
+
/** ID of the recording on this track. */
|
|
161
|
+
recordingId: string;
|
|
162
|
+
/** Revenue split for this track within the release (in basis points). */
|
|
163
|
+
splitBps: BPS;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ============================================================================
|
|
167
|
+
// Release
|
|
168
|
+
// ============================================================================
|
|
169
|
+
|
|
170
|
+
/** Lifecycle state of a release. */
|
|
171
|
+
export type ReleaseState =
|
|
172
|
+
| { type: "Initialized" }
|
|
173
|
+
| { type: "Published"; timestampMs: number };
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* A music release (album, EP, or single).
|
|
177
|
+
*
|
|
178
|
+
* A release is a flat, ordered tracklist with per-track revenue distribution
|
|
179
|
+
* configuration. Display grouping (discs, vinyl sides), cover art, and edition
|
|
180
|
+
* naming live in extensions — the stored tracklist has the same shape as the
|
|
181
|
+
* digest pre-image every track consented to.
|
|
182
|
+
*
|
|
183
|
+
* State machine: Initialized -> Published (immutable after publish)
|
|
184
|
+
*/
|
|
185
|
+
export interface Release {
|
|
186
|
+
/** Unique identifier for this release. */
|
|
187
|
+
id: string;
|
|
188
|
+
/** Current lifecycle state. */
|
|
189
|
+
state: ReleaseState;
|
|
190
|
+
/** Title of the release. */
|
|
191
|
+
title: string;
|
|
192
|
+
/** The ordered tracklist. */
|
|
193
|
+
tracks: Track[];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Emitted once when a release is published. A pure pointer carrying only the
|
|
198
|
+
* release's identity — an indexer fetches the full immutable object by
|
|
199
|
+
* `releaseId`.
|
|
200
|
+
*/
|
|
201
|
+
export interface ReleasePublishedEvent {
|
|
202
|
+
releaseId: string;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Emitted when package initialization shares the canonical release registry. */
|
|
206
|
+
export interface ReleaseRegistryCreatedEvent {
|
|
207
|
+
registryId: string;
|
|
208
|
+
createdBy: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Admin cap for a Release, derived deterministically from the Release object ID.
|
|
213
|
+
*
|
|
214
|
+
* Unlike Composition and Recording admin caps, ReleaseAdminCap is not generic
|
|
215
|
+
* (Release has no share type parameter) and stores a reference to its Release.
|
|
216
|
+
*/
|
|
217
|
+
export interface ReleaseAdminCap {
|
|
218
|
+
/** The object ID of the admin cap. */
|
|
219
|
+
id: string;
|
|
220
|
+
/** The object ID of the Release this cap administers. */
|
|
221
|
+
releaseId: string;
|
|
222
|
+
}
|
package/src/view.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Copyright (c) Miso Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
// Simulate-based reads (the `view` surface). These build a transaction and run it
|
|
5
|
+
// through the Core `simulateTransaction` API to read a computed value without
|
|
6
|
+
// changing state — used where the value is a pure function of inputs the chain
|
|
7
|
+
// derives (e.g. the deterministic release id).
|
|
8
|
+
|
|
9
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
10
|
+
import { bcs } from "@mysten/sui/bcs";
|
|
11
|
+
import type { ClientWithCoreApi } from "@mysten/sui/client";
|
|
12
|
+
import * as release from "./contracts/musicos/release.ts";
|
|
13
|
+
import { asU256, asU64, type UnsignedInput } from "./numeric.ts";
|
|
14
|
+
|
|
15
|
+
export interface DeriveTargetReleaseIdParams {
|
|
16
|
+
/** Sender for the simulation (any address; not charged). */
|
|
17
|
+
sender: string;
|
|
18
|
+
/** Recording object ids, in track order. */
|
|
19
|
+
recordingIds: string[];
|
|
20
|
+
/** Per-track split basis points, aligned to `recordingIds`. */
|
|
21
|
+
splitBps: UnsignedInput[];
|
|
22
|
+
/** The release nonce (u256 as a decimal string). */
|
|
23
|
+
nonce: UnsignedInput;
|
|
24
|
+
/** Shared canonical core `miso::release::ReleaseRegistry` object ID. */
|
|
25
|
+
releaseRegistryId: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Derives the release id the on-chain `release::new` will produce for these
|
|
30
|
+
* inputs, via a `simulateTransaction` call to `release::derive_target_release_id`.
|
|
31
|
+
* Tracks embedded in a release must reference this exact ID, so it is computed
|
|
32
|
+
* up front and threaded into the core release builder.
|
|
33
|
+
*/
|
|
34
|
+
export async function deriveTargetReleaseId(
|
|
35
|
+
client: ClientWithCoreApi,
|
|
36
|
+
misoPackageId: string,
|
|
37
|
+
params: DeriveTargetReleaseIdParams,
|
|
38
|
+
): Promise<string> {
|
|
39
|
+
if (params.recordingIds.length !== params.splitBps.length) {
|
|
40
|
+
throw new Error(`deriveTargetReleaseId: recordingIds (${params.recordingIds.length}) and splitBps (${params.splitBps.length}) length mismatch.`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const tx = new Transaction();
|
|
44
|
+
tx.setSender(params.sender);
|
|
45
|
+
tx.add(
|
|
46
|
+
release.deriveTargetReleaseId({
|
|
47
|
+
package: misoPackageId,
|
|
48
|
+
arguments: [
|
|
49
|
+
params.releaseRegistryId,
|
|
50
|
+
params.recordingIds,
|
|
51
|
+
params.splitBps.map((v) => asU64("track split bps", v)),
|
|
52
|
+
asU256("release nonce", params.nonce),
|
|
53
|
+
],
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// gRPC/Core equivalent of devInspect: simulate with per-command return values.
|
|
58
|
+
const res = await client.core.simulateTransaction({ transaction: tx, include: { commandResults: true } });
|
|
59
|
+
if (res.$kind !== "Transaction") {
|
|
60
|
+
throw new Error(`derive_target_release_id simulation failed: ${JSON.stringify(res.FailedTransaction.status)}`);
|
|
61
|
+
}
|
|
62
|
+
const returned = res.commandResults?.[0]?.returnValues?.[0]?.bcs;
|
|
63
|
+
if (!returned) throw new Error("derive_target_release_id returned no value.");
|
|
64
|
+
return bcs.Address.parse(returned);
|
|
65
|
+
}
|