@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.
Files changed (46) hide show
  1. package/README.md +4 -2
  2. package/dist/client.d.ts +1 -4
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +0 -5
  5. package/dist/client.js.map +1 -1
  6. package/dist/contracts.d.ts +1 -1
  7. package/dist/contracts.d.ts.map +1 -1
  8. package/dist/contracts.js +1 -1
  9. package/dist/contracts.js.map +1 -1
  10. package/dist/cover.d.ts +5 -8
  11. package/dist/cover.d.ts.map +1 -1
  12. package/dist/cover.js +5 -17
  13. package/dist/cover.js.map +1 -1
  14. package/dist/deployments.d.ts +62 -65
  15. package/dist/deployments.d.ts.map +1 -1
  16. package/dist/deployments.js +34 -35
  17. package/dist/deployments.js.map +1 -1
  18. package/dist/internal.d.ts +11 -0
  19. package/dist/internal.d.ts.map +1 -1
  20. package/dist/internal.js +18 -1
  21. package/dist/internal.js.map +1 -1
  22. package/dist/mix.d.ts +0 -14
  23. package/dist/mix.d.ts.map +1 -1
  24. package/dist/mix.js +21 -43
  25. package/dist/mix.js.map +1 -1
  26. package/dist/publication.d.ts +2 -1
  27. package/dist/publication.d.ts.map +1 -1
  28. package/dist/publication.js +12 -9
  29. package/dist/publication.js.map +1 -1
  30. package/dist/read/catalog.d.ts.map +1 -1
  31. package/dist/read/catalog.js +3 -7
  32. package/dist/read/catalog.js.map +1 -1
  33. package/dist/recording-extensions.d.ts +24 -7
  34. package/dist/recording-extensions.d.ts.map +1 -1
  35. package/dist/recording-extensions.js +39 -16
  36. package/dist/recording-extensions.js.map +1 -1
  37. package/package.json +3 -3
  38. package/src/client.ts +1 -11
  39. package/src/contracts.ts +1 -1
  40. package/src/cover.ts +21 -41
  41. package/src/deployments.ts +37 -40
  42. package/src/internal.ts +25 -0
  43. package/src/mix.ts +21 -68
  44. package/src/publication.ts +17 -9
  45. package/src/read/catalog.ts +2 -11
  46. 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::WalrusData`. We build the ref
6
- // (`ori::walrus_data::new_blob`, a raw call — ori is an external dep), wrap it in a
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 `walrus_data::new_blob` / the `WalrusData` type). */
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}::walrus_data::WalrusData`;
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` / `walrusDataUrl`).
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::WalrusData` value (a MoveEnum: `Blob` or `QuiltPatch`). */
147
- type ParsedWalrusData =
148
- | { $kind: "Blob"; Blob: [string | number | bigint, unknown] }
149
- | {
150
- $kind: "QuiltPatch";
151
- QuiltPatch: [string | number | bigint, number, number, number];
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: ParsedWalrusData;
189
- animated: ParsedWalrusData | null;
168
+ still: ParsedWalrusBlob;
169
+ animated: ParsedWalrusBlob | null;
190
170
  } | null;
191
171
  if (!cover) return null;
192
172
 
@@ -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
- /** Canonical plaintext session pointer extension; absent before publication. */
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
- readonly recordingPreview: string;
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
- "0x75e5fa520c39322e0526ff56a495f9a2a88d097e2df7902d94e58a9a12831e76",
252
+ "0xc9411d3e2cb9600081544572036bec049624db1707f9354c342090f440b6e1a2",
254
253
  recordShopPackageId:
255
- "0x2b97df3773040bb2cffd8c329bfd57f05f1fd2defb6ab156050ba1ae540d5d2a",
254
+ "0xc6d49266080b8f165b6c1fc48e1aa4a6d719183d78a8d1043bfe0f2d6c744ed1",
256
255
  },
257
256
  operations: {
258
257
  status: "available",
259
258
  vault: {
260
259
  packageId:
261
- "0xaed1aa729452c77f4c62882b73317851d628c30af55355c81eb1c93d3d3276ac",
260
+ "0x77b74e9221874b9e29f6743a277810480bf89d71b5cb71741cd52dfcd83035d2",
262
261
  registryId:
263
- "0x5de3c379a15e4609260a94ace3d186cc466366fc6aebafe5663c016057b6a2d6",
262
+ "0x0fcfe3bb47f0ee2fbf0dcb65b48741efd06b4d746f1df14fe6ac3c00e9e35287",
264
263
  },
265
264
  actions: {
266
265
  compositionRoyaltyPool:
267
- "0x46b9b193255f28ec5190e8cd37ae85397c9110266da73a4a7a94fcb6e990155b",
266
+ "0x26c574e0aa01f504833b4f01dad44e2cd17b8718630e025d85ce05b843092085",
268
267
  recordingRoyaltyPool:
269
- "0x78964bdc2dd7fad943633542edf5a1c9be38b1d2d25de1cc6cca64757c7d037a",
268
+ "0x84b3cc36907112da74c88c78d1ac20e17010a30e206dfa4322a300c87032d405",
270
269
  partyWallet:
271
- "0x934f15715f725e3eed2acaeda5c717b6641dce4bb88b7670db26249cb6646728",
270
+ "0xa3d6016f2da63b53546e3f9922e8f0c12c27ca532509ef8c0e778f3e7cd56ee6",
272
271
  compositionRoutedStake:
273
- "0xb1539001eaf32350d7044acb03092dcbd5a366e708d959aece0cca683f7f57fc",
272
+ "0x8e32cdb08953afe0b72f46fde2b0fe1ab0ab3c12885c1e41883ccb5d8703e144",
274
273
  releaseRevenueDistributor:
275
- "0xd19dde6c20fa41092c9645e8300284cf1a268ab5ed3b3c7a2a12593672203b45",
274
+ "0x5ab255ed56c601c5d3c79502e81cfd4fd534c166fa731c2275a65d5fd2b34615",
276
275
  },
277
276
  plugins: {
278
277
  compositionRoyaltyPool:
279
- "0xad3525b86fad3f2aaaa3fdf0430d690efba249e378b1b89ed8180ecbc5d89392",
278
+ "0x6969b98c0322a8a7ba2478d900fc88e1c9ba17903c310c7fdb133c0789bd5ba8",
280
279
  recordingRoyaltyPool:
281
- "0x2adfc809152c5c8cf07f0e466d881b62d48c7da3ae2e787c0471deb867a6a385",
280
+ "0x4ac310583eda99e148207f99618ce5d21d7e7680e7c92b58422113b155a97455",
282
281
  releaseRevenueDistributor:
283
- "0x4f1da8c04ec53749f6cf6e8d2d48701fd72654078240050e20e41dc774f93d46",
282
+ "0xf13e254b32cee1315d9c0af3c4ef6e3bb770c293eee90afe30a009cde30bb381",
284
283
  },
285
284
  },
286
285
  packages: {
287
286
  minato:
288
287
  "0xcdf58ed7e4580118a6a3f2a8077abffe633c551b2f19e95ce01685d42f90b8d9",
289
288
  credit:
290
- "0xc5a82310ce313af8f0ec18a4e564af11971b360db9e2ae686fef86fb2297a9a9",
289
+ "0xb82c6c2524ede481cfa3c1066c70c1e43b1a5f6f11e40d5633153c2c3150bba7",
291
290
  compositionCredits:
292
- "0xc58ac5d69740866f6514f68f2e9c86b1d069d819ad0bcf5384b6aaa66e0fbf53",
291
+ "0x09434b8b65fb25a703b9c762abbb9075b5bfde6baffc923baac9353ab2191a65",
293
292
  recordingCredits:
294
- "0x7bafa653854f0820d911b8f6aa0aac3b131163c254b0021330881b77206d4d79",
293
+ "0x598303437c97ab1ec232be884d041587f18647b71fb36f4cf76cbbcc3c276dd2",
295
294
  releaseCredits:
296
- "0x47ccd23c669b023b8678193e7748235916e16e737fdd8ba48b131ded29c76a00",
295
+ "0xd6e9f090d581779099cc4beaf6c8843f1d569dea85fdde004748c8f03aadafcb",
297
296
  royaltyPool:
298
- "0xecaa5a29cf8e110face3b80f0e4a5554e8c80edd8eda0983ed2f8015367eecca",
297
+ "0xce4a1415255ac043301f3057b1dbd1095ad4959fcbe5bfceb9dbb7cf1144def1",
299
298
  routedStake:
300
- "0x30ed387d3fea69579ddb34d011fa6e1416580bfb3ee6587aabf103fb0d17bced",
299
+ "0xaa37871d4ba3ce4a465c13c79d1a701941efbf33491633c744ad4b7035f7f894",
301
300
  coverArt:
302
- "0x2b811f82d33cf6a9448adb11a598f6b04c14970cfc8e2982cde1d468e8e7d4a4",
301
+ "0x711f7041fc9e12d045b278c07ff9cf5047b69002e91e9dd881ad51c09ec389f6",
303
302
  releaseCoverArt:
304
- "0x4f0a8736685f6b1ddbcd0bddcd7aae2d072aa3d4043efc0ad4042a7786068999",
303
+ "0xfb1dc55719142fb575c6242f338447fa87bf4618f6903c7a6e30489f4e810fb3",
305
304
  genre:
306
- "0x01e58dbc76c15c9ac137dabac1823ebd6ef81efd563c5121000bc11c51a47cc7",
305
+ "0x095c412a9e9846b091b8f93d9bd50bca5d98a2e65063cb6c20265dc307c4b319",
307
306
  releaseDescription:
308
- "0x50f5acf7c0c05cdc7656072fd1bfc5ee76d02beabeae090103734b2d75118fa3",
307
+ "0x957b633fd186f65f953e17caaeec2e3385431c6f55914cb31dfb775368f89d9e",
309
308
  releaseDspLink:
310
- "0x9ca9ad8cab49c4897cd3cb89628b771ee4f10831ddc273036837751a5339d02a",
309
+ "0x7bce4d548314d9cff3145732f19ad7e67b3c00e2cf4d6f295f8af6d02108884e",
311
310
  releaseGenre:
312
- "0xfb73b04be2f72704ec5e6a1035bfab108e5ee2a72e72c0505f999291e23219bd",
311
+ "0x9770bc7cf9d9b2fa35af194d14f0c36320fbf6541c5ee12b884f0db44d1b5a4f",
313
312
  releaseKind:
314
- "0xfb2e5790f0577aca3ac8ddd672c4c58ef1e49ef1c3dfe14fb9676aaabf769169",
313
+ "0x187f6f881623cc843d2c6dc98fe23203598fd3992b6a78c1b5990f3fd60a0f5b",
315
314
  recordingAdvisory:
316
- "0x23abf3f248466c08edc3349b202d6e809064c0e52098ff290cef1fdc51d5942e",
315
+ "0x8f745dac70fef5327e686b31acbe3f3504dc7eeb63da5f31a4660bb5aea5ee4b",
317
316
  recordingLanguage:
318
- "0xb3e1c578638a79acc7ab573c994206047ad8ef76893f9c5c987887c5b10a5c68",
317
+ "0xd6b7f206f838018a28d33b77bade2b8476ccafab5fe526345c375d3b47bb892f",
319
318
  recordingMasterReference:
320
- "0x92a752854b80a6103721743125ee48223b577a023fe360e25d3aa695462a6d15",
319
+ "0x65309bf315f3e035b0f10c706eb5c327af5038be1637a0cee74f4ae62872f6ce",
321
320
  recordingEngineSession:
322
- "0xdd8f817a221e2acd5a4e6f34d0192d8e0dbddeb76c2dff2fdc82991cb4feb6c6",
321
+ "0x2fcb9ab90772711487e5858e20393a4f222df538a3d5104d2a884bb54663af33",
322
+ recordingStreamingTranscode:
323
+ "0x622cd2a9e49ee2639f5c1d922d2fc75e89e810e80da8dd6d4a843bcefa0aacb0",
323
324
  recordSealPolicy:
324
- "0xfa22d0678eaec39ad36b74c2c5439d574292e8fb19a9a15272733267499d5351",
325
- recordingPreview:
326
- "0x2be8405f6b77a30d6942cb240c0d804d608ef761395e6f861b71d9ae3c98f997",
327
- ori: "0xf35cf353a62cef01084b51a9cf3da4c64c8724685ad1862f2f8284b71bd26c1a",
325
+ "0x2b806033f31ed0af5a9118429111dd5c91f44d9229c41aa9d5cbaec7e3910c0a",
326
+ ori: "0x51792b9adb9a5d05d7c4d74d7d0cb5aefc5639afa80c0089399cab8b99752e60",
328
327
  },
329
328
  objects: {
330
329
  releaseRegistry:
331
- "0x452c9904677a1bbf92d4e07d86d2c3eb038c47595b0e17a23756f03887eb2a2a",
330
+ "0x40700d8fd9de26392d10c4a3c0759b08f60be43e2f80681650e87a4efdac5cf1",
332
331
  genreRegistry:
333
- "0xda4cc070da1a71d43387973027a7230587a1b9c829d37c2af4a3adbc15fdb8a8",
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 { WalrusData } from "@misofm/protocol/contracts/recording_master_reference/deps/ori/walrus_data";
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: bcs.tuple([bcs.bool()]),
436
- value: bcs.struct("EngineSession", { reference: WalrusData }),
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(WalrusData))]),
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 reference = EngineSessionField.parse(content).value.reference;
496
- if (reference.$kind !== "Blob") {
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(id) };
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
  }
@@ -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
- readonly previewBlobId?: bigint | string;
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.moveCall({
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.previewBlobId !== undefined) setRecordingPreview({
881
+ if (node.engineSessionBlobId !== undefined) setRecordingEngineSession({
875
882
  recordingId: parts.work, authority,
876
883
  recordingShareType: node.shareType,
877
884
  compositionShareType: node.compositionShareType,
878
- recordingPreviewPackageId: p.deployment.packages.recordingPreview,
879
- reference: walrusBlob(tx, p, node.previewBlobId),
885
+ recordingEngineSessionPackageId: p.deployment.packages.recordingEngineSession!,
886
+ oriPackageId: p.deployment.packages.ori,
887
+ sessionBlobId: node.engineSessionBlobId,
880
888
  })(tx);
881
889
  });
882
890
 
@@ -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, whichever Walrus variant it is. */
77
+ /** Aggregator URL for a cover image ref (a standalone Walrus blob). */
79
78
  function imageUrl(aggregator: string, ref: CoverImageRef): string {
80
- const base = aggregator.replace(/\/$/, "");
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/walrus_data";
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 preview from "@misofm/protocol/contracts/recording_preview/recording_preview";
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::WalrusData value assembled in the same PTB (must be a standalone blob on chain). */
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
- /** Removes the Recording's streaming-transcode reference, if present. */
135
- export function unsetRecordingStreamingTranscode(
136
- p: UnsetRecordingStreamingTranscodeParams,
137
- ): TxThunk {
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.recordingStreamingTranscodePackageId}::recording_streaming_transcode::unset_streaming_transcode`,
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 interface SetRecordingPreviewParams extends RecordingWalrusReferenceParams {
149
- readonly recordingPreviewPackageId: string;
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
- export function setRecordingPreview(p: SetRecordingPreviewParams): TxThunk {
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.recordingPreviewPackageId}::recording_preview::set_preview`,
187
+ target: `${p.recordingStreamingTranscodePackageId}::recording_streaming_transcode::unset_streaming_transcode`,
155
188
  typeArguments: [p.recordingShareType, p.compositionShareType],
156
- arguments: [object(tx, p.recordingId), p.reference],
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::WalrusData value inline in a
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.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
- /** Parse an attached master reference's standalone Walrus blob id. */
178
- export function parseRecordingMasterReferenceContent(
179
- content: Uint8Array,
180
- ): string | null {
181
- const reference = MasterReferenceField.parse(content).value as
182
- | { $kind: "Blob"; Blob: [string | number | bigint, unknown] }
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
- const blobId = parseRecordingMasterReferenceContent(object.content);
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
  }