@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.
- package/README.md +145 -53
- package/dist/client.d.ts +156 -48
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +289 -48
- package/dist/client.js.map +1 -1
- package/dist/contracts/composition_royalty_pool/composition_royalty_pool.d.ts +11 -11
- package/dist/contracts/composition_royalty_pool/composition_royalty_pool.d.ts.map +1 -1
- package/dist/contracts/composition_royalty_pool/composition_royalty_pool.js +9 -9
- package/dist/contracts/composition_royalty_pool/composition_royalty_pool.js.map +1 -1
- package/dist/contracts/miso_record/deps/std/type_name.d.ts.map +1 -0
- package/dist/contracts/miso_record/deps/std/type_name.js.map +1 -0
- package/dist/contracts/miso_record/deps/sui/vec_set.d.ts +21 -0
- package/dist/contracts/miso_record/deps/sui/vec_set.d.ts.map +1 -0
- package/dist/contracts/miso_record/deps/sui/vec_set.js +20 -0
- package/dist/contracts/miso_record/deps/sui/vec_set.js.map +1 -0
- package/dist/contracts/miso_record/pressing.d.ts +327 -0
- package/dist/contracts/miso_record/pressing.d.ts.map +1 -0
- package/dist/contracts/miso_record/pressing.js +345 -0
- package/dist/contracts/miso_record/pressing.js.map +1 -0
- package/dist/contracts/miso_record/record.d.ts +190 -0
- package/dist/contracts/miso_record/record.d.ts.map +1 -0
- package/dist/contracts/miso_record/record.js +226 -0
- package/dist/contracts/miso_record/record.js.map +1 -0
- package/dist/contracts/miso_record_shop/deps/std/type_name.d.ts +18 -0
- package/dist/contracts/miso_record_shop/deps/std/type_name.d.ts.map +1 -0
- package/dist/contracts/miso_record_shop/deps/std/type_name.js +20 -0
- package/dist/contracts/miso_record_shop/deps/std/type_name.js.map +1 -0
- package/dist/contracts/miso_record_shop/listing.d.ts +387 -0
- package/dist/contracts/miso_record_shop/listing.d.ts.map +1 -0
- package/dist/contracts/miso_record_shop/listing.js +380 -0
- package/dist/contracts/miso_record_shop/listing.js.map +1 -0
- package/dist/contracts/miso_record_shop/witness.d.ts +7 -0
- package/dist/contracts/miso_record_shop/witness.d.ts.map +1 -0
- package/dist/contracts/miso_record_shop/witness.js +9 -0
- package/dist/contracts/miso_record_shop/witness.js.map +1 -0
- package/dist/contracts/recording_royalty_pool/recording_royalty_pool.d.ts +10 -12
- package/dist/contracts/recording_royalty_pool/recording_royalty_pool.d.ts.map +1 -1
- package/dist/contracts/recording_royalty_pool/recording_royalty_pool.js +8 -10
- package/dist/contracts/recording_royalty_pool/recording_royalty_pool.js.map +1 -1
- package/dist/contracts.d.ts +3 -3
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +5 -4
- package/dist/contracts.js.map +1 -1
- package/dist/deployments.d.ts +37 -4
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +40 -2
- package/dist/deployments.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mix.d.ts +144 -0
- package/dist/mix.d.ts.map +1 -0
- package/dist/mix.js +656 -0
- package/dist/mix.js.map +1 -0
- package/dist/pressing.d.ts +72 -156
- package/dist/pressing.d.ts.map +1 -1
- package/dist/pressing.js +269 -261
- package/dist/pressing.js.map +1 -1
- package/dist/publication.d.ts +5 -2
- package/dist/publication.d.ts.map +1 -1
- package/dist/publication.js +57 -32
- package/dist/publication.js.map +1 -1
- package/dist/read/catalog.d.ts +8 -5
- package/dist/read/catalog.d.ts.map +1 -1
- package/dist/read/catalog.js +47 -35
- package/dist/read/catalog.js.map +1 -1
- package/dist/read/config.d.ts +6 -4
- package/dist/read/config.d.ts.map +1 -1
- package/dist/read/config.js +1 -2
- package/dist/read/config.js.map +1 -1
- package/dist/read/index.d.ts +1 -1
- package/dist/read/index.d.ts.map +1 -1
- package/dist/read/index.js +1 -1
- package/dist/read/index.js.map +1 -1
- package/dist/read/internal/scalars.d.ts.map +1 -1
- package/dist/read/internal/scalars.js +4 -3
- package/dist/read/internal/scalars.js.map +1 -1
- package/dist/read/internal/walrus.d.ts.map +1 -1
- package/dist/read/internal/walrus.js +2 -1
- package/dist/read/internal/walrus.js.map +1 -1
- package/dist/read/receipts.d.ts +21 -12
- package/dist/read/receipts.d.ts.map +1 -1
- package/dist/read/receipts.js +159 -56
- package/dist/read/receipts.js.map +1 -1
- package/dist/read/types.d.ts +34 -24
- package/dist/read/types.d.ts.map +1 -1
- package/dist/read/wallet.d.ts.map +1 -1
- package/dist/read/wallet.js +31 -46
- package/dist/read/wallet.js.map +1 -1
- package/dist/vault.d.ts +40 -11
- package/dist/vault.d.ts.map +1 -1
- package/dist/vault.js +94 -22
- package/dist/vault.js.map +1 -1
- package/package.json +10 -3
- package/src/client.ts +386 -72
- package/src/contracts/composition_royalty_pool/composition_royalty_pool.ts +15 -15
- package/src/contracts/miso_record/deps/sui/vec_set.ts +21 -0
- package/src/contracts/miso_record/pressing.ts +522 -0
- package/src/contracts/miso_record/record.ts +338 -0
- package/src/contracts/miso_record_shop/deps/std/type_name.ts +22 -0
- package/src/contracts/miso_record_shop/listing.ts +602 -0
- package/src/contracts/miso_record_shop/witness.ts +11 -0
- package/src/contracts/recording_royalty_pool/recording_royalty_pool.ts +14 -16
- package/src/contracts.ts +5 -4
- package/src/deployments.ts +131 -38
- package/src/index.ts +2 -0
- package/src/mix.ts +910 -0
- package/src/pressing.ts +428 -423
- package/src/publication.ts +62 -33
- package/src/read/catalog.ts +49 -34
- package/src/read/config.ts +7 -7
- package/src/read/index.ts +9 -1
- package/src/read/internal/scalars.ts +4 -2
- package/src/read/internal/walrus.ts +2 -1
- package/src/read/receipts.ts +181 -66
- package/src/read/types.ts +35 -22
- package/src/read/wallet.ts +29 -50
- package/src/vault.ts +142 -32
- package/dist/contracts/miso_pressing/certificate.d.ts +0 -89
- package/dist/contracts/miso_pressing/certificate.d.ts.map +0 -1
- package/dist/contracts/miso_pressing/certificate.js +0 -108
- package/dist/contracts/miso_pressing/certificate.js.map +0 -1
- package/dist/contracts/miso_pressing/deps/std/type_name.d.ts.map +0 -1
- package/dist/contracts/miso_pressing/deps/std/type_name.js.map +0 -1
- package/dist/contracts/miso_pressing/listing.d.ts +0 -434
- package/dist/contracts/miso_pressing/listing.d.ts.map +0 -1
- package/dist/contracts/miso_pressing/listing.js +0 -401
- package/dist/contracts/miso_pressing/listing.js.map +0 -1
- package/dist/contracts/miso_pressing/pressing.d.ts +0 -334
- package/dist/contracts/miso_pressing/pressing.d.ts.map +0 -1
- package/dist/contracts/miso_pressing/pressing.js +0 -298
- package/dist/contracts/miso_pressing/pressing.js.map +0 -1
- package/src/contracts/miso_pressing/certificate.ts +0 -164
- package/src/contracts/miso_pressing/listing.ts +0 -592
- package/src/contracts/miso_pressing/pressing.ts +0 -399
- /package/dist/contracts/{miso_pressing → miso_record}/deps/std/type_name.d.ts +0 -0
- /package/dist/contracts/{miso_pressing → miso_record}/deps/std/type_name.js +0 -0
- /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
|
|
7
|
-
import * as
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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,
|
|
67
|
+
listingId: deriveListingId(pressingId, currencyType, recordShopPackageId),
|
|
44
68
|
};
|
|
45
69
|
}
|
|
46
|
-
function priceArg(tx,
|
|
47
|
-
const
|
|
48
|
-
return tx.add(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
*
|
|
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
|
|
80
|
-
|
|
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
|
-
|
|
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(
|
|
90
|
-
package:
|
|
103
|
+
const listing = tx.add(listingContract._new({
|
|
104
|
+
package: p.recordShopPackageId,
|
|
91
105
|
arguments: [
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
priceArg(tx,
|
|
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(
|
|
101
|
-
|
|
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
|
|
111
|
-
|
|
112
|
-
package: pkg,
|
|
157
|
+
const listing = tx.add(listingContract._new({
|
|
158
|
+
package: p.recordShopPackageId,
|
|
113
159
|
arguments: [
|
|
114
|
-
|
|
160
|
+
p.pressingId,
|
|
115
161
|
p.pressingAdminCapId,
|
|
116
|
-
priceArg(tx,
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
tx.add(listing.setPrice({
|
|
134
|
-
package: pkg,
|
|
186
|
+
tx.add(listingContract.setPrice({
|
|
187
|
+
package: p.recordShopPackageId,
|
|
135
188
|
arguments: [
|
|
136
|
-
|
|
189
|
+
deriveListingId(p.pressingId, p.currencyType, p.recordShopPackageId),
|
|
137
190
|
p.pressingAdminCapId,
|
|
138
|
-
priceArg(tx,
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
tx.add(listing.setState({
|
|
150
|
-
package: pkg,
|
|
199
|
+
tx.add(listingContract.setState({
|
|
200
|
+
package: p.recordShopPackageId,
|
|
151
201
|
arguments: [
|
|
152
|
-
|
|
202
|
+
deriveListingId(p.pressingId, p.currencyType, p.recordShopPackageId),
|
|
153
203
|
p.pressingAdminCapId,
|
|
154
|
-
|
|
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
|
|
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
|
-
|
|
201
|
-
useGasCoin: p.useGasCoin ?? false,
|
|
216
|
+
useGasCoin: false,
|
|
202
217
|
});
|
|
203
|
-
const record = tx.add(
|
|
204
|
-
package:
|
|
205
|
-
arguments: [
|
|
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 (
|
|
226
|
-
if (isNotFound(
|
|
243
|
+
catch (error) {
|
|
244
|
+
if (isNotFound(error))
|
|
227
245
|
return null;
|
|
228
|
-
throw
|
|
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
|
-
|
|
240
|
-
function requirePressingType(type, misoPressingPackageId) {
|
|
256
|
+
function requireExactType(type, expected, label) {
|
|
241
257
|
const actual = normalizeStructTag(type);
|
|
242
|
-
const
|
|
243
|
-
if (actual !==
|
|
244
|
-
throw new Error(
|
|
245
|
-
}
|
|
258
|
+
const normalizedExpected = normalizeStructTag(expected);
|
|
259
|
+
if (actual !== normalizedExpected)
|
|
260
|
+
throw new Error(`${label} has type ${actual}, expected ${normalizedExpected}`);
|
|
246
261
|
}
|
|
247
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
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 (
|
|
274
|
+
if (value.$kind === name || Object.hasOwn(value, name))
|
|
269
275
|
return name;
|
|
270
|
-
|
|
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
|
|
287
|
-
|
|
288
|
-
|
|
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,
|
|
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
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
const
|
|
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
|
|
319
|
-
|
|
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
|
-
|
|
328
|
-
|
|
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
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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.
|
|
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
|
|
348
|
-
|
|
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.
|
|
358
|
-
const
|
|
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.
|
|
361
|
-
if (
|
|
362
|
-
requireId("Sale pressing release",
|
|
363
|
-
if (
|
|
364
|
-
requireId("Sale listing release",
|
|
365
|
-
requireId("Sale listing pressing",
|
|
366
|
-
if (
|
|
367
|
-
throw new Error(`Sale listing currency ${
|
|
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
|
|
378
|
+
return { pressing, listing };
|
|
371
379
|
}
|
|
372
|
-
function parseBatchPressing(
|
|
380
|
+
function parseBatchPressing(id, content, type, packageId) {
|
|
373
381
|
if (!content || !type)
|
|
374
|
-
throw new Error(`Pressing ${
|
|
375
|
-
return parsePressing(
|
|
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(
|
|
385
|
+
function parseBatchListing(id, content, type, packageId) {
|
|
378
386
|
if (!content || !type)
|
|
379
|
-
throw new Error(`Listing ${
|
|
380
|
-
return parseListing(
|
|
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
|