@misofm/platform 0.20.0 → 0.21.1
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 +15 -17
- package/dist/deployments.d.ts +6 -2
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +3 -1
- package/dist/deployments.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/publication.d.ts +14 -2
- package/dist/publication.d.ts.map +1 -1
- package/dist/publication.js +4 -3
- package/dist/publication.js.map +1 -1
- package/dist/read/catalog.d.ts +1 -1
- package/dist/read/catalog.d.ts.map +1 -1
- package/dist/read/catalog.js +3 -16
- package/dist/read/catalog.js.map +1 -1
- package/dist/read/config.d.ts +0 -2
- package/dist/read/config.d.ts.map +1 -1
- package/dist/read/config.js.map +1 -1
- package/dist/read/internal/walrus.js +1 -1
- package/dist/read/internal/walrus.js.map +1 -1
- package/dist/read/types.d.ts +0 -2
- package/dist/read/types.d.ts.map +1 -1
- package/dist/recording-extensions.d.ts +32 -7
- package/dist/recording-extensions.d.ts.map +1 -1
- package/dist/recording-extensions.js +90 -8
- package/dist/recording-extensions.js.map +1 -1
- package/dist/walrus-ids.d.ts +11 -0
- package/dist/walrus-ids.d.ts.map +1 -0
- package/dist/walrus-ids.js +96 -0
- package/dist/walrus-ids.js.map +1 -0
- package/package.json +2 -8
- package/src/deployments.ts +8 -2
- package/src/index.ts +1 -2
- package/src/publication.ts +20 -5
- package/src/read/catalog.ts +2 -18
- package/src/read/config.ts +0 -2
- package/src/read/internal/walrus.ts +1 -1
- package/src/read/types.ts +0 -2
- package/src/recording-extensions.ts +127 -11
- package/src/walrus-ids.ts +102 -0
- package/dist/mix.d.ts +0 -130
- package/dist/mix.d.ts.map +0 -1
- package/dist/mix.js +0 -634
- package/dist/mix.js.map +0 -1
- package/src/mix.ts +0 -863
package/src/index.ts
CHANGED
|
@@ -49,7 +49,7 @@ export * from "./share-template.ts";
|
|
|
49
49
|
export * from "./release-graph.ts";
|
|
50
50
|
export * from "./publication.ts";
|
|
51
51
|
export * from "./catalog.ts";
|
|
52
|
-
export * from "./
|
|
52
|
+
export * from "./walrus-ids.ts";
|
|
53
53
|
|
|
54
54
|
// High-level, JSON-safe platform projections used directly by clients and by
|
|
55
55
|
// the thin HTTP read service. Namespaced because these composed view types are
|
|
@@ -62,7 +62,6 @@ export * from "./credits.ts";
|
|
|
62
62
|
export * from "./cover.ts";
|
|
63
63
|
export * from "./release-extensions.ts";
|
|
64
64
|
export * from "./recording-extensions.ts";
|
|
65
|
-
export * from "./mix.ts";
|
|
66
65
|
export * from "./vault.ts";
|
|
67
66
|
|
|
68
67
|
// Generated, ABI-bound bindings (BCS structs + type-safe Move calls).
|
package/src/publication.ts
CHANGED
|
@@ -150,6 +150,20 @@ type PublicationRecordingParent =
|
|
|
150
150
|
| { readonly parentCompositionIndex: number; readonly parentCompositionId?: never }
|
|
151
151
|
| { readonly parentCompositionIndex?: never; readonly parentCompositionId: string };
|
|
152
152
|
|
|
153
|
+
/** One stem a Session V1 document references, paired with its Walrus blob. */
|
|
154
|
+
export interface PublicationEngineSessionStem {
|
|
155
|
+
/** 32-byte SHA-256 of the stem's canonical PCM (engine STEM_IDENTITY_V1); bytes or 64 hex chars. */
|
|
156
|
+
readonly digest: Uint8Array | string;
|
|
157
|
+
/** Unencrypted Walrus blob holding the stem's FLAC, as its on-chain `u256`. */
|
|
158
|
+
readonly blobId: bigint | string;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export interface PublicationEngineSession {
|
|
162
|
+
/** Unencrypted Walrus blob holding the canonical Session V1 JSON, as its on-chain `u256`. */
|
|
163
|
+
readonly sessionBlobId: bigint | string;
|
|
164
|
+
readonly stems: readonly PublicationEngineSessionStem[];
|
|
165
|
+
}
|
|
166
|
+
|
|
153
167
|
export type PublicationRecordingLanguages =
|
|
154
168
|
| { readonly kind: "instrumental" }
|
|
155
169
|
| { readonly kind: "languages"; readonly codes: string[] };
|
|
@@ -173,8 +187,8 @@ export type PublicationRecording = PublicationRecordingParent & {
|
|
|
173
187
|
readonly masterReferenceBlobId?: bigint | string;
|
|
174
188
|
/** Complete Walrus Quilt ID containing this Recording's streaming transcodes. */
|
|
175
189
|
readonly streamingTranscodeQuiltId?: bigint | string;
|
|
176
|
-
/**
|
|
177
|
-
readonly
|
|
190
|
+
/** This Recording's Miso Engine session: the Session V1 blob and every stem it plays. */
|
|
191
|
+
readonly engineSession?: PublicationEngineSession;
|
|
178
192
|
};
|
|
179
193
|
|
|
180
194
|
export interface PublicationFreshTrack {
|
|
@@ -654,7 +668,7 @@ export function publishAtomicCatalog(p: AtomicPublicationParams): TxThunk {
|
|
|
654
668
|
);
|
|
655
669
|
}
|
|
656
670
|
if (
|
|
657
|
-
p.recordings.some((node) => node.
|
|
671
|
+
p.recordings.some((node) => node.engineSession !== undefined) &&
|
|
658
672
|
!p.deployment.packages.recordingEngineSession
|
|
659
673
|
) {
|
|
660
674
|
throw new Error(
|
|
@@ -878,13 +892,14 @@ export function publishAtomicCatalog(p: AtomicPublicationParams): TxThunk {
|
|
|
878
892
|
oriPackageId: p.deployment.packages.ori,
|
|
879
893
|
quiltId: node.streamingTranscodeQuiltId,
|
|
880
894
|
})(tx);
|
|
881
|
-
if (node.
|
|
895
|
+
if (node.engineSession !== undefined) setRecordingEngineSession({
|
|
882
896
|
recordingId: parts.work, authority,
|
|
883
897
|
recordingShareType: node.shareType,
|
|
884
898
|
compositionShareType: node.compositionShareType,
|
|
885
899
|
recordingEngineSessionPackageId: p.deployment.packages.recordingEngineSession!,
|
|
886
900
|
oriPackageId: p.deployment.packages.ori,
|
|
887
|
-
sessionBlobId: node.
|
|
901
|
+
sessionBlobId: node.engineSession.sessionBlobId,
|
|
902
|
+
stems: node.engineSession.stems,
|
|
888
903
|
})(tx);
|
|
889
904
|
});
|
|
890
905
|
|
package/src/read/catalog.ts
CHANGED
|
@@ -38,10 +38,6 @@ import {
|
|
|
38
38
|
releaseKindFieldId,
|
|
39
39
|
} from "../release-extensions.ts";
|
|
40
40
|
import { getRecordingMasterReferencesByIds } from "../recording-extensions.ts";
|
|
41
|
-
import {
|
|
42
|
-
getReleaseMixReferences,
|
|
43
|
-
walrusBlobIdFromU256,
|
|
44
|
-
} from "../mix.ts";
|
|
45
41
|
import { getTrackCreditsByRecordingIds } from "../catalog.ts";
|
|
46
42
|
import { getReleaseById, getReleasesByIds, isNotFound } from "@misofm/protocol";
|
|
47
43
|
import type { Release } from "@misofm/protocol";
|
|
@@ -203,11 +199,9 @@ export function toTracks(
|
|
|
203
199
|
release: Release,
|
|
204
200
|
titles: Record<string, string>,
|
|
205
201
|
masterBlobIds: Partial<Record<string, string>>,
|
|
206
|
-
mixBlobIds: Partial<Record<number, string>> = {},
|
|
207
202
|
): TrackView[] {
|
|
208
203
|
return release.tracks.map((track, index) => {
|
|
209
204
|
const masterBlobId = masterBlobIds[track.recordingId];
|
|
210
|
-
const mixBlobId = mixBlobIds[index];
|
|
211
205
|
return {
|
|
212
206
|
no: `${index + 1}`,
|
|
213
207
|
title: titles[track.recordingId] ?? "Untitled",
|
|
@@ -216,7 +210,6 @@ export function toTracks(
|
|
|
216
210
|
splitBps: int(track.splitBps.value),
|
|
217
211
|
disc: 1,
|
|
218
212
|
...(masterBlobId ? { masterBlobId } : {}),
|
|
219
|
-
...(mixBlobId ? { mixBlobId } : {}),
|
|
220
213
|
};
|
|
221
214
|
});
|
|
222
215
|
}
|
|
@@ -364,8 +357,7 @@ export async function getReleaseDetail(
|
|
|
364
357
|
);
|
|
365
358
|
|
|
366
359
|
const recordingIds = release.tracks.map((track) => track.recordingId);
|
|
367
|
-
const
|
|
368
|
-
const [titles, masterReferences, mixReferences, trackCredits] = await Promise.all([
|
|
360
|
+
const [titles, masterReferences, trackCredits] = await Promise.all([
|
|
369
361
|
getRecordingTitles(
|
|
370
362
|
client.protocol,
|
|
371
363
|
client.graphql,
|
|
@@ -377,9 +369,6 @@ export async function getReleaseDetail(
|
|
|
377
369
|
recordingIds,
|
|
378
370
|
client.config.protocol.recordingMasterReference,
|
|
379
371
|
).catch(() => ({})),
|
|
380
|
-
mixPackageId
|
|
381
|
-
? getReleaseMixReferences(client.protocol, releaseId, mixPackageId).catch(() => null)
|
|
382
|
-
: Promise.resolve(null),
|
|
383
372
|
options.include?.includes("trackCredits")
|
|
384
373
|
? getTrackCreditsForRecordingIds(client, recordingIds)
|
|
385
374
|
: Promise.resolve(undefined),
|
|
@@ -388,11 +377,6 @@ export async function getReleaseDetail(
|
|
|
388
377
|
for (const [recordingId, blobId] of Object.entries(masterReferences)) {
|
|
389
378
|
if (blobId) masterBlobIds[recordingId] = u256ToB64Url(blobId);
|
|
390
379
|
}
|
|
391
|
-
const mixBlobIds: Record<number, string> = {};
|
|
392
|
-
for (let index = 0; index < (mixReferences?.length ?? 0); index += 1) {
|
|
393
|
-
const reference = mixReferences?.[index];
|
|
394
|
-
if (reference) mixBlobIds[index] = walrusBlobIdFromU256(reference.blobId);
|
|
395
|
-
}
|
|
396
380
|
|
|
397
381
|
const creditViews = credits ?? [];
|
|
398
382
|
return {
|
|
@@ -407,7 +391,7 @@ export async function getReleaseDetail(
|
|
|
407
391
|
credits: creditViews,
|
|
408
392
|
primaryArtists: primaryArtistNames(creditViews),
|
|
409
393
|
discCount: release.tracks.length > 0 ? 1 : 0,
|
|
410
|
-
tracks: toTracks(release, titles, masterBlobIds
|
|
394
|
+
tracks: toTracks(release, titles, masterBlobIds),
|
|
411
395
|
...(trackCredits !== undefined ? { trackCredits } : {}),
|
|
412
396
|
};
|
|
413
397
|
}
|
package/src/read/config.ts
CHANGED
|
@@ -33,8 +33,6 @@ export interface ProtocolIds {
|
|
|
33
33
|
releaseKind: string;
|
|
34
34
|
/** `recording_master_reference` — optional Walrus master pointers. */
|
|
35
35
|
recordingMasterReference: string;
|
|
36
|
-
/** `release_mix_reference` — optional per-track delivery descriptor pointers. */
|
|
37
|
-
releaseMixReference?: string;
|
|
38
36
|
/** `composition_credits` / `recording_credits` / `release_credits` extensions. */
|
|
39
37
|
compositionCredits: string;
|
|
40
38
|
recordingCredits: string;
|
package/src/read/types.ts
CHANGED
|
@@ -76,8 +76,6 @@ export interface TrackView {
|
|
|
76
76
|
disc: number;
|
|
77
77
|
/** Base64url Walrus blob id for the master stream, when attached on-chain. */
|
|
78
78
|
masterBlobId?: string;
|
|
79
|
-
/** Base64url Walrus blob id for the public mix-delivery descriptor. */
|
|
80
|
-
mixBlobId?: string;
|
|
81
79
|
}
|
|
82
80
|
|
|
83
81
|
/** A release with everything a page renders: metadata, cover, credits, tracklist. */
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
import { bcs } from "@mysten/sui/bcs";
|
|
7
7
|
import type { ClientWithCoreApi } from "@mysten/sui/client";
|
|
8
8
|
import type { Transaction, TransactionArgument, TransactionObjectArgument } from "@mysten/sui/transactions";
|
|
9
|
-
import { deriveDynamicFieldID } from "@mysten/sui/utils";
|
|
9
|
+
import { deriveDynamicFieldID, fromHex, toHex } from "@mysten/sui/utils";
|
|
10
|
+
import { isNotFound } from "@misofm/protocol";
|
|
10
11
|
import type { TxThunk } from "./transactions.ts";
|
|
11
12
|
import { invokeWithAdminCap, type AdminCapAuthority, type ObjectInput } from "./vault.ts";
|
|
12
13
|
import * as advisory from "@misofm/protocol/contracts/recording_advisory/recording_advisory";
|
|
@@ -132,28 +133,76 @@ export type UnsetRecordingStreamingTranscodeParams = Omit<
|
|
|
132
133
|
"oriPackageId" | "quiltId"
|
|
133
134
|
>;
|
|
134
135
|
|
|
136
|
+
/** One stem a Session V1 document references, paired with its Walrus blob. */
|
|
137
|
+
export interface RecordingEngineSessionStemInput {
|
|
138
|
+
/** 32-byte SHA-256 of the stem's canonical PCM (engine STEM_IDENTITY_V1): raw bytes or 64 hex chars. */
|
|
139
|
+
readonly digest: Uint8Array | string;
|
|
140
|
+
/** Unencrypted Walrus blob holding the stem's FLAC, as its on-chain `u256`. */
|
|
141
|
+
readonly blobId: bigint | string;
|
|
142
|
+
}
|
|
143
|
+
|
|
135
144
|
export interface SetRecordingEngineSessionParams extends RecordingExtensionTarget {
|
|
136
145
|
readonly recordingEngineSessionPackageId: string;
|
|
137
|
-
/** External `ori` package used to construct the plaintext Walrus blob
|
|
146
|
+
/** External `ori` package used to construct the plaintext Walrus blob references. */
|
|
138
147
|
readonly oriPackageId: string;
|
|
139
|
-
/** Unencrypted Walrus blob
|
|
148
|
+
/** Unencrypted Walrus blob holding the canonical Session V1 JSON, as its on-chain `u256`. */
|
|
140
149
|
readonly sessionBlobId: bigint | string;
|
|
150
|
+
/** Every stem the document's sources reference. Order does not matter; the builder sorts. */
|
|
151
|
+
readonly stems: readonly RecordingEngineSessionStemInput[];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const STEM_DIGEST_BYTES = 32;
|
|
155
|
+
|
|
156
|
+
function stemDigestBytes(digest: Uint8Array | string): Uint8Array {
|
|
157
|
+
const bytes = typeof digest === "string" ? fromHex(digest) : digest;
|
|
158
|
+
if (bytes.length !== STEM_DIGEST_BYTES) {
|
|
159
|
+
throw new Error(`stem digest must be ${STEM_DIGEST_BYTES} bytes`);
|
|
160
|
+
}
|
|
161
|
+
return bytes;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function compareBytes(a: Uint8Array, b: Uint8Array): number {
|
|
165
|
+
for (let index = 0; index < a.length; index += 1) {
|
|
166
|
+
if (a[index] !== b[index]) return a[index]! - b[index]!;
|
|
167
|
+
}
|
|
168
|
+
return 0;
|
|
141
169
|
}
|
|
142
170
|
|
|
143
171
|
/**
|
|
144
|
-
* Sets or replaces the Miso Engine session
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
172
|
+
* Sets or replaces the Miso Engine session attached to a Recording: the
|
|
173
|
+
* Session V1 blob plus one `Stem` per source. Stems are sorted by digest and
|
|
174
|
+
* checked for duplicates here, mirroring `recording_engine_session::new`, so a
|
|
175
|
+
* bad input fails before signing rather than on chain.
|
|
148
176
|
*/
|
|
149
177
|
export function setRecordingEngineSession(p: SetRecordingEngineSessionParams): TxThunk {
|
|
178
|
+
const stems = p.stems
|
|
179
|
+
.map((stem) => ({ digest: stemDigestBytes(stem.digest), blobId: stem.blobId }))
|
|
180
|
+
.sort((a, b) => compareBytes(a.digest, b.digest));
|
|
181
|
+
for (let index = 1; index < stems.length; index += 1) {
|
|
182
|
+
if (compareBytes(stems[index - 1]!.digest, stems[index]!.digest) === 0) {
|
|
183
|
+
throw new Error(`duplicate stem digest ${toHex(stems[index]!.digest)}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
150
186
|
return (tx) => {
|
|
187
|
+
const pkg = p.recordingEngineSessionPackageId;
|
|
188
|
+
const sessionBlob = unencryptedWalrusBlob(tx, p.oriPackageId, p.sessionBlobId);
|
|
189
|
+
const stemValues = stems.map((stem) => tx.add(engineSession.newStem({
|
|
190
|
+
package: pkg,
|
|
191
|
+
arguments: [
|
|
192
|
+
tx.pure.vector("u8", Array.from(stem.digest)),
|
|
193
|
+
unencryptedWalrusBlob(tx, p.oriPackageId, stem.blobId),
|
|
194
|
+
],
|
|
195
|
+
})));
|
|
196
|
+
const stemVector = tx.makeMoveVec({
|
|
197
|
+
type: `${pkg}::recording_engine_session::Stem`,
|
|
198
|
+
elements: stemValues,
|
|
199
|
+
});
|
|
151
200
|
const session = tx.add(engineSession._new({
|
|
152
|
-
package:
|
|
153
|
-
arguments: [
|
|
201
|
+
package: pkg,
|
|
202
|
+
arguments: [sessionBlob, stemVector],
|
|
154
203
|
}));
|
|
155
204
|
invokeWithAdminCap(tx, p.authority, {
|
|
156
|
-
target: `${
|
|
205
|
+
target: `${pkg}::recording_engine_session::set_engine_session`,
|
|
157
206
|
typeArguments: [p.recordingShareType, p.compositionShareType],
|
|
158
207
|
arguments: [object(tx, p.recordingId), session],
|
|
159
208
|
adminCapIndex: 1,
|
|
@@ -163,7 +212,7 @@ export function setRecordingEngineSession(p: SetRecordingEngineSessionParams): T
|
|
|
163
212
|
|
|
164
213
|
export type UnsetRecordingEngineSessionParams = Omit<
|
|
165
214
|
SetRecordingEngineSessionParams,
|
|
166
|
-
"oriPackageId" | "sessionBlobId"
|
|
215
|
+
"oriPackageId" | "sessionBlobId" | "stems"
|
|
167
216
|
>;
|
|
168
217
|
|
|
169
218
|
/** Removes the Recording's Miso Engine session reference, if present. */
|
|
@@ -192,6 +241,73 @@ export function unsetRecordingStreamingTranscode(
|
|
|
192
241
|
};
|
|
193
242
|
}
|
|
194
243
|
|
|
244
|
+
// ── Engine-session reads ─────────────────────────────────────────────────────
|
|
245
|
+
|
|
246
|
+
/** A Recording's attached engine session, ids as decimal `u256` strings. */
|
|
247
|
+
export interface RecordingEngineSessionView {
|
|
248
|
+
/** Unencrypted Walrus blob holding the canonical Session V1 JSON. */
|
|
249
|
+
readonly sessionBlobId: string;
|
|
250
|
+
/** Sorted by digest, as stored. `digest` is 64 lowercase hex chars. */
|
|
251
|
+
readonly stems: readonly { readonly digest: string; readonly blobId: string }[];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const EngineSessionField = bcs.struct("Field", {
|
|
255
|
+
id: bcs.Address,
|
|
256
|
+
name: engineSession.ExtensionKey,
|
|
257
|
+
value: engineSession.EngineSession,
|
|
258
|
+
});
|
|
259
|
+
const ENGINE_SESSION_KEY_BYTES = engineSession.ExtensionKey.serialize([false]).toBytes();
|
|
260
|
+
|
|
261
|
+
/** Parse an engine-session dynamic field's BCS content. */
|
|
262
|
+
export function parseRecordingEngineSessionContent(content: Uint8Array): RecordingEngineSessionView {
|
|
263
|
+
const { value } = EngineSessionField.parse(content);
|
|
264
|
+
if (value.data.confidentiality.$kind !== "Unencrypted") {
|
|
265
|
+
throw new Error("Recording engine session is unexpectedly encrypted");
|
|
266
|
+
}
|
|
267
|
+
return {
|
|
268
|
+
sessionBlobId: String(value.data.blob_id),
|
|
269
|
+
stems: value.stems.map((stem) => {
|
|
270
|
+
if (stem.data.confidentiality.$kind !== "Unencrypted") {
|
|
271
|
+
throw new Error("Recording engine session stem is unexpectedly encrypted");
|
|
272
|
+
}
|
|
273
|
+
return { digest: toHex(Uint8Array.from(stem.digest)), blobId: String(stem.data.blob_id) };
|
|
274
|
+
}),
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** Deterministic dynamic-field id for a Recording's engine session. */
|
|
279
|
+
export function recordingEngineSessionFieldId(
|
|
280
|
+
recordingId: string,
|
|
281
|
+
recordingEngineSessionPackageId: string,
|
|
282
|
+
): string {
|
|
283
|
+
return deriveDynamicFieldID(
|
|
284
|
+
recordingId,
|
|
285
|
+
`${recordingEngineSessionPackageId}::recording_engine_session::ExtensionKey`,
|
|
286
|
+
ENGINE_SESSION_KEY_BYTES,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Read one Recording's engine session, or null when none is attached. */
|
|
291
|
+
export async function getRecordingEngineSession(
|
|
292
|
+
client: ClientWithCoreApi,
|
|
293
|
+
recordingId: string,
|
|
294
|
+
recordingEngineSessionPackageId: string,
|
|
295
|
+
): Promise<RecordingEngineSessionView | null> {
|
|
296
|
+
const fieldId = recordingEngineSessionFieldId(recordingId, recordingEngineSessionPackageId);
|
|
297
|
+
const { objects } = await client.core.getObjects({
|
|
298
|
+
objectIds: [fieldId],
|
|
299
|
+
include: { content: true },
|
|
300
|
+
});
|
|
301
|
+
const field = objects[0];
|
|
302
|
+
if (!field) throw new Error("Recording engine-session read returned no result");
|
|
303
|
+
if (field instanceof Error) {
|
|
304
|
+
if (isNotFound(field)) return null;
|
|
305
|
+
throw field;
|
|
306
|
+
}
|
|
307
|
+
if (!field.content) throw new Error("Recording engine-session field is missing BCS content");
|
|
308
|
+
return parseRecordingEngineSessionContent(field.content);
|
|
309
|
+
}
|
|
310
|
+
|
|
195
311
|
// ── Master-reference reads ───────────────────────────────────────────────────
|
|
196
312
|
|
|
197
313
|
// recording_master_reference stores the ori::data::WalrusBlob value inline in a
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Copyright (c) Miso Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Walrus blob id conversions.
|
|
6
|
+
*
|
|
7
|
+
* On chain a blob id is a `u256` (BCS little-endian). Off chain it is the
|
|
8
|
+
* unpadded base64url encoding of those same 32 little-endian bytes, which is
|
|
9
|
+
* also its key in a `miso-sources` staging bucket and its path on an
|
|
10
|
+
* aggregator. Both directions here are canonical: a value that does not
|
|
11
|
+
* round-trip byte for byte is rejected.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const ALPHABET =
|
|
15
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
16
|
+
|
|
17
|
+
/** Parse a `bigint` or decimal string as an exact `u256`. */
|
|
18
|
+
export function walrusU256(label: string, value: bigint | string): bigint {
|
|
19
|
+
let parsed: bigint;
|
|
20
|
+
try {
|
|
21
|
+
parsed = typeof value === "bigint" ? value : BigInt(value);
|
|
22
|
+
} catch {
|
|
23
|
+
throw new Error(`${label} must be an exact u256 integer`);
|
|
24
|
+
}
|
|
25
|
+
if (parsed < 0n || parsed >= 1n << 256n) {
|
|
26
|
+
throw new Error(`${label} is outside u256 range`);
|
|
27
|
+
}
|
|
28
|
+
return parsed;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** The base64url Walrus blob id for an on-chain `u256` blob id. */
|
|
32
|
+
export function walrusBlobIdFromU256(value: bigint | string): string {
|
|
33
|
+
let remaining = walrusU256("Walrus blob id", value);
|
|
34
|
+
const bytes = new Uint8Array(32);
|
|
35
|
+
for (let index = 0; index < 32; index += 1) {
|
|
36
|
+
bytes[index] = Number(remaining & 0xffn);
|
|
37
|
+
remaining >>= 8n;
|
|
38
|
+
}
|
|
39
|
+
return bytesToBase64Url(bytes);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The on-chain `u256` for a base64url Walrus blob id (43 characters). */
|
|
43
|
+
export function walrusBlobIdToU256(blobId: string): bigint {
|
|
44
|
+
const bytes = base64UrlToBytes(blobId);
|
|
45
|
+
if (bytes.length !== 32) {
|
|
46
|
+
throw new Error("Walrus blob id must decode to exactly 32 bytes");
|
|
47
|
+
}
|
|
48
|
+
let value = 0n;
|
|
49
|
+
for (let index = 31; index >= 0; index -= 1) {
|
|
50
|
+
value = (value << 8n) | BigInt(bytes[index]!);
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Unpadded base64url. */
|
|
56
|
+
export function bytesToBase64Url(bytes: Uint8Array): string {
|
|
57
|
+
let output = "";
|
|
58
|
+
for (let index = 0; index < bytes.length; index += 3) {
|
|
59
|
+
const a = bytes[index] ?? 0;
|
|
60
|
+
const b = bytes[index + 1] ?? 0;
|
|
61
|
+
const c = bytes[index + 2] ?? 0;
|
|
62
|
+
output += ALPHABET[a >>> 2];
|
|
63
|
+
output += ALPHABET[((a & 3) << 4) | (b >>> 4)];
|
|
64
|
+
if (index + 1 < bytes.length) {
|
|
65
|
+
output += ALPHABET[((b & 15) << 2) | (c >>> 6)];
|
|
66
|
+
}
|
|
67
|
+
if (index + 2 < bytes.length) output += ALPHABET[c & 63];
|
|
68
|
+
}
|
|
69
|
+
return output;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Strict inverse of {@link bytesToBase64Url}: no padding, no stray bits. */
|
|
73
|
+
export function base64UrlToBytes(value: string): Uint8Array {
|
|
74
|
+
if (
|
|
75
|
+
typeof value !== "string" ||
|
|
76
|
+
value.length % 4 === 1 ||
|
|
77
|
+
value.includes("=") ||
|
|
78
|
+
!/^[A-Za-z0-9_-]*$/.test(value)
|
|
79
|
+
) {
|
|
80
|
+
throw new Error("invalid canonical base64url");
|
|
81
|
+
}
|
|
82
|
+
const bytes = new Uint8Array(Math.floor((value.length * 6) / 8));
|
|
83
|
+
let accumulator = 0;
|
|
84
|
+
let bits = 0;
|
|
85
|
+
let outputIndex = 0;
|
|
86
|
+
for (const character of value) {
|
|
87
|
+
const digit = ALPHABET.indexOf(character);
|
|
88
|
+
if (digit < 0) throw new Error("invalid canonical base64url");
|
|
89
|
+
accumulator = (accumulator << 6) | digit;
|
|
90
|
+
bits += 6;
|
|
91
|
+
if (bits >= 8) {
|
|
92
|
+
bits -= 8;
|
|
93
|
+
bytes[outputIndex] = (accumulator >>> bits) & 0xff;
|
|
94
|
+
outputIndex += 1;
|
|
95
|
+
accumulator &= (1 << bits) - 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (bytesToBase64Url(bytes) !== value) {
|
|
99
|
+
throw new Error("invalid canonical base64url padding bits");
|
|
100
|
+
}
|
|
101
|
+
return bytes;
|
|
102
|
+
}
|
package/dist/mix.d.ts
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import type { ClientWithCoreApi } from "@mysten/sui/client";
|
|
2
|
-
export declare const RECORDING_SESSION_ID_BYTES = 98;
|
|
3
|
-
export declare const RECORDING_SESSION_ID_SCHEMA: 1;
|
|
4
|
-
export declare const RECORDING_SESSION_ID_KIND: 1;
|
|
5
|
-
export declare const ENGINE_SESSION_SCHEMA_V1: "miso.engine-session/1";
|
|
6
|
-
export declare const ENGINE_SESSION_NETWORK_V1: "testnet";
|
|
7
|
-
export declare const STEM_CIPHER_FRAMING_V1: "aes-256-gcm-hkdf-stream/2";
|
|
8
|
-
export declare const STEM_CIPHER_CHUNK_BYTES: 1048576;
|
|
9
|
-
export declare const STEM_CIPHER_TAG_BYTES: 16;
|
|
10
|
-
export declare const STEM_CIPHER_HEADER_BYTES: 25;
|
|
11
|
-
export declare const MAX_ENGINE_SESSION_BYTES: number;
|
|
12
|
-
export declare const MAX_ENGINE_SESSION_STEMS = 32;
|
|
13
|
-
export declare const MAX_STEM_FLAC_BYTES: number;
|
|
14
|
-
export declare const MAX_SESSION_FLAC_BYTES: number;
|
|
15
|
-
export declare const MAX_STEM_CANONICAL_PCM_BYTES: number;
|
|
16
|
-
export declare const ENGINE_SESSION_SAMPLE_RATES: readonly [44100, 48000, 88200, 96000];
|
|
17
|
-
export type EngineSessionSampleRate = (typeof ENGINE_SESSION_SAMPLE_RATES)[number];
|
|
18
|
-
export interface RecordingSessionIdentity {
|
|
19
|
-
readonly schema: typeof RECORDING_SESSION_ID_SCHEMA;
|
|
20
|
-
readonly kind: typeof RECORDING_SESSION_ID_KIND;
|
|
21
|
-
readonly recordGateId: string;
|
|
22
|
-
readonly recordingId: string;
|
|
23
|
-
readonly nonce: Uint8Array;
|
|
24
|
-
}
|
|
25
|
-
/** Encode `[schema | kind | gate | recording | 32-byte nonce]`. */
|
|
26
|
-
export declare function encodeRecordingSessionIdentity(identity: Omit<RecordingSessionIdentity, "schema" | "kind"> & Partial<Pick<RecordingSessionIdentity, "schema" | "kind">>): Uint8Array;
|
|
27
|
-
/** Strictly parse one exact identity; short and trailing bytes are rejected. */
|
|
28
|
-
export declare function parseRecordingSessionIdentity(bytes: Uint8Array): RecordingSessionIdentity;
|
|
29
|
-
export declare function recordingSessionIdentityHex(identity: Parameters<typeof encodeRecordingSessionIdentity>[0]): string;
|
|
30
|
-
/** Stable unique HKDF/AAD domain for one encrypted stem. */
|
|
31
|
-
export declare function stemCipherDomain(stemId: string): Uint8Array;
|
|
32
|
-
export interface EngineSessionEffectPreset {
|
|
33
|
-
readonly slot: number;
|
|
34
|
-
readonly bypassed: boolean;
|
|
35
|
-
readonly params: Readonly<Record<string, number>>;
|
|
36
|
-
}
|
|
37
|
-
export interface EngineSessionStemPreset {
|
|
38
|
-
readonly faderDb: number;
|
|
39
|
-
readonly pan: number;
|
|
40
|
-
readonly muted: boolean;
|
|
41
|
-
readonly soloed: boolean;
|
|
42
|
-
readonly effects: readonly EngineSessionEffectPreset[];
|
|
43
|
-
}
|
|
44
|
-
export interface EngineSessionStemV1 {
|
|
45
|
-
/** Portable encryption-domain id, independent of PCM/container identity. */
|
|
46
|
-
readonly id: string;
|
|
47
|
-
/** Canonical decoded PCM identity consumed by the stem store. */
|
|
48
|
-
readonly identity: `sha256:${string}`;
|
|
49
|
-
readonly name: string;
|
|
50
|
-
readonly role: string;
|
|
51
|
-
readonly channels: 1 | 2;
|
|
52
|
-
readonly bitDepth: 16 | 24;
|
|
53
|
-
readonly frames: number;
|
|
54
|
-
readonly preset: EngineSessionStemPreset;
|
|
55
|
-
/** Standalone Walrus blob containing framed AES-GCM ciphertext. */
|
|
56
|
-
readonly blobId: string;
|
|
57
|
-
readonly ciphertextSha256: string;
|
|
58
|
-
readonly plainBytes: number;
|
|
59
|
-
readonly cipherBytes: number;
|
|
60
|
-
}
|
|
61
|
-
export interface EngineSessionV1 {
|
|
62
|
-
readonly schema: typeof ENGINE_SESSION_SCHEMA_V1;
|
|
63
|
-
readonly network: typeof ENGINE_SESSION_NETWORK_V1;
|
|
64
|
-
readonly recordingId: string;
|
|
65
|
-
readonly title: string;
|
|
66
|
-
readonly artist: string;
|
|
67
|
-
readonly sampleRateHz: EngineSessionSampleRate;
|
|
68
|
-
readonly seal: {
|
|
69
|
-
/** Canonical base64url Seal EncryptedObject wrapping exactly 32 AES bytes. */
|
|
70
|
-
readonly encryptedKey: string;
|
|
71
|
-
};
|
|
72
|
-
readonly cipher: {
|
|
73
|
-
readonly framing: typeof STEM_CIPHER_FRAMING_V1;
|
|
74
|
-
readonly chunkSize: typeof STEM_CIPHER_CHUNK_BYTES;
|
|
75
|
-
readonly tagSize: typeof STEM_CIPHER_TAG_BYTES;
|
|
76
|
-
};
|
|
77
|
-
readonly stems: readonly EngineSessionStemV1[];
|
|
78
|
-
}
|
|
79
|
-
/** Ciphertext length implied by the fixed authenticated-record framing. */
|
|
80
|
-
export declare function stemCipherBytes(plainBytes: number): number;
|
|
81
|
-
/** Validate exact shape, bounds, identity, and the embedded Seal object. */
|
|
82
|
-
export declare function assertEngineSessionV1(value: unknown): asserts value is EngineSessionV1;
|
|
83
|
-
/** Canonical plaintext bytes uploaded as the Recording's session blob. */
|
|
84
|
-
export declare function encodeEngineSessionV1(session: EngineSessionV1): Uint8Array;
|
|
85
|
-
/** Parse only canonical JSON: unknown keys, whitespace, and trailing data fail. */
|
|
86
|
-
export declare function parseEngineSessionV1(input: Uint8Array | string): EngineSessionV1;
|
|
87
|
-
export interface InspectedEngineSessionKey {
|
|
88
|
-
readonly packageId: string;
|
|
89
|
-
readonly innerId: Uint8Array;
|
|
90
|
-
readonly services: readonly (readonly [string, number])[];
|
|
91
|
-
readonly threshold: number;
|
|
92
|
-
}
|
|
93
|
-
/** Parse and constrain the official Seal object carrying the session AES key. */
|
|
94
|
-
export declare function inspectEngineSessionKey(bytes: Uint8Array): InspectedEngineSessionKey;
|
|
95
|
-
export interface RecordingEngineSessionReference {
|
|
96
|
-
readonly blobId: bigint;
|
|
97
|
-
}
|
|
98
|
-
export interface ReleaseMixReference {
|
|
99
|
-
readonly blobId: bigint;
|
|
100
|
-
}
|
|
101
|
-
/** Read the release-aligned optional descriptor references in track order. */
|
|
102
|
-
export declare function getReleaseMixReferences(client: ClientWithCoreApi, releaseId: string, packageId: string): Promise<Array<ReleaseMixReference | null> | null>;
|
|
103
|
-
export declare function recordingEngineSessionFieldId(recordingId: string, packageId: string): string;
|
|
104
|
-
export declare function parseRecordingEngineSessionContent(content: Uint8Array): RecordingEngineSessionReference;
|
|
105
|
-
export declare function getRecordingEngineSession(client: ClientWithCoreApi, recordingId: string, packageId: string): Promise<RecordingEngineSessionReference | null>;
|
|
106
|
-
/** Exact concrete Record read using BCS, never transport-dependent JSON. */
|
|
107
|
-
export declare function getRecordReleaseId(client: ClientWithCoreApi, recordId: string, recordPackageId: string): Promise<string>;
|
|
108
|
-
export interface ResolvedRecordEngineSession {
|
|
109
|
-
readonly releaseId: string;
|
|
110
|
-
readonly recordingId: string;
|
|
111
|
-
readonly sessionBlobId: string;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Resolve Record → immutable Release track → Recording dynamic field.
|
|
115
|
-
*
|
|
116
|
-
* Every edge is a direct Sui object read. No event scan, dynamic-field list,
|
|
117
|
-
* API hint, or indexer-maintained relation participates in the answer.
|
|
118
|
-
*/
|
|
119
|
-
export declare function resolveRecordEngineSession(client: ClientWithCoreApi, input: {
|
|
120
|
-
readonly recordId: string;
|
|
121
|
-
readonly trackIndex: number;
|
|
122
|
-
readonly recordPackageId: string;
|
|
123
|
-
readonly recordingEngineSessionPackageId: string;
|
|
124
|
-
}): Promise<ResolvedRecordEngineSession>;
|
|
125
|
-
export declare function walrusBlobIdFromU256(value: bigint | string): string;
|
|
126
|
-
export declare function bytesToBase64Url(bytes: Uint8Array): string;
|
|
127
|
-
export declare function base64UrlToBytes(value: string): Uint8Array;
|
|
128
|
-
export declare function bytesToHex(bytes: Uint8Array): string;
|
|
129
|
-
export declare function hexToBytes(value: string, expectedBytes?: number, label?: string): Uint8Array;
|
|
130
|
-
//# sourceMappingURL=mix.d.ts.map
|
package/dist/mix.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mix.d.ts","sourceRoot":"","sources":["../src/mix.ts"],"names":[],"mappings":"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"}
|