@misofm/platform 0.18.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 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +0 -5
- package/dist/client.js.map +1 -1
- package/dist/contracts.d.ts +1 -1
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +1 -1
- 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 +62 -65
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +34 -35
- package/dist/deployments.js.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 -1
- package/dist/publication.d.ts.map +1 -1
- package/dist/publication.js +12 -9
- 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 -7
- package/dist/recording-extensions.d.ts.map +1 -1
- package/dist/recording-extensions.js +39 -16
- package/dist/recording-extensions.js.map +1 -1
- package/package.json +3 -3
- package/src/client.ts +1 -11
- package/src/contracts.ts +1 -1
- package/src/cover.ts +21 -41
- package/src/deployments.ts +37 -40
- package/src/internal.ts +25 -0
- package/src/mix.ts +21 -68
- package/src/publication.ts +17 -9
- package/src/read/catalog.ts +2 -11
- package/src/recording-extensions.ts +57 -29
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,12 +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
|
-
|
|
224
|
-
/** External `ori::walrus_data::WalrusData` dependency used by cover art. */
|
|
223
|
+
/** External `ori` package (`data::WalrusBlob`, `data::WalrusQuilt`) used by Walrus-backed extensions. */
|
|
225
224
|
readonly ori: string;
|
|
226
225
|
};
|
|
227
226
|
readonly objects: {
|
|
@@ -250,89 +249,87 @@ export const MISO_PLATFORM_DEPLOYMENTS = immutableSnapshot({
|
|
|
250
249
|
recordSales: {
|
|
251
250
|
status: "available",
|
|
252
251
|
recordPackageId:
|
|
253
|
-
"
|
|
252
|
+
"0xc9411d3e2cb9600081544572036bec049624db1707f9354c342090f440b6e1a2",
|
|
254
253
|
recordShopPackageId:
|
|
255
|
-
"
|
|
254
|
+
"0xc6d49266080b8f165b6c1fc48e1aa4a6d719183d78a8d1043bfe0f2d6c744ed1",
|
|
256
255
|
},
|
|
257
256
|
operations: {
|
|
258
257
|
status: "available",
|
|
259
258
|
vault: {
|
|
260
259
|
packageId:
|
|
261
|
-
"
|
|
260
|
+
"0x77b74e9221874b9e29f6743a277810480bf89d71b5cb71741cd52dfcd83035d2",
|
|
262
261
|
registryId:
|
|
263
|
-
"
|
|
262
|
+
"0x0fcfe3bb47f0ee2fbf0dcb65b48741efd06b4d746f1df14fe6ac3c00e9e35287",
|
|
264
263
|
},
|
|
265
264
|
actions: {
|
|
266
265
|
compositionRoyaltyPool:
|
|
267
|
-
"
|
|
266
|
+
"0x26c574e0aa01f504833b4f01dad44e2cd17b8718630e025d85ce05b843092085",
|
|
268
267
|
recordingRoyaltyPool:
|
|
269
|
-
"
|
|
268
|
+
"0x84b3cc36907112da74c88c78d1ac20e17010a30e206dfa4322a300c87032d405",
|
|
270
269
|
partyWallet:
|
|
271
|
-
"
|
|
270
|
+
"0xa3d6016f2da63b53546e3f9922e8f0c12c27ca532509ef8c0e778f3e7cd56ee6",
|
|
272
271
|
compositionRoutedStake:
|
|
273
|
-
"
|
|
272
|
+
"0x8e32cdb08953afe0b72f46fde2b0fe1ab0ab3c12885c1e41883ccb5d8703e144",
|
|
274
273
|
releaseRevenueDistributor:
|
|
275
|
-
"
|
|
274
|
+
"0x5ab255ed56c601c5d3c79502e81cfd4fd534c166fa731c2275a65d5fd2b34615",
|
|
276
275
|
},
|
|
277
276
|
plugins: {
|
|
278
277
|
compositionRoyaltyPool:
|
|
279
|
-
"
|
|
278
|
+
"0x6969b98c0322a8a7ba2478d900fc88e1c9ba17903c310c7fdb133c0789bd5ba8",
|
|
280
279
|
recordingRoyaltyPool:
|
|
281
|
-
"
|
|
280
|
+
"0x4ac310583eda99e148207f99618ce5d21d7e7680e7c92b58422113b155a97455",
|
|
282
281
|
releaseRevenueDistributor:
|
|
283
|
-
"
|
|
282
|
+
"0xf13e254b32cee1315d9c0af3c4ef6e3bb770c293eee90afe30a009cde30bb381",
|
|
284
283
|
},
|
|
285
284
|
},
|
|
286
285
|
packages: {
|
|
287
286
|
minato:
|
|
288
287
|
"0xcdf58ed7e4580118a6a3f2a8077abffe633c551b2f19e95ce01685d42f90b8d9",
|
|
289
288
|
credit:
|
|
290
|
-
"
|
|
289
|
+
"0xb82c6c2524ede481cfa3c1066c70c1e43b1a5f6f11e40d5633153c2c3150bba7",
|
|
291
290
|
compositionCredits:
|
|
292
|
-
"
|
|
291
|
+
"0x09434b8b65fb25a703b9c762abbb9075b5bfde6baffc923baac9353ab2191a65",
|
|
293
292
|
recordingCredits:
|
|
294
|
-
"
|
|
293
|
+
"0x598303437c97ab1ec232be884d041587f18647b71fb36f4cf76cbbcc3c276dd2",
|
|
295
294
|
releaseCredits:
|
|
296
|
-
"
|
|
295
|
+
"0xd6e9f090d581779099cc4beaf6c8843f1d569dea85fdde004748c8f03aadafcb",
|
|
297
296
|
royaltyPool:
|
|
298
|
-
"
|
|
297
|
+
"0xce4a1415255ac043301f3057b1dbd1095ad4959fcbe5bfceb9dbb7cf1144def1",
|
|
299
298
|
routedStake:
|
|
300
|
-
"
|
|
299
|
+
"0xaa37871d4ba3ce4a465c13c79d1a701941efbf33491633c744ad4b7035f7f894",
|
|
301
300
|
coverArt:
|
|
302
|
-
"
|
|
301
|
+
"0x711f7041fc9e12d045b278c07ff9cf5047b69002e91e9dd881ad51c09ec389f6",
|
|
303
302
|
releaseCoverArt:
|
|
304
|
-
"
|
|
303
|
+
"0xfb1dc55719142fb575c6242f338447fa87bf4618f6903c7a6e30489f4e810fb3",
|
|
305
304
|
genre:
|
|
306
|
-
"
|
|
305
|
+
"0x095c412a9e9846b091b8f93d9bd50bca5d98a2e65063cb6c20265dc307c4b319",
|
|
307
306
|
releaseDescription:
|
|
308
|
-
"
|
|
307
|
+
"0x957b633fd186f65f953e17caaeec2e3385431c6f55914cb31dfb775368f89d9e",
|
|
309
308
|
releaseDspLink:
|
|
310
|
-
"
|
|
309
|
+
"0x7bce4d548314d9cff3145732f19ad7e67b3c00e2cf4d6f295f8af6d02108884e",
|
|
311
310
|
releaseGenre:
|
|
312
|
-
"
|
|
311
|
+
"0x9770bc7cf9d9b2fa35af194d14f0c36320fbf6541c5ee12b884f0db44d1b5a4f",
|
|
313
312
|
releaseKind:
|
|
314
|
-
"
|
|
313
|
+
"0x187f6f881623cc843d2c6dc98fe23203598fd3992b6a78c1b5990f3fd60a0f5b",
|
|
315
314
|
recordingAdvisory:
|
|
316
|
-
"
|
|
315
|
+
"0x8f745dac70fef5327e686b31acbe3f3504dc7eeb63da5f31a4660bb5aea5ee4b",
|
|
317
316
|
recordingLanguage:
|
|
318
|
-
"
|
|
317
|
+
"0xd6b7f206f838018a28d33b77bade2b8476ccafab5fe526345c375d3b47bb892f",
|
|
319
318
|
recordingMasterReference:
|
|
320
|
-
"
|
|
319
|
+
"0x65309bf315f3e035b0f10c706eb5c327af5038be1637a0cee74f4ae62872f6ce",
|
|
321
320
|
recordingEngineSession:
|
|
322
|
-
"
|
|
321
|
+
"0x2fcb9ab90772711487e5858e20393a4f222df538a3d5104d2a884bb54663af33",
|
|
322
|
+
recordingStreamingTranscode:
|
|
323
|
+
"0x622cd2a9e49ee2639f5c1d922d2fc75e89e810e80da8dd6d4a843bcefa0aacb0",
|
|
323
324
|
recordSealPolicy:
|
|
324
|
-
"
|
|
325
|
-
|
|
326
|
-
"0x2be8405f6b77a30d6942cb240c0d804d608ef761395e6f861b71d9ae3c98f997",
|
|
327
|
-
ori: "0xf35cf353a62cef01084b51a9cf3da4c64c8724685ad1862f2f8284b71bd26c1a",
|
|
325
|
+
"0x2b806033f31ed0af5a9118429111dd5c91f44d9229c41aa9d5cbaec7e3910c0a",
|
|
326
|
+
ori: "0x51792b9adb9a5d05d7c4d74d7d0cb5aefc5639afa80c0089399cab8b99752e60",
|
|
328
327
|
},
|
|
329
328
|
objects: {
|
|
330
329
|
releaseRegistry:
|
|
331
|
-
"
|
|
330
|
+
"0x40700d8fd9de26392d10c4a3c0759b08f60be43e2f80681650e87a4efdac5cf1",
|
|
332
331
|
genreRegistry:
|
|
333
|
-
"
|
|
334
|
-
recordGate:
|
|
335
|
-
"0x8fd51c8b31bb6012fb03d2be39ed7b9f0f581329b6b338c60c209110cc659f31",
|
|
332
|
+
"0x479a1f43c8118b24d10cba62d64ad782c19fad974cdbc5020c909ea943c857a8",
|
|
336
333
|
},
|
|
337
334
|
legacy: {
|
|
338
335
|
releaseCoverArtPackages: [],
|
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,12 +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
|
-
setRecordingPreview,
|
|
55
55
|
setRecordingStreamingTranscode,
|
|
56
56
|
} from "./recording-extensions.ts";
|
|
57
|
+
import { unencryptedWalrusBlob } from "./internal.ts";
|
|
57
58
|
import {
|
|
58
59
|
setReleaseDescription,
|
|
59
60
|
setReleaseDspLinks,
|
|
@@ -172,7 +173,8 @@ export type PublicationRecording = PublicationRecordingParent & {
|
|
|
172
173
|
readonly masterReferenceBlobId?: bigint | string;
|
|
173
174
|
/** Complete Walrus Quilt ID containing this Recording's streaming transcodes. */
|
|
174
175
|
readonly streamingTranscodeQuiltId?: bigint | string;
|
|
175
|
-
|
|
176
|
+
/** Unencrypted Walrus blob ID of this Recording's Miso Engine session file. */
|
|
177
|
+
readonly engineSessionBlobId?: bigint | string;
|
|
176
178
|
};
|
|
177
179
|
|
|
178
180
|
export interface PublicationFreshTrack {
|
|
@@ -334,10 +336,7 @@ function languageVector(tx: Transaction, p: AtomicPublicationParams, codes: stri
|
|
|
334
336
|
}
|
|
335
337
|
|
|
336
338
|
function walrusBlob(tx: Transaction, p: AtomicPublicationParams, blobId: bigint | string) {
|
|
337
|
-
return tx.
|
|
338
|
-
target: `${p.deployment.packages.ori}::walrus_data::new_blob`,
|
|
339
|
-
arguments: [tx.pure.u256(blobId)],
|
|
340
|
-
});
|
|
339
|
+
return unencryptedWalrusBlob(tx, p.deployment.packages.ori, blobId);
|
|
341
340
|
}
|
|
342
341
|
|
|
343
342
|
function listingPrice(tx: Transaction, p: AtomicPublicationParams, price: ListingPrice) {
|
|
@@ -654,6 +653,14 @@ export function publishAtomicCatalog(p: AtomicPublicationParams): TxThunk {
|
|
|
654
653
|
"A recording streaming transcode requires deployment.packages.recordingStreamingTranscode",
|
|
655
654
|
);
|
|
656
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
|
+
}
|
|
657
664
|
if (publicationUsesVault(p)) {
|
|
658
665
|
requireOperationsDeployment(p.deployment.operations);
|
|
659
666
|
}
|
|
@@ -871,12 +878,13 @@ export function publishAtomicCatalog(p: AtomicPublicationParams): TxThunk {
|
|
|
871
878
|
oriPackageId: p.deployment.packages.ori,
|
|
872
879
|
quiltId: node.streamingTranscodeQuiltId,
|
|
873
880
|
})(tx);
|
|
874
|
-
if (node.
|
|
881
|
+
if (node.engineSessionBlobId !== undefined) setRecordingEngineSession({
|
|
875
882
|
recordingId: parts.work, authority,
|
|
876
883
|
recordingShareType: node.shareType,
|
|
877
884
|
compositionShareType: node.compositionShareType,
|
|
878
|
-
|
|
879
|
-
|
|
885
|
+
recordingEngineSessionPackageId: p.deployment.packages.recordingEngineSession!,
|
|
886
|
+
oriPackageId: p.deployment.packages.ori,
|
|
887
|
+
sessionBlobId: node.engineSessionBlobId,
|
|
880
888
|
})(tx);
|
|
881
889
|
});
|
|
882
890
|
|
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,10 +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
|
|
16
|
+
import * as engineSession from "@misofm/protocol/contracts/recording_engine_session/recording_engine_session";
|
|
17
17
|
import * as streamingTranscode from "@misofm/protocol/contracts/recording_streaming_transcode/recording_streaming_transcode";
|
|
18
|
+
import { unencryptedWalrusBlob } from "./internal.ts";
|
|
18
19
|
|
|
19
20
|
export interface RecordingExtensionTarget {
|
|
20
21
|
readonly recordingId: ObjectInput;
|
|
@@ -78,7 +79,7 @@ export function setRecordingInstrumental(p: Omit<SetRecordingLanguagesParams, "l
|
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
interface RecordingWalrusReferenceParams extends RecordingExtensionTarget {
|
|
81
|
-
/** An ori::
|
|
82
|
+
/** An `ori::data::WalrusBlob` value assembled in the same PTB. */
|
|
82
83
|
readonly reference: TransactionArgument;
|
|
83
84
|
}
|
|
84
85
|
|
|
@@ -131,29 +132,61 @@ export type UnsetRecordingStreamingTranscodeParams = Omit<
|
|
|
131
132
|
"oriPackageId" | "quiltId"
|
|
132
133
|
>;
|
|
133
134
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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 {
|
|
138
150
|
return (tx) => {
|
|
151
|
+
const session = tx.add(engineSession._new({
|
|
152
|
+
package: p.recordingEngineSessionPackageId,
|
|
153
|
+
arguments: [unencryptedWalrusBlob(tx, p.oriPackageId, p.sessionBlobId)],
|
|
154
|
+
}));
|
|
139
155
|
invokeWithAdminCap(tx, p.authority, {
|
|
140
|
-
target: `${p.
|
|
156
|
+
target: `${p.recordingEngineSessionPackageId}::recording_engine_session::set_engine_session`,
|
|
141
157
|
typeArguments: [p.recordingShareType, p.compositionShareType],
|
|
142
|
-
arguments: [object(tx, p.recordingId)],
|
|
158
|
+
arguments: [object(tx, p.recordingId), session],
|
|
143
159
|
adminCapIndex: 1,
|
|
144
160
|
});
|
|
145
161
|
};
|
|
146
162
|
}
|
|
147
163
|
|
|
148
|
-
export
|
|
149
|
-
|
|
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
|
+
};
|
|
150
179
|
}
|
|
151
|
-
|
|
180
|
+
|
|
181
|
+
/** Removes the Recording's streaming-transcode reference, if present. */
|
|
182
|
+
export function unsetRecordingStreamingTranscode(
|
|
183
|
+
p: UnsetRecordingStreamingTranscodeParams,
|
|
184
|
+
): TxThunk {
|
|
152
185
|
return (tx) => {
|
|
153
186
|
invokeWithAdminCap(tx, p.authority, {
|
|
154
|
-
target: `${p.
|
|
187
|
+
target: `${p.recordingStreamingTranscodePackageId}::recording_streaming_transcode::unset_streaming_transcode`,
|
|
155
188
|
typeArguments: [p.recordingShareType, p.compositionShareType],
|
|
156
|
-
arguments: [object(tx, p.recordingId)
|
|
189
|
+
arguments: [object(tx, p.recordingId)],
|
|
157
190
|
adminCapIndex: 1,
|
|
158
191
|
});
|
|
159
192
|
};
|
|
@@ -161,30 +194,26 @@ export function setRecordingPreview(p: SetRecordingPreviewParams): TxThunk {
|
|
|
161
194
|
|
|
162
195
|
// ── Master-reference reads ───────────────────────────────────────────────────
|
|
163
196
|
|
|
164
|
-
// recording_master_reference stores the ori::
|
|
197
|
+
// recording_master_reference stores the ori::data::WalrusBlob value inline in a
|
|
165
198
|
// dynamic field on the Recording. Its empty ExtensionKey serializes to one false
|
|
166
199
|
// byte, so the field object id can be derived without listing the Recording's
|
|
167
200
|
// dynamic fields.
|
|
168
201
|
const MasterReferenceField = bcs.struct("Field", {
|
|
169
202
|
id: bcs.Address,
|
|
170
203
|
name: masterReference.ExtensionKey,
|
|
171
|
-
value: walrusData.
|
|
204
|
+
value: walrusData.WalrusBlob,
|
|
172
205
|
});
|
|
173
206
|
const MASTER_REFERENCE_KEY_BYTES = masterReference.ExtensionKey.serialize([
|
|
174
207
|
false,
|
|
175
208
|
]).toBytes();
|
|
176
209
|
|
|
177
|
-
/**
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
$kind: "QuiltPatch";
|
|
185
|
-
QuiltPatch: [string | number | bigint, number, number, number];
|
|
186
|
-
};
|
|
187
|
-
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);
|
|
188
217
|
}
|
|
189
218
|
|
|
190
219
|
/** Deterministic dynamic-field id for a Recording's master reference. */
|
|
@@ -246,8 +275,7 @@ export async function getRecordingMasterReferencesByIds(
|
|
|
246
275
|
const target = targets[index];
|
|
247
276
|
if (!target || object instanceof Error || !object.content) return;
|
|
248
277
|
try {
|
|
249
|
-
|
|
250
|
-
if (blobId) out[target.recordingId] = blobId;
|
|
278
|
+
out[target.recordingId] = parseRecordingMasterReferenceContent(object.content);
|
|
251
279
|
} catch {
|
|
252
280
|
// Extension metadata is soft: retain valid tracks when one field is stale.
|
|
253
281
|
}
|