@misofm/sdk 0.3.0 → 0.5.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 +31 -0
- package/dist/auth.d.ts +73 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +193 -0
- package/dist/auth.js.map +1 -0
- package/dist/catalog.d.ts +4 -17
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +46 -58
- package/dist/catalog.js.map +1 -1
- package/dist/cover.d.ts +10 -0
- package/dist/cover.d.ts.map +1 -1
- package/dist/cover.js +66 -19
- package/dist/cover.js.map +1 -1
- package/dist/credits.d.ts +10 -0
- package/dist/credits.d.ts.map +1 -1
- package/dist/credits.js +149 -39
- package/dist/credits.js.map +1 -1
- package/dist/drop.d.ts +7 -0
- package/dist/drop.d.ts.map +1 -1
- package/dist/drop.js +84 -34
- package/dist/drop.js.map +1 -1
- package/dist/pressing.d.ts.map +1 -1
- package/dist/pressing.js +59 -16
- package/dist/pressing.js.map +1 -1
- package/dist/read/artist.d.ts +1 -6
- package/dist/read/artist.d.ts.map +1 -1
- package/dist/read/artist.js +39 -22
- package/dist/read/artist.js.map +1 -1
- package/dist/read/catalog.d.ts +24 -3
- package/dist/read/catalog.d.ts.map +1 -1
- package/dist/read/catalog.js +190 -89
- package/dist/read/catalog.js.map +1 -1
- package/dist/read/index.d.ts +5 -3
- package/dist/read/index.d.ts.map +1 -1
- package/dist/read/index.js +2 -2
- package/dist/read/index.js.map +1 -1
- package/dist/read/types.d.ts +12 -1
- package/dist/read/types.d.ts.map +1 -1
- package/dist/read/works.d.ts +3 -2
- package/dist/read/works.d.ts.map +1 -1
- package/dist/read/works.js +158 -48
- package/dist/read/works.js.map +1 -1
- package/package.json +5 -1
- package/src/auth.ts +275 -0
- package/src/catalog.ts +71 -77
- package/src/cover.ts +107 -26
- package/src/credits.ts +353 -89
- package/src/drop.ts +150 -40
- package/src/pressing.ts +146 -36
- package/src/read/artist.ts +73 -34
- package/src/read/catalog.ts +324 -89
- package/src/read/index.ts +23 -2
- package/src/read/types.ts +16 -2
- package/src/read/works.ts +224 -59
package/src/drop.ts
CHANGED
|
@@ -12,11 +12,13 @@ import type { ClientWithCoreApi } from "@mysten/sui/client";
|
|
|
12
12
|
import { deriveDynamicFieldID } from "@mysten/sui/utils";
|
|
13
13
|
import { bcs } from "@mysten/sui/bcs";
|
|
14
14
|
import type { TxThunk } from "./transactions.ts";
|
|
15
|
-
import { isNotFound } from "./queries.ts";
|
|
16
15
|
import * as drop from "./contracts/miso_drop/drop.ts";
|
|
17
16
|
|
|
18
17
|
/** Pricing policy: pay exactly `amount` (fixed) or at least `amount` (floor). */
|
|
19
|
-
export type DropPrice = {
|
|
18
|
+
export type DropPrice = {
|
|
19
|
+
kind: "fixed" | "floor";
|
|
20
|
+
amount: bigint | number | string;
|
|
21
|
+
};
|
|
20
22
|
|
|
21
23
|
export interface CreateDropParams {
|
|
22
24
|
/** The `Release` object the drop sells copies of — also the drop's derivation
|
|
@@ -48,7 +50,13 @@ export function createDrop(p: CreateDropParams): TxThunk {
|
|
|
48
50
|
tx.add(
|
|
49
51
|
drop._new({
|
|
50
52
|
package: p.misoDropPackageId,
|
|
51
|
-
arguments: [
|
|
53
|
+
arguments: [
|
|
54
|
+
p.releaseId,
|
|
55
|
+
p.releaseAdminCapId,
|
|
56
|
+
terms.price,
|
|
57
|
+
terms.supply,
|
|
58
|
+
terms.window,
|
|
59
|
+
],
|
|
52
60
|
typeArguments: [p.currencyType],
|
|
53
61
|
}),
|
|
54
62
|
);
|
|
@@ -88,7 +96,14 @@ export function newEdition(p: NewEditionParams): TxThunk {
|
|
|
88
96
|
tx.add(
|
|
89
97
|
drop.newEdition({
|
|
90
98
|
package: p.misoDropPackageId,
|
|
91
|
-
arguments: [
|
|
99
|
+
arguments: [
|
|
100
|
+
p.releaseId,
|
|
101
|
+
p.oldDropId,
|
|
102
|
+
p.releaseAdminCapId,
|
|
103
|
+
terms.price,
|
|
104
|
+
terms.supply,
|
|
105
|
+
terms.window,
|
|
106
|
+
],
|
|
92
107
|
typeArguments: [p.oldCurrencyType, p.currencyType],
|
|
93
108
|
}),
|
|
94
109
|
);
|
|
@@ -99,20 +114,37 @@ export function newEdition(p: NewEditionParams): TxThunk {
|
|
|
99
114
|
* facade params — the flat shape stays the public API; the enums are a wire detail. */
|
|
100
115
|
function buildTerms(
|
|
101
116
|
tx: Parameters<TxThunk>[0],
|
|
102
|
-
p: Pick<
|
|
117
|
+
p: Pick<
|
|
118
|
+
CreateDropParams,
|
|
119
|
+
| "price"
|
|
120
|
+
| "maxSupply"
|
|
121
|
+
| "startTimestampMs"
|
|
122
|
+
| "endTimestampMs"
|
|
123
|
+
| "misoDropPackageId"
|
|
124
|
+
>,
|
|
103
125
|
) {
|
|
104
126
|
const pkg = { package: p.misoDropPackageId };
|
|
105
|
-
const makePrice =
|
|
106
|
-
|
|
127
|
+
const makePrice =
|
|
128
|
+
p.price.kind === "fixed" ? drop.newFixedPrice : drop.newFloorPrice;
|
|
129
|
+
const price = tx.add(
|
|
130
|
+
makePrice({ ...pkg, arguments: [BigInt(p.price.amount)] }),
|
|
131
|
+
);
|
|
107
132
|
const supply =
|
|
108
133
|
p.maxSupply == null
|
|
109
134
|
? tx.add(drop.newUncappedSupply({ ...pkg, arguments: [] }))
|
|
110
|
-
: tx.add(
|
|
135
|
+
: tx.add(
|
|
136
|
+
drop.newCappedSupply({ ...pkg, arguments: [BigInt(p.maxSupply)] }),
|
|
137
|
+
);
|
|
111
138
|
const start = BigInt(p.startTimestampMs ?? 0);
|
|
112
139
|
const window =
|
|
113
140
|
p.endTimestampMs == null
|
|
114
141
|
? tx.add(drop.newUnboundedWindow({ ...pkg, arguments: [start] }))
|
|
115
|
-
: tx.add(
|
|
142
|
+
: tx.add(
|
|
143
|
+
drop.newBoundedWindow({
|
|
144
|
+
...pkg,
|
|
145
|
+
arguments: [start, BigInt(p.endTimestampMs)],
|
|
146
|
+
}),
|
|
147
|
+
);
|
|
116
148
|
return { price, supply, window };
|
|
117
149
|
}
|
|
118
150
|
|
|
@@ -143,7 +175,11 @@ export function buyRecord(p: BuyRecordParams): TxThunk {
|
|
|
143
175
|
const [first, ...rest] = p.paymentCoinIds;
|
|
144
176
|
if (!first) throw new Error("buyRecord: no payment coins provided");
|
|
145
177
|
const primary = tx.object(first);
|
|
146
|
-
if (rest.length > 0)
|
|
178
|
+
if (rest.length > 0)
|
|
179
|
+
tx.mergeCoins(
|
|
180
|
+
primary,
|
|
181
|
+
rest.map((id) => tx.object(id)),
|
|
182
|
+
);
|
|
147
183
|
const [payment] = tx.splitCoins(primary, [tx.pure.u64(BigInt(p.amount))]);
|
|
148
184
|
const record = tx.add(
|
|
149
185
|
drop.buy({
|
|
@@ -187,21 +223,24 @@ function currencyFromType(type: string | null | undefined): string | null {
|
|
|
187
223
|
* drop ids — a party's featured drop, a superseded edition — where "no such
|
|
188
224
|
* drop" is a normal state, so absence is `null` and only transport failures throw.
|
|
189
225
|
*/
|
|
190
|
-
export async function getDrop(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
type = object?.type;
|
|
197
|
-
} catch (e) {
|
|
198
|
-
if (isNotFound(e)) return null;
|
|
199
|
-
throw e;
|
|
200
|
-
}
|
|
201
|
-
if (!content) return null;
|
|
226
|
+
export async function getDrop(
|
|
227
|
+
client: ClientWithCoreApi,
|
|
228
|
+
dropId: string,
|
|
229
|
+
): Promise<DropView | null> {
|
|
230
|
+
return (await getDropsByIds(client, [dropId]))[dropId] ?? null;
|
|
231
|
+
}
|
|
202
232
|
|
|
233
|
+
function parseDrop(
|
|
234
|
+
dropId: string,
|
|
235
|
+
content: Uint8Array,
|
|
236
|
+
type?: string,
|
|
237
|
+
): DropView {
|
|
203
238
|
const d = drop.Drop.parse(content);
|
|
204
|
-
const price = d.price as {
|
|
239
|
+
const price = d.price as {
|
|
240
|
+
$kind?: string;
|
|
241
|
+
Fixed?: { amount: string };
|
|
242
|
+
Floor?: { amount: string };
|
|
243
|
+
};
|
|
205
244
|
const isFixed = price.$kind === "Fixed" || price.Fixed != null;
|
|
206
245
|
const amount = (isFixed ? price.Fixed?.amount : price.Floor?.amount) ?? "0";
|
|
207
246
|
const supply = d.supply as { $kind?: string; Capped?: { max: string } };
|
|
@@ -221,16 +260,51 @@ export async function getDrop(client: ClientWithCoreApi, dropId: string): Promis
|
|
|
221
260
|
maxSupply: capped ? BigInt(supply.Capped?.max ?? "0") : null,
|
|
222
261
|
quantitySold: BigInt(d.quantity_sold),
|
|
223
262
|
startTimestampMs: BigInt(
|
|
224
|
-
(bounded
|
|
263
|
+
(bounded
|
|
264
|
+
? window.Bounded?.start_timestamp_ms
|
|
265
|
+
: window.Unbounded?.start_timestamp_ms) ?? "0",
|
|
225
266
|
),
|
|
226
|
-
endTimestampMs: bounded
|
|
267
|
+
endTimestampMs: bounded
|
|
268
|
+
? BigInt(window.Bounded?.end_timestamp_ms ?? "0")
|
|
269
|
+
: null,
|
|
227
270
|
currencyType: currencyFromType(type),
|
|
228
271
|
};
|
|
229
272
|
}
|
|
230
273
|
|
|
274
|
+
/** Fetch and parse many Drop objects through one Core bulk request. */
|
|
275
|
+
export async function getDropsByIds(
|
|
276
|
+
client: ClientWithCoreApi,
|
|
277
|
+
dropIdsInput: readonly string[],
|
|
278
|
+
): Promise<Partial<Record<string, DropView>>> {
|
|
279
|
+
const dropIds = [...new Set(dropIdsInput)];
|
|
280
|
+
if (dropIds.length === 0) return {};
|
|
281
|
+
const { objects } = await client.core.getObjects({
|
|
282
|
+
objectIds: dropIds,
|
|
283
|
+
include: { content: true },
|
|
284
|
+
});
|
|
285
|
+
const out: Partial<Record<string, DropView>> = {};
|
|
286
|
+
objects.forEach((object, index) => {
|
|
287
|
+
const dropId = dropIds[index];
|
|
288
|
+
if (
|
|
289
|
+
!dropId ||
|
|
290
|
+
object instanceof Error ||
|
|
291
|
+
!object.content ||
|
|
292
|
+
!/::drop::Drop</.test(object.type ?? "")
|
|
293
|
+
) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
out[dropId] = parseDrop(dropId, object.content, object.type);
|
|
297
|
+
});
|
|
298
|
+
return out;
|
|
299
|
+
}
|
|
300
|
+
|
|
231
301
|
// The release's `CurrentDropKey` dynamic field holds a bare `ID`; the field object
|
|
232
302
|
// serializes as `Field { id, name: CurrentDropKey (unit), value: ID }`.
|
|
233
|
-
const CurrentDropField = bcs.struct("Field", {
|
|
303
|
+
const CurrentDropField = bcs.struct("Field", {
|
|
304
|
+
id: bcs.Address,
|
|
305
|
+
name: bcs.bool(),
|
|
306
|
+
value: bcs.Address,
|
|
307
|
+
});
|
|
234
308
|
|
|
235
309
|
// Unit-struct key bytes (single `0x00` for the dummy bool field).
|
|
236
310
|
const CURRENT_DROP_KEY_BYTES = drop.CurrentDropKey.serialize([false]).toBytes();
|
|
@@ -247,20 +321,56 @@ export interface GetCurrentDropParams {
|
|
|
247
321
|
* destroyed, so this — not derived-address probing — is how the current edition is
|
|
248
322
|
* found.
|
|
249
323
|
*/
|
|
250
|
-
export async function getCurrentDrop(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
324
|
+
export async function getCurrentDrop(
|
|
325
|
+
client: ClientWithCoreApi,
|
|
326
|
+
p: GetCurrentDropParams,
|
|
327
|
+
): Promise<DropView | null> {
|
|
328
|
+
return (
|
|
329
|
+
(await getCurrentDrops(client, [p.releaseId], p.misoDropPackageId))[
|
|
330
|
+
p.releaseId
|
|
331
|
+
] ?? null
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Resolve the live drops for many releases in two Core bulk requests: all
|
|
337
|
+
* CurrentDrop pointer fields, then all pointed-to Drop objects.
|
|
338
|
+
*/
|
|
339
|
+
export async function getCurrentDrops(
|
|
340
|
+
client: ClientWithCoreApi,
|
|
341
|
+
releaseIdsInput: readonly string[],
|
|
342
|
+
misoDropPackageId: string,
|
|
343
|
+
): Promise<Partial<Record<string, DropView>>> {
|
|
344
|
+
const releaseIds = [...new Set(releaseIdsInput)];
|
|
345
|
+
if (releaseIds.length === 0) return {};
|
|
346
|
+
const fieldIds = releaseIds.map((releaseId) =>
|
|
347
|
+
deriveDynamicFieldID(
|
|
348
|
+
releaseId,
|
|
349
|
+
`${misoDropPackageId}::drop::CurrentDropKey`,
|
|
350
|
+
CURRENT_DROP_KEY_BYTES,
|
|
351
|
+
),
|
|
352
|
+
);
|
|
353
|
+
const { objects } = await client.core.getObjects({
|
|
354
|
+
objectIds: fieldIds,
|
|
355
|
+
include: { content: true },
|
|
356
|
+
});
|
|
357
|
+
const dropIdByRelease: Partial<Record<string, string>> = {};
|
|
358
|
+
objects.forEach((object, index) => {
|
|
359
|
+
const releaseId = releaseIds[index];
|
|
360
|
+
if (!releaseId || object instanceof Error || !object.content) return;
|
|
361
|
+
dropIdByRelease[releaseId] = CurrentDropField.parse(object.content).value;
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const drops = await getDropsByIds(
|
|
365
|
+
client,
|
|
366
|
+
Object.values(dropIdByRelease).filter(
|
|
367
|
+
(id): id is string => id !== undefined,
|
|
368
|
+
),
|
|
255
369
|
);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
} catch (e) {
|
|
261
|
-
if (isNotFound(e)) return null;
|
|
262
|
-
throw e;
|
|
370
|
+
const out: Partial<Record<string, DropView>> = {};
|
|
371
|
+
for (const [releaseId, dropId] of Object.entries(dropIdByRelease)) {
|
|
372
|
+
const dropView = dropId ? drops[dropId] : undefined;
|
|
373
|
+
if (dropView) out[releaseId] = dropView;
|
|
263
374
|
}
|
|
264
|
-
|
|
265
|
-
return getDrop(client, CurrentDropField.parse(content).value);
|
|
375
|
+
return out;
|
|
266
376
|
}
|
package/src/pressing.ts
CHANGED
|
@@ -22,7 +22,10 @@ import * as listing from "./contracts/miso_pressing/listing.ts";
|
|
|
22
22
|
import * as pressing from "./contracts/miso_pressing/pressing.ts";
|
|
23
23
|
|
|
24
24
|
/** Pricing policy: pay exactly `amount` (fixed) or at least `amount` (floor). */
|
|
25
|
-
export type ListingPrice = {
|
|
25
|
+
export type ListingPrice = {
|
|
26
|
+
kind: "fixed" | "floor";
|
|
27
|
+
amount: bigint | number | string;
|
|
28
|
+
};
|
|
26
29
|
|
|
27
30
|
/** Whether a currency's listing takes payment. Below the pressing's own run state. */
|
|
28
31
|
export type ListingSwitch = "enabled" | "disabled";
|
|
@@ -54,15 +57,25 @@ const UNIT_STRUCT_KEY_BYTES = new Uint8Array([0x00]);
|
|
|
54
57
|
* that is the address a Move type tag canonicalises to. `miso_pressing` is published
|
|
55
58
|
* immutable, so its original and current ids are the same.
|
|
56
59
|
*/
|
|
57
|
-
export function derivePressingId(
|
|
58
|
-
|
|
60
|
+
export function derivePressingId(
|
|
61
|
+
releaseId: string,
|
|
62
|
+
misoPressingPackageId: string,
|
|
63
|
+
): string {
|
|
64
|
+
return deriveObjectID(
|
|
65
|
+
releaseId,
|
|
66
|
+
`${misoPressingPackageId}::pressing::PressingKey`,
|
|
67
|
+
UNIT_STRUCT_KEY_BYTES,
|
|
68
|
+
);
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
/**
|
|
62
72
|
* Where `pressingId`'s admin cap was minted. The cap is transferable, so this is not
|
|
63
73
|
* where it lives — only where it came from.
|
|
64
74
|
*/
|
|
65
|
-
export function derivePressingAdminCapId(
|
|
75
|
+
export function derivePressingAdminCapId(
|
|
76
|
+
pressingId: string,
|
|
77
|
+
misoPressingPackageId: string,
|
|
78
|
+
): string {
|
|
66
79
|
return deriveObjectID(
|
|
67
80
|
pressingId,
|
|
68
81
|
`${misoPressingPackageId}::pressing::PressingAdminCapKey`,
|
|
@@ -93,7 +106,10 @@ export function deriveSaleIds(
|
|
|
93
106
|
misoPressingPackageId: string,
|
|
94
107
|
): { pressingId: string; listingId: string } {
|
|
95
108
|
const pressingId = derivePressingId(releaseId, misoPressingPackageId);
|
|
96
|
-
return {
|
|
109
|
+
return {
|
|
110
|
+
pressingId,
|
|
111
|
+
listingId: deriveListingId(pressingId, currencyType, misoPressingPackageId),
|
|
112
|
+
};
|
|
97
113
|
}
|
|
98
114
|
|
|
99
115
|
// ============================================================================
|
|
@@ -103,20 +119,37 @@ export function deriveSaleIds(
|
|
|
103
119
|
type Tx = Parameters<TxThunk>[0];
|
|
104
120
|
|
|
105
121
|
function priceArg(tx: Tx, misoPressingPackageId: string, price: ListingPrice) {
|
|
106
|
-
const make =
|
|
107
|
-
|
|
122
|
+
const make =
|
|
123
|
+
price.kind === "fixed" ? listing.newFixedPrice : listing.newFloorPrice;
|
|
124
|
+
return tx.add(
|
|
125
|
+
make({ package: misoPressingPackageId, arguments: [BigInt(price.amount)] }),
|
|
126
|
+
);
|
|
108
127
|
}
|
|
109
128
|
|
|
110
|
-
function switchArg(
|
|
111
|
-
|
|
129
|
+
function switchArg(
|
|
130
|
+
tx: Tx,
|
|
131
|
+
misoPressingPackageId: string,
|
|
132
|
+
state: ListingSwitch,
|
|
133
|
+
) {
|
|
134
|
+
const make =
|
|
135
|
+
state === "enabled" ? listing.newEnabledState : listing.newDisabledState;
|
|
112
136
|
return tx.add(make({ package: misoPressingPackageId }));
|
|
113
137
|
}
|
|
114
138
|
|
|
115
|
-
function runStateArg(
|
|
139
|
+
function runStateArg(
|
|
140
|
+
tx: Tx,
|
|
141
|
+
misoPressingPackageId: string,
|
|
142
|
+
state: PressingRunState,
|
|
143
|
+
) {
|
|
116
144
|
const pkg = { package: misoPressingPackageId };
|
|
117
145
|
switch (state.kind) {
|
|
118
146
|
case "scheduled":
|
|
119
|
-
return tx.add(
|
|
147
|
+
return tx.add(
|
|
148
|
+
pressing.newScheduledState({
|
|
149
|
+
...pkg,
|
|
150
|
+
arguments: [BigInt(state.startTimestampMs)],
|
|
151
|
+
}),
|
|
152
|
+
);
|
|
120
153
|
case "active":
|
|
121
154
|
return tx.add(pressing.newActiveState(pkg));
|
|
122
155
|
case "paused":
|
|
@@ -169,7 +202,11 @@ export function openPressing(p: OpenPressingParams): TxThunk {
|
|
|
169
202
|
const [run, adminCap] = tx.add(
|
|
170
203
|
pressing._new({
|
|
171
204
|
package: pkg,
|
|
172
|
-
arguments: [
|
|
205
|
+
arguments: [
|
|
206
|
+
p.releaseId,
|
|
207
|
+
p.releaseAdminCapId,
|
|
208
|
+
runStateArg(tx, pkg, p.state ?? { kind: "active" }),
|
|
209
|
+
],
|
|
173
210
|
}),
|
|
174
211
|
);
|
|
175
212
|
for (const terms of p.listings) {
|
|
@@ -246,7 +283,11 @@ export function setListingPrice(p: SetListingPriceParams): TxThunk {
|
|
|
246
283
|
tx.add(
|
|
247
284
|
listing.setPrice({
|
|
248
285
|
package: pkg,
|
|
249
|
-
arguments: [
|
|
286
|
+
arguments: [
|
|
287
|
+
listingId,
|
|
288
|
+
p.pressingAdminCapId,
|
|
289
|
+
priceArg(tx, pkg, p.price),
|
|
290
|
+
],
|
|
250
291
|
typeArguments: [p.currencyType],
|
|
251
292
|
}),
|
|
252
293
|
);
|
|
@@ -269,7 +310,11 @@ export function setListingState(p: SetListingStateParams): TxThunk {
|
|
|
269
310
|
tx.add(
|
|
270
311
|
listing.setState({
|
|
271
312
|
package: pkg,
|
|
272
|
-
arguments: [
|
|
313
|
+
arguments: [
|
|
314
|
+
listingId,
|
|
315
|
+
p.pressingAdminCapId,
|
|
316
|
+
switchArg(tx, pkg, p.state),
|
|
317
|
+
],
|
|
273
318
|
typeArguments: [p.currencyType],
|
|
274
319
|
}),
|
|
275
320
|
);
|
|
@@ -352,7 +397,11 @@ export interface BuyRecordParams {
|
|
|
352
397
|
export function buyRecord(p: BuyRecordParams): TxThunk {
|
|
353
398
|
return (tx) => {
|
|
354
399
|
const pkg = p.misoPressingPackageId;
|
|
355
|
-
const { pressingId, listingId } = deriveSaleIds(
|
|
400
|
+
const { pressingId, listingId } = deriveSaleIds(
|
|
401
|
+
p.releaseId,
|
|
402
|
+
p.currencyType,
|
|
403
|
+
pkg,
|
|
404
|
+
);
|
|
356
405
|
const payment = tx.balance({
|
|
357
406
|
type: p.currencyType,
|
|
358
407
|
balance: BigInt(p.amount),
|
|
@@ -407,8 +456,13 @@ async function fetch(
|
|
|
407
456
|
objectId: string,
|
|
408
457
|
): Promise<{ content: Uint8Array; type?: string } | null> {
|
|
409
458
|
try {
|
|
410
|
-
const { object } = await client.core.getObject({
|
|
411
|
-
|
|
459
|
+
const { object } = await client.core.getObject({
|
|
460
|
+
objectId,
|
|
461
|
+
include: { content: true },
|
|
462
|
+
});
|
|
463
|
+
return object?.content
|
|
464
|
+
? { content: object.content, type: object.type }
|
|
465
|
+
: null;
|
|
412
466
|
} catch (e) {
|
|
413
467
|
if (isNotFound(e)) return null;
|
|
414
468
|
throw e;
|
|
@@ -417,8 +471,12 @@ async function fetch(
|
|
|
417
471
|
|
|
418
472
|
// The generated `MoveEnum` parsers emit `{ $kind, <Variant>: … }`; older ones omitted
|
|
419
473
|
// `$kind`. Both shapes are accepted so a codegen bump cannot silently mis-read a price.
|
|
420
|
-
function variant<T extends string>(
|
|
421
|
-
|
|
474
|
+
function variant<T extends string>(
|
|
475
|
+
v: { $kind?: string } & Record<string, unknown>,
|
|
476
|
+
...names: T[]
|
|
477
|
+
): T {
|
|
478
|
+
for (const name of names)
|
|
479
|
+
if (v.$kind === name || v[name] != null) return name;
|
|
422
480
|
return names[0]!;
|
|
423
481
|
}
|
|
424
482
|
|
|
@@ -430,18 +488,31 @@ function variant<T extends string>(v: { $kind?: string } & Record<string, unknow
|
|
|
430
488
|
* computable for ANY release, so probing one that was never opened is a normal state,
|
|
431
489
|
* not a broken reference — absence is `null` and only transport failures throw.
|
|
432
490
|
*/
|
|
433
|
-
export async function getPressing(
|
|
491
|
+
export async function getPressing(
|
|
492
|
+
client: ClientWithCoreApi,
|
|
493
|
+
pressingId: string,
|
|
494
|
+
): Promise<PressingView | null> {
|
|
434
495
|
const got = await fetch(client, pressingId);
|
|
435
496
|
if (!got) return null;
|
|
436
|
-
|
|
437
|
-
|
|
497
|
+
return parsePressing(pressingId, got.content);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function parsePressing(pressingId: string, content: Uint8Array): PressingView {
|
|
501
|
+
const parsed = pressing.Pressing.parse(content);
|
|
502
|
+
const s = parsed.state as {
|
|
503
|
+
$kind?: string;
|
|
504
|
+
Scheduled?: { start_timestamp_ms: string };
|
|
505
|
+
};
|
|
438
506
|
const kind = variant(s, "Scheduled", "Active", "Paused");
|
|
439
507
|
return {
|
|
440
508
|
id: pressingId,
|
|
441
509
|
releaseId: parsed.release_id,
|
|
442
510
|
state:
|
|
443
511
|
kind === "Scheduled"
|
|
444
|
-
? {
|
|
512
|
+
? {
|
|
513
|
+
kind: "scheduled",
|
|
514
|
+
startTimestampMs: BigInt(s.Scheduled?.start_timestamp_ms ?? "0"),
|
|
515
|
+
}
|
|
445
516
|
: kind === "Paused"
|
|
446
517
|
? { kind: "paused" }
|
|
447
518
|
: { kind: "active" },
|
|
@@ -450,23 +521,45 @@ export async function getPressing(client: ClientWithCoreApi, pressingId: string)
|
|
|
450
521
|
}
|
|
451
522
|
|
|
452
523
|
/** Fetches and parses a `Listing<Currency>`, or `null` if that currency is not listed. */
|
|
453
|
-
export async function getListing(
|
|
524
|
+
export async function getListing(
|
|
525
|
+
client: ClientWithCoreApi,
|
|
526
|
+
listingId: string,
|
|
527
|
+
): Promise<ListingView | null> {
|
|
454
528
|
const got = await fetch(client, listingId);
|
|
455
529
|
if (!got) return null;
|
|
456
|
-
|
|
457
|
-
|
|
530
|
+
return parseListing(listingId, got.content, got.type);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function parseListing(
|
|
534
|
+
listingId: string,
|
|
535
|
+
content: Uint8Array,
|
|
536
|
+
type?: string,
|
|
537
|
+
): ListingView {
|
|
538
|
+
const parsed = listing.Listing.parse(content);
|
|
539
|
+
const p = parsed.price as {
|
|
540
|
+
$kind?: string;
|
|
541
|
+
Fixed?: { amount: string };
|
|
542
|
+
Floor?: { amount: string };
|
|
543
|
+
};
|
|
458
544
|
const priceKind = variant(p, "Fixed", "Floor");
|
|
459
|
-
const st = parsed.state as {
|
|
545
|
+
const st = parsed.state as {
|
|
546
|
+
$kind?: string;
|
|
547
|
+
Enabled?: unknown;
|
|
548
|
+
Disabled?: unknown;
|
|
549
|
+
};
|
|
460
550
|
return {
|
|
461
551
|
id: listingId,
|
|
462
552
|
releaseId: parsed.release_id,
|
|
463
553
|
pressingId: parsed.pressing_id,
|
|
464
554
|
price: {
|
|
465
555
|
kind: priceKind === "Fixed" ? "fixed" : "floor",
|
|
466
|
-
amount: BigInt(
|
|
556
|
+
amount: BigInt(
|
|
557
|
+
(priceKind === "Fixed" ? p.Fixed?.amount : p.Floor?.amount) ?? "0",
|
|
558
|
+
),
|
|
467
559
|
},
|
|
468
|
-
state:
|
|
469
|
-
|
|
560
|
+
state:
|
|
561
|
+
variant(st, "Enabled", "Disabled") === "Enabled" ? "enabled" : "disabled",
|
|
562
|
+
currencyType: currencyFromType(type),
|
|
470
563
|
};
|
|
471
564
|
}
|
|
472
565
|
|
|
@@ -488,10 +581,27 @@ export async function getSale(
|
|
|
488
581
|
client: ClientWithCoreApi,
|
|
489
582
|
p: GetSaleParams,
|
|
490
583
|
): Promise<{ pressing: PressingView | null; listing: ListingView | null }> {
|
|
491
|
-
const { pressingId, listingId } = deriveSaleIds(
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
584
|
+
const { pressingId, listingId } = deriveSaleIds(
|
|
585
|
+
p.releaseId,
|
|
586
|
+
p.currencyType,
|
|
587
|
+
p.misoPressingPackageId,
|
|
588
|
+
);
|
|
589
|
+
const { objects } = await client.core.getObjects({
|
|
590
|
+
objectIds: [pressingId, listingId],
|
|
591
|
+
include: { content: true },
|
|
592
|
+
});
|
|
593
|
+
const pressingObject = objects[0];
|
|
594
|
+
const listingObject = objects[1];
|
|
595
|
+
return {
|
|
596
|
+
pressing:
|
|
597
|
+
!pressingObject ||
|
|
598
|
+
pressingObject instanceof Error ||
|
|
599
|
+
!pressingObject.content
|
|
600
|
+
? null
|
|
601
|
+
: parsePressing(pressingId, pressingObject.content),
|
|
602
|
+
listing:
|
|
603
|
+
!listingObject || listingObject instanceof Error || !listingObject.content
|
|
604
|
+
? null
|
|
605
|
+
: parseListing(listingId, listingObject.content, listingObject.type),
|
|
606
|
+
};
|
|
497
607
|
}
|