@misofm/sdk 0.15.11 → 0.16.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 (139) hide show
  1. package/README.md +145 -53
  2. package/dist/client.d.ts +156 -48
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +289 -48
  5. package/dist/client.js.map +1 -1
  6. package/dist/contracts/composition_royalty_pool/composition_royalty_pool.d.ts +11 -11
  7. package/dist/contracts/composition_royalty_pool/composition_royalty_pool.d.ts.map +1 -1
  8. package/dist/contracts/composition_royalty_pool/composition_royalty_pool.js +9 -9
  9. package/dist/contracts/composition_royalty_pool/composition_royalty_pool.js.map +1 -1
  10. package/dist/contracts/miso_record/deps/std/type_name.d.ts.map +1 -0
  11. package/dist/contracts/miso_record/deps/std/type_name.js.map +1 -0
  12. package/dist/contracts/miso_record/deps/sui/vec_set.d.ts +21 -0
  13. package/dist/contracts/miso_record/deps/sui/vec_set.d.ts.map +1 -0
  14. package/dist/contracts/miso_record/deps/sui/vec_set.js +20 -0
  15. package/dist/contracts/miso_record/deps/sui/vec_set.js.map +1 -0
  16. package/dist/contracts/miso_record/pressing.d.ts +327 -0
  17. package/dist/contracts/miso_record/pressing.d.ts.map +1 -0
  18. package/dist/contracts/miso_record/pressing.js +345 -0
  19. package/dist/contracts/miso_record/pressing.js.map +1 -0
  20. package/dist/contracts/miso_record/record.d.ts +190 -0
  21. package/dist/contracts/miso_record/record.d.ts.map +1 -0
  22. package/dist/contracts/miso_record/record.js +226 -0
  23. package/dist/contracts/miso_record/record.js.map +1 -0
  24. package/dist/contracts/miso_record_shop/deps/std/type_name.d.ts +18 -0
  25. package/dist/contracts/miso_record_shop/deps/std/type_name.d.ts.map +1 -0
  26. package/dist/contracts/miso_record_shop/deps/std/type_name.js +20 -0
  27. package/dist/contracts/miso_record_shop/deps/std/type_name.js.map +1 -0
  28. package/dist/contracts/miso_record_shop/listing.d.ts +387 -0
  29. package/dist/contracts/miso_record_shop/listing.d.ts.map +1 -0
  30. package/dist/contracts/miso_record_shop/listing.js +380 -0
  31. package/dist/contracts/miso_record_shop/listing.js.map +1 -0
  32. package/dist/contracts/miso_record_shop/witness.d.ts +7 -0
  33. package/dist/contracts/miso_record_shop/witness.d.ts.map +1 -0
  34. package/dist/contracts/miso_record_shop/witness.js +9 -0
  35. package/dist/contracts/miso_record_shop/witness.js.map +1 -0
  36. package/dist/contracts/recording_royalty_pool/recording_royalty_pool.d.ts +10 -12
  37. package/dist/contracts/recording_royalty_pool/recording_royalty_pool.d.ts.map +1 -1
  38. package/dist/contracts/recording_royalty_pool/recording_royalty_pool.js +8 -10
  39. package/dist/contracts/recording_royalty_pool/recording_royalty_pool.js.map +1 -1
  40. package/dist/contracts.d.ts +3 -3
  41. package/dist/contracts.d.ts.map +1 -1
  42. package/dist/contracts.js +5 -4
  43. package/dist/contracts.js.map +1 -1
  44. package/dist/deployments.d.ts +37 -4
  45. package/dist/deployments.d.ts.map +1 -1
  46. package/dist/deployments.js +40 -2
  47. package/dist/deployments.js.map +1 -1
  48. package/dist/index.d.ts +2 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +2 -0
  51. package/dist/index.js.map +1 -1
  52. package/dist/mix.d.ts +144 -0
  53. package/dist/mix.d.ts.map +1 -0
  54. package/dist/mix.js +656 -0
  55. package/dist/mix.js.map +1 -0
  56. package/dist/pressing.d.ts +72 -156
  57. package/dist/pressing.d.ts.map +1 -1
  58. package/dist/pressing.js +269 -261
  59. package/dist/pressing.js.map +1 -1
  60. package/dist/publication.d.ts +5 -2
  61. package/dist/publication.d.ts.map +1 -1
  62. package/dist/publication.js +57 -32
  63. package/dist/publication.js.map +1 -1
  64. package/dist/read/catalog.d.ts +8 -5
  65. package/dist/read/catalog.d.ts.map +1 -1
  66. package/dist/read/catalog.js +47 -35
  67. package/dist/read/catalog.js.map +1 -1
  68. package/dist/read/config.d.ts +6 -4
  69. package/dist/read/config.d.ts.map +1 -1
  70. package/dist/read/config.js +1 -2
  71. package/dist/read/config.js.map +1 -1
  72. package/dist/read/index.d.ts +1 -1
  73. package/dist/read/index.d.ts.map +1 -1
  74. package/dist/read/index.js +1 -1
  75. package/dist/read/index.js.map +1 -1
  76. package/dist/read/internal/scalars.d.ts.map +1 -1
  77. package/dist/read/internal/scalars.js +4 -3
  78. package/dist/read/internal/scalars.js.map +1 -1
  79. package/dist/read/internal/walrus.d.ts.map +1 -1
  80. package/dist/read/internal/walrus.js +2 -1
  81. package/dist/read/internal/walrus.js.map +1 -1
  82. package/dist/read/receipts.d.ts +21 -12
  83. package/dist/read/receipts.d.ts.map +1 -1
  84. package/dist/read/receipts.js +159 -56
  85. package/dist/read/receipts.js.map +1 -1
  86. package/dist/read/types.d.ts +34 -24
  87. package/dist/read/types.d.ts.map +1 -1
  88. package/dist/read/wallet.d.ts.map +1 -1
  89. package/dist/read/wallet.js +31 -46
  90. package/dist/read/wallet.js.map +1 -1
  91. package/dist/vault.d.ts +40 -11
  92. package/dist/vault.d.ts.map +1 -1
  93. package/dist/vault.js +94 -22
  94. package/dist/vault.js.map +1 -1
  95. package/package.json +10 -3
  96. package/src/client.ts +386 -72
  97. package/src/contracts/composition_royalty_pool/composition_royalty_pool.ts +15 -15
  98. package/src/contracts/miso_record/deps/sui/vec_set.ts +21 -0
  99. package/src/contracts/miso_record/pressing.ts +522 -0
  100. package/src/contracts/miso_record/record.ts +338 -0
  101. package/src/contracts/miso_record_shop/deps/std/type_name.ts +22 -0
  102. package/src/contracts/miso_record_shop/listing.ts +602 -0
  103. package/src/contracts/miso_record_shop/witness.ts +11 -0
  104. package/src/contracts/recording_royalty_pool/recording_royalty_pool.ts +14 -16
  105. package/src/contracts.ts +5 -4
  106. package/src/deployments.ts +131 -38
  107. package/src/index.ts +2 -0
  108. package/src/mix.ts +910 -0
  109. package/src/pressing.ts +428 -423
  110. package/src/publication.ts +62 -33
  111. package/src/read/catalog.ts +49 -34
  112. package/src/read/config.ts +7 -7
  113. package/src/read/index.ts +9 -1
  114. package/src/read/internal/scalars.ts +4 -2
  115. package/src/read/internal/walrus.ts +2 -1
  116. package/src/read/receipts.ts +181 -66
  117. package/src/read/types.ts +35 -22
  118. package/src/read/wallet.ts +29 -50
  119. package/src/vault.ts +142 -32
  120. package/dist/contracts/miso_pressing/certificate.d.ts +0 -89
  121. package/dist/contracts/miso_pressing/certificate.d.ts.map +0 -1
  122. package/dist/contracts/miso_pressing/certificate.js +0 -108
  123. package/dist/contracts/miso_pressing/certificate.js.map +0 -1
  124. package/dist/contracts/miso_pressing/deps/std/type_name.d.ts.map +0 -1
  125. package/dist/contracts/miso_pressing/deps/std/type_name.js.map +0 -1
  126. package/dist/contracts/miso_pressing/listing.d.ts +0 -434
  127. package/dist/contracts/miso_pressing/listing.d.ts.map +0 -1
  128. package/dist/contracts/miso_pressing/listing.js +0 -401
  129. package/dist/contracts/miso_pressing/listing.js.map +0 -1
  130. package/dist/contracts/miso_pressing/pressing.d.ts +0 -334
  131. package/dist/contracts/miso_pressing/pressing.d.ts.map +0 -1
  132. package/dist/contracts/miso_pressing/pressing.js +0 -298
  133. package/dist/contracts/miso_pressing/pressing.js.map +0 -1
  134. package/src/contracts/miso_pressing/certificate.ts +0 -164
  135. package/src/contracts/miso_pressing/listing.ts +0 -592
  136. package/src/contracts/miso_pressing/pressing.ts +0 -399
  137. /package/dist/contracts/{miso_pressing → miso_record}/deps/std/type_name.d.ts +0 -0
  138. /package/dist/contracts/{miso_pressing → miso_record}/deps/std/type_name.js +0 -0
  139. /package/src/contracts/{miso_pressing → miso_record}/deps/std/type_name.ts +0 -0
package/dist/pressing.js CHANGED
@@ -1,214 +1,233 @@
1
1
  // Copyright (c) Miso Labs, Inc.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- import { deriveObjectID, normalizeStructTag, normalizeSuiAddress, parseStructTag } from "@mysten/sui/utils";
3
+ import { deriveObjectID, normalizeStructTag, normalizeSuiAddress, parseStructTag, } from "@mysten/sui/utils";
4
4
  import { isNotFound } from "./queries.js";
5
5
  import { asU64 } from "./vault.js";
6
- import * as listing from "./contracts/miso_pressing/listing.js";
7
- import * as pressing from "./contracts/miso_pressing/pressing.js";
8
- // ============================================================================
9
- // Address math
10
- // ============================================================================
11
- /** Key bytes for Move unit structs (single `0x00` for `dummy_field: bool = false`). */
12
- const UNIT_STRUCT_KEY_BYTES = new Uint8Array([0x00]);
13
- /**
14
- * Where `releaseId`'s pressing lives — computable before it has been opened, and
15
- * stable forever after, because a release can only ever claim one.
16
- *
17
- * `misoPressingPackageId` must be the package's ORIGINAL (first-published) id, since
18
- * that is the address a Move type tag canonicalises to. `miso_pressing` is published
19
- * immutable, so its original and current ids are the same.
20
- */
21
- export function derivePressingId(releaseId, misoPressingPackageId) {
22
- return deriveObjectID(releaseId, `${misoPressingPackageId}::pressing::PressingKey`, UNIT_STRUCT_KEY_BYTES);
23
- }
24
- /**
25
- * Where `pressingId`'s admin cap was minted. The cap is transferable, so this is not
26
- * where it lives — only where it came from.
27
- */
28
- export function derivePressingAdminCapId(pressingId, misoPressingPackageId) {
29
- return deriveObjectID(pressingId, `${misoPressingPackageId}::pressing::PressingAdminCapKey`, UNIT_STRUCT_KEY_BYTES);
30
- }
31
- /**
32
- * Where `currencyType`'s listing on `pressingId` lives. The key is phantom-typed, so
33
- * the currency rides in the key's TYPE — one listing per (pressing, currency), ever.
34
- */
35
- export function deriveListingId(pressingId, currencyType, misoPressingPackageId) {
36
- return deriveObjectID(pressingId, `${misoPressingPackageId}::listing::ListingKey<${normalizeStructTag(currencyType)}>`, UNIT_STRUCT_KEY_BYTES);
37
- }
38
- /** Both derived ids a sale needs, from the release id alone. */
39
- export function deriveSaleIds(releaseId, currencyType, misoPressingPackageId) {
40
- const pressingId = derivePressingId(releaseId, misoPressingPackageId);
6
+ import * as pressingContract from "./contracts/miso_record/pressing.js";
7
+ import * as recordContract from "./contracts/miso_record/record.js";
8
+ import * as listingContract from "./contracts/miso_record_shop/listing.js";
9
+ const MAX_U16 = 0xffff;
10
+ const MAX_U32 = 0xffff_ffff;
11
+ const UNIT_STRUCT_KEY_BYTES = new Uint8Array([0]);
12
+ /** Fixed cross-client parity vector for the finalized Record/Record Shop
13
+ * derived-object ABI. Outputs are literals, not initialized through the
14
+ * derivation helpers they verify. */
15
+ export const RECORD_SALES_DERIVATION_VECTOR_V1 = {
16
+ releaseId: "0x3333333333333333333333333333333333333333333333333333333333333333",
17
+ edition: 2,
18
+ currencyType: "0x2::sui::SUI",
19
+ recordPackageId: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
20
+ recordShopPackageId: "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
21
+ pressingId: "0x3e74b7f16951f027684e3bc44dec1efa35a0754017417ad5d4d4131f92a20c16",
22
+ pressingAdminCapId: "0xbaec8eab17a06cc3c3a5d13e4b5b636a210776bd60f86b423d245f70f8e965a6",
23
+ listingId: "0x7fbf4cb7cce881a50bdc848ee65545299fec0887213524de29e039bed31e0e37",
24
+ recordNumber: 7,
25
+ recordId: "0xd492af6fc9b88d71c6674e486ab7aeca911ab797f651bae891a1cf8e54f94f1a",
26
+ };
27
+ function uint(label, value, max) {
28
+ if (!Number.isSafeInteger(value) || value < 0 || value > max) {
29
+ throw new RangeError(`${label} must be an integer from 0 to ${max}`);
30
+ }
31
+ return value;
32
+ }
33
+ function edition(value) {
34
+ const out = uint("edition", value, MAX_U16);
35
+ if (out === 0)
36
+ throw new RangeError("edition must be greater than zero");
37
+ return out;
38
+ }
39
+ function maxSupply(value) {
40
+ if (value == null)
41
+ return null;
42
+ const out = uint("max supply", value, MAX_U32);
43
+ if (out === 0)
44
+ throw new RangeError("max supply must be greater than zero");
45
+ return out;
46
+ }
47
+ export function derivePressingId(releaseId, editionNumber, recordPackageId) {
48
+ const value = edition(editionNumber);
49
+ return deriveObjectID(releaseId, `${recordPackageId}::pressing::PressingKey`, pressingContract.PressingKey.serialize([value]).toBytes());
50
+ }
51
+ export function derivePressingAdminCapId(pressingId, recordPackageId) {
52
+ return deriveObjectID(pressingId, `${recordPackageId}::pressing::PressingAdminCapKey`, UNIT_STRUCT_KEY_BYTES);
53
+ }
54
+ export function deriveRecordId(pressingId, number, recordPackageId) {
55
+ const value = uint("record number", number, MAX_U32);
56
+ if (value === 0)
57
+ throw new RangeError("record number must be greater than zero");
58
+ return deriveObjectID(pressingId, `${recordPackageId}::record::RecordKey`, recordContract.RecordKey.serialize([value]).toBytes());
59
+ }
60
+ export function deriveListingId(pressingId, currencyType, recordShopPackageId) {
61
+ return deriveObjectID(pressingId, `${recordShopPackageId}::listing::ListingKey<${normalizeStructTag(currencyType)}>`, UNIT_STRUCT_KEY_BYTES);
62
+ }
63
+ export function deriveSaleIds(releaseId, editionNumber, currencyType, recordPackageId, recordShopPackageId) {
64
+ const pressingId = derivePressingId(releaseId, editionNumber, recordPackageId);
41
65
  return {
42
66
  pressingId,
43
- listingId: deriveListingId(pressingId, currencyType, misoPressingPackageId),
67
+ listingId: deriveListingId(pressingId, currencyType, recordShopPackageId),
44
68
  };
45
69
  }
46
- function priceArg(tx, misoPressingPackageId, price) {
47
- const make = price.kind === "fixed" ? listing.newFixedPrice : listing.newFloorPrice;
48
- return tx.add(make({ package: misoPressingPackageId, arguments: [asU64("listing price", price.amount)] }));
49
- }
50
- function switchArg(tx, misoPressingPackageId, state) {
51
- const make = state === "enabled" ? listing.newEnabledState : listing.newDisabledState;
52
- return tx.add(make({ package: misoPressingPackageId }));
53
- }
54
- function runStateArg(tx, misoPressingPackageId, state) {
55
- const pkg = { package: misoPressingPackageId };
56
- switch (state.kind) {
57
- case "scheduled":
58
- return tx.add(pressing.newScheduledState({
59
- ...pkg,
60
- arguments: [asU64("pressing schedule timestamp", state.startTimestampMs)],
61
- }));
62
- case "active":
63
- return tx.add(pressing.newActiveState(pkg));
64
- case "paused":
65
- return tx.add(pressing.newPausedState(pkg));
66
- }
70
+ function priceArg(tx, packageId, price) {
71
+ const fn = price.kind === "fixed" ? listingContract.fixed : listingContract.floor;
72
+ return tx.add(fn({
73
+ package: packageId,
74
+ arguments: [asU64("listing price", price.amount)],
75
+ }));
76
+ }
77
+ function stateArg(tx, packageId, state) {
78
+ const fn = state === "enabled" ? listingContract.enabled : listingContract.disabled;
79
+ return tx.add(fn({ package: packageId }));
80
+ }
81
+ function witnessType(recordShopPackageId) {
82
+ return `${recordShopPackageId}::witness::Witness`;
67
83
  }
68
- /**
69
- * Opens a release's pressing and lists it, in ONE transaction.
70
- *
71
- * `pressing::new` hands the `Pressing` back UNSHARED precisely so the listings can be
72
- * claimed off it before `share` puts it on chain — that ordering is the whole reason
73
- * this is a single builder and not three. A release can only ever open one pressing,
74
- * so this call is once-per-release forever; changing price or currency afterwards is
75
- * an edit ({@link setListingPrice}, {@link openListing}), never a re-open.
76
- */
84
+ /** Initial setup: create the Pressing, authorize Record Shop, open/share Listings,
85
+ * share the Pressing, and transfer its admin capability. */
77
86
  export function openPressing(p) {
78
87
  return (tx) => {
79
- const pkg = p.misoPressingPackageId;
80
- const [run, adminCap] = tx.add(pressing._new({
81
- package: pkg,
88
+ const [pressing, cap] = tx.add(pressingContract._new({
89
+ package: p.recordPackageId,
82
90
  arguments: [
83
91
  p.releaseId,
84
92
  p.releaseAdminCapId,
85
- runStateArg(tx, pkg, p.state ?? { kind: "active" }),
93
+ edition(p.edition),
94
+ maxSupply(p.maxSupply),
86
95
  ],
87
96
  }));
97
+ tx.add(pressingContract.authorizeDistributor({
98
+ package: p.recordPackageId,
99
+ arguments: [pressing, cap],
100
+ typeArguments: [witnessType(p.recordShopPackageId)],
101
+ }));
88
102
  for (const terms of p.listings) {
89
- tx.add(listing._new({
90
- package: pkg,
103
+ const listing = tx.add(listingContract._new({
104
+ package: p.recordShopPackageId,
91
105
  arguments: [
92
- run,
93
- adminCap,
94
- priceArg(tx, pkg, terms.price),
95
- switchArg(tx, pkg, terms.state ?? "enabled"),
106
+ pressing,
107
+ cap,
108
+ priceArg(tx, p.recordShopPackageId, terms.price),
96
109
  ],
97
110
  typeArguments: [terms.currencyType],
98
111
  }));
112
+ if (terms.state === "disabled") {
113
+ tx.add(listingContract.setState({
114
+ package: p.recordShopPackageId,
115
+ arguments: [
116
+ listing,
117
+ cap,
118
+ stateArg(tx, p.recordShopPackageId, "disabled"),
119
+ ],
120
+ typeArguments: [terms.currencyType],
121
+ }));
122
+ }
123
+ tx.add(listingContract.share({
124
+ package: p.recordShopPackageId,
125
+ arguments: [listing],
126
+ typeArguments: [terms.currencyType],
127
+ }));
99
128
  }
100
- tx.add(pressing.share({ package: pkg, arguments: [run] }));
101
- tx.transferObjects([adminCap], p.adminCapRecipient);
129
+ tx.add(pressingContract.share({
130
+ package: p.recordPackageId,
131
+ arguments: [pressing],
132
+ }));
133
+ tx.transferObjects([cap], p.adminCapRecipient);
134
+ };
135
+ }
136
+ export function authorizeRecordShop(p) {
137
+ return (tx) => {
138
+ tx.add(pressingContract.authorizeDistributor({
139
+ package: p.recordPackageId,
140
+ arguments: [p.pressingId, p.pressingAdminCapId],
141
+ typeArguments: [witnessType(p.recordShopPackageId)],
142
+ }));
143
+ };
144
+ }
145
+ export function revokeRecordShop(p) {
146
+ return (tx) => {
147
+ tx.add(pressingContract.revokeDistributor({
148
+ package: p.recordPackageId,
149
+ arguments: [p.pressingId, p.pressingAdminCapId],
150
+ typeArguments: [witnessType(p.recordShopPackageId)],
151
+ }));
102
152
  };
103
153
  }
104
- /**
105
- * Adds a currency to a live pressing. Once per currency, ever — the slot is a derived
106
- * claim, so a second call for the same currency aborts. Everything after is an edit.
107
- */
154
+ /** Add one permanent currency Listing. Authorization is deliberately separate. */
108
155
  export function openListing(p) {
109
156
  return (tx) => {
110
- const pkg = p.misoPressingPackageId;
111
- tx.add(listing._new({
112
- package: pkg,
157
+ const listing = tx.add(listingContract._new({
158
+ package: p.recordShopPackageId,
113
159
  arguments: [
114
- derivePressingId(p.releaseId, pkg),
160
+ p.pressingId,
115
161
  p.pressingAdminCapId,
116
- priceArg(tx, pkg, p.terms.price),
117
- switchArg(tx, pkg, p.terms.state ?? "enabled"),
162
+ priceArg(tx, p.recordShopPackageId, p.terms.price),
118
163
  ],
119
164
  typeArguments: [p.terms.currencyType],
120
165
  }));
166
+ if (p.terms.state === "disabled") {
167
+ tx.add(listingContract.setState({
168
+ package: p.recordShopPackageId,
169
+ arguments: [
170
+ listing,
171
+ p.pressingAdminCapId,
172
+ stateArg(tx, p.recordShopPackageId, "disabled"),
173
+ ],
174
+ typeArguments: [p.terms.currencyType],
175
+ }));
176
+ }
177
+ tx.add(listingContract.share({
178
+ package: p.recordShopPackageId,
179
+ arguments: [listing],
180
+ typeArguments: [p.terms.currencyType],
181
+ }));
121
182
  };
122
183
  }
123
- /**
124
- * Reprices one currency in place, keeping the listing's address and identity. Safe
125
- * against in-flight buys by construction: a `fixed` buyer pays exactly, so a stale
126
- * payment aborts against the new price, and a `floor` buyer never pays more than the
127
- * balance they sent.
128
- */
129
184
  export function setListingPrice(p) {
130
185
  return (tx) => {
131
- const pkg = p.misoPressingPackageId;
132
- const { listingId } = deriveSaleIds(p.releaseId, p.currencyType, pkg);
133
- tx.add(listing.setPrice({
134
- package: pkg,
186
+ tx.add(listingContract.setPrice({
187
+ package: p.recordShopPackageId,
135
188
  arguments: [
136
- listingId,
189
+ deriveListingId(p.pressingId, p.currencyType, p.recordShopPackageId),
137
190
  p.pressingAdminCapId,
138
- priceArg(tx, pkg, p.price),
191
+ priceArg(tx, p.recordShopPackageId, p.price),
139
192
  ],
140
193
  typeArguments: [p.currencyType],
141
194
  }));
142
195
  };
143
196
  }
144
- /** Stops or resumes ONE currency. The run's other currencies carry on. */
145
197
  export function setListingState(p) {
146
198
  return (tx) => {
147
- const pkg = p.misoPressingPackageId;
148
- const { listingId } = deriveSaleIds(p.releaseId, p.currencyType, pkg);
149
- tx.add(listing.setState({
150
- package: pkg,
199
+ tx.add(listingContract.setState({
200
+ package: p.recordShopPackageId,
151
201
  arguments: [
152
- listingId,
202
+ deriveListingId(p.pressingId, p.currencyType, p.recordShopPackageId),
153
203
  p.pressingAdminCapId,
154
- switchArg(tx, pkg, p.state),
204
+ stateArg(tx, p.recordShopPackageId, p.state),
155
205
  ],
156
206
  typeArguments: [p.currencyType],
157
207
  }));
158
208
  };
159
209
  }
160
- /**
161
- * Moves the whole run between its three modes, over every currency at once. There is
162
- * no "end" — ending a campaign is `{ kind: "paused" }`.
163
- */
164
- export function setPressingState(p) {
210
+ export function purchaseRecord(p) {
165
211
  return (tx) => {
166
- const pkg = p.misoPressingPackageId;
167
- tx.add(pressing.setState({
168
- package: pkg,
169
- arguments: [
170
- derivePressingId(p.releaseId, pkg),
171
- p.pressingAdminCapId,
172
- runStateArg(tx, pkg, p.state),
173
- ],
174
- }));
175
- };
176
- }
177
- /**
178
- * Buys one record: sources the payment, calls `listing::buy`, and sends the pressed
179
- * `Record` to `recipient`. `buy` RETURNS the record rather than transferring it, so
180
- * the transfer here is not optional. The `Clock` is auto-supplied.
181
- *
182
- * ONE payment path, no coin picking. `tx.balance()` resolves the money at build time,
183
- * preferring the buyer's ADDRESS BALANCE — where value is assumed to live — and falling
184
- * back to coin objects inside the SDK if it must. Callers never enumerate coins: that
185
- * road showed a buyer their $1000 and then refused to spend a cent of it, because the
186
- * listing only saw `Coin<T>` objects and the money was in the address balance.
187
- *
188
- * `listing::buy` takes a bare `Balance<Currency>`, which is what makes that resolution
189
- * cheap: when the address balance covers the price, `tx.balance()` emits a single
190
- * `balance::redeem_funds` straight off the accumulator and no coin object is minted,
191
- * touched, or destroyed — leaving the sale free of any owned-object contention. Only
192
- * when it must fall back to coins does it merge, split, and `coin::into_balance`.
193
- */
194
- export function buyRecord(p) {
195
- return (tx) => {
196
- const pkg = p.misoPressingPackageId;
197
- const { pressingId, listingId } = deriveSaleIds(p.releaseId, p.currencyType, pkg);
212
+ const { pressingId, listingId } = deriveSaleIds(p.releaseId, p.edition, p.currencyType, p.recordPackageId, p.recordShopPackageId);
198
213
  const payment = tx.balance({
214
+ balance: asU64("purchase amount", p.paymentAmount),
199
215
  type: p.currencyType,
200
- balance: asU64("purchase amount", p.amount),
201
- useGasCoin: p.useGasCoin ?? false,
216
+ useGasCoin: false,
202
217
  });
203
- const record = tx.add(listing.buy({
204
- package: pkg,
205
- arguments: [listingId, pressingId, payment],
218
+ const record = tx.add(listingContract.purchase({
219
+ package: p.recordShopPackageId,
220
+ arguments: [
221
+ listingId,
222
+ pressingId,
223
+ payment,
224
+ priceArg(tx, p.recordShopPackageId, p.expectedPricing),
225
+ ],
206
226
  typeArguments: [p.currencyType],
207
227
  }));
208
228
  tx.transferObjects([record], p.recipient);
209
229
  };
210
230
  }
211
- /** Reads one object's BCS content + type, or `null` only when it does not exist. */
212
231
  async function fetch(client, objectId) {
213
232
  try {
214
233
  const { object } = await client.core.getObject({
@@ -217,166 +236,155 @@ async function fetch(client, objectId) {
217
236
  });
218
237
  if (!object)
219
238
  return null;
220
- if (!object.content || !object.type) {
239
+ if (!object.content || !object.type)
221
240
  throw new Error(`object ${objectId} has no BCS content or full type`);
222
- }
223
241
  return { content: object.content, type: object.type };
224
242
  }
225
- catch (e) {
226
- if (isNotFound(e))
243
+ catch (error) {
244
+ if (isNotFound(error))
227
245
  return null;
228
- throw e;
246
+ throw error;
229
247
  }
230
248
  }
231
249
  function sameId(a, b) {
232
250
  return normalizeSuiAddress(a) === normalizeSuiAddress(b);
233
251
  }
234
252
  function requireId(label, actual, expected) {
235
- if (!sameId(actual, expected)) {
253
+ if (!sameId(actual, expected))
236
254
  throw new Error(`${label} ${actual} does not match expected ${expected}`);
237
- }
238
255
  }
239
- /** Require the exact configured package/module/struct outer tag. */
240
- function requirePressingType(type, misoPressingPackageId) {
256
+ function requireExactType(type, expected, label) {
241
257
  const actual = normalizeStructTag(type);
242
- const expected = normalizeStructTag(`${misoPressingPackageId}::pressing::Pressing`);
243
- if (actual !== expected) {
244
- throw new Error(`Pressing has type ${actual}, expected configured ${expected}`);
245
- }
258
+ const normalizedExpected = normalizeStructTag(expected);
259
+ if (actual !== normalizedExpected)
260
+ throw new Error(`${label} has type ${actual}, expected ${normalizedExpected}`);
246
261
  }
247
- /** Validate the whole Listing<CURRENCY> tag and return its normalized Currency. */
248
- function requireListingCurrency(type, misoPressingPackageId) {
262
+ function requireListingCurrency(type, recordShopPackageId) {
249
263
  const actual = normalizeStructTag(type);
250
264
  const tag = parseStructTag(actual);
251
- if (tag.address !== normalizeSuiAddress(misoPressingPackageId) ||
265
+ if (tag.address !== normalizeSuiAddress(recordShopPackageId) ||
252
266
  tag.module !== "listing" ||
253
267
  tag.name !== "Listing" ||
254
- tag.typeParams.length !== 1) {
255
- throw new Error(`Listing has type ${actual}, not a configured miso_pressing::listing::Listing<CURRENCY>`);
256
- }
257
- const currencyType = normalizeStructTag(tag.typeParams[0]);
258
- const expected = normalizeStructTag(`${misoPressingPackageId}::listing::Listing<${currencyType}>`);
259
- if (actual !== expected) {
260
- throw new Error(`Listing has non-canonical type ${actual}, expected ${expected}`);
261
- }
262
- return currencyType;
268
+ tag.typeParams.length !== 1)
269
+ throw new Error(`Listing has type ${actual}, not the configured Record Shop Listing<Currency>`);
270
+ return normalizeStructTag(tag.typeParams[0]);
263
271
  }
264
- // The generated `MoveEnum` parsers emit `{ $kind, <Variant>: … }`; older ones omitted
265
- // `$kind`. Both shapes are accepted so a codegen bump cannot silently mis-read a price.
266
- function variant(v, ...names) {
272
+ function enumKind(value, names) {
267
273
  for (const name of names)
268
- if (v.$kind === name || v[name] != null)
274
+ if (value.$kind === name || Object.hasOwn(value, name))
269
275
  return name;
270
- return names[0];
271
- }
272
- /**
273
- * Fetches and parses a `Pressing`, or `null` if the release has never opened one.
274
- *
275
- * This deliberately deviates from the core-getter convention in `./queries.ts`
276
- * (throw on missing object). A Pressing's address is computable for any release, so
277
- * probing one that was never opened is a normal state, not a broken reference —
278
- * absence is `null` and only transport failures throw.
279
- */
280
- export async function getPressing(client, pressingId, misoPressingPackageId) {
281
- const got = await fetch(client, pressingId);
282
- if (!got)
283
- return null;
284
- return parsePressing(pressingId, got.content, got.type, misoPressingPackageId);
276
+ throw new Error(`unknown enum variant; expected ${names.join(" or ")}`);
285
277
  }
286
- function parsePressing(pressingId, content, type, misoPressingPackageId) {
287
- requirePressingType(type, misoPressingPackageId);
288
- const parsed = pressing.Pressing.parse(content);
278
+ function parsePricing(value) {
279
+ if (!value || typeof value !== "object")
280
+ throw new Error("Listing has malformed pricing");
281
+ const v = value;
282
+ const kind = enumKind(v, ["Fixed", "Floor"]);
283
+ const amount = kind === "Fixed" ? v.Fixed : v.Floor;
284
+ if (amount == null || BigInt(amount) <= 0n)
285
+ throw new Error("Listing has invalid pricing amount");
286
+ return { kind: kind === "Fixed" ? "fixed" : "floor", amount };
287
+ }
288
+ function parsePressing(pressingId, content, type, recordPackageId) {
289
+ requireExactType(type, `${recordPackageId}::pressing::Pressing`, "Pressing");
290
+ const parsed = pressingContract.Pressing.parse(content);
289
291
  requireId("Pressing UID", parsed.id, pressingId);
290
- requireId("Pressing derived id", pressingId, derivePressingId(parsed.release_id, misoPressingPackageId));
291
- const s = parsed.state;
292
- const kind = variant(s, "Scheduled", "Active", "Paused");
292
+ requireId("Pressing derived id", pressingId, derivePressingId(parsed.release_id, parsed.edition, recordPackageId));
293
293
  return {
294
294
  id: pressingId,
295
295
  releaseId: parsed.release_id,
296
- state: kind === "Scheduled"
297
- ? {
298
- kind: "scheduled",
299
- startTimestampMs: BigInt(s.Scheduled?.start_timestamp_ms ?? "0"),
300
- }
301
- : kind === "Paused"
302
- ? { kind: "paused" }
303
- : { kind: "active" },
304
- supply: BigInt(parsed.supply),
296
+ edition: parsed.edition,
297
+ supply: parsed.supply,
298
+ maxSupply: parsed.max_supply,
299
+ distributors: parsed.distributors.contents.map((item) => normalizeStructTag(item.name)),
305
300
  };
306
301
  }
307
- /** Fetches and parses a `Listing<Currency>`, or `null` if that currency is not listed. */
308
- export async function getListing(client, listingId, misoPressingPackageId) {
309
- const got = await fetch(client, listingId);
310
- if (!got)
311
- return null;
312
- return parseListing(listingId, got.content, got.type, misoPressingPackageId);
313
- }
314
- function parseListing(listingId, content, type, misoPressingPackageId) {
315
- const currencyType = requireListingCurrency(type, misoPressingPackageId);
316
- const parsed = listing.Listing.parse(content);
302
+ function parseListing(listingId, content, type, recordShopPackageId) {
303
+ const currencyType = requireListingCurrency(type, recordShopPackageId);
304
+ const parsed = listingContract.Listing.parse(content);
317
305
  requireId("Listing UID", parsed.id, listingId);
318
- requireId("Listing pressing", parsed.pressing_id, derivePressingId(parsed.release_id, misoPressingPackageId));
319
- requireId("Listing derived id", listingId, deriveListingId(parsed.pressing_id, currencyType, misoPressingPackageId));
320
- const p = parsed.price;
321
- const priceKind = variant(p, "Fixed", "Floor");
322
- const st = parsed.state;
306
+ requireId("Listing derived id", listingId, deriveListingId(parsed.pressing_id, currencyType, recordShopPackageId));
307
+ const state = enumKind(parsed.state, ["Enabled", "Disabled"]);
323
308
  return {
324
309
  id: listingId,
325
310
  releaseId: parsed.release_id,
326
311
  pressingId: parsed.pressing_id,
327
- price: {
328
- kind: priceKind === "Fixed" ? "fixed" : "floor",
329
- amount: BigInt((priceKind === "Fixed" ? p.Fixed?.amount : p.Floor?.amount) ?? "0"),
330
- },
331
- state: variant(st, "Enabled", "Disabled") === "Enabled" ? "enabled" : "disabled",
312
+ pricing: parsePricing(parsed.pricing),
313
+ state: state === "Enabled" ? "enabled" : "disabled",
332
314
  currencyType,
333
315
  };
334
316
  }
335
- /**
336
- * Resolves a release's run AND one currency's offer in a single round trip, by pure
337
- * address math — no registry, no pointer, no event scan. `pressing: null` means the
338
- * release has never opened one; `listing: null` means it does not sell in that
339
- * currency (the other currencies, if any, are unaffected).
340
- */
317
+ function parseRecord(recordId, content, type, recordPackageId) {
318
+ requireExactType(type, `${recordPackageId}::record::Record`, "Record");
319
+ const parsed = recordContract.Record.parse(content);
320
+ requireId("Record UID", parsed.id, recordId);
321
+ requireId("Record derived id", recordId, deriveRecordId(parsed.pressing_id, parsed.number, recordPackageId));
322
+ return {
323
+ id: recordId,
324
+ releaseId: parsed.release_id,
325
+ pressingId: parsed.pressing_id,
326
+ edition: parsed.edition,
327
+ number: parsed.number,
328
+ purchaseCurrency: normalizeStructTag(parsed.purchase_currency.name),
329
+ purchasePrice: parsed.purchase_price,
330
+ purchasedBy: parsed.purchased_by,
331
+ purchasedTimestampMs: parsed.purchased_timestamp_ms,
332
+ };
333
+ }
334
+ export async function getPressing(client, pressingId, recordPackageId) {
335
+ const got = await fetch(client, pressingId);
336
+ return got
337
+ ? parsePressing(pressingId, got.content, got.type, recordPackageId)
338
+ : null;
339
+ }
340
+ export async function getListing(client, listingId, recordShopPackageId) {
341
+ const got = await fetch(client, listingId);
342
+ return got
343
+ ? parseListing(listingId, got.content, got.type, recordShopPackageId)
344
+ : null;
345
+ }
346
+ export async function getRecord(client, recordId, recordPackageId) {
347
+ const got = await fetch(client, recordId);
348
+ return got
349
+ ? parseRecord(recordId, got.content, got.type, recordPackageId)
350
+ : null;
351
+ }
341
352
  export async function getSale(client, p) {
342
- const { pressingId, listingId } = deriveSaleIds(p.releaseId, p.currencyType, p.misoPressingPackageId);
353
+ const { pressingId, listingId } = deriveSaleIds(p.releaseId, p.edition, p.currencyType, p.recordPackageId, p.recordShopPackageId);
343
354
  const { objects } = await client.core.getObjects({
344
355
  objectIds: [pressingId, listingId],
345
356
  include: { content: true },
346
357
  });
347
- const pressingObject = objects[0];
348
- const listingObject = objects[1];
349
- if (pressingObject instanceof Error && !isNotFound(pressingObject)) {
358
+ const [pressingObject, listingObject] = objects;
359
+ if (pressingObject instanceof Error && !isNotFound(pressingObject))
350
360
  throw pressingObject;
351
- }
352
- if (listingObject instanceof Error && !isNotFound(listingObject)) {
361
+ if (listingObject instanceof Error && !isNotFound(listingObject))
353
362
  throw listingObject;
354
- }
355
- const parsedPressing = !pressingObject || pressingObject instanceof Error
363
+ const pressing = !pressingObject || pressingObject instanceof Error
356
364
  ? null
357
- : parseBatchPressing(pressingId, pressingObject.content, pressingObject.type, p.misoPressingPackageId);
358
- const parsedListing = !listingObject || listingObject instanceof Error
365
+ : parseBatchPressing(pressingId, pressingObject.content, pressingObject.type, p.recordPackageId);
366
+ const listing = !listingObject || listingObject instanceof Error
359
367
  ? null
360
- : parseBatchListing(listingId, listingObject.content, listingObject.type, p.misoPressingPackageId);
361
- if (parsedPressing)
362
- requireId("Sale pressing release", parsedPressing.releaseId, p.releaseId);
363
- if (parsedListing) {
364
- requireId("Sale listing release", parsedListing.releaseId, p.releaseId);
365
- requireId("Sale listing pressing", parsedListing.pressingId, pressingId);
366
- if (parsedListing.currencyType !== normalizeStructTag(p.currencyType)) {
367
- throw new Error(`Sale listing currency ${parsedListing.currencyType} does not match requested ${normalizeStructTag(p.currencyType)}`);
368
+ : parseBatchListing(listingId, listingObject.content, listingObject.type, p.recordShopPackageId);
369
+ if (pressing)
370
+ requireId("Sale pressing release", pressing.releaseId, p.releaseId);
371
+ if (listing) {
372
+ requireId("Sale listing release", listing.releaseId, p.releaseId);
373
+ requireId("Sale listing pressing", listing.pressingId, pressingId);
374
+ if (listing.currencyType !== normalizeStructTag(p.currencyType)) {
375
+ throw new Error(`Sale listing currency ${listing.currencyType} does not match requested ${normalizeStructTag(p.currencyType)}`);
368
376
  }
369
377
  }
370
- return { pressing: parsedPressing, listing: parsedListing };
378
+ return { pressing, listing };
371
379
  }
372
- function parseBatchPressing(pressingId, content, type, misoPressingPackageId) {
380
+ function parseBatchPressing(id, content, type, packageId) {
373
381
  if (!content || !type)
374
- throw new Error(`Pressing ${pressingId} has no BCS content or full type`);
375
- return parsePressing(pressingId, content, type, misoPressingPackageId);
382
+ throw new Error(`Pressing ${id} has no BCS content or full type`);
383
+ return parsePressing(id, content, type, packageId);
376
384
  }
377
- function parseBatchListing(listingId, content, type, misoPressingPackageId) {
385
+ function parseBatchListing(id, content, type, packageId) {
378
386
  if (!content || !type)
379
- throw new Error(`Listing ${listingId} has no BCS content or full type`);
380
- return parseListing(listingId, content, type, misoPressingPackageId);
387
+ throw new Error(`Listing ${id} has no BCS content or full type`);
388
+ return parseListing(id, content, type, packageId);
381
389
  }
382
390
  //# sourceMappingURL=pressing.js.map