@misofm/platform 0.19.0 → 0.20.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 +4 -2
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/contracts.d.ts +1 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +1 -0
- package/dist/contracts.js.map +1 -1
- package/dist/cover.d.ts +5 -8
- package/dist/cover.d.ts.map +1 -1
- package/dist/cover.js +5 -17
- package/dist/cover.js.map +1 -1
- package/dist/deployments.d.ts +2 -2
- package/dist/deployments.d.ts.map +1 -1
- package/dist/internal.d.ts +11 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +18 -1
- package/dist/internal.js.map +1 -1
- package/dist/mix.d.ts +0 -14
- package/dist/mix.d.ts.map +1 -1
- package/dist/mix.js +21 -43
- package/dist/mix.js.map +1 -1
- package/dist/publication.d.ts +2 -0
- package/dist/publication.d.ts.map +1 -1
- package/dist/publication.js +16 -5
- package/dist/publication.js.map +1 -1
- package/dist/read/catalog.d.ts.map +1 -1
- package/dist/read/catalog.js +3 -7
- package/dist/read/catalog.js.map +1 -1
- package/dist/recording-extensions.d.ts +24 -3
- package/dist/recording-extensions.d.ts.map +1 -1
- package/dist/recording-extensions.js +43 -9
- package/dist/recording-extensions.js.map +1 -1
- package/package.json +2 -2
- package/src/client.ts +1 -1
- package/src/contracts.ts +1 -0
- package/src/cover.ts +21 -41
- package/src/deployments.ts +2 -2
- package/src/internal.ts +25 -0
- package/src/mix.ts +21 -68
- package/src/publication.ts +21 -4
- package/src/read/catalog.ts +2 -11
- package/src/recording-extensions.ts +60 -17
package/src/cover.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
// Release cover art. A cover is a still image (optionally an animation) stored as
|
|
5
|
-
// a Walrus blob and referenced on-chain via `ori::
|
|
6
|
-
// (`ori::
|
|
7
|
-
// `cover_art::CoverArt`, and attach it to the Release with
|
|
5
|
+
// a Walrus blob and referenced on-chain via `ori::data::WalrusBlob`. We build the
|
|
6
|
+
// plaintext ref (`ori::data::new_blob`, a raw call — ori is an external dep), wrap
|
|
7
|
+
// it in a `cover_art::CoverArt`, and attach it to the Release with
|
|
8
8
|
// `release_cover_art::set_cover` (gated by the ReleaseAdminCap).
|
|
9
9
|
//
|
|
10
10
|
// Blob ids are passed as `u256` (decimal string or bigint) — the CLI converts the
|
|
@@ -20,7 +20,7 @@ import { deriveDynamicFieldID } from "@mysten/sui/utils";
|
|
|
20
20
|
import type { Transaction, TransactionObjectArgument } from "@mysten/sui/transactions";
|
|
21
21
|
import type { TxThunk } from "./transactions.ts";
|
|
22
22
|
import { asU64, directAdminCap, invokeWithAdminCap, type AdminCapAuthority, type ObjectInput, type U64Input } from "./vault.ts";
|
|
23
|
-
import { OPTION_NONE, OPTION_SOME } from "./internal.ts";
|
|
23
|
+
import { OPTION_NONE, OPTION_SOME, unencryptedWalrusBlob } from "./internal.ts";
|
|
24
24
|
import * as coverArt from "@misofm/protocol/contracts/cover_art/cover_art";
|
|
25
25
|
import * as releaseCoverArt from "@misofm/protocol/contracts/release_cover_art/release_cover_art";
|
|
26
26
|
|
|
@@ -44,7 +44,7 @@ interface SetReleaseCoverParamsBase {
|
|
|
44
44
|
coverArtPackageId: string;
|
|
45
45
|
/** `release_cover_art` package — home of the `set_cover` extension entry point. */
|
|
46
46
|
releaseCoverArtPackageId: string;
|
|
47
|
-
/** `ori` package (home of `
|
|
47
|
+
/** `ori` package (home of `data::new_blob` / the `WalrusBlob` type). */
|
|
48
48
|
oriPackageId: string;
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -59,12 +59,8 @@ export type SetReleaseTrackCoverParams = SetReleaseCoverParams & {
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
function buildCover(tx: Parameters<TxThunk>[0], p: SetReleaseCoverParams) {
|
|
62
|
-
const walrusType = `${p.oriPackageId}::
|
|
63
|
-
const blob = (id: bigint | string) =>
|
|
64
|
-
tx.moveCall({
|
|
65
|
-
target: `${p.oriPackageId}::walrus_data::new_blob`,
|
|
66
|
-
arguments: [tx.pure.u256(id)],
|
|
67
|
-
});
|
|
62
|
+
const walrusType = `${p.oriPackageId}::data::WalrusBlob`;
|
|
63
|
+
const blob = (id: bigint | string) => unencryptedWalrusBlob(tx, p.oriPackageId, id);
|
|
68
64
|
|
|
69
65
|
const still = blob(p.stillBlobId);
|
|
70
66
|
const animated =
|
|
@@ -113,17 +109,12 @@ export function setReleaseTrackCover(p: SetReleaseTrackCoverParams): TxThunk {
|
|
|
113
109
|
/**
|
|
114
110
|
* A normalized reference to a cover image's Walrus data. Blob ids are returned as
|
|
115
111
|
* `u256` decimal strings (the on-chain form); callers convert to a base64url
|
|
116
|
-
* aggregator URL with `@unconfirmed/ori` (`u256ToB64Url` / `
|
|
112
|
+
* aggregator URL with `@unconfirmed/ori` (`u256ToB64Url` / `walrusBlobUrl`).
|
|
113
|
+
*
|
|
114
|
+
* The current `cover_art` generation stores standalone `ori::data::WalrusBlob`
|
|
115
|
+
* values only, so every cover image is a `blob` reference.
|
|
117
116
|
*/
|
|
118
|
-
export type CoverImageRef =
|
|
119
|
-
| { kind: "blob"; blobId: string }
|
|
120
|
-
| {
|
|
121
|
-
kind: "quiltPatch";
|
|
122
|
-
quiltId: string;
|
|
123
|
-
version: number;
|
|
124
|
-
startIndex: number;
|
|
125
|
-
endIndex: number;
|
|
126
|
-
};
|
|
117
|
+
export type CoverImageRef = { kind: "blob"; blobId: string };
|
|
127
118
|
|
|
128
119
|
/** A release's album-level cover: a still image and an optional animation. */
|
|
129
120
|
export interface ReleaseCoverView {
|
|
@@ -143,24 +134,13 @@ const COVER_ART_KEY_BYTES = releaseCoverArt.ExtensionKey.serialize([
|
|
|
143
134
|
false,
|
|
144
135
|
]).toBytes();
|
|
145
136
|
|
|
146
|
-
/** A parsed `ori::
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
function toCoverImageRef(wd: ParsedWalrusData): CoverImageRef {
|
|
155
|
-
if (wd.$kind === "Blob") return { kind: "blob", blobId: String(wd.Blob[0]) };
|
|
156
|
-
const [quiltId, version, startIndex, endIndex] = wd.QuiltPatch;
|
|
157
|
-
return {
|
|
158
|
-
kind: "quiltPatch",
|
|
159
|
-
quiltId: String(quiltId),
|
|
160
|
-
version,
|
|
161
|
-
startIndex,
|
|
162
|
-
endIndex,
|
|
163
|
-
};
|
|
137
|
+
/** A parsed `ori::data::WalrusBlob` value. */
|
|
138
|
+
interface ParsedWalrusBlob {
|
|
139
|
+
blob_id: string | number | bigint;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function toCoverImageRef(blob: ParsedWalrusBlob): CoverImageRef {
|
|
143
|
+
return { kind: "blob", blobId: String(blob.blob_id) };
|
|
164
144
|
}
|
|
165
145
|
|
|
166
146
|
/**
|
|
@@ -185,8 +165,8 @@ export function parseReleaseCoverContent(
|
|
|
185
165
|
content: Uint8Array,
|
|
186
166
|
): ReleaseCoverView | null {
|
|
187
167
|
const cover = CoverArtField.parse(content).value.cover as {
|
|
188
|
-
still:
|
|
189
|
-
animated:
|
|
168
|
+
still: ParsedWalrusBlob;
|
|
169
|
+
animated: ParsedWalrusBlob | null;
|
|
190
170
|
} | null;
|
|
191
171
|
if (!cover) return null;
|
|
192
172
|
|
package/src/deployments.ts
CHANGED
|
@@ -216,11 +216,11 @@ export interface MisoPlatformDeployment {
|
|
|
216
216
|
readonly recordingMasterReference: string;
|
|
217
217
|
/** Complete Walrus Quilt containing the Recording's streaming transcodes. */
|
|
218
218
|
readonly recordingStreamingTranscode?: string;
|
|
219
|
-
/**
|
|
219
|
+
/** Unencrypted Walrus blob of a Recording's Miso Engine session file; absent before publication. */
|
|
220
220
|
readonly recordingEngineSession?: string;
|
|
221
221
|
/** Original immutable Record-gated Seal policy; absent before publication. */
|
|
222
222
|
readonly recordSealPolicy?: string;
|
|
223
|
-
/** External `ori::
|
|
223
|
+
/** External `ori` package (`data::WalrusBlob`, `data::WalrusQuilt`) used by Walrus-backed extensions. */
|
|
224
224
|
readonly ori: string;
|
|
225
225
|
};
|
|
226
226
|
readonly objects: {
|
package/src/internal.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
// Internal shared helpers (deliberately NOT exported from the package root).
|
|
5
|
+
|
|
6
|
+
import type { Transaction, TransactionArgument } from "@mysten/sui/transactions";
|
|
5
7
|
//
|
|
6
8
|
// PTB building blocks — the `0x1::option` move-call targets used when a generated
|
|
7
9
|
// call needs an `Option` argument built inline. Consumed by `./cover` and
|
|
@@ -18,6 +20,29 @@
|
|
|
18
20
|
export const OPTION_NONE = "0x1::option::none";
|
|
19
21
|
export const OPTION_SOME = "0x1::option::some";
|
|
20
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Build a plaintext `ori::data::WalrusBlob` in the PTB: `confidentiality::new_unencrypted()`
|
|
25
|
+
* followed by `data::new_blob(blob_id, confidentiality)`. `ori` is an external
|
|
26
|
+
* dependency, so these are raw calls against the deployment's `ori` package.
|
|
27
|
+
*
|
|
28
|
+
* Every platform extension that stores a standalone blob (cover art, master
|
|
29
|
+
* reference, engine session) builds its reference here so the ori ABI is pinned
|
|
30
|
+
* in exactly one place.
|
|
31
|
+
*/
|
|
32
|
+
export function unencryptedWalrusBlob(
|
|
33
|
+
tx: Transaction,
|
|
34
|
+
oriPackageId: string,
|
|
35
|
+
blobId: bigint | string,
|
|
36
|
+
): TransactionArgument {
|
|
37
|
+
const confidentiality = tx.moveCall({
|
|
38
|
+
target: `${oriPackageId}::confidentiality::new_unencrypted`,
|
|
39
|
+
});
|
|
40
|
+
return tx.moveCall({
|
|
41
|
+
target: `${oriPackageId}::data::new_blob`,
|
|
42
|
+
arguments: [tx.pure.u256(blobId), confidentiality],
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
21
46
|
/**
|
|
22
47
|
* Clone arrays and plain records recursively, then freeze the clone.
|
|
23
48
|
*
|
package/src/mix.ts
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
parseStructTag,
|
|
24
24
|
} from "@mysten/sui/utils";
|
|
25
25
|
import { getReleaseById, isNotFound } from "@misofm/protocol";
|
|
26
|
-
import
|
|
26
|
+
import * as engineSessionContract from "@misofm/protocol/contracts/recording_engine_session/recording_engine_session";
|
|
27
27
|
import * as recordContract from "@misofm/protocol/contracts/miso_record/record";
|
|
28
28
|
import type { TxThunk } from "./transactions.ts";
|
|
29
29
|
import {
|
|
@@ -432,14 +432,27 @@ export function inspectEngineSessionKey(
|
|
|
432
432
|
|
|
433
433
|
const EngineSessionField = bcs.struct("Field", {
|
|
434
434
|
id: bcs.Address,
|
|
435
|
-
name:
|
|
436
|
-
value:
|
|
435
|
+
name: engineSessionContract.ExtensionKey,
|
|
436
|
+
value: engineSessionContract.EngineSession,
|
|
437
|
+
});
|
|
438
|
+
const ENGINE_SESSION_KEY_BYTES = engineSessionContract.ExtensionKey.serialize([
|
|
439
|
+
false,
|
|
440
|
+
]).toBytes();
|
|
441
|
+
// `release_mix_reference` predates the ori `walrus_data` → `data` split and is
|
|
442
|
+
// not part of the current deployment. Its stored value is still the legacy
|
|
443
|
+
// `ori::walrus_data::WalrusData` enum, kept here verbatim for reads.
|
|
444
|
+
const LegacyConfidentiality = bcs.enum("Confidentiality", {
|
|
445
|
+
Unencrypted: null,
|
|
446
|
+
Encrypted: bcs.struct("Confidentiality.Encrypted", { dek: bcs.vector(bcs.u8()) }),
|
|
447
|
+
});
|
|
448
|
+
const LegacyWalrusData = bcs.enum("WalrusData", {
|
|
449
|
+
Blob: bcs.tuple([bcs.u256(), LegacyConfidentiality]),
|
|
450
|
+
QuiltPatch: bcs.tuple([bcs.u256(), bcs.u8(), bcs.u16(), bcs.u16()]),
|
|
437
451
|
});
|
|
438
|
-
const ENGINE_SESSION_KEY_BYTES = new Uint8Array([0]);
|
|
439
452
|
const ReleaseMixReferenceField = bcs.struct("Field", {
|
|
440
453
|
id: bcs.Address,
|
|
441
454
|
name: bcs.tuple([bcs.bool()]),
|
|
442
|
-
value: bcs.tuple([bcs.vector(bcs.option(
|
|
455
|
+
value: bcs.tuple([bcs.vector(bcs.option(LegacyWalrusData))]),
|
|
443
456
|
});
|
|
444
457
|
|
|
445
458
|
export interface RecordingEngineSessionReference {
|
|
@@ -492,15 +505,11 @@ export function recordingEngineSessionFieldId(
|
|
|
492
505
|
export function parseRecordingEngineSessionContent(
|
|
493
506
|
content: Uint8Array,
|
|
494
507
|
): RecordingEngineSessionReference {
|
|
495
|
-
const
|
|
496
|
-
if (
|
|
497
|
-
throw new Error("Recording engine session is not a standalone Walrus blob");
|
|
498
|
-
}
|
|
499
|
-
const [id, confidentiality] = reference.Blob;
|
|
500
|
-
if (confidentiality.$kind !== "Unencrypted") {
|
|
508
|
+
const { data } = EngineSessionField.parse(content).value;
|
|
509
|
+
if (data.confidentiality.$kind !== "Unencrypted") {
|
|
501
510
|
throw new Error("Recording engine session is unexpectedly encrypted");
|
|
502
511
|
}
|
|
503
|
-
return { blobId: BigInt(
|
|
512
|
+
return { blobId: BigInt(data.blob_id) };
|
|
504
513
|
}
|
|
505
514
|
|
|
506
515
|
export async function getRecordingEngineSession(
|
|
@@ -596,62 +605,6 @@ export async function resolveRecordEngineSession(
|
|
|
596
605
|
};
|
|
597
606
|
}
|
|
598
607
|
|
|
599
|
-
// ── Recording extension writes ──────────────────────────────────────────────
|
|
600
|
-
|
|
601
|
-
export interface WriteRecordingEngineSessionParams {
|
|
602
|
-
readonly recordingId: ObjectInput;
|
|
603
|
-
readonly authority: AdminCapAuthority;
|
|
604
|
-
readonly recordingShareType: string;
|
|
605
|
-
readonly compositionShareType: string;
|
|
606
|
-
readonly sessionBlobId: bigint | string;
|
|
607
|
-
readonly oriPackageId: string;
|
|
608
|
-
readonly recordingEngineSessionPackageId: string;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
export function attachRecordingEngineSession(
|
|
612
|
-
params: WriteRecordingEngineSessionParams,
|
|
613
|
-
): TxThunk {
|
|
614
|
-
return writeRecordingEngineSession("attach_engine_session", params);
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
export function replaceRecordingEngineSession(
|
|
618
|
-
params: WriteRecordingEngineSessionParams,
|
|
619
|
-
): TxThunk {
|
|
620
|
-
return writeRecordingEngineSession("replace_engine_session", params);
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
export function unsetRecordingEngineSession(
|
|
624
|
-
params: Omit<WriteRecordingEngineSessionParams, "sessionBlobId" | "oriPackageId">,
|
|
625
|
-
): TxThunk {
|
|
626
|
-
return (tx) => {
|
|
627
|
-
invokeWithAdminCap(tx, params.authority, {
|
|
628
|
-
target: `${params.recordingEngineSessionPackageId}::recording_engine_session::unset_engine_session`,
|
|
629
|
-
typeArguments: [params.recordingShareType, params.compositionShareType],
|
|
630
|
-
arguments: [object(tx, params.recordingId)],
|
|
631
|
-
adminCapIndex: 1,
|
|
632
|
-
});
|
|
633
|
-
};
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
function writeRecordingEngineSession(
|
|
637
|
-
fn: "attach_engine_session" | "replace_engine_session",
|
|
638
|
-
params: WriteRecordingEngineSessionParams,
|
|
639
|
-
): TxThunk {
|
|
640
|
-
const blob = u256("sessionBlobId", params.sessionBlobId);
|
|
641
|
-
return (tx) => {
|
|
642
|
-
const reference = tx.moveCall({
|
|
643
|
-
target: `${params.oriPackageId}::walrus_data::new_blob`,
|
|
644
|
-
arguments: [tx.pure.u256(blob)],
|
|
645
|
-
});
|
|
646
|
-
invokeWithAdminCap(tx, params.authority, {
|
|
647
|
-
target: `${params.recordingEngineSessionPackageId}::recording_engine_session::${fn}`,
|
|
648
|
-
typeArguments: [params.recordingShareType, params.compositionShareType],
|
|
649
|
-
arguments: [object(tx, params.recordingId), reference],
|
|
650
|
-
adminCapIndex: 1,
|
|
651
|
-
});
|
|
652
|
-
};
|
|
653
|
-
}
|
|
654
|
-
|
|
655
608
|
function object(tx: Transaction, input: ObjectInput): TransactionObjectArgument {
|
|
656
609
|
return typeof input === "string" ? tx.object(input) : input;
|
|
657
610
|
}
|
package/src/publication.ts
CHANGED
|
@@ -48,11 +48,13 @@ import {
|
|
|
48
48
|
} from "./credits.ts";
|
|
49
49
|
import {
|
|
50
50
|
setRecordingAdvisory,
|
|
51
|
+
setRecordingEngineSession,
|
|
51
52
|
setRecordingInstrumental,
|
|
52
53
|
setRecordingLanguages,
|
|
53
54
|
setRecordingMasterReference,
|
|
54
55
|
setRecordingStreamingTranscode,
|
|
55
56
|
} from "./recording-extensions.ts";
|
|
57
|
+
import { unencryptedWalrusBlob } from "./internal.ts";
|
|
56
58
|
import {
|
|
57
59
|
setReleaseDescription,
|
|
58
60
|
setReleaseDspLinks,
|
|
@@ -171,6 +173,8 @@ export type PublicationRecording = PublicationRecordingParent & {
|
|
|
171
173
|
readonly masterReferenceBlobId?: bigint | string;
|
|
172
174
|
/** Complete Walrus Quilt ID containing this Recording's streaming transcodes. */
|
|
173
175
|
readonly streamingTranscodeQuiltId?: bigint | string;
|
|
176
|
+
/** Unencrypted Walrus blob ID of this Recording's Miso Engine session file. */
|
|
177
|
+
readonly engineSessionBlobId?: bigint | string;
|
|
174
178
|
};
|
|
175
179
|
|
|
176
180
|
export interface PublicationFreshTrack {
|
|
@@ -332,10 +336,7 @@ function languageVector(tx: Transaction, p: AtomicPublicationParams, codes: stri
|
|
|
332
336
|
}
|
|
333
337
|
|
|
334
338
|
function walrusBlob(tx: Transaction, p: AtomicPublicationParams, blobId: bigint | string) {
|
|
335
|
-
return tx.
|
|
336
|
-
target: `${p.deployment.packages.ori}::walrus_data::new_blob`,
|
|
337
|
-
arguments: [tx.pure.u256(blobId)],
|
|
338
|
-
});
|
|
339
|
+
return unencryptedWalrusBlob(tx, p.deployment.packages.ori, blobId);
|
|
339
340
|
}
|
|
340
341
|
|
|
341
342
|
function listingPrice(tx: Transaction, p: AtomicPublicationParams, price: ListingPrice) {
|
|
@@ -652,6 +653,14 @@ export function publishAtomicCatalog(p: AtomicPublicationParams): TxThunk {
|
|
|
652
653
|
"A recording streaming transcode requires deployment.packages.recordingStreamingTranscode",
|
|
653
654
|
);
|
|
654
655
|
}
|
|
656
|
+
if (
|
|
657
|
+
p.recordings.some((node) => node.engineSessionBlobId !== undefined) &&
|
|
658
|
+
!p.deployment.packages.recordingEngineSession
|
|
659
|
+
) {
|
|
660
|
+
throw new Error(
|
|
661
|
+
"A recording engine session requires deployment.packages.recordingEngineSession",
|
|
662
|
+
);
|
|
663
|
+
}
|
|
655
664
|
if (publicationUsesVault(p)) {
|
|
656
665
|
requireOperationsDeployment(p.deployment.operations);
|
|
657
666
|
}
|
|
@@ -869,6 +878,14 @@ export function publishAtomicCatalog(p: AtomicPublicationParams): TxThunk {
|
|
|
869
878
|
oriPackageId: p.deployment.packages.ori,
|
|
870
879
|
quiltId: node.streamingTranscodeQuiltId,
|
|
871
880
|
})(tx);
|
|
881
|
+
if (node.engineSessionBlobId !== undefined) setRecordingEngineSession({
|
|
882
|
+
recordingId: parts.work, authority,
|
|
883
|
+
recordingShareType: node.shareType,
|
|
884
|
+
compositionShareType: node.compositionShareType,
|
|
885
|
+
recordingEngineSessionPackageId: p.deployment.packages.recordingEngineSession!,
|
|
886
|
+
oriPackageId: p.deployment.packages.ori,
|
|
887
|
+
sessionBlobId: node.engineSessionBlobId,
|
|
888
|
+
})(tx);
|
|
872
889
|
});
|
|
873
890
|
|
|
874
891
|
if (p.release && releaseObject && releaseAdminCap) {
|
package/src/read/catalog.ts
CHANGED
|
@@ -49,7 +49,6 @@ import type { MisoClient } from "./client.ts";
|
|
|
49
49
|
import { getRecordingTitles, parseReleaseObject } from "./works.ts";
|
|
50
50
|
import { int } from "./internal/scalars.ts";
|
|
51
51
|
import {
|
|
52
|
-
quiltPatchId,
|
|
53
52
|
u256ToB64Url,
|
|
54
53
|
walrusBlobReadUrl,
|
|
55
54
|
} from "./internal/walrus.ts";
|
|
@@ -75,17 +74,9 @@ import type {
|
|
|
75
74
|
|
|
76
75
|
// ── Walrus URLs ──────────────────────────────────────────────────────────────
|
|
77
76
|
|
|
78
|
-
/** Aggregator URL for a cover image ref
|
|
77
|
+
/** Aggregator URL for a cover image ref (a standalone Walrus blob). */
|
|
79
78
|
function imageUrl(aggregator: string, ref: CoverImageRef): string {
|
|
80
|
-
|
|
81
|
-
if (ref.kind === "blob") return walrusBlobReadUrl(base, ref.blobId);
|
|
82
|
-
const patch = quiltPatchId(
|
|
83
|
-
ref.quiltId,
|
|
84
|
-
ref.version,
|
|
85
|
-
ref.startIndex,
|
|
86
|
-
ref.endIndex,
|
|
87
|
-
);
|
|
88
|
-
return `${base}/v1/blobs/by-quilt-patch-id/${patch}`;
|
|
79
|
+
return walrusBlobReadUrl(aggregator.replace(/\/$/, ""), ref.blobId);
|
|
89
80
|
}
|
|
90
81
|
|
|
91
82
|
function toCover(
|
|
@@ -11,9 +11,11 @@ import type { TxThunk } from "./transactions.ts";
|
|
|
11
11
|
import { invokeWithAdminCap, type AdminCapAuthority, type ObjectInput } from "./vault.ts";
|
|
12
12
|
import * as advisory from "@misofm/protocol/contracts/recording_advisory/recording_advisory";
|
|
13
13
|
import * as language from "@misofm/protocol/contracts/recording_language/recording_language";
|
|
14
|
-
import * as walrusData from "@misofm/protocol/contracts/recording_master_reference/deps/ori/
|
|
14
|
+
import * as walrusData from "@misofm/protocol/contracts/recording_master_reference/deps/ori/data";
|
|
15
15
|
import * as masterReference from "@misofm/protocol/contracts/recording_master_reference/recording_master_reference";
|
|
16
|
+
import * as engineSession from "@misofm/protocol/contracts/recording_engine_session/recording_engine_session";
|
|
16
17
|
import * as streamingTranscode from "@misofm/protocol/contracts/recording_streaming_transcode/recording_streaming_transcode";
|
|
18
|
+
import { unencryptedWalrusBlob } from "./internal.ts";
|
|
17
19
|
|
|
18
20
|
export interface RecordingExtensionTarget {
|
|
19
21
|
readonly recordingId: ObjectInput;
|
|
@@ -77,7 +79,7 @@ export function setRecordingInstrumental(p: Omit<SetRecordingLanguagesParams, "l
|
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
interface RecordingWalrusReferenceParams extends RecordingExtensionTarget {
|
|
80
|
-
/** An ori::
|
|
82
|
+
/** An `ori::data::WalrusBlob` value assembled in the same PTB. */
|
|
81
83
|
readonly reference: TransactionArgument;
|
|
82
84
|
}
|
|
83
85
|
|
|
@@ -130,6 +132,52 @@ export type UnsetRecordingStreamingTranscodeParams = Omit<
|
|
|
130
132
|
"oriPackageId" | "quiltId"
|
|
131
133
|
>;
|
|
132
134
|
|
|
135
|
+
export interface SetRecordingEngineSessionParams extends RecordingExtensionTarget {
|
|
136
|
+
readonly recordingEngineSessionPackageId: string;
|
|
137
|
+
/** External `ori` package used to construct the plaintext Walrus blob reference. */
|
|
138
|
+
readonly oriPackageId: string;
|
|
139
|
+
/** Unencrypted Walrus blob ID of the Miso Engine session file, as its on-chain `u256`. */
|
|
140
|
+
readonly sessionBlobId: bigint | string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Sets or replaces the Miso Engine session file attached to a Recording.
|
|
145
|
+
*
|
|
146
|
+
* `recording_engine_session::new` rejects encrypted blobs on chain, so the
|
|
147
|
+
* reference is always built as a plaintext `ori::data::WalrusBlob`.
|
|
148
|
+
*/
|
|
149
|
+
export function setRecordingEngineSession(p: SetRecordingEngineSessionParams): TxThunk {
|
|
150
|
+
return (tx) => {
|
|
151
|
+
const session = tx.add(engineSession._new({
|
|
152
|
+
package: p.recordingEngineSessionPackageId,
|
|
153
|
+
arguments: [unencryptedWalrusBlob(tx, p.oriPackageId, p.sessionBlobId)],
|
|
154
|
+
}));
|
|
155
|
+
invokeWithAdminCap(tx, p.authority, {
|
|
156
|
+
target: `${p.recordingEngineSessionPackageId}::recording_engine_session::set_engine_session`,
|
|
157
|
+
typeArguments: [p.recordingShareType, p.compositionShareType],
|
|
158
|
+
arguments: [object(tx, p.recordingId), session],
|
|
159
|
+
adminCapIndex: 1,
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export type UnsetRecordingEngineSessionParams = Omit<
|
|
165
|
+
SetRecordingEngineSessionParams,
|
|
166
|
+
"oriPackageId" | "sessionBlobId"
|
|
167
|
+
>;
|
|
168
|
+
|
|
169
|
+
/** Removes the Recording's Miso Engine session reference, if present. */
|
|
170
|
+
export function unsetRecordingEngineSession(p: UnsetRecordingEngineSessionParams): TxThunk {
|
|
171
|
+
return (tx) => {
|
|
172
|
+
invokeWithAdminCap(tx, p.authority, {
|
|
173
|
+
target: `${p.recordingEngineSessionPackageId}::recording_engine_session::unset_engine_session`,
|
|
174
|
+
typeArguments: [p.recordingShareType, p.compositionShareType],
|
|
175
|
+
arguments: [object(tx, p.recordingId)],
|
|
176
|
+
adminCapIndex: 1,
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
133
181
|
/** Removes the Recording's streaming-transcode reference, if present. */
|
|
134
182
|
export function unsetRecordingStreamingTranscode(
|
|
135
183
|
p: UnsetRecordingStreamingTranscodeParams,
|
|
@@ -146,30 +194,26 @@ export function unsetRecordingStreamingTranscode(
|
|
|
146
194
|
|
|
147
195
|
// ── Master-reference reads ───────────────────────────────────────────────────
|
|
148
196
|
|
|
149
|
-
// recording_master_reference stores the ori::
|
|
197
|
+
// recording_master_reference stores the ori::data::WalrusBlob value inline in a
|
|
150
198
|
// dynamic field on the Recording. Its empty ExtensionKey serializes to one false
|
|
151
199
|
// byte, so the field object id can be derived without listing the Recording's
|
|
152
200
|
// dynamic fields.
|
|
153
201
|
const MasterReferenceField = bcs.struct("Field", {
|
|
154
202
|
id: bcs.Address,
|
|
155
203
|
name: masterReference.ExtensionKey,
|
|
156
|
-
value: walrusData.
|
|
204
|
+
value: walrusData.WalrusBlob,
|
|
157
205
|
});
|
|
158
206
|
const MASTER_REFERENCE_KEY_BYTES = masterReference.ExtensionKey.serialize([
|
|
159
207
|
false,
|
|
160
208
|
]).toBytes();
|
|
161
209
|
|
|
162
|
-
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
$kind: "QuiltPatch";
|
|
170
|
-
QuiltPatch: [string | number | bigint, number, number, number];
|
|
171
|
-
};
|
|
172
|
-
return reference.$kind === "Blob" ? String(reference.Blob[0]) : null;
|
|
210
|
+
/**
|
|
211
|
+
* Parse an attached master reference's standalone Walrus blob id (decimal
|
|
212
|
+
* `u256`). Encrypted masters are returned as-is: the reference is the same
|
|
213
|
+
* either way, and access control belongs to the caller.
|
|
214
|
+
*/
|
|
215
|
+
export function parseRecordingMasterReferenceContent(content: Uint8Array): string {
|
|
216
|
+
return String(MasterReferenceField.parse(content).value.blob_id);
|
|
173
217
|
}
|
|
174
218
|
|
|
175
219
|
/** Deterministic dynamic-field id for a Recording's master reference. */
|
|
@@ -231,8 +275,7 @@ export async function getRecordingMasterReferencesByIds(
|
|
|
231
275
|
const target = targets[index];
|
|
232
276
|
if (!target || object instanceof Error || !object.content) return;
|
|
233
277
|
try {
|
|
234
|
-
|
|
235
|
-
if (blobId) out[target.recordingId] = blobId;
|
|
278
|
+
out[target.recordingId] = parseRecordingMasterReferenceContent(object.content);
|
|
236
279
|
} catch {
|
|
237
280
|
// Extension metadata is soft: retain valid tracks when one field is stale.
|
|
238
281
|
}
|