@misofm/platform 0.0.0 → 0.18.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 (168) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +686 -3
  3. package/dist/auth.d.ts +73 -0
  4. package/dist/auth.d.ts.map +1 -0
  5. package/dist/auth.js +193 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/catalog.d.ts +48 -0
  8. package/dist/catalog.d.ts.map +1 -0
  9. package/dist/catalog.js +92 -0
  10. package/dist/catalog.js.map +1 -0
  11. package/dist/client.d.ts +462 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +788 -0
  14. package/dist/client.js.map +1 -0
  15. package/dist/contracts.d.ts +34 -0
  16. package/dist/contracts.d.ts.map +1 -0
  17. package/dist/contracts.js +49 -0
  18. package/dist/contracts.js.map +1 -0
  19. package/dist/cover.d.ts +69 -0
  20. package/dist/cover.d.ts.map +1 -0
  21. package/dist/cover.js +132 -0
  22. package/dist/cover.js.map +1 -0
  23. package/dist/credits.d.ts +200 -0
  24. package/dist/credits.d.ts.map +1 -0
  25. package/dist/credits.js +465 -0
  26. package/dist/credits.js.map +1 -0
  27. package/dist/deployments.d.ts +224 -0
  28. package/dist/deployments.d.ts.map +1 -0
  29. package/dist/deployments.js +177 -0
  30. package/dist/deployments.js.map +1 -0
  31. package/dist/execute.d.ts +30 -0
  32. package/dist/execute.d.ts.map +1 -0
  33. package/dist/execute.js +31 -0
  34. package/dist/execute.js.map +1 -0
  35. package/dist/index.d.ts +21 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +52 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/internal.d.ts +13 -0
  40. package/dist/internal.d.ts.map +1 -0
  41. package/dist/internal.js +41 -0
  42. package/dist/internal.js.map +1 -0
  43. package/dist/mix.d.ts +144 -0
  44. package/dist/mix.d.ts.map +1 -0
  45. package/dist/mix.js +656 -0
  46. package/dist/mix.js.map +1 -0
  47. package/dist/pressing.d.ts +137 -0
  48. package/dist/pressing.d.ts.map +1 -0
  49. package/dist/pressing.js +390 -0
  50. package/dist/pressing.js.map +1 -0
  51. package/dist/publication.d.ts +216 -0
  52. package/dist/publication.d.ts.map +1 -0
  53. package/dist/publication.js +872 -0
  54. package/dist/publication.js.map +1 -0
  55. package/dist/queries.d.ts +2 -0
  56. package/dist/queries.d.ts.map +1 -0
  57. package/dist/queries.js +8 -0
  58. package/dist/queries.js.map +1 -0
  59. package/dist/read/artist.d.ts +18 -0
  60. package/dist/read/artist.d.ts.map +1 -0
  61. package/dist/read/artist.js +86 -0
  62. package/dist/read/artist.js.map +1 -0
  63. package/dist/read/catalog.d.ts +93 -0
  64. package/dist/read/catalog.d.ts.map +1 -0
  65. package/dist/read/catalog.js +441 -0
  66. package/dist/read/catalog.js.map +1 -0
  67. package/dist/read/client.d.ts +37 -0
  68. package/dist/read/client.d.ts.map +1 -0
  69. package/dist/read/client.js +50 -0
  70. package/dist/read/client.js.map +1 -0
  71. package/dist/read/config.d.ts +68 -0
  72. package/dist/read/config.d.ts.map +1 -0
  73. package/dist/read/config.js +63 -0
  74. package/dist/read/config.js.map +1 -0
  75. package/dist/read/genres.d.ts +7 -0
  76. package/dist/read/genres.d.ts.map +1 -0
  77. package/dist/read/genres.js +38 -0
  78. package/dist/read/genres.js.map +1 -0
  79. package/dist/read/index.d.ts +14 -0
  80. package/dist/read/index.d.ts.map +1 -0
  81. package/dist/read/index.js +23 -0
  82. package/dist/read/index.js.map +1 -0
  83. package/dist/read/internal/scalars.d.ts +23 -0
  84. package/dist/read/internal/scalars.d.ts.map +1 -0
  85. package/dist/read/internal/scalars.js +57 -0
  86. package/dist/read/internal/scalars.js.map +1 -0
  87. package/dist/read/internal/walrus.d.ts +6 -0
  88. package/dist/read/internal/walrus.d.ts.map +1 -0
  89. package/dist/read/internal/walrus.js +29 -0
  90. package/dist/read/internal/walrus.js.map +1 -0
  91. package/dist/read/receipts.d.ts +41 -0
  92. package/dist/read/receipts.d.ts.map +1 -0
  93. package/dist/read/receipts.js +398 -0
  94. package/dist/read/receipts.js.map +1 -0
  95. package/dist/read/types.d.ts +328 -0
  96. package/dist/read/types.d.ts.map +1 -0
  97. package/dist/read/types.js +21 -0
  98. package/dist/read/types.js.map +1 -0
  99. package/dist/read/wallet.d.ts +74 -0
  100. package/dist/read/wallet.d.ts.map +1 -0
  101. package/dist/read/wallet.js +578 -0
  102. package/dist/read/wallet.js.map +1 -0
  103. package/dist/read/works.d.ts +29 -0
  104. package/dist/read/works.d.ts.map +1 -0
  105. package/dist/read/works.js +191 -0
  106. package/dist/read/works.js.map +1 -0
  107. package/dist/recording-extensions.d.ts +62 -0
  108. package/dist/recording-extensions.d.ts.map +1 -0
  109. package/dist/recording-extensions.js +159 -0
  110. package/dist/recording-extensions.js.map +1 -0
  111. package/dist/release-extensions.d.ts +93 -0
  112. package/dist/release-extensions.d.ts.map +1 -0
  113. package/dist/release-extensions.js +190 -0
  114. package/dist/release-extensions.js.map +1 -0
  115. package/dist/release-graph.d.ts +65 -0
  116. package/dist/release-graph.d.ts.map +1 -0
  117. package/dist/release-graph.js +136 -0
  118. package/dist/release-graph.js.map +1 -0
  119. package/dist/share-template.d.ts +3 -0
  120. package/dist/share-template.d.ts.map +1 -0
  121. package/dist/share-template.js +46 -0
  122. package/dist/share-template.js.map +1 -0
  123. package/dist/share.d.ts +67 -0
  124. package/dist/share.d.ts.map +1 -0
  125. package/dist/share.js +157 -0
  126. package/dist/share.js.map +1 -0
  127. package/dist/transactions.d.ts +216 -0
  128. package/dist/transactions.d.ts.map +1 -0
  129. package/dist/transactions.js +314 -0
  130. package/dist/transactions.js.map +1 -0
  131. package/dist/vault.d.ts +364 -0
  132. package/dist/vault.d.ts.map +1 -0
  133. package/dist/vault.js +507 -0
  134. package/dist/vault.js.map +1 -0
  135. package/package.json +145 -5
  136. package/src/auth.ts +275 -0
  137. package/src/catalog.ts +189 -0
  138. package/src/client.ts +1320 -0
  139. package/src/contracts.ts +54 -0
  140. package/src/cover.ts +240 -0
  141. package/src/credits.ts +906 -0
  142. package/src/deployments.ts +357 -0
  143. package/src/execute.ts +52 -0
  144. package/src/index.ts +69 -0
  145. package/src/internal.ts +46 -0
  146. package/src/mix.ts +910 -0
  147. package/src/pressing.ts +705 -0
  148. package/src/publication.ts +1214 -0
  149. package/src/queries.ts +9 -0
  150. package/src/read/artist.ts +118 -0
  151. package/src/read/catalog.ts +668 -0
  152. package/src/read/client.ts +87 -0
  153. package/src/read/config.ts +138 -0
  154. package/src/read/genres.ts +37 -0
  155. package/src/read/index.ts +85 -0
  156. package/src/read/internal/scalars.ts +59 -0
  157. package/src/read/internal/walrus.ts +42 -0
  158. package/src/read/receipts.ts +476 -0
  159. package/src/read/types.ts +415 -0
  160. package/src/read/wallet.ts +687 -0
  161. package/src/read/works.ts +297 -0
  162. package/src/recording-extensions.ts +256 -0
  163. package/src/release-extensions.ts +311 -0
  164. package/src/release-graph.ts +219 -0
  165. package/src/share-template.ts +55 -0
  166. package/src/share.ts +261 -0
  167. package/src/transactions.ts +542 -0
  168. package/src/vault.ts +1009 -0
package/src/vault.ts ADDED
@@ -0,0 +1,1009 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ /**
5
+ * Capability custody, raw-cap Action, and safe crank-plugin transaction builders.
6
+ *
7
+ * A direct admin cap remains supported for existing works. New work should give
8
+ * the owner a `VaultAdminCap<AdminCap>` and keep the raw admin cap inside the
9
+ * shared Vault. Every authorized call borrows and returns the raw cap inside
10
+ * one helper; borrowed capabilities are never exposed to application code.
11
+ * Party wallet and routed-stake operations remain Actions because their useful
12
+ * results must stay under the caller's control.
13
+ */
14
+
15
+ import type { BcsType } from "@mysten/sui/bcs";
16
+ import type { ClientWithCoreApi } from "@mysten/sui/client";
17
+ import type {
18
+ Transaction,
19
+ TransactionArgument,
20
+ TransactionObjectArgument,
21
+ } from "@mysten/sui/transactions";
22
+ import { deriveObjectID, normalizeStructTag } from "@mysten/sui/utils";
23
+ import * as vault from "@misofm/protocol/contracts/vault/vault";
24
+ import * as releaseRevenueDistributor from "@misofm/protocol/contracts/release_revenue_distributor/release_revenue_distributor";
25
+ import * as compositionRoyaltyPoolPlugin from "@misofm/protocol/contracts/composition_royalty_pool_plugin/composition_royalty_pool_plugin";
26
+ import * as recordingRoyaltyPoolPlugin from "@misofm/protocol/contracts/recording_royalty_pool_plugin/recording_royalty_pool_plugin";
27
+ import * as releaseRevenueDistributorPlugin from "@misofm/protocol/contracts/release_revenue_distributor_plugin/release_revenue_distributor_plugin";
28
+ import * as routedStake from "@misofm/protocol/contracts/routed_stake/routed_stake";
29
+
30
+ /** A legacy work whose raw protocol admin cap is still address-owned. */
31
+ /** An object id resolved lazily when a transaction thunk is applied. */
32
+ export type ObjectInput = string | TransactionObjectArgument;
33
+
34
+ /** The framework singleton read by `balance::settled_funds_value`. */
35
+ export const SUI_ACCUMULATOR_ROOT_OBJECT_ID = "0xacc";
36
+
37
+ function object(tx: Transaction, value: ObjectInput): TransactionObjectArgument {
38
+ return typeof value === "string" ? tx.object(value) : value;
39
+ }
40
+
41
+ export interface DirectAdminCapAuthority {
42
+ readonly kind: "direct";
43
+ readonly adminCap: ObjectInput;
44
+ }
45
+
46
+ /** A work whose protocol admin cap is custodied by a shared Vault. */
47
+ export interface VaultAdminCapAuthority {
48
+ readonly kind: "vault";
49
+ readonly vault: ObjectInput;
50
+ readonly vaultAdminCap: ObjectInput;
51
+ /** Fully-qualified protocol cap type, e.g. `0x…::release::ReleaseAdminCap`. */
52
+ readonly capType: string;
53
+ readonly vaultPackageId: string;
54
+ }
55
+
56
+ /** Explicit compatibility boundary for protocol mutations. */
57
+ export type AdminCapAuthority =
58
+ | DirectAdminCapAuthority
59
+ | VaultAdminCapAuthority;
60
+
61
+ export function directAdminCap(
62
+ adminCap: ObjectInput,
63
+ ): DirectAdminCapAuthority {
64
+ return { kind: "direct", adminCap };
65
+ }
66
+
67
+ function requiredVaultResult<T>(
68
+ result: { readonly [index: number]: T | undefined },
69
+ index: number,
70
+ command: string,
71
+ ): T {
72
+ const value = result[index];
73
+ if (value === undefined) throw new Error(`${command} did not return result ${index}`);
74
+ return value;
75
+ }
76
+
77
+ export function vaultAdminCap(
78
+ authority: Omit<VaultAdminCapAuthority, "kind">,
79
+ ): VaultAdminCapAuthority {
80
+ return { kind: "vault", ...authority };
81
+ }
82
+
83
+ /**
84
+ * Lend an authority's raw protocol cap to `use` for the scope of this PTB.
85
+ *
86
+ * The vault branch deliberately encloses `use` between `borrow_as_admin` and
87
+ * `put_back`; callers cannot accidentally leave a non-drop `Borrow` receipt in
88
+ * the transaction. The direct branch preserves compatibility with pre-vault
89
+ * work without silently treating it as protected custody.
90
+ */
91
+ /**
92
+ * A Move call whose argument list contains exactly one temporarily lent cap.
93
+ * No callback receives that cap, so it cannot escape past `put_back`.
94
+ */
95
+ export interface AdminCapMoveCall {
96
+ readonly target: string;
97
+ readonly typeArguments?: string[];
98
+ readonly arguments: TransactionArgument[];
99
+ readonly adminCapIndex: number;
100
+ }
101
+
102
+ /**
103
+ * Invoke one cap-authorized Move call without exposing a borrowed cap to JS.
104
+ * The returned PTB result belongs to `call.target`, never to the Vault borrow.
105
+ */
106
+ export function invokeWithAdminCap(
107
+ tx: Transaction,
108
+ authority: AdminCapAuthority,
109
+ call: AdminCapMoveCall,
110
+ ): TransactionObjectArgument {
111
+ if (call.adminCapIndex < 0 || call.adminCapIndex > call.arguments.length) {
112
+ throw new Error("admin cap argument index is out of range");
113
+ }
114
+
115
+ const invoke = (adminCap: TransactionArgument) => tx.moveCall({
116
+ target: call.target,
117
+ typeArguments: call.typeArguments,
118
+ arguments: [
119
+ ...call.arguments.slice(0, call.adminCapIndex),
120
+ adminCap,
121
+ ...call.arguments.slice(call.adminCapIndex),
122
+ ],
123
+ });
124
+ if (authority.kind === "direct") return invoke(object(tx, authority.adminCap));
125
+
126
+ const borrowed = tx.add(
127
+ vault.borrowAsAdmin({
128
+ package: authority.vaultPackageId,
129
+ typeArguments: [authority.capType],
130
+ arguments: [object(tx, authority.vault), object(tx, authority.vaultAdminCap)],
131
+ }),
132
+ );
133
+ const adminCap = borrowed[0];
134
+ const receipt = borrowed[1];
135
+ if (adminCap === undefined || receipt === undefined) {
136
+ throw new Error("vault::borrow_as_admin returned an incomplete result");
137
+ }
138
+ const result = invoke(adminCap);
139
+ tx.add(
140
+ vault.putBack({
141
+ package: authority.vaultPackageId,
142
+ typeArguments: [authority.capType],
143
+ arguments: [authority.vault, adminCap, receipt],
144
+ }),
145
+ );
146
+ return result;
147
+ }
148
+
149
+ export interface CustodyNewAdminCapParams {
150
+ /** The freshly-created raw protocol cap, consumed into the Vault. */
151
+ readonly adminCap: TransactionObjectArgument;
152
+ /** Shared singleton from which canonical Vault IDs are derived. */
153
+ readonly vaultRegistry: ObjectInput;
154
+ readonly capType: string;
155
+ readonly vaultPackageId: string;
156
+ /** Recipient of the only owner-held authority: VaultAdminCap. */
157
+ readonly owner: string | TransactionArgument;
158
+ /** Optional installation/configuration while the new Vault is still owned. */
159
+ readonly configure?: (
160
+ vaultObject: TransactionObjectArgument,
161
+ vaultAdminCapObject: TransactionObjectArgument,
162
+ ) => void;
163
+ }
164
+
165
+ /** Where a newly-created raw protocol cap ends up after its work is published. */
166
+ export type AdminCapCustody =
167
+ | { readonly kind: "direct"; readonly owner: string | TransactionArgument }
168
+ | {
169
+ readonly kind: "vault";
170
+ readonly owner: string | TransactionArgument;
171
+ readonly vaultRegistry: ObjectInput;
172
+ readonly capType: string;
173
+ readonly vaultPackageId: string;
174
+ readonly configure?: CustodyNewAdminCapParams["configure"];
175
+ };
176
+
177
+ /** Explicitly transfer a new cap or custody it before the PTB finishes. */
178
+ export function disposeNewAdminCap(
179
+ tx: Transaction,
180
+ adminCap: TransactionObjectArgument,
181
+ custody: AdminCapCustody,
182
+ ): void {
183
+ if (custody.kind === "direct") {
184
+ tx.transferObjects([adminCap], custody.owner);
185
+ return;
186
+ }
187
+ custodyNewAdminCap(tx, {
188
+ adminCap,
189
+ vaultRegistry: custody.vaultRegistry,
190
+ capType: custody.capType,
191
+ vaultPackageId: custody.vaultPackageId,
192
+ owner: custody.owner,
193
+ configure: custody.configure,
194
+ });
195
+ }
196
+
197
+ /** Withdraw the raw capability while leaving its canonical Vault shell intact. */
198
+ export function withdrawVaultCapability(
199
+ tx: Transaction,
200
+ params: {
201
+ readonly vault: ObjectInput;
202
+ readonly vaultAdminCap: ObjectInput;
203
+ readonly capType: string;
204
+ readonly vaultPackageId: string;
205
+ },
206
+ ): TransactionObjectArgument {
207
+ return tx.add(vault.withdrawCap({
208
+ package: params.vaultPackageId,
209
+ typeArguments: [params.capType],
210
+ arguments: [object(tx, params.vault), object(tx, params.vaultAdminCap)],
211
+ }));
212
+ }
213
+
214
+ /** Restore the one exact capability permanently assigned to a Vault. */
215
+ export function restoreVaultCapability(
216
+ tx: Transaction,
217
+ params: {
218
+ readonly vault: ObjectInput;
219
+ readonly vaultAdminCap: ObjectInput;
220
+ readonly adminCap: ObjectInput;
221
+ readonly capType: string;
222
+ readonly vaultPackageId: string;
223
+ },
224
+ ): void {
225
+ tx.add(vault.restoreCap({
226
+ package: params.vaultPackageId,
227
+ typeArguments: [params.capType],
228
+ arguments: [
229
+ object(tx, params.vault),
230
+ object(tx, params.vaultAdminCap),
231
+ object(tx, params.adminCap),
232
+ ],
233
+ }));
234
+ }
235
+
236
+ /** Transfer the `key + store` VaultAdminCap to its next owner. */
237
+ export function transferVaultAdminCap(
238
+ tx: Transaction,
239
+ params: {
240
+ readonly vaultAdminCap: ObjectInput;
241
+ readonly owner: string | TransactionArgument;
242
+ readonly capType: string;
243
+ readonly vaultPackageId: string;
244
+ },
245
+ ): void {
246
+ tx.transferObjects([object(tx, params.vaultAdminCap)], params.owner);
247
+ }
248
+
249
+ /**
250
+ * Custody a freshly-created raw admin cap, optionally configure it, share the
251
+ * Vault, then transfer only the VaultAdminCap to its owner.
252
+ */
253
+ export function custodyNewAdminCap(
254
+ tx: Transaction,
255
+ params: CustodyNewAdminCapParams,
256
+ ): void {
257
+ const created = tx.add(
258
+ vault._new({
259
+ package: params.vaultPackageId,
260
+ typeArguments: [params.capType],
261
+ arguments: [object(tx, params.vaultRegistry), params.adminCap],
262
+ }),
263
+ );
264
+ const vaultObject = requiredVaultResult(created, 0, "vault::_new");
265
+ const vaultAdminCap = requiredVaultResult(created, 1, "vault::_new");
266
+ params.configure?.(vaultObject, vaultAdminCap);
267
+ tx.add(
268
+ vault.share({
269
+ package: params.vaultPackageId,
270
+ typeArguments: [params.capType],
271
+ arguments: [vaultObject],
272
+ }),
273
+ );
274
+ transferVaultAdminCap(tx, {
275
+ vaultAdminCap,
276
+ owner: params.owner,
277
+ capType: params.capType,
278
+ vaultPackageId: params.vaultPackageId,
279
+ });
280
+ }
281
+
282
+ export interface VaultIdParams {
283
+ readonly vaultRegistryId: string;
284
+ readonly capId: string;
285
+ readonly capType: string;
286
+ readonly vaultPackageId: string;
287
+ }
288
+
289
+ /** Derive the canonical Vault ID without an RPC lookup. */
290
+ export function deriveVaultId(params: VaultIdParams): string {
291
+ const keyType = normalizeStructTag(
292
+ `${params.vaultPackageId}::vault::VaultKey<${params.capType}>`,
293
+ );
294
+ return deriveObjectID(
295
+ params.vaultRegistryId,
296
+ keyType,
297
+ vault.VaultKey.serialize([params.capId]).toBytes(),
298
+ );
299
+ }
300
+
301
+ /** Derive the canonical VaultAdminCap ID from its Vault ID. */
302
+ export function deriveVaultAdminCapId(
303
+ vaultId: string,
304
+ vaultPackageId: string,
305
+ ): string {
306
+ return deriveObjectID(
307
+ vaultId,
308
+ `${vaultPackageId}::vault::VaultAdminCapKey`,
309
+ vault.VaultAdminCapKey.serialize([false]).toBytes(),
310
+ );
311
+ }
312
+
313
+ export interface CompositionRoyaltyPoolPluginParams {
314
+ readonly vault: TransactionObjectArgument;
315
+ readonly vaultAdminCap: TransactionObjectArgument;
316
+ readonly compositionShareType: string;
317
+ readonly pluginPackageId: string;
318
+ }
319
+
320
+ /** Install the composition royalty-pool plugin; its witness stays internal. */
321
+ export function installCompositionRoyaltyPoolPlugin(
322
+ tx: Transaction,
323
+ params: CompositionRoyaltyPoolPluginParams,
324
+ ): void {
325
+ tx.add(
326
+ compositionRoyaltyPoolPlugin.install({
327
+ package: params.pluginPackageId,
328
+ typeArguments: [params.compositionShareType],
329
+ arguments: [params.vault, params.vaultAdminCap],
330
+ }),
331
+ );
332
+ }
333
+
334
+ export function uninstallCompositionRoyaltyPoolPlugin(
335
+ tx: Transaction,
336
+ params: CompositionRoyaltyPoolPluginParams,
337
+ ): void {
338
+ tx.add(
339
+ compositionRoyaltyPoolPlugin.uninstall({
340
+ package: params.pluginPackageId,
341
+ typeArguments: [params.compositionShareType],
342
+ arguments: [params.vault, params.vaultAdminCap],
343
+ }),
344
+ );
345
+ }
346
+
347
+ export interface NewCompositionRoyaltyPoolParams {
348
+ readonly authority: AdminCapAuthority;
349
+ readonly composition: TransactionObjectArgument;
350
+ readonly actionPackageId: string;
351
+ readonly currencyType: string;
352
+ readonly compositionShareType: string;
353
+ }
354
+
355
+ /** Create the canonical pool without sharing it so callers can configure fresh stakes first. */
356
+ export function newCompositionRoyaltyPool(
357
+ tx: Transaction,
358
+ params: NewCompositionRoyaltyPoolParams,
359
+ ): TransactionObjectArgument {
360
+ return invokeWithAdminCap(tx, params.authority, {
361
+ target: `${params.actionPackageId}::composition_royalty_pool::new_pool`,
362
+ typeArguments: [params.compositionShareType, params.currencyType],
363
+ arguments: [params.composition],
364
+ adminCapIndex: 1,
365
+ });
366
+ }
367
+
368
+ export interface CompositionRoyaltyPoolCrankParams {
369
+ readonly vault: TransactionObjectArgument;
370
+ readonly composition: TransactionObjectArgument;
371
+ readonly pool: TransactionObjectArgument;
372
+ readonly compositionShareType: string;
373
+ readonly currencyType: string;
374
+ readonly pluginPackageId: string;
375
+ }
376
+
377
+ /** JSON-safe input for an on-chain u64. Numbers are rejected to prevent rounding. */
378
+ export type U64Input = bigint | string | number;
379
+
380
+ /** An exact scalar or the result of an earlier PTB command returning `u64`. */
381
+ export type U64Argument = U64Input | TransactionArgument;
382
+
383
+ /** Validate an SDK scalar before serializing it as a Move u64. */
384
+ export function asU64(name: string, value: U64Input): bigint {
385
+ if (typeof value === "number" && (!Number.isSafeInteger(value) || value < 0)) {
386
+ throw new Error(`${name}: number must be a non-negative safe integer; use bigint or decimal string`);
387
+ }
388
+ if (typeof value === "string" && !/^(0|[1-9][0-9]*)$/.test(value)) {
389
+ throw new Error(`${name}: expected an unsigned decimal u64`);
390
+ }
391
+ const parsed = typeof value === "bigint" ? value : BigInt(value);
392
+ if (parsed < 0n || parsed > 18_446_744_073_709_551_615n) {
393
+ throw new Error(`${name}: value is outside u64`);
394
+ }
395
+ return parsed;
396
+ }
397
+
398
+ function asU64Argument(tx: Transaction, name: string, value: U64Argument): TransactionArgument {
399
+ if (
400
+ typeof value === "bigint" ||
401
+ typeof value === "string" ||
402
+ typeof value === "number"
403
+ ) {
404
+ return tx.pure.u64(asU64(name, value));
405
+ }
406
+ return value;
407
+ }
408
+
409
+ /** Read the commit-settled accumulator balance for an address inside this PTB. */
410
+ export function settledFundsValue(
411
+ tx: Transaction,
412
+ params: {
413
+ readonly address: string | TransactionArgument;
414
+ readonly currencyType: string;
415
+ readonly accumulatorRoot?: ObjectInput;
416
+ },
417
+ ): TransactionArgument {
418
+ return tx.moveCall({
419
+ target: "0x2::balance::settled_funds_value",
420
+ typeArguments: [params.currencyType],
421
+ arguments: [
422
+ object(tx, params.accumulatorRoot ?? SUI_ACCUMULATOR_ROOT_OBJECT_ID),
423
+ typeof params.address === "string"
424
+ ? tx.pure.address(params.address)
425
+ : params.address,
426
+ ],
427
+ });
428
+ }
429
+
430
+ /** Permissionless crank: redeem an exact Composition amount into its pool. */
431
+ export function redeemAndDepositCompositionRoyaltyPool(
432
+ tx: Transaction,
433
+ params: CompositionRoyaltyPoolCrankParams & {
434
+ readonly value: U64Argument;
435
+ },
436
+ ): void {
437
+ tx.add(
438
+ compositionRoyaltyPoolPlugin.redeemAndDeposit({
439
+ package: params.pluginPackageId,
440
+ typeArguments: [params.compositionShareType, params.currencyType],
441
+ arguments: [
442
+ params.vault,
443
+ params.composition,
444
+ params.pool,
445
+ asU64Argument(tx, "value", params.value),
446
+ ],
447
+ }),
448
+ );
449
+ }
450
+
451
+ /** Redeem exactly the framework-reported settled Composition funds. */
452
+ export function settleCompositionRoyaltyPool(
453
+ tx: Transaction,
454
+ params: Omit<CompositionRoyaltyPoolCrankParams, "composition"> & {
455
+ readonly compositionId: string;
456
+ readonly accumulatorRoot?: ObjectInput;
457
+ },
458
+ ): void {
459
+ const value = settledFundsValue(tx, {
460
+ address: params.compositionId,
461
+ currencyType: params.currencyType,
462
+ accumulatorRoot: params.accumulatorRoot,
463
+ });
464
+ redeemAndDepositCompositionRoyaltyPool(tx, {
465
+ ...params,
466
+ composition: tx.object(params.compositionId),
467
+ value,
468
+ });
469
+ }
470
+
471
+ /** Permissionless crank: receive selected Composition-owned coins into the pool. */
472
+ export function receiveCompositionRoyaltyPool(
473
+ tx: Transaction,
474
+ params: CompositionRoyaltyPoolCrankParams & { readonly coins: readonly ReceivingObjectRef[] },
475
+ ): void {
476
+ tx.add(
477
+ compositionRoyaltyPoolPlugin.receiveAndDeposit({
478
+ package: params.pluginPackageId,
479
+ typeArguments: [params.compositionShareType, params.currencyType],
480
+ arguments: [
481
+ params.vault,
482
+ params.composition,
483
+ params.pool,
484
+ receivingCoins(tx, params.currencyType, params.coins),
485
+ ],
486
+ }),
487
+ );
488
+ }
489
+
490
+ export interface RecordingRoyaltyPoolPluginParams {
491
+ readonly vault: TransactionObjectArgument;
492
+ readonly vaultAdminCap: TransactionObjectArgument;
493
+ readonly recordingShareType: string;
494
+ readonly compositionShareType: string;
495
+ readonly pluginPackageId: string;
496
+ }
497
+
498
+ export function installRecordingRoyaltyPoolPlugin(
499
+ tx: Transaction,
500
+ params: RecordingRoyaltyPoolPluginParams,
501
+ ): void {
502
+ tx.add(
503
+ recordingRoyaltyPoolPlugin.install({
504
+ package: params.pluginPackageId,
505
+ typeArguments: [params.recordingShareType],
506
+ arguments: [params.vault, params.vaultAdminCap],
507
+ }),
508
+ );
509
+ }
510
+
511
+ export interface PartyWalletFundsParams {
512
+ readonly authority: AdminCapAuthority;
513
+ readonly party: TransactionObjectArgument;
514
+ readonly currencyType: string;
515
+ readonly actionPackageId: string;
516
+ }
517
+
518
+ /** Receive selected Party-owned coins and return their merged Balance. */
519
+ export function receivePartyWalletBalance(
520
+ tx: Transaction,
521
+ params: PartyWalletFundsParams & { readonly coins: readonly ReceivingObjectRef[] },
522
+ ): TransactionArgument {
523
+ return invokeWithAdminCap(tx, params.authority, {
524
+ target: `${params.actionPackageId}::party_wallet::receive_balance`,
525
+ typeArguments: [params.currencyType],
526
+ arguments: [params.party, receivingCoins(tx, params.currencyType, params.coins)],
527
+ adminCapIndex: 1,
528
+ });
529
+ }
530
+
531
+ /** Redeem an exact Party accumulator amount and return its Balance. */
532
+ export function redeemPartyWalletBalance(
533
+ tx: Transaction,
534
+ params: PartyWalletFundsParams & { readonly value: U64Argument },
535
+ ): TransactionArgument {
536
+ return invokeWithAdminCap(tx, params.authority, {
537
+ target: `${params.actionPackageId}::party_wallet::redeem_balance`,
538
+ typeArguments: [params.currencyType],
539
+ arguments: [params.party, asU64Argument(tx, "value", params.value)],
540
+ adminCapIndex: 1,
541
+ });
542
+ }
543
+
544
+ /** Redeem exactly the framework-reported settled Party funds. */
545
+ export function settlePartyWalletBalance(
546
+ tx: Transaction,
547
+ params: Omit<PartyWalletFundsParams, "party"> & {
548
+ readonly partyId: string;
549
+ readonly accumulatorRoot?: ObjectInput;
550
+ },
551
+ ): TransactionArgument {
552
+ const value = settledFundsValue(tx, {
553
+ address: params.partyId,
554
+ currencyType: params.currencyType,
555
+ accumulatorRoot: params.accumulatorRoot,
556
+ });
557
+ return redeemPartyWalletBalance(tx, {
558
+ ...params,
559
+ party: tx.object(params.partyId),
560
+ value,
561
+ });
562
+ }
563
+
564
+ export function uninstallRecordingRoyaltyPoolPlugin(
565
+ tx: Transaction,
566
+ params: RecordingRoyaltyPoolPluginParams,
567
+ ): void {
568
+ tx.add(
569
+ recordingRoyaltyPoolPlugin.uninstall({
570
+ package: params.pluginPackageId,
571
+ typeArguments: [params.recordingShareType],
572
+ arguments: [params.vault, params.vaultAdminCap],
573
+ }),
574
+ );
575
+ }
576
+
577
+ export interface NewRecordingRoyaltyPoolParams {
578
+ readonly authority: AdminCapAuthority;
579
+ readonly recording: TransactionObjectArgument;
580
+ readonly actionPackageId: string;
581
+ readonly currencyType: string;
582
+ readonly recordingShareType: string;
583
+ readonly compositionShareType: string;
584
+ }
585
+
586
+ /** Create the canonical pool without sharing it so callers can configure fresh stakes first. */
587
+ export function newRecordingRoyaltyPool(
588
+ tx: Transaction,
589
+ params: NewRecordingRoyaltyPoolParams,
590
+ ): TransactionObjectArgument {
591
+ return invokeWithAdminCap(tx, params.authority, {
592
+ target: `${params.actionPackageId}::recording_royalty_pool::new_pool`,
593
+ typeArguments: [
594
+ params.recordingShareType,
595
+ params.compositionShareType,
596
+ params.currencyType,
597
+ ],
598
+ arguments: [params.recording],
599
+ adminCapIndex: 1,
600
+ });
601
+ }
602
+
603
+ export interface RecordingRoyaltyPoolCrankParams {
604
+ readonly vault: TransactionObjectArgument;
605
+ readonly recording: TransactionObjectArgument;
606
+ readonly pool: TransactionObjectArgument;
607
+ readonly recordingShareType: string;
608
+ readonly compositionShareType: string;
609
+ readonly currencyType: string;
610
+ readonly pluginPackageId: string;
611
+ }
612
+
613
+ /** Permissionless crank: redeem an exact Recording amount into its pool. */
614
+ export function redeemAndDepositRecordingRoyaltyPool(
615
+ tx: Transaction,
616
+ params: RecordingRoyaltyPoolCrankParams & {
617
+ readonly value: U64Argument;
618
+ },
619
+ ): void {
620
+ tx.add(
621
+ recordingRoyaltyPoolPlugin.redeemAndDeposit({
622
+ package: params.pluginPackageId,
623
+ typeArguments: [
624
+ params.recordingShareType,
625
+ params.compositionShareType,
626
+ params.currencyType,
627
+ ],
628
+ arguments: [
629
+ params.vault,
630
+ params.recording,
631
+ params.pool,
632
+ asU64Argument(tx, "value", params.value),
633
+ ],
634
+ }),
635
+ );
636
+ }
637
+
638
+ /** Redeem exactly the framework-reported settled Recording funds. */
639
+ export function settleRecordingRoyaltyPool(
640
+ tx: Transaction,
641
+ params: Omit<RecordingRoyaltyPoolCrankParams, "recording"> & {
642
+ readonly recordingId: string;
643
+ readonly accumulatorRoot?: ObjectInput;
644
+ },
645
+ ): void {
646
+ const value = settledFundsValue(tx, {
647
+ address: params.recordingId,
648
+ currencyType: params.currencyType,
649
+ accumulatorRoot: params.accumulatorRoot,
650
+ });
651
+ redeemAndDepositRecordingRoyaltyPool(tx, {
652
+ ...params,
653
+ recording: tx.object(params.recordingId),
654
+ value,
655
+ });
656
+ }
657
+
658
+ /** Permissionless crank: receive selected Recording-owned coins into the pool. */
659
+ export function receiveRecordingRoyaltyPool(
660
+ tx: Transaction,
661
+ params: RecordingRoyaltyPoolCrankParams & { readonly coins: readonly ReceivingObjectRef[] },
662
+ ): void {
663
+ tx.add(
664
+ recordingRoyaltyPoolPlugin.receiveAndDeposit({
665
+ package: params.pluginPackageId,
666
+ typeArguments: [
667
+ params.recordingShareType,
668
+ params.compositionShareType,
669
+ params.currencyType,
670
+ ],
671
+ arguments: [
672
+ params.vault,
673
+ params.recording,
674
+ params.pool,
675
+ receivingCoins(tx, params.currencyType, params.coins),
676
+ ],
677
+ }),
678
+ );
679
+ }
680
+
681
+ export interface ReleaseRevenueDistributorPluginParams {
682
+ readonly vault: TransactionObjectArgument;
683
+ readonly vaultAdminCap: TransactionObjectArgument;
684
+ readonly pluginPackageId: string;
685
+ }
686
+
687
+ export function installReleaseRevenueDistributorPlugin(
688
+ tx: Transaction,
689
+ params: ReleaseRevenueDistributorPluginParams,
690
+ ): void {
691
+ tx.add(
692
+ releaseRevenueDistributorPlugin.install({
693
+ package: params.pluginPackageId,
694
+ arguments: [params.vault, params.vaultAdminCap],
695
+ }),
696
+ );
697
+ }
698
+
699
+ export function uninstallReleaseRevenueDistributorPlugin(
700
+ tx: Transaction,
701
+ params: ReleaseRevenueDistributorPluginParams,
702
+ ): void {
703
+ tx.add(releaseRevenueDistributorPlugin.uninstall({ package: params.pluginPackageId, arguments: [params.vault, params.vaultAdminCap] }));
704
+ }
705
+
706
+ export interface ReleaseRevenueDistributorActionParams {
707
+ readonly authority: AdminCapAuthority;
708
+ readonly release: TransactionObjectArgument;
709
+ readonly currencyType: string;
710
+ readonly actionPackageId: string;
711
+ }
712
+
713
+ /** Raw-admin composition: redeem an explicit amount and route it by track BPS. */
714
+ export function redeemAndDistributeReleaseRevenue(
715
+ tx: Transaction,
716
+ params: ReleaseRevenueDistributorActionParams & {
717
+ readonly value: U64Argument;
718
+ },
719
+ ): void {
720
+ invokeWithAdminCap(tx, params.authority, {
721
+ target: `${params.actionPackageId}::release_revenue_distributor::redeem_and_distribute`,
722
+ typeArguments: [params.currencyType],
723
+ arguments: [params.release, asU64Argument(tx, "value", params.value)],
724
+ adminCapIndex: 1,
725
+ });
726
+ }
727
+
728
+ /** Fixed permissionless crank: redeem the commit-settled Release balance. */
729
+ export function redeemAllAndDistributeReleaseRevenue(
730
+ tx: Transaction,
731
+ params: Omit<ReleaseRevenueDistributorPluginParams, "vaultAdminCap"> & {
732
+ readonly release: TransactionObjectArgument;
733
+ readonly currencyType: string;
734
+ readonly accumulatorRoot?: ObjectInput;
735
+ },
736
+ ): void {
737
+ tx.add(
738
+ releaseRevenueDistributorPlugin.redeemAllAndDistribute({
739
+ package: params.pluginPackageId,
740
+ typeArguments: [params.currencyType],
741
+ arguments: [
742
+ params.vault,
743
+ params.release,
744
+ object(tx, params.accumulatorRoot ?? SUI_ACCUMULATOR_ROOT_OBJECT_ID),
745
+ ],
746
+ }),
747
+ );
748
+ }
749
+
750
+ /** Convenience form of the fixed crank for a known Release object ID. */
751
+ export function settleAndDistributeReleaseRevenue(
752
+ tx: Transaction,
753
+ params: Omit<ReleaseRevenueDistributorPluginParams, "vaultAdminCap"> & {
754
+ readonly releaseId: string;
755
+ readonly currencyType: string;
756
+ readonly accumulatorRoot?: ObjectInput;
757
+ },
758
+ ): void {
759
+ redeemAllAndDistributeReleaseRevenue(tx, {
760
+ ...params,
761
+ release: tx.object(params.releaseId),
762
+ });
763
+ }
764
+
765
+ /** Permissionless crank: receive release-owned coins and route them by track BPS. */
766
+ export function receiveAndDistributeReleaseRevenue(
767
+ tx: Transaction,
768
+ params: Omit<ReleaseRevenueDistributorPluginParams, "vaultAdminCap"> & {
769
+ readonly release: TransactionObjectArgument;
770
+ readonly currencyType: string;
771
+ readonly coins: readonly ReceivingObjectRef[];
772
+ },
773
+ ): void {
774
+ tx.add(
775
+ releaseRevenueDistributorPlugin.receiveAndDistribute({
776
+ package: params.pluginPackageId,
777
+ typeArguments: [params.currencyType],
778
+ arguments: [
779
+ params.vault,
780
+ params.release,
781
+ receivingCoins(tx, params.currencyType, params.coins),
782
+ ],
783
+ }),
784
+ );
785
+ }
786
+
787
+ export interface CompositionRoutedStakeActionParams {
788
+ readonly authority: AdminCapAuthority;
789
+ readonly compositionShareType: string;
790
+ readonly actionPackageId: string;
791
+ }
792
+
793
+ export interface CreateCompositionRoutedStakeParams
794
+ extends CompositionRoutedStakeActionParams {
795
+ readonly recording: TransactionObjectArgument;
796
+ readonly composition: TransactionObjectArgument;
797
+ readonly recordingShareType: string;
798
+ readonly value: U64Input;
799
+ }
800
+
801
+ export function createCompositionRoutedStake(
802
+ tx: Transaction,
803
+ params: CreateCompositionRoutedStakeParams,
804
+ ): TransactionObjectArgument {
805
+ return invokeWithAdminCap(tx, params.authority, {
806
+ target: `${params.actionPackageId}::composition_routed_stake::create_stake`,
807
+ typeArguments: [params.recordingShareType, params.compositionShareType],
808
+ arguments: [params.composition, params.recording, tx.pure.u64(asU64("value", params.value))],
809
+ adminCapIndex: 1,
810
+ });
811
+ }
812
+
813
+ export interface ManageCompositionRoutedStakeParams
814
+ extends CompositionRoutedStakeActionParams {
815
+ readonly composition: TransactionObjectArgument;
816
+ readonly recording: TransactionObjectArgument;
817
+ readonly routedStake: TransactionObjectArgument;
818
+ readonly royaltyPool: TransactionObjectArgument;
819
+ readonly recordingShareType: string;
820
+ readonly currencyType: string;
821
+ }
822
+
823
+ /** Register the routed stake with the matching Recording royalty pool. */
824
+ export function registerCompositionRoutedStake(
825
+ tx: Transaction,
826
+ params: ManageCompositionRoutedStakeParams,
827
+ ): void {
828
+ invokeWithAdminCap(tx, params.authority, {
829
+ target: `${params.actionPackageId}::composition_routed_stake::register`,
830
+ typeArguments: [params.recordingShareType, params.compositionShareType, params.currencyType],
831
+ arguments: [params.composition, params.recording, params.routedStake, params.royaltyPool],
832
+ adminCapIndex: 1,
833
+ });
834
+ }
835
+
836
+ /** Share a configured routed stake so anyone can sweep its rewards to the parent pool. */
837
+ export function shareRoutedStake(
838
+ tx: Transaction,
839
+ params: {
840
+ readonly routedStake: TransactionObjectArgument;
841
+ readonly routedStakePackageId: string;
842
+ readonly stakeShareType: string;
843
+ readonly poolShareType: string;
844
+ },
845
+ ): void {
846
+ tx.add(routedStake.share({
847
+ package: params.routedStakePackageId,
848
+ typeArguments: [params.stakeShareType, params.poolShareType],
849
+ arguments: [params.routedStake],
850
+ }));
851
+ }
852
+
853
+ /** Unregister a routed stake after pending rewards have been swept. */
854
+ export function unregisterCompositionRoutedStake(
855
+ tx: Transaction,
856
+ params: ManageCompositionRoutedStakeParams,
857
+ ): void {
858
+ invokeWithAdminCap(tx, params.authority, {
859
+ target: `${params.actionPackageId}::composition_routed_stake::unregister`,
860
+ typeArguments: [params.recordingShareType, params.compositionShareType, params.currencyType],
861
+ arguments: [params.composition, params.recording, params.routedStake, params.royaltyPool],
862
+ adminCapIndex: 1,
863
+ });
864
+ }
865
+
866
+ /** Unstake and return the routed principal for caller-selected composition. */
867
+ export function unstakeCompositionRoutedStake(
868
+ tx: Transaction,
869
+ params: Omit<ManageCompositionRoutedStakeParams, "recording" | "royaltyPool" | "currencyType">,
870
+ ): TransactionObjectArgument {
871
+ return invokeWithAdminCap(tx, params.authority, {
872
+ target: `${params.actionPackageId}::composition_routed_stake::unstake`,
873
+ typeArguments: [params.recordingShareType, params.compositionShareType],
874
+ arguments: [params.composition, params.routedStake],
875
+ adminCapIndex: 1,
876
+ });
877
+ }
878
+
879
+ /** Refill an empty routed stake with caller-supplied Recording shares. */
880
+ export function restakeCompositionRoutedStake(
881
+ tx: Transaction,
882
+ params: Omit<ManageCompositionRoutedStakeParams, "recording" | "royaltyPool" | "currencyType"> & {
883
+ readonly shares: TransactionArgument;
884
+ },
885
+ ): void {
886
+ invokeWithAdminCap(tx, params.authority, {
887
+ target: `${params.actionPackageId}::composition_routed_stake::restake`,
888
+ typeArguments: [params.recordingShareType, params.compositionShareType],
889
+ arguments: [params.composition, params.routedStake, params.shares],
890
+ adminCapIndex: 1,
891
+ });
892
+ }
893
+
894
+ /** Permissionlessly sweep a routed stake's accrued rewards into its parent pool. */
895
+ export function sweepRoutedStake(
896
+ tx: Transaction,
897
+ params: {
898
+ readonly routedStake: ObjectInput;
899
+ /** The pool where the wrapped stake accrues rewards. */
900
+ readonly stakePool: ObjectInput;
901
+ readonly parentId: string;
902
+ readonly royaltyPool: ObjectInput;
903
+ readonly routedStakePackageId: string;
904
+ readonly stakeShareType: string;
905
+ readonly poolShareType: string;
906
+ readonly currencyType: string;
907
+ },
908
+ ): void {
909
+ tx.add(routedStake.sweep({
910
+ package: params.routedStakePackageId,
911
+ typeArguments: [params.stakeShareType, params.poolShareType, params.currencyType],
912
+ arguments: [object(tx, params.routedStake), object(tx, params.stakePool), object(tx, params.royaltyPool), params.parentId],
913
+ }));
914
+ }
915
+
916
+ /** Parse a VaultAdminCap whose phantom capability does not affect BCS layout. */
917
+ export function parseVaultAdminCap(content: Uint8Array) {
918
+ return vault.VaultAdminCap.parse(content);
919
+ }
920
+
921
+ /** Parse lifecycle events whose phantom type parameters do not affect BCS. */
922
+ export function parseVaultCreatedEvent(content: Uint8Array) {
923
+ return vault.VaultCreatedEvent.parse(content);
924
+ }
925
+
926
+ /** Parse the release-distribution summary event into JSON-safe quantities. */
927
+ export function parseReleaseRevenueDistributedEvent(content: Uint8Array) {
928
+ const event = releaseRevenueDistributor.ReleaseRevenueDistributedEvent.parse(
929
+ content,
930
+ );
931
+ return {
932
+ releaseId: event.release_id,
933
+ totalInput: event.total_input.toString(),
934
+ totalDistributed: event.total_distributed.toString(),
935
+ remainder: event.remainder.toString(),
936
+ };
937
+ }
938
+
939
+ /** Parse one per-track routing event, retaining its u64 values as strings. */
940
+ export function parseReleaseTrackRevenueDistributedEvent(content: Uint8Array) {
941
+ const event = releaseRevenueDistributor.ReleaseTrackRevenueDistributedEvent.parse(content);
942
+ return {
943
+ releaseId: event.release_id,
944
+ trackIndex: event.track_index.toString(),
945
+ recordingId: event.recording_id,
946
+ amount: event.amount.toString(),
947
+ };
948
+ }
949
+
950
+ /** Read and BCS-parse an owner-held VaultAdminCap. */
951
+ export async function getVaultAdminCap(
952
+ client: ClientWithCoreApi,
953
+ vaultAdminCapId: string,
954
+ expected: { readonly vaultPackageId: string; readonly capType: string },
955
+ ) {
956
+ const { object } = await client.core.getObject({
957
+ objectId: vaultAdminCapId,
958
+ include: { content: true },
959
+ });
960
+ if (!object || object instanceof Error || !object.content) return null;
961
+ const expectedType = normalizeStructTag(
962
+ `${expected.vaultPackageId}::vault::VaultAdminCap<${expected.capType}>`,
963
+ );
964
+ if (!object.type || normalizeStructTag(object.type) !== expectedType) {
965
+ throw new Error(
966
+ `getVaultAdminCap: expected ${expectedType}, received ${object.type ?? "unknown"}`,
967
+ );
968
+ }
969
+ return parseVaultAdminCap(object.content);
970
+ }
971
+
972
+ /**
973
+ * Build a `vector<Receiving<Coin<Currency>>>` for receive-and-* plugin calls.
974
+ * The caller supplies only object ids; recipient/ownership checks still happen
975
+ * on chain when `hikida::receive_balance` opens each receiving object.
976
+ */
977
+ export interface ReceivingObjectRef {
978
+ readonly objectId: string;
979
+ readonly version: string | number;
980
+ readonly digest: string;
981
+ }
982
+
983
+ /** Resolve owned coins to the exact references required by a Receiving input. */
984
+ export async function resolveReceivingCoins(
985
+ client: ClientWithCoreApi,
986
+ coinIds: readonly string[],
987
+ ): Promise<ReceivingObjectRef[]> {
988
+ const { objects } = await client.core.getObjects({ objectIds: [...coinIds] });
989
+ return objects.map((coin, index) => {
990
+ if (coin instanceof Error || !coin) {
991
+ throw new Error(`resolveReceivingCoins: could not resolve ${coinIds[index]}`);
992
+ }
993
+ return { objectId: coin.objectId, version: coin.version, digest: coin.digest };
994
+ });
995
+ }
996
+
997
+ export function receivingCoins(
998
+ tx: Transaction,
999
+ currencyType: string,
1000
+ coins: readonly ReceivingObjectRef[],
1001
+ ): TransactionArgument {
1002
+ return tx.makeMoveVec({
1003
+ type: `0x2::transfer::Receiving<0x2::coin::Coin<${currencyType}>>`,
1004
+ elements: coins.map((coin) => tx.receivingRef(coin)),
1005
+ });
1006
+ }
1007
+
1008
+ /** Type-only helper for consumers that supply a generated admin-cap BCS type. */
1009
+ export type VaultCapBcs<Cap extends BcsType<unknown>> = Cap;