@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,280 @@
|
|
|
1
|
+
/**************************************************************
|
|
2
|
+
* THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
|
|
3
|
+
**************************************************************/
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a musical composition (song, instrumental work) in musicos.
|
|
8
|
+
* Compositions are the underlying written works that recordings are based on. Each
|
|
9
|
+
* composition has its own share token for ownership distribution.
|
|
10
|
+
*
|
|
11
|
+
* ### Key Features:
|
|
12
|
+
*
|
|
13
|
+
* - Share token initialization with fixed supply (10M tokens, 6 decimals)
|
|
14
|
+
* - State machine: Initialized -> Published (embedded fields immutable after
|
|
15
|
+
* publish; dynamic fields remain extensible via `uid_mut`)
|
|
16
|
+
* - Deterministic addresses via derived object pattern
|
|
17
|
+
*
|
|
18
|
+
* Attribution (credits) is intentionally NOT part of core: it is display-oriented,
|
|
19
|
+
* varies across platforms, and is never read by the economics. It lives in a
|
|
20
|
+
* first-party credits extension attached via `uid_mut`, so core takes no
|
|
21
|
+
* dependency on an identity package and core publish enforces no attribution.
|
|
22
|
+
*
|
|
23
|
+
* ### Lifecycle and trust model
|
|
24
|
+
*
|
|
25
|
+
* A composition is `key`-only with no `drop`: a fresh `Initialized` object cannot
|
|
26
|
+
* be transferred, wrapped, publicly shared, or discarded, and its only by-value
|
|
27
|
+
* consumer is `publish`. Create-and-publish is therefore atomic by construction —
|
|
28
|
+
* an `Initialized` composition cannot outlive its creating transaction, and every
|
|
29
|
+
* composition that exists on-chain is `Published` and shared. There is
|
|
30
|
+
* deliberately no keep function; staged building must fit one transaction.
|
|
31
|
+
*
|
|
32
|
+
* `uid_mut` works in any lifecycle state and is permanent root over ALL dynamic
|
|
33
|
+
* fields on the object — including fields attached by other extensions. "Immutable
|
|
34
|
+
* after publish" covers the embedded fields only; extension-layer data stays
|
|
35
|
+
* admin-mutable in perpetuity. This is the designed extension surface, and it is
|
|
36
|
+
* the one trust assumption that never expires: integrators should model the cap
|
|
37
|
+
* holder as able to mutate or delete any extension data, forever.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
import { MoveEnum, MoveStruct, MoveTuple, normalizeMoveArguments, type RawTransactionArgument } from '../utils/index.ts';
|
|
41
|
+
import { bcs } from '@mysten/sui/bcs';
|
|
42
|
+
import type {} from "@mysten/bcs";
|
|
43
|
+
import { type Transaction } from '@mysten/sui/transactions';
|
|
44
|
+
import * as bps from './deps/bps/bps.ts';
|
|
45
|
+
const $moduleName = '@local-pkg/musicos::composition';
|
|
46
|
+
/** Lifecycle state of a composition. */
|
|
47
|
+
export const CompositionState = new MoveEnum({ name: `${$moduleName}::CompositionState`, fields: {
|
|
48
|
+
/** Composition is initialized but not published. */
|
|
49
|
+
Initialized: null,
|
|
50
|
+
/** Composition is published and immutable. Includes publication timestamp. */
|
|
51
|
+
Published: bcs.u64()
|
|
52
|
+
} });
|
|
53
|
+
export const Composition = new MoveStruct({ name: `${$moduleName}::Composition<phantom CompositionShare>`, fields: {
|
|
54
|
+
/** Unique identifier for this composition. */
|
|
55
|
+
id: bcs.Address,
|
|
56
|
+
/** Current lifecycle state. */
|
|
57
|
+
state: CompositionState,
|
|
58
|
+
/** Primary title of the composition. */
|
|
59
|
+
title: bcs.string(),
|
|
60
|
+
/** Royalty rate this composition earns from each recording's revenue. */
|
|
61
|
+
royalty_rate: bps.BPS
|
|
62
|
+
} });
|
|
63
|
+
export const CompositionAdminCap = new MoveStruct({ name: `${$moduleName}::CompositionAdminCap<phantom CompositionShare>`, fields: {
|
|
64
|
+
/** Unique identifier for this capability. */
|
|
65
|
+
id: bcs.Address
|
|
66
|
+
} });
|
|
67
|
+
export const CompositionAdminCapKey = new MoveTuple({ name: `${$moduleName}::CompositionAdminCapKey`, fields: [bcs.bool()] });
|
|
68
|
+
export const CompositionPublishedEvent = new MoveStruct({ name: `${$moduleName}::CompositionPublishedEvent<phantom CompositionShare>`, fields: {
|
|
69
|
+
composition_id: bcs.Address
|
|
70
|
+
} });
|
|
71
|
+
export interface NewArguments {
|
|
72
|
+
title: RawTransactionArgument<string>;
|
|
73
|
+
royaltyRateBps: RawTransactionArgument<number>;
|
|
74
|
+
shareCurrency: RawTransactionArgument<string>;
|
|
75
|
+
shareTreasuryCap: RawTransactionArgument<string>;
|
|
76
|
+
}
|
|
77
|
+
export interface NewOptions {
|
|
78
|
+
package?: string;
|
|
79
|
+
arguments: NewArguments | [
|
|
80
|
+
title: RawTransactionArgument<string>,
|
|
81
|
+
royaltyRateBps: RawTransactionArgument<number>,
|
|
82
|
+
shareCurrency: RawTransactionArgument<string>,
|
|
83
|
+
shareTreasuryCap: RawTransactionArgument<string>
|
|
84
|
+
];
|
|
85
|
+
typeArguments: [
|
|
86
|
+
string
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Creates a new composition with the given title and royalty rate.
|
|
91
|
+
*
|
|
92
|
+
* The rate is set once, here, and is immutable for the composition's lifetime: it
|
|
93
|
+
* is a permanent standing offer that recorders and share buyers can price against
|
|
94
|
+
* without trusting the admin. The protocol imposes no opinion on it beyond the
|
|
95
|
+
* arithmetic bound of 100% (10000 bps, enforced by `bps::new`). There is no floor
|
|
96
|
+
* — 0% is permitted (e.g. a generative recording with no authored composition) —
|
|
97
|
+
* and no protocol ceiling: an uncompetitive rate simply attracts no recordings.
|
|
98
|
+
* What rate is reasonable is a client-side concern; per-deal deviations settle as
|
|
99
|
+
* voluntary share transfers after recording creation. Initializes share tokens
|
|
100
|
+
* (10M supply, 6 decimals) and returns:
|
|
101
|
+
*
|
|
102
|
+
* - The composition object
|
|
103
|
+
* - Admin capability for the owner
|
|
104
|
+
* - Initial share token balance
|
|
105
|
+
*/
|
|
106
|
+
export function _new(options: NewOptions) {
|
|
107
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
108
|
+
const argumentsTypes = [
|
|
109
|
+
'0x1::string::String',
|
|
110
|
+
'u16',
|
|
111
|
+
null,
|
|
112
|
+
null
|
|
113
|
+
] satisfies (string | null)[];
|
|
114
|
+
const parameterNames = ["title", "royaltyRateBps", "shareCurrency", "shareTreasuryCap"];
|
|
115
|
+
return (tx: Transaction) => tx.moveCall({
|
|
116
|
+
package: packageAddress,
|
|
117
|
+
module: 'composition',
|
|
118
|
+
function: 'new',
|
|
119
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
120
|
+
typeArguments: options.typeArguments
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
export interface PublishArguments {
|
|
124
|
+
self: RawTransactionArgument<string>;
|
|
125
|
+
_: RawTransactionArgument<string>;
|
|
126
|
+
}
|
|
127
|
+
export interface PublishOptions {
|
|
128
|
+
package?: string;
|
|
129
|
+
arguments: PublishArguments | [
|
|
130
|
+
self: RawTransactionArgument<string>,
|
|
131
|
+
_: RawTransactionArgument<string>
|
|
132
|
+
];
|
|
133
|
+
typeArguments: [
|
|
134
|
+
string
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Publishes the composition, making its embedded fields immutable. Required State:
|
|
139
|
+
* Initialized
|
|
140
|
+
*
|
|
141
|
+
* Note: core enforces no attribution requirement — credits live in the credits
|
|
142
|
+
* extension and may be attached before or after publish via `uid_mut`.
|
|
143
|
+
*/
|
|
144
|
+
export function publish(options: PublishOptions) {
|
|
145
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
146
|
+
const argumentsTypes = [
|
|
147
|
+
null,
|
|
148
|
+
null,
|
|
149
|
+
'0x2::clock::Clock'
|
|
150
|
+
] satisfies (string | null)[];
|
|
151
|
+
const parameterNames = ["self", "_"];
|
|
152
|
+
return (tx: Transaction) => tx.moveCall({
|
|
153
|
+
package: packageAddress,
|
|
154
|
+
module: 'composition',
|
|
155
|
+
function: 'publish',
|
|
156
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
157
|
+
typeArguments: options.typeArguments
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
export interface TitleArguments {
|
|
161
|
+
self: RawTransactionArgument<string>;
|
|
162
|
+
}
|
|
163
|
+
export interface TitleOptions {
|
|
164
|
+
package?: string;
|
|
165
|
+
arguments: TitleArguments | [
|
|
166
|
+
self: RawTransactionArgument<string>
|
|
167
|
+
];
|
|
168
|
+
typeArguments: [
|
|
169
|
+
string
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
/** Returns the primary title. */
|
|
173
|
+
export function title(options: TitleOptions) {
|
|
174
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
175
|
+
const argumentsTypes = [
|
|
176
|
+
null
|
|
177
|
+
] satisfies (string | null)[];
|
|
178
|
+
const parameterNames = ["self"];
|
|
179
|
+
return (tx: Transaction) => tx.moveCall({
|
|
180
|
+
package: packageAddress,
|
|
181
|
+
module: 'composition',
|
|
182
|
+
function: 'title',
|
|
183
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
184
|
+
typeArguments: options.typeArguments
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
export interface RoyaltyRateArguments {
|
|
188
|
+
self: RawTransactionArgument<string>;
|
|
189
|
+
}
|
|
190
|
+
export interface RoyaltyRateOptions {
|
|
191
|
+
package?: string;
|
|
192
|
+
arguments: RoyaltyRateArguments | [
|
|
193
|
+
self: RawTransactionArgument<string>
|
|
194
|
+
];
|
|
195
|
+
typeArguments: [
|
|
196
|
+
string
|
|
197
|
+
];
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Returns the royalty rate this composition earns from each recording. Immutable
|
|
201
|
+
* for the composition's lifetime — the value read here is, by construction, the
|
|
202
|
+
* value `recording::new` will apply.
|
|
203
|
+
*/
|
|
204
|
+
export function royaltyRate(options: RoyaltyRateOptions) {
|
|
205
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
206
|
+
const argumentsTypes = [
|
|
207
|
+
null
|
|
208
|
+
] satisfies (string | null)[];
|
|
209
|
+
const parameterNames = ["self"];
|
|
210
|
+
return (tx: Transaction) => tx.moveCall({
|
|
211
|
+
package: packageAddress,
|
|
212
|
+
module: 'composition',
|
|
213
|
+
function: 'royalty_rate',
|
|
214
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
215
|
+
typeArguments: options.typeArguments
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
export interface UidArguments {
|
|
219
|
+
self: RawTransactionArgument<string>;
|
|
220
|
+
}
|
|
221
|
+
export interface UidOptions {
|
|
222
|
+
package?: string;
|
|
223
|
+
arguments: UidArguments | [
|
|
224
|
+
self: RawTransactionArgument<string>
|
|
225
|
+
];
|
|
226
|
+
typeArguments: [
|
|
227
|
+
string
|
|
228
|
+
];
|
|
229
|
+
}
|
|
230
|
+
/** Returns a reference to the composition's UID for reading dynamic fields. */
|
|
231
|
+
export function uid(options: UidOptions) {
|
|
232
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
233
|
+
const argumentsTypes = [
|
|
234
|
+
null
|
|
235
|
+
] satisfies (string | null)[];
|
|
236
|
+
const parameterNames = ["self"];
|
|
237
|
+
return (tx: Transaction) => tx.moveCall({
|
|
238
|
+
package: packageAddress,
|
|
239
|
+
module: 'composition',
|
|
240
|
+
function: 'uid',
|
|
241
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
242
|
+
typeArguments: options.typeArguments
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
export interface UidMutArguments {
|
|
246
|
+
self: RawTransactionArgument<string>;
|
|
247
|
+
_: RawTransactionArgument<string>;
|
|
248
|
+
}
|
|
249
|
+
export interface UidMutOptions {
|
|
250
|
+
package?: string;
|
|
251
|
+
arguments: UidMutArguments | [
|
|
252
|
+
self: RawTransactionArgument<string>,
|
|
253
|
+
_: RawTransactionArgument<string>
|
|
254
|
+
];
|
|
255
|
+
typeArguments: [
|
|
256
|
+
string
|
|
257
|
+
];
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Returns a mutable reference to the composition's UID. Requires the admin
|
|
261
|
+
* capability. Works in any lifecycle state — dynamic fields are the extension
|
|
262
|
+
* surface and stay admin-mutable after publish; only the embedded fields are
|
|
263
|
+
* frozen. The reference is root over every dynamic field on the object, including
|
|
264
|
+
* fields attached by other extensions.
|
|
265
|
+
*/
|
|
266
|
+
export function uidMut(options: UidMutOptions) {
|
|
267
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
268
|
+
const argumentsTypes = [
|
|
269
|
+
null,
|
|
270
|
+
null
|
|
271
|
+
] satisfies (string | null)[];
|
|
272
|
+
const parameterNames = ["self", "_"];
|
|
273
|
+
return (tx: Transaction) => tx.moveCall({
|
|
274
|
+
package: packageAddress,
|
|
275
|
+
module: 'composition',
|
|
276
|
+
function: 'uid_mut',
|
|
277
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
278
|
+
typeArguments: options.typeArguments
|
|
279
|
+
});
|
|
280
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**************************************************************
|
|
2
|
+
* THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
|
|
3
|
+
**************************************************************/
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Basis-points arithmetic with a newtype wrapper.
|
|
8
|
+
*
|
|
9
|
+
* 1 bps = 0.01%. 10_000 bps = 100%.
|
|
10
|
+
*
|
|
11
|
+
* Storage-optimal: `BPS` stores a `u16` (2 bytes), the tightest width that fits
|
|
12
|
+
* the `[0, 10_000]` range. Apply functions cover every standard integer width
|
|
13
|
+
* (`u8` through `u256`). Arithmetic on `u8`–`u128` widens to the next-larger type
|
|
14
|
+
* before multiplying. `u256` uses quotient/remainder decomposition and is total
|
|
15
|
+
* over its entire input domain.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { MoveTuple } from '../../../utils/index.ts';
|
|
19
|
+
import { bcs } from '@mysten/sui/bcs';
|
|
20
|
+
import type {} from "@mysten/bcs";
|
|
21
|
+
const $moduleName = 'bps::bps';
|
|
22
|
+
export const BPS = new MoveTuple({ name: `${$moduleName}::BPS`, fields: [bcs.u16()] });
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**************************************************************
|
|
2
|
+
* THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
|
|
3
|
+
**************************************************************/
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents an audio recording of a composition in musicos. Recordings are the
|
|
8
|
+
* audio performances that are distributed and played. Each recording has its own
|
|
9
|
+
* share token for ownership distribution.
|
|
10
|
+
*
|
|
11
|
+
* ### Key Features:
|
|
12
|
+
*
|
|
13
|
+
* - Share token initialization with fixed supply (10M tokens, 6 decimals)
|
|
14
|
+
* - State machine: Initialized -> Published (embedded fields immutable after
|
|
15
|
+
* publish; dynamic fields remain extensible via `uid_mut`, e.g. masters, and
|
|
16
|
+
* credits/attribution attached by the credits extension)
|
|
17
|
+
* - Deterministic addresses via derived object pattern
|
|
18
|
+
*
|
|
19
|
+
* Attribution (credits, primary/featured artists) is intentionally NOT part of
|
|
20
|
+
* core: it is display-oriented, varies across platforms, and is never read by the
|
|
21
|
+
* economics. It lives in a first-party credits extension attached via `uid_mut`,
|
|
22
|
+
* so core takes no dependency on an identity package and core publish enforces no
|
|
23
|
+
* attribution.
|
|
24
|
+
*
|
|
25
|
+
* A recording carries no name of its own. Its display title is its composition's
|
|
26
|
+
* title, read by reference — composition titles are immutable, so an embedded copy
|
|
27
|
+
* would carry no information. Anything that names this particular take — "(Live)",
|
|
28
|
+
* "Radio Edit", a translated title — has more than one correct rendering, which
|
|
29
|
+
* makes it presentation, and presentation lives in the metadata extension, never
|
|
30
|
+
* in the frozen core. Core stores what a recording _is_; extensions describe it.
|
|
31
|
+
*
|
|
32
|
+
* ### Lifecycle and trust model
|
|
33
|
+
*
|
|
34
|
+
* A recording is `key`-only with no `drop`: a fresh `Initialized` object cannot be
|
|
35
|
+
* transferred, wrapped, publicly shared, or discarded, and its only by-value
|
|
36
|
+
* consumer is `publish`. Create-and-publish is therefore atomic by construction —
|
|
37
|
+
* an `Initialized` recording cannot outlive its creating transaction, and every
|
|
38
|
+
* recording that exists on-chain is `Published` and shared. There is deliberately
|
|
39
|
+
* no keep function; staged building must fit one transaction.
|
|
40
|
+
*
|
|
41
|
+
* `uid_mut` works in any lifecycle state and is permanent root over ALL dynamic
|
|
42
|
+
* fields on the object — including fields attached by other extensions. "Immutable
|
|
43
|
+
* after publish" covers the embedded fields only; extension-layer data stays
|
|
44
|
+
* admin-mutable in perpetuity. This is the designed extension surface, and it is
|
|
45
|
+
* the one trust assumption that never expires: integrators should model the cap
|
|
46
|
+
* holder as able to mutate or delete any extension data, forever.
|
|
47
|
+
*
|
|
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 musicos 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.
|
|
57
|
+
*
|
|
58
|
+
* A recording is its own freshly-created object (`object::new`), not a derived
|
|
59
|
+
* child of its composition: `recording::new` takes a read-only `&Composition`
|
|
60
|
+
* (only to read its royalty rate and id), so publishing recordings under a
|
|
61
|
+
* composition neither contends on the composition's shared-object version nor
|
|
62
|
+
* collides on a per-composition index.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
import { MoveEnum, MoveStruct, MoveTuple, normalizeMoveArguments, type RawTransactionArgument } from '../utils/index.ts';
|
|
66
|
+
import { bcs } from '@mysten/sui/bcs';
|
|
67
|
+
import type {} from "@mysten/bcs";
|
|
68
|
+
import { type Transaction } from '@mysten/sui/transactions';
|
|
69
|
+
const $moduleName = '@local-pkg/musicos::recording';
|
|
70
|
+
/** Lifecycle state of a recording. */
|
|
71
|
+
export const RecordingState = new MoveEnum({ name: `${$moduleName}::RecordingState`, fields: {
|
|
72
|
+
/** Recording is being set up and can be modified. */
|
|
73
|
+
Initialized: null,
|
|
74
|
+
/** Recording is published and immutable. Includes publication timestamp. */
|
|
75
|
+
Published: bcs.u64()
|
|
76
|
+
} });
|
|
77
|
+
export const Recording = new MoveStruct({ name: `${$moduleName}::Recording<phantom RecordingShare, phantom CompositionShare>`, fields: {
|
|
78
|
+
/** Unique identifier for this recording. */
|
|
79
|
+
id: bcs.Address,
|
|
80
|
+
/** Current lifecycle state. */
|
|
81
|
+
state: RecordingState,
|
|
82
|
+
/**
|
|
83
|
+
* Object ID of the parent composition. The address-level counterpart of the
|
|
84
|
+
* `CompositionShare` phantom, set from the `&Composition` passed to `new` (the
|
|
85
|
+
* shared phantom proves the pairing). An identity handle — not a revenue routing
|
|
86
|
+
* target: the composition is paid through its recording-share ownership, settled
|
|
87
|
+
* at creation.
|
|
88
|
+
*/
|
|
89
|
+
composition_id: bcs.Address
|
|
90
|
+
} });
|
|
91
|
+
export const RecordingAdminCap = new MoveStruct({ name: `${$moduleName}::RecordingAdminCap<phantom RecordingShare>`, fields: {
|
|
92
|
+
/** Unique identifier for this capability. */
|
|
93
|
+
id: bcs.Address
|
|
94
|
+
} });
|
|
95
|
+
export const RecordingAdminCapKey = new MoveTuple({ name: `${$moduleName}::RecordingAdminCapKey`, fields: [bcs.bool()] });
|
|
96
|
+
export const RecordingPublishedEvent = new MoveStruct({ name: `${$moduleName}::RecordingPublishedEvent<phantom RecordingShare, phantom CompositionShare>`, fields: {
|
|
97
|
+
recording_id: bcs.Address
|
|
98
|
+
} });
|
|
99
|
+
export const CompositionSharesGrantedEvent = new MoveStruct({ name: `${$moduleName}::CompositionSharesGrantedEvent<phantom RecordingShare, phantom CompositionShare>`, fields: {
|
|
100
|
+
recording_id: bcs.Address,
|
|
101
|
+
composition_id: bcs.Address,
|
|
102
|
+
/** Recording-share base units granted to the composition. */
|
|
103
|
+
value: bcs.u64(),
|
|
104
|
+
/** The composition royalty rate applied at creation, in basis points. */
|
|
105
|
+
rate_bps: bcs.u16(),
|
|
106
|
+
granted_by: bcs.Address
|
|
107
|
+
} });
|
|
108
|
+
export interface NewArguments {
|
|
109
|
+
composition: RawTransactionArgument<string>;
|
|
110
|
+
shareCurrency: RawTransactionArgument<string>;
|
|
111
|
+
shareTreasuryCap: RawTransactionArgument<string>;
|
|
112
|
+
}
|
|
113
|
+
export interface NewOptions {
|
|
114
|
+
package?: string;
|
|
115
|
+
arguments: NewArguments | [
|
|
116
|
+
composition: RawTransactionArgument<string>,
|
|
117
|
+
shareCurrency: RawTransactionArgument<string>,
|
|
118
|
+
shareTreasuryCap: RawTransactionArgument<string>
|
|
119
|
+
];
|
|
120
|
+
typeArguments: [
|
|
121
|
+
string,
|
|
122
|
+
string
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Creates a new recording for a composition.
|
|
127
|
+
*
|
|
128
|
+
* Initializes share tokens (10M supply, 6 decimals), then splits the composition's
|
|
129
|
+
* royalty-rate worth of those shares off the freshly minted supply and
|
|
130
|
+
* `send_funds`es them to the composition's address. This settles the composition's
|
|
131
|
+
* cut as cap-table ownership: the composition literally owns its share of the
|
|
132
|
+
* recording, so its claim on recording revenue is enforced by share ownership
|
|
133
|
+
* rather than by any revenue distributor choosing to honor a rate. What the
|
|
134
|
+
* composition owner then does with the shares (hold, stake, sell) is outside the
|
|
135
|
+
* protocol's scope.
|
|
136
|
+
*
|
|
137
|
+
* The composition's royalty rate is immutable, so the rate a recorder's client
|
|
138
|
+
* displayed is exactly the rate applied here — no slippage protection is needed or
|
|
139
|
+
* possible. Whether that rate is acceptable is the recorder's decision to make
|
|
140
|
+
* before calling; per-deal deviations settle as voluntary share transfers after
|
|
141
|
+
* creation.
|
|
142
|
+
*
|
|
143
|
+
* The composition need not be `Published`: within the composition's own creating
|
|
144
|
+
* transaction its creator can already mint recordings against it. Third parties
|
|
145
|
+
* only ever see `Published`, shared compositions (an `Initialized` one cannot
|
|
146
|
+
* escape its creating transaction), so indexers may observe a recording created
|
|
147
|
+
* "against an unpublished composition" only as an intra-transaction ordering,
|
|
148
|
+
* never across transactions.
|
|
149
|
+
*
|
|
150
|
+
* Returns:
|
|
151
|
+
*
|
|
152
|
+
* - The recording object (typed to its parent composition's `CompositionShare`)
|
|
153
|
+
* - Admin capability for the owner
|
|
154
|
+
* - The creator's remaining share balance (full supply minus the composition's
|
|
155
|
+
* cut)
|
|
156
|
+
*/
|
|
157
|
+
export function _new(options: NewOptions) {
|
|
158
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
159
|
+
const argumentsTypes = [
|
|
160
|
+
null,
|
|
161
|
+
null,
|
|
162
|
+
null
|
|
163
|
+
] satisfies (string | null)[];
|
|
164
|
+
const parameterNames = ["composition", "shareCurrency", "shareTreasuryCap"];
|
|
165
|
+
return (tx: Transaction) => tx.moveCall({
|
|
166
|
+
package: packageAddress,
|
|
167
|
+
module: 'recording',
|
|
168
|
+
function: 'new',
|
|
169
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
170
|
+
typeArguments: options.typeArguments
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
export interface PublishArguments {
|
|
174
|
+
self: RawTransactionArgument<string>;
|
|
175
|
+
_: RawTransactionArgument<string>;
|
|
176
|
+
}
|
|
177
|
+
export interface PublishOptions {
|
|
178
|
+
package?: string;
|
|
179
|
+
arguments: PublishArguments | [
|
|
180
|
+
self: RawTransactionArgument<string>,
|
|
181
|
+
_: RawTransactionArgument<string>
|
|
182
|
+
];
|
|
183
|
+
typeArguments: [
|
|
184
|
+
string,
|
|
185
|
+
string
|
|
186
|
+
];
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Publishes the recording, making its embedded fields immutable. Required State:
|
|
190
|
+
* Initialized
|
|
191
|
+
*
|
|
192
|
+
* Note: core enforces no attribution requirement — credits live in the credits
|
|
193
|
+
* extension and may be attached before or after publish via `uid_mut`.
|
|
194
|
+
*/
|
|
195
|
+
export function publish(options: PublishOptions) {
|
|
196
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
197
|
+
const argumentsTypes = [
|
|
198
|
+
null,
|
|
199
|
+
null,
|
|
200
|
+
'0x2::clock::Clock'
|
|
201
|
+
] satisfies (string | null)[];
|
|
202
|
+
const parameterNames = ["self", "_"];
|
|
203
|
+
return (tx: Transaction) => tx.moveCall({
|
|
204
|
+
package: packageAddress,
|
|
205
|
+
module: 'recording',
|
|
206
|
+
function: 'publish',
|
|
207
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
208
|
+
typeArguments: options.typeArguments
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
export interface CompositionIdArguments {
|
|
212
|
+
self: RawTransactionArgument<string>;
|
|
213
|
+
}
|
|
214
|
+
export interface CompositionIdOptions {
|
|
215
|
+
package?: string;
|
|
216
|
+
arguments: CompositionIdArguments | [
|
|
217
|
+
self: RawTransactionArgument<string>
|
|
218
|
+
];
|
|
219
|
+
typeArguments: [
|
|
220
|
+
string,
|
|
221
|
+
string
|
|
222
|
+
];
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Returns the object ID of the parent composition. An identity/membership handle
|
|
226
|
+
* (the address-level counterpart of the `CompositionShare` phantom) — not a
|
|
227
|
+
* revenue routing target: the composition is paid via its recording-share
|
|
228
|
+
* ownership.
|
|
229
|
+
*/
|
|
230
|
+
export function compositionId(options: CompositionIdOptions) {
|
|
231
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
232
|
+
const argumentsTypes = [
|
|
233
|
+
null
|
|
234
|
+
] satisfies (string | null)[];
|
|
235
|
+
const parameterNames = ["self"];
|
|
236
|
+
return (tx: Transaction) => tx.moveCall({
|
|
237
|
+
package: packageAddress,
|
|
238
|
+
module: 'recording',
|
|
239
|
+
function: 'composition_id',
|
|
240
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
241
|
+
typeArguments: options.typeArguments
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
export interface UidArguments {
|
|
245
|
+
self: RawTransactionArgument<string>;
|
|
246
|
+
}
|
|
247
|
+
export interface UidOptions {
|
|
248
|
+
package?: string;
|
|
249
|
+
arguments: UidArguments | [
|
|
250
|
+
self: RawTransactionArgument<string>
|
|
251
|
+
];
|
|
252
|
+
typeArguments: [
|
|
253
|
+
string,
|
|
254
|
+
string
|
|
255
|
+
];
|
|
256
|
+
}
|
|
257
|
+
/** Returns a reference to the recording's UID for reading dynamic fields. */
|
|
258
|
+
export function uid(options: UidOptions) {
|
|
259
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
260
|
+
const argumentsTypes = [
|
|
261
|
+
null
|
|
262
|
+
] satisfies (string | null)[];
|
|
263
|
+
const parameterNames = ["self"];
|
|
264
|
+
return (tx: Transaction) => tx.moveCall({
|
|
265
|
+
package: packageAddress,
|
|
266
|
+
module: 'recording',
|
|
267
|
+
function: 'uid',
|
|
268
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
269
|
+
typeArguments: options.typeArguments
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
export interface UidMutArguments {
|
|
273
|
+
self: RawTransactionArgument<string>;
|
|
274
|
+
_: RawTransactionArgument<string>;
|
|
275
|
+
}
|
|
276
|
+
export interface UidMutOptions {
|
|
277
|
+
package?: string;
|
|
278
|
+
arguments: UidMutArguments | [
|
|
279
|
+
self: RawTransactionArgument<string>,
|
|
280
|
+
_: RawTransactionArgument<string>
|
|
281
|
+
];
|
|
282
|
+
typeArguments: [
|
|
283
|
+
string,
|
|
284
|
+
string
|
|
285
|
+
];
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Returns a mutable reference to the recording's UID. Requires the admin
|
|
289
|
+
* capability. Works in any lifecycle state — dynamic fields are the extension
|
|
290
|
+
* surface (e.g. masters, credits) and stay admin-mutable after publish; only the
|
|
291
|
+
* embedded fields are frozen. The reference is root over every dynamic field on
|
|
292
|
+
* the object, including fields attached by other extensions.
|
|
293
|
+
*/
|
|
294
|
+
export function uidMut(options: UidMutOptions) {
|
|
295
|
+
const packageAddress = options.package ?? '@local-pkg/musicos';
|
|
296
|
+
const argumentsTypes = [
|
|
297
|
+
null,
|
|
298
|
+
null
|
|
299
|
+
] satisfies (string | null)[];
|
|
300
|
+
const parameterNames = ["self", "_"];
|
|
301
|
+
return (tx: Transaction) => tx.moveCall({
|
|
302
|
+
package: packageAddress,
|
|
303
|
+
module: 'recording',
|
|
304
|
+
function: 'uid_mut',
|
|
305
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes, parameterNames),
|
|
306
|
+
typeArguments: options.typeArguments
|
|
307
|
+
});
|
|
308
|
+
}
|