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