@misofm/platform 0.0.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +686 -3
  3. package/dist/auth.d.ts +73 -0
  4. package/dist/auth.d.ts.map +1 -0
  5. package/dist/auth.js +193 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/catalog.d.ts +48 -0
  8. package/dist/catalog.d.ts.map +1 -0
  9. package/dist/catalog.js +92 -0
  10. package/dist/catalog.js.map +1 -0
  11. package/dist/client.d.ts +462 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +788 -0
  14. package/dist/client.js.map +1 -0
  15. package/dist/contracts.d.ts +34 -0
  16. package/dist/contracts.d.ts.map +1 -0
  17. package/dist/contracts.js +49 -0
  18. package/dist/contracts.js.map +1 -0
  19. package/dist/cover.d.ts +69 -0
  20. package/dist/cover.d.ts.map +1 -0
  21. package/dist/cover.js +132 -0
  22. package/dist/cover.js.map +1 -0
  23. package/dist/credits.d.ts +200 -0
  24. package/dist/credits.d.ts.map +1 -0
  25. package/dist/credits.js +465 -0
  26. package/dist/credits.js.map +1 -0
  27. package/dist/deployments.d.ts +224 -0
  28. package/dist/deployments.d.ts.map +1 -0
  29. package/dist/deployments.js +177 -0
  30. package/dist/deployments.js.map +1 -0
  31. package/dist/execute.d.ts +30 -0
  32. package/dist/execute.d.ts.map +1 -0
  33. package/dist/execute.js +31 -0
  34. package/dist/execute.js.map +1 -0
  35. package/dist/index.d.ts +21 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +52 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/internal.d.ts +13 -0
  40. package/dist/internal.d.ts.map +1 -0
  41. package/dist/internal.js +41 -0
  42. package/dist/internal.js.map +1 -0
  43. package/dist/mix.d.ts +144 -0
  44. package/dist/mix.d.ts.map +1 -0
  45. package/dist/mix.js +656 -0
  46. package/dist/mix.js.map +1 -0
  47. package/dist/pressing.d.ts +137 -0
  48. package/dist/pressing.d.ts.map +1 -0
  49. package/dist/pressing.js +390 -0
  50. package/dist/pressing.js.map +1 -0
  51. package/dist/publication.d.ts +216 -0
  52. package/dist/publication.d.ts.map +1 -0
  53. package/dist/publication.js +872 -0
  54. package/dist/publication.js.map +1 -0
  55. package/dist/queries.d.ts +2 -0
  56. package/dist/queries.d.ts.map +1 -0
  57. package/dist/queries.js +8 -0
  58. package/dist/queries.js.map +1 -0
  59. package/dist/read/artist.d.ts +18 -0
  60. package/dist/read/artist.d.ts.map +1 -0
  61. package/dist/read/artist.js +86 -0
  62. package/dist/read/artist.js.map +1 -0
  63. package/dist/read/catalog.d.ts +93 -0
  64. package/dist/read/catalog.d.ts.map +1 -0
  65. package/dist/read/catalog.js +441 -0
  66. package/dist/read/catalog.js.map +1 -0
  67. package/dist/read/client.d.ts +37 -0
  68. package/dist/read/client.d.ts.map +1 -0
  69. package/dist/read/client.js +50 -0
  70. package/dist/read/client.js.map +1 -0
  71. package/dist/read/config.d.ts +68 -0
  72. package/dist/read/config.d.ts.map +1 -0
  73. package/dist/read/config.js +63 -0
  74. package/dist/read/config.js.map +1 -0
  75. package/dist/read/genres.d.ts +7 -0
  76. package/dist/read/genres.d.ts.map +1 -0
  77. package/dist/read/genres.js +38 -0
  78. package/dist/read/genres.js.map +1 -0
  79. package/dist/read/index.d.ts +14 -0
  80. package/dist/read/index.d.ts.map +1 -0
  81. package/dist/read/index.js +23 -0
  82. package/dist/read/index.js.map +1 -0
  83. package/dist/read/internal/scalars.d.ts +23 -0
  84. package/dist/read/internal/scalars.d.ts.map +1 -0
  85. package/dist/read/internal/scalars.js +57 -0
  86. package/dist/read/internal/scalars.js.map +1 -0
  87. package/dist/read/internal/walrus.d.ts +6 -0
  88. package/dist/read/internal/walrus.d.ts.map +1 -0
  89. package/dist/read/internal/walrus.js +29 -0
  90. package/dist/read/internal/walrus.js.map +1 -0
  91. package/dist/read/receipts.d.ts +41 -0
  92. package/dist/read/receipts.d.ts.map +1 -0
  93. package/dist/read/receipts.js +398 -0
  94. package/dist/read/receipts.js.map +1 -0
  95. package/dist/read/types.d.ts +328 -0
  96. package/dist/read/types.d.ts.map +1 -0
  97. package/dist/read/types.js +21 -0
  98. package/dist/read/types.js.map +1 -0
  99. package/dist/read/wallet.d.ts +74 -0
  100. package/dist/read/wallet.d.ts.map +1 -0
  101. package/dist/read/wallet.js +578 -0
  102. package/dist/read/wallet.js.map +1 -0
  103. package/dist/read/works.d.ts +29 -0
  104. package/dist/read/works.d.ts.map +1 -0
  105. package/dist/read/works.js +191 -0
  106. package/dist/read/works.js.map +1 -0
  107. package/dist/recording-extensions.d.ts +62 -0
  108. package/dist/recording-extensions.d.ts.map +1 -0
  109. package/dist/recording-extensions.js +159 -0
  110. package/dist/recording-extensions.js.map +1 -0
  111. package/dist/release-extensions.d.ts +93 -0
  112. package/dist/release-extensions.d.ts.map +1 -0
  113. package/dist/release-extensions.js +190 -0
  114. package/dist/release-extensions.js.map +1 -0
  115. package/dist/release-graph.d.ts +65 -0
  116. package/dist/release-graph.d.ts.map +1 -0
  117. package/dist/release-graph.js +136 -0
  118. package/dist/release-graph.js.map +1 -0
  119. package/dist/share-template.d.ts +3 -0
  120. package/dist/share-template.d.ts.map +1 -0
  121. package/dist/share-template.js +46 -0
  122. package/dist/share-template.js.map +1 -0
  123. package/dist/share.d.ts +67 -0
  124. package/dist/share.d.ts.map +1 -0
  125. package/dist/share.js +157 -0
  126. package/dist/share.js.map +1 -0
  127. package/dist/transactions.d.ts +216 -0
  128. package/dist/transactions.d.ts.map +1 -0
  129. package/dist/transactions.js +314 -0
  130. package/dist/transactions.js.map +1 -0
  131. package/dist/vault.d.ts +364 -0
  132. package/dist/vault.d.ts.map +1 -0
  133. package/dist/vault.js +507 -0
  134. package/dist/vault.js.map +1 -0
  135. package/package.json +145 -5
  136. package/src/auth.ts +275 -0
  137. package/src/catalog.ts +189 -0
  138. package/src/client.ts +1320 -0
  139. package/src/contracts.ts +54 -0
  140. package/src/cover.ts +240 -0
  141. package/src/credits.ts +906 -0
  142. package/src/deployments.ts +357 -0
  143. package/src/execute.ts +52 -0
  144. package/src/index.ts +69 -0
  145. package/src/internal.ts +46 -0
  146. package/src/mix.ts +910 -0
  147. package/src/pressing.ts +705 -0
  148. package/src/publication.ts +1214 -0
  149. package/src/queries.ts +9 -0
  150. package/src/read/artist.ts +118 -0
  151. package/src/read/catalog.ts +668 -0
  152. package/src/read/client.ts +87 -0
  153. package/src/read/config.ts +138 -0
  154. package/src/read/genres.ts +37 -0
  155. package/src/read/index.ts +85 -0
  156. package/src/read/internal/scalars.ts +59 -0
  157. package/src/read/internal/walrus.ts +42 -0
  158. package/src/read/receipts.ts +476 -0
  159. package/src/read/types.ts +415 -0
  160. package/src/read/wallet.ts +687 -0
  161. package/src/read/works.ts +297 -0
  162. package/src/recording-extensions.ts +256 -0
  163. package/src/release-extensions.ts +311 -0
  164. package/src/release-graph.ts +219 -0
  165. package/src/share-template.ts +55 -0
  166. package/src/share.ts +261 -0
  167. package/src/transactions.ts +542 -0
  168. package/src/vault.ts +1009 -0
@@ -0,0 +1,87 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // The one client every read in this SDK goes through.
5
+ //
6
+ // Two transports, because Sui splits the job:
7
+ // core (gRPC) the data plane — objects by id, objects by owner, balances,
8
+ // transactions. Everything cheap and current.
9
+ // graphql the two questions gRPC cannot answer: "which object has type X"
10
+ // (share type → work id, for the studio catalog and the receipt's
11
+ // royalty hop) and "what did this pruned transaction do".
12
+ //
13
+ // It also carries the resolved `MisoConfig`, so a read function takes ONE argument
14
+ // and never has a package id threaded through its signature.
15
+ //
16
+ // Party now shares the same network SDK registration and deployment as protocol
17
+ // core, so every read hangs off one `sui.miso` namespace.
18
+
19
+ import { SuiGrpcClient } from "@mysten/sui/grpc";
20
+ import { SuiGraphQLClient } from "@mysten/sui/graphql";
21
+ import { miso, type MisoProtocolClient } from "@misofm/protocol/client";
22
+ import { misoConfig, networkFrom, type MisoConfig, type MisoConfigOverrides, type Network } from "./config.ts";
23
+
24
+ function definedOverrides<T extends object>(value: T): Partial<T> {
25
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined)) as Partial<T>;
26
+ }
27
+
28
+ /**
29
+ * The structural slice of a Sui client the protocol SDK's read helpers want. They
30
+ * declare `ClientWithCoreApi` against their own @mysten/sui; this alias names the
31
+ * same shape from our side so the one cast in `createMisoClient` is explicit
32
+ * rather than an `any` smeared across the codebase.
33
+ */
34
+ export type ProtocolClient = Parameters<typeof import("@misofm/protocol").getReleaseById>[0];
35
+
36
+ /** A GraphQL client in the shape the protocol SDK's type-discovery queries want. */
37
+ export type ProtocolGraphQLClient = SuiGraphQLClient;
38
+
39
+ export interface MisoClient {
40
+ config: MisoConfig;
41
+ /** gRPC data plane, including Party at `sui.miso.party`. */
42
+ sui: SuiGrpcClient & { miso: MisoProtocolClient };
43
+ /** The same client, typed for the protocol SDK's read helpers. */
44
+ protocol: ProtocolClient;
45
+ /** GraphQL RPC, typed for the protocol SDK's type-discovery queries. */
46
+ graphql: ProtocolGraphQLClient;
47
+ /** The raw GraphQL client, for this SDK's own queries (the pruned-transaction read). */
48
+ graphqlRaw: SuiGraphQLClient;
49
+ }
50
+
51
+ export interface CreateMisoClientOptions extends MisoConfigOverrides {
52
+ /** "testnet" | "mainnet". A bare string (e.g. a Worker's `NETWORK` var) is accepted. */
53
+ network?: Network | string;
54
+ /** Complete verified configuration for a custom or unbundled deployment. */
55
+ config?: MisoConfig;
56
+ }
57
+
58
+ /**
59
+ * Build the client from a bundled network or a complete verified custom config.
60
+ */
61
+ export function createMisoClient(options: CreateMisoClientOptions = {}): MisoClient {
62
+ const { network, config: providedConfig, ...overrides } = options;
63
+ const requestedNetwork = networkFrom(network);
64
+ // A caller-supplied verified deployment may still override transport URLs or
65
+ // the discover shelf; undefined fields never erase verified config values.
66
+ const config = providedConfig
67
+ ? { ...providedConfig, ...definedOverrides(overrides) }
68
+ : misoConfig(requestedNetwork, overrides);
69
+ if (network !== undefined && config.network !== requestedNetwork) {
70
+ throw new Error(
71
+ `@misofm/platform/read: provided config is for ${config.network}, not ${requestedNetwork}.`,
72
+ );
73
+ }
74
+
75
+ const grpc = new SuiGrpcClient({ baseUrl: config.grpcUrl, network: config.network });
76
+ const graphqlRaw = new SuiGraphQLClient({ url: config.graphqlUrl, network: config.network });
77
+
78
+ const sui = grpc.$extend(miso({ deployment: config.deployment }));
79
+
80
+ return {
81
+ config,
82
+ sui,
83
+ protocol: sui as unknown as ProtocolClient,
84
+ graphql: graphqlRaw as unknown as ProtocolGraphQLClient,
85
+ graphqlRaw,
86
+ };
87
+ }
@@ -0,0 +1,138 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // Per-network on-chain identity: which packages the reads address, which objects
5
+ // they read, and which endpoints they read through. Every id that used to be a
6
+ // hard-coded constant inside miso-app (`lib/party.ts`, `lib/release.ts`,
7
+ // `lib/money.ts`, `lib/pressing.ts`) lives here instead, so a redeploy is a change
8
+ // in ONE file that every surface picks up.
9
+ //
10
+ // Testnet values are derived from the same verified deployment record exported
11
+ // by the platform SDK. Mainnet remains deliberately unavailable until a complete
12
+ // deployment is bundled for it.
13
+
14
+ import type { MisoDeployment } from "@misofm/protocol/deployments";
15
+ import { getMisoPlatformDeployment, type RecordSalesDeployment } from "../deployments.ts";
16
+
17
+ export type Network = "testnet" | "mainnet";
18
+
19
+ /** Missing defaults to Testnet for local development; invalid values fail closed. */
20
+ export function networkFrom(value: string | undefined): Network {
21
+ if (value === undefined || value === "testnet") return "testnet";
22
+ if (value === "mainnet") return "mainnet";
23
+ throw new Error(`@misofm/platform/read: unsupported network "${value}".`);
24
+ }
25
+
26
+ /** Package ids for the miso protocol core and the extensions the read layer touches. */
27
+ export interface ProtocolIds {
28
+ /** `vault` — shared custody for protocol admin capabilities. */
29
+ vault: string;
30
+ /** `release_cover_art` — the release cover extension. */
31
+ releaseCoverArt: string;
32
+ /** `release_kind` — the Release's optional self-declared kind. */
33
+ releaseKind: string;
34
+ /** `recording_master_reference` — optional Walrus master pointers. */
35
+ recordingMasterReference: string;
36
+ /** `release_mix_reference` — optional per-track delivery descriptor pointers. */
37
+ releaseMixReference?: string;
38
+ /** `composition_credits` / `recording_credits` / `release_credits` extensions. */
39
+ compositionCredits: string;
40
+ recordingCredits: string;
41
+ releaseCredits: string;
42
+ /** `miso_credit` — the shared `Credit<Role>` value type credits are built from. */
43
+ credit: string;
44
+ }
45
+
46
+ /** The currency the app prices records in, and where test dollars come from. */
47
+ export interface MoneyIds {
48
+ /** Coin type balances, listings, and purchases are denominated in. */
49
+ usdCoinType: string;
50
+ usdDecimals: number;
51
+ }
52
+
53
+ export interface MisoConfig {
54
+ network: Network;
55
+ /** Complete package set used by the integrated `client.miso` SDK. */
56
+ deployment: MisoDeployment;
57
+ protocol: ProtocolIds;
58
+ /** Final Record/Record Shop deployment, or an explicit unavailable legacy state. */
59
+ recordSales: RecordSalesDeployment;
60
+ money: MoneyIds;
61
+ /** Sui gRPC-web endpoint the data plane reads through. */
62
+ grpcUrl: string;
63
+ /**
64
+ * Sui GraphQL RPC endpoint. Needed for the two things gRPC cannot answer:
65
+ * "which object has type X" (share type → work id) and reading a transaction
66
+ * the fullnode has already pruned.
67
+ */
68
+ graphqlUrl: string;
69
+ /** Walrus aggregator serving cover art and party media for this network. */
70
+ walrusAggregatorUrl: string;
71
+ /**
72
+ * Public origin of the Miso API, used to build avatar URLs (`/media/avatar/…`).
73
+ * Avatars are an R2-backed API lane, not on-chain data, so the SDK needs the
74
+ * public host to hand back a URL a browser can actually fetch.
75
+ */
76
+ apiBaseUrl: string;
77
+ /** Explicit currency offers on the Discover shelf, in display order. */
78
+ discoverSales: readonly DiscoverSale[];
79
+ }
80
+
81
+ /** One release/currency pair to resolve by Pressing and Listing derived address. */
82
+ export interface DiscoverSale {
83
+ releaseId: string;
84
+ edition: number;
85
+ currencyType: string;
86
+ }
87
+
88
+ /** Fields a deployment may override without forking the whole config (endpoints, shelf). */
89
+ export type MisoConfigOverrides = Partial<
90
+ Pick<MisoConfig, "grpcUrl" | "graphqlUrl" | "walrusAggregatorUrl" | "apiBaseUrl" | "discoverSales">
91
+ >;
92
+
93
+ /** The config for `network`, derived from this SDK's verified deployment map. */
94
+ export function misoConfig(network: Network, overrides: MisoConfigOverrides = {}): MisoConfig {
95
+ const platform = getMisoPlatformDeployment(network);
96
+ const vaultPackageId =
97
+ platform.operations.status === "available"
98
+ ? platform.operations.vault.packageId
99
+ : platform.operations.legacy?.vaultPackageId;
100
+ if (!vaultPackageId) {
101
+ throw new Error(
102
+ `@misofm/platform/read: no current or legacy Vault type metadata for "${network}".`,
103
+ );
104
+ }
105
+ const config: MisoConfig = {
106
+ network,
107
+ deployment: platform.protocol,
108
+ recordSales: platform.recordSales,
109
+ protocol: {
110
+ // Read-only legacy type discovery does not make this package an
111
+ // executable operations ABI; client call surfaces remain fail closed.
112
+ vault: vaultPackageId,
113
+ releaseCoverArt: platform.packages.releaseCoverArt,
114
+ releaseKind: platform.packages.releaseKind,
115
+ recordingMasterReference: platform.packages.recordingMasterReference,
116
+ compositionCredits: platform.packages.compositionCredits,
117
+ recordingCredits: platform.packages.recordingCredits,
118
+ releaseCredits: platform.packages.releaseCredits,
119
+ credit: platform.packages.credit,
120
+ },
121
+ money: {
122
+ usdCoinType:
123
+ "0x77774cb7b8cb5622b4ef2658101bf5f1e965418297fe874b683df8f760b6e749::fakeusd::FakeUsd",
124
+ usdDecimals: 6,
125
+ },
126
+ grpcUrl: "https://fullnode.testnet.sui.io",
127
+ graphqlUrl: "https://graphql.testnet.sui.io/graphql",
128
+ walrusAggregatorUrl: "https://aggregator.walrus-testnet.walrus.space",
129
+ apiBaseUrl: "https://api.testnet.miso.fm",
130
+ discoverSales: [],
131
+ };
132
+ return { ...config, ...stripUndefined(overrides) };
133
+ }
134
+
135
+ /** `{ a: undefined }` must not clobber a real default when spread. */
136
+ function stripUndefined<T extends object>(o: T): Partial<T> {
137
+ return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined)) as Partial<T>;
138
+ }
@@ -0,0 +1,37 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // Genre name resolution. `party.getGenres` returns `Genre` OBJECT IDS; each Genre
5
+ // object carries a screaming-snake name ("HIP_HOP"). There is no id→name table
6
+ // anywhere off-chain, so the names are read from the objects and humanized.
7
+
8
+ import type { MisoClient } from "./client.ts";
9
+
10
+ /** "HIP_HOP" → "Hip Hop". */
11
+ function humanize(name: string): string {
12
+ return name
13
+ .split("_")
14
+ .filter(Boolean)
15
+ .map((w) => w.charAt(0) + w.slice(1).toLowerCase())
16
+ .join(" ");
17
+ }
18
+
19
+ /**
20
+ * Resolve `Genre` object ids to display names. Best-effort: an id that fails to
21
+ * read is dropped rather than failing the artist page around it.
22
+ */
23
+ export async function resolveGenreNames(client: MisoClient, ids: string[]): Promise<string[]> {
24
+ if (ids.length === 0) return [];
25
+ try {
26
+ const { objects } = await client.protocol.core.getObjects({ objectIds: ids, include: { json: true } });
27
+ const out: string[] = [];
28
+ for (const o of objects) {
29
+ if (o instanceof Error) continue;
30
+ const name = (o.json as { name?: unknown } | null)?.name;
31
+ if (typeof name === "string" && name) out.push(humanize(name));
32
+ }
33
+ return out;
34
+ } catch {
35
+ return [];
36
+ }
37
+ }
@@ -0,0 +1,85 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // @misofm/platform/read — Miso's high-level platform read surface.
5
+ //
6
+ // One place that knows how to turn Sui objects into the things Miso talks about:
7
+ // a pressing, a release, an artist, a library, a receipt. It composes
8
+ // @misofm/protocol, owns the per-network id manifest, and returns view types that
9
+ // survive JSON.
10
+ //
11
+ // Browser- and server-compatible. The HTTP API is a thin cached transport over
12
+ // this same surface; direct clients can use it without going through the API.
13
+ //
14
+ // const miso = createMisoClient({ network: "testnet" })
15
+ // const pressing = await getPressingDetail(miso, pressingId)
16
+
17
+ export { createMisoClient } from "./client.ts";
18
+ export type { MisoClient, CreateMisoClientOptions } from "./client.ts";
19
+
20
+ export { misoConfig, networkFrom } from "./config.ts";
21
+ export type {
22
+ MisoConfig,
23
+ MisoConfigOverrides,
24
+ DiscoverSale,
25
+ MoneyIds,
26
+ Network,
27
+ ProtocolIds,
28
+ } from "./config.ts";
29
+
30
+ export {
31
+ currencyInfo,
32
+ getDiscoverShelf,
33
+ getListingView,
34
+ getPressingDetail,
35
+ getPressingView,
36
+ getPressingSaleDetail,
37
+ getPressingPreview,
38
+ getRecordAlbum,
39
+ getReleaseDetail,
40
+ getReleaseResources,
41
+ getTrackCredits,
42
+ getSaleDetail,
43
+ primaryArtistNames,
44
+ readReleaseCover,
45
+ } from "./catalog.ts";
46
+ export type {
47
+ GetRecordAlbumOptions,
48
+ GetReleaseOptions,
49
+ RecordAlbumInclude,
50
+ ReleaseInclude,
51
+ ReleaseResourceInclude,
52
+ } from "./catalog.ts";
53
+ export type { ReleaseResources } from "./catalog.ts";
54
+
55
+ export {
56
+ getArtistProfile,
57
+ getPartySummaries,
58
+ partyAvatarUrl,
59
+ } from "./artist.ts";
60
+ export type { ArtistInclude, GetArtistOptions } from "./artist.ts";
61
+
62
+ export { resolveGenreNames } from "./genres.ts";
63
+
64
+ export {
65
+ getBalance,
66
+ getOwnedParties,
67
+ getPendingMemberships,
68
+ getOwnedRecords,
69
+ getOwnedWorks,
70
+ getWorkByCap,
71
+ ownsParty,
72
+ ownsRecord,
73
+ } from "./wallet.ts";
74
+
75
+ export {
76
+ breakdown,
77
+ findRecordSale,
78
+ findRecordSales,
79
+ getPurchaseReceipt,
80
+ getPurchaseReceipts,
81
+ isRecordSoldEventType,
82
+ recordSoldCurrencyType,
83
+ } from "./receipts.ts";
84
+
85
+ export type * from "./types.ts";
@@ -0,0 +1,59 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // The bigint→JSON boundary. Every u64/u128 the protocol SDKs hand back arrives as
5
+ // a `bigint`, which `JSON.stringify` throws on; these convert once, here, so no
6
+ // view type can carry one out of the SDK (see the header of ../types.ts).
7
+
8
+ /** A u64/u128 as it may arrive off the wire, in BCS, or from a JSON projection. */
9
+ export type NumericLike = bigint | number | string | null | undefined;
10
+
11
+ /**
12
+ * Base-unit scalar → decimal string. Returns `"0"` for anything unreadable, which
13
+ * is the honest projection of "the chain gave us no number" for quantities and
14
+ * amounts. Use {@link u64OrNull} where absent must stay distinguishable from zero.
15
+ */
16
+ export function u64(v: NumericLike): string {
17
+ return u64OrNull(v) ?? "0";
18
+ }
19
+
20
+ /** Base-unit scalar → decimal string, or `null` when absent/unparseable. */
21
+ export function u64OrNull(v: NumericLike): string | null {
22
+ if (v == null) return null;
23
+ if (typeof v === "bigint") return v >= 0n ? v.toString() : null;
24
+ if (typeof v === "number") {
25
+ return Number.isSafeInteger(v) && v >= 0 ? BigInt(v).toString() : null;
26
+ }
27
+ const s = v.trim();
28
+ return /^\d+$/.test(s) ? BigInt(s).toString() : null;
29
+ }
30
+
31
+ /**
32
+ * A millisecond timestamp → `number`. Milliseconds stay numbers (they are far
33
+ * inside Number.MAX_SAFE_INTEGER and `new Date()` wants one), unlike token
34
+ * amounts which must not lose precision.
35
+ */
36
+ export function msOrNull(v: NumericLike): number | null {
37
+ const s = u64OrNull(v);
38
+ if (s === null) return null;
39
+ const n = Number(s);
40
+ return Number.isSafeInteger(n) ? n : null;
41
+ }
42
+
43
+ /** As {@link msOrNull}, defaulting to `0` (the epoch) when absent. */
44
+ export function ms(v: NumericLike): number {
45
+ return msOrNull(v) ?? 0;
46
+ }
47
+
48
+ /** A plain integer field (bps, edition, counts) → `number`, defaulting to `0`. */
49
+ export function int(v: NumericLike): number {
50
+ if (typeof v === "number" && Number.isFinite(v)) return Math.trunc(v);
51
+ if (typeof v === "bigint") return Number(v);
52
+ if (typeof v === "string" && /^-?\d+$/.test(v.trim())) return Number(v.trim());
53
+ return 0;
54
+ }
55
+
56
+ /** Integer comparison over two decimal strings — `a >= b` without going through Number. */
57
+ export function gte(a: string, b: string): boolean {
58
+ return BigInt(a) >= BigInt(b);
59
+ }
@@ -0,0 +1,42 @@
1
+ // Copyright (c) Miso Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { bcs } from "@mysten/sui/bcs";
5
+ import { toBase64 } from "@mysten/sui/utils";
6
+ import { walrusBlobIdFromU256 } from "../../mix.ts";
7
+
8
+ const u256 = bcs.u256();
9
+
10
+ function toBase64Url(bytes: Uint8Array): string {
11
+ return toBase64(bytes).replace(/=*$/, "").replaceAll("+", "-").replaceAll("/", "_");
12
+ }
13
+
14
+ export function u256ToB64Url(value: bigint | string): string {
15
+ return walrusBlobIdFromU256(value);
16
+ }
17
+
18
+ /** Build a blob URL with Walrus's non-strict default made explicit. */
19
+ export function walrusBlobReadUrl(
20
+ aggregator: string,
21
+ blobId: bigint | string,
22
+ ): string {
23
+ const base = aggregator.replace(/\/$/, "");
24
+ return `${base}/v1/blobs/${u256ToB64Url(blobId)}?strict_consistency_check=false`;
25
+ }
26
+
27
+ /** Build Walrus's 37-byte quilt-patch id. All fields use BCS little-endian. */
28
+ export function quiltPatchId(
29
+ quiltId: bigint | string,
30
+ version: number,
31
+ startIndex: number,
32
+ endIndex: number,
33
+ ): string {
34
+ const bytes = new Uint8Array(37);
35
+ bytes.set(u256.serialize(BigInt(quiltId)).toBytes(), 0);
36
+ bytes[32] = version;
37
+ bytes[33] = startIndex & 0xff;
38
+ bytes[34] = (startIndex >> 8) & 0xff;
39
+ bytes[35] = endIndex & 0xff;
40
+ bytes[36] = (endIndex >> 8) & 0xff;
41
+ return toBase64Url(bytes);
42
+ }