@bananapus/nana-sdk-core 1.2.0 → 1.4.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 (167) hide show
  1. package/dist/cjs/utils/hook.d.ts +15 -0
  2. package/dist/cjs/utils/hook.d.ts.map +1 -1
  3. package/dist/cjs/utils/hook.js +20 -0
  4. package/dist/cjs/utils/hook.js.map +1 -1
  5. package/dist/cjs/utils/index.d.ts +1 -0
  6. package/dist/cjs/utils/index.d.ts.map +1 -1
  7. package/dist/cjs/utils/index.js +1 -0
  8. package/dist/cjs/utils/index.js.map +1 -1
  9. package/dist/cjs/utils/ipfs.d.ts +33 -1
  10. package/dist/cjs/utils/ipfs.d.ts.map +1 -1
  11. package/dist/cjs/utils/ipfs.js +212 -8
  12. package/dist/cjs/utils/ipfs.js.map +1 -1
  13. package/dist/cjs/utils/ipfs.test.js +34 -0
  14. package/dist/cjs/utils/ipfs.test.js.map +1 -1
  15. package/dist/cjs/v6/cashOut.d.ts +23 -0
  16. package/dist/cjs/v6/cashOut.d.ts.map +1 -1
  17. package/dist/cjs/v6/cashOut.js +35 -0
  18. package/dist/cjs/v6/cashOut.js.map +1 -1
  19. package/dist/cjs/v6/cashOut.test.js +20 -0
  20. package/dist/cjs/v6/cashOut.test.js.map +1 -1
  21. package/dist/cjs/v6/index.d.ts +3 -0
  22. package/dist/cjs/v6/index.d.ts.map +1 -1
  23. package/dist/cjs/v6/index.js +3 -0
  24. package/dist/cjs/v6/index.js.map +1 -1
  25. package/dist/cjs/v6/launch.d.ts +23 -2
  26. package/dist/cjs/v6/launch.d.ts.map +1 -1
  27. package/dist/cjs/v6/launch.js +40 -1
  28. package/dist/cjs/v6/launch.js.map +1 -1
  29. package/dist/cjs/v6/launch.test.js +25 -0
  30. package/dist/cjs/v6/launch.test.js.map +1 -1
  31. package/dist/cjs/v6/nft.d.ts +165 -0
  32. package/dist/cjs/v6/nft.d.ts.map +1 -0
  33. package/dist/cjs/v6/nft.js +356 -0
  34. package/dist/cjs/v6/nft.js.map +1 -0
  35. package/dist/cjs/v6/nft.test.d.ts +2 -0
  36. package/dist/cjs/v6/nft.test.d.ts.map +1 -0
  37. package/dist/cjs/v6/nft.test.js +279 -0
  38. package/dist/cjs/v6/nft.test.js.map +1 -0
  39. package/dist/cjs/v6/pay.d.ts +13 -5
  40. package/dist/cjs/v6/pay.d.ts.map +1 -1
  41. package/dist/cjs/v6/pay.js +15 -18
  42. package/dist/cjs/v6/pay.js.map +1 -1
  43. package/dist/cjs/v6/pay.test.js +7 -0
  44. package/dist/cjs/v6/pay.test.js.map +1 -1
  45. package/dist/cjs/v6/permissions.d.ts +21 -0
  46. package/dist/cjs/v6/permissions.d.ts.map +1 -1
  47. package/dist/cjs/v6/permissions.js +44 -1
  48. package/dist/cjs/v6/permissions.js.map +1 -1
  49. package/dist/cjs/v6/permissions.test.js +25 -0
  50. package/dist/cjs/v6/permissions.test.js.map +1 -1
  51. package/dist/cjs/v6/projectPayers.d.ts +178 -0
  52. package/dist/cjs/v6/projectPayers.d.ts.map +1 -0
  53. package/dist/cjs/v6/projectPayers.js +108 -0
  54. package/dist/cjs/v6/projectPayers.js.map +1 -0
  55. package/dist/cjs/v6/projectPayers.test.d.ts +2 -0
  56. package/dist/cjs/v6/projectPayers.test.d.ts.map +1 -0
  57. package/dist/cjs/v6/projectPayers.test.js +85 -0
  58. package/dist/cjs/v6/projectPayers.test.js.map +1 -0
  59. package/dist/cjs/v6/revnets.d.ts +3 -2
  60. package/dist/cjs/v6/revnets.d.ts.map +1 -1
  61. package/dist/cjs/v6/revnets.js +3 -2
  62. package/dist/cjs/v6/revnets.js.map +1 -1
  63. package/dist/cjs/v6/rulesets.d.ts +42 -0
  64. package/dist/cjs/v6/rulesets.d.ts.map +1 -1
  65. package/dist/cjs/v6/rulesets.js +87 -0
  66. package/dist/cjs/v6/rulesets.js.map +1 -1
  67. package/dist/cjs/v6/rulesets.test.js +54 -0
  68. package/dist/cjs/v6/rulesets.test.js.map +1 -1
  69. package/dist/cjs/v6/suckers.d.ts +740 -2
  70. package/dist/cjs/v6/suckers.d.ts.map +1 -1
  71. package/dist/cjs/v6/suckers.js +647 -8
  72. package/dist/cjs/v6/suckers.js.map +1 -1
  73. package/dist/cjs/v6/suckers.test.js +228 -0
  74. package/dist/cjs/v6/suckers.test.js.map +1 -1
  75. package/dist/cjs/v6/uniswapV4.d.ts +82 -0
  76. package/dist/cjs/v6/uniswapV4.d.ts.map +1 -0
  77. package/dist/cjs/v6/uniswapV4.js +336 -0
  78. package/dist/cjs/v6/uniswapV4.js.map +1 -0
  79. package/dist/cjs/v6/uniswapV4.test.d.ts +2 -0
  80. package/dist/cjs/v6/uniswapV4.test.d.ts.map +1 -0
  81. package/dist/cjs/v6/uniswapV4.test.js +128 -0
  82. package/dist/cjs/v6/uniswapV4.test.js.map +1 -0
  83. package/dist/esm/utils/hook.d.ts +15 -0
  84. package/dist/esm/utils/hook.d.ts.map +1 -1
  85. package/dist/esm/utils/hook.js +20 -1
  86. package/dist/esm/utils/hook.js.map +1 -1
  87. package/dist/esm/utils/index.d.ts +1 -0
  88. package/dist/esm/utils/index.d.ts.map +1 -1
  89. package/dist/esm/utils/index.js +1 -0
  90. package/dist/esm/utils/index.js.map +1 -1
  91. package/dist/esm/utils/ipfs.d.ts +33 -1
  92. package/dist/esm/utils/ipfs.d.ts.map +1 -1
  93. package/dist/esm/utils/ipfs.js +204 -8
  94. package/dist/esm/utils/ipfs.js.map +1 -1
  95. package/dist/esm/utils/ipfs.test.js +35 -1
  96. package/dist/esm/utils/ipfs.test.js.map +1 -1
  97. package/dist/esm/v6/cashOut.d.ts +23 -0
  98. package/dist/esm/v6/cashOut.d.ts.map +1 -1
  99. package/dist/esm/v6/cashOut.js +34 -0
  100. package/dist/esm/v6/cashOut.js.map +1 -1
  101. package/dist/esm/v6/cashOut.test.js +22 -2
  102. package/dist/esm/v6/cashOut.test.js.map +1 -1
  103. package/dist/esm/v6/index.d.ts +3 -0
  104. package/dist/esm/v6/index.d.ts.map +1 -1
  105. package/dist/esm/v6/index.js +3 -0
  106. package/dist/esm/v6/index.js.map +1 -1
  107. package/dist/esm/v6/launch.d.ts +23 -2
  108. package/dist/esm/v6/launch.d.ts.map +1 -1
  109. package/dist/esm/v6/launch.js +39 -2
  110. package/dist/esm/v6/launch.js.map +1 -1
  111. package/dist/esm/v6/launch.test.js +27 -2
  112. package/dist/esm/v6/launch.test.js.map +1 -1
  113. package/dist/esm/v6/nft.d.ts +165 -0
  114. package/dist/esm/v6/nft.d.ts.map +1 -0
  115. package/dist/esm/v6/nft.js +342 -0
  116. package/dist/esm/v6/nft.js.map +1 -0
  117. package/dist/esm/v6/nft.test.d.ts +2 -0
  118. package/dist/esm/v6/nft.test.d.ts.map +1 -0
  119. package/dist/esm/v6/nft.test.js +277 -0
  120. package/dist/esm/v6/nft.test.js.map +1 -0
  121. package/dist/esm/v6/pay.d.ts +13 -5
  122. package/dist/esm/v6/pay.d.ts.map +1 -1
  123. package/dist/esm/v6/pay.js +17 -20
  124. package/dist/esm/v6/pay.js.map +1 -1
  125. package/dist/esm/v6/pay.test.js +7 -0
  126. package/dist/esm/v6/pay.test.js.map +1 -1
  127. package/dist/esm/v6/permissions.d.ts +21 -0
  128. package/dist/esm/v6/permissions.d.ts.map +1 -1
  129. package/dist/esm/v6/permissions.js +40 -0
  130. package/dist/esm/v6/permissions.js.map +1 -1
  131. package/dist/esm/v6/permissions.test.js +26 -1
  132. package/dist/esm/v6/permissions.test.js.map +1 -1
  133. package/dist/esm/v6/projectPayers.d.ts +178 -0
  134. package/dist/esm/v6/projectPayers.d.ts.map +1 -0
  135. package/dist/esm/v6/projectPayers.js +101 -0
  136. package/dist/esm/v6/projectPayers.js.map +1 -0
  137. package/dist/esm/v6/projectPayers.test.d.ts +2 -0
  138. package/dist/esm/v6/projectPayers.test.d.ts.map +1 -0
  139. package/dist/esm/v6/projectPayers.test.js +83 -0
  140. package/dist/esm/v6/projectPayers.test.js.map +1 -0
  141. package/dist/esm/v6/revnets.d.ts +3 -2
  142. package/dist/esm/v6/revnets.d.ts.map +1 -1
  143. package/dist/esm/v6/revnets.js +3 -2
  144. package/dist/esm/v6/revnets.js.map +1 -1
  145. package/dist/esm/v6/rulesets.d.ts +42 -0
  146. package/dist/esm/v6/rulesets.d.ts.map +1 -1
  147. package/dist/esm/v6/rulesets.js +83 -0
  148. package/dist/esm/v6/rulesets.js.map +1 -1
  149. package/dist/esm/v6/rulesets.test.js +55 -1
  150. package/dist/esm/v6/rulesets.test.js.map +1 -1
  151. package/dist/esm/v6/suckers.d.ts +740 -2
  152. package/dist/esm/v6/suckers.d.ts.map +1 -1
  153. package/dist/esm/v6/suckers.js +630 -8
  154. package/dist/esm/v6/suckers.js.map +1 -1
  155. package/dist/esm/v6/suckers.test.js +230 -2
  156. package/dist/esm/v6/suckers.test.js.map +1 -1
  157. package/dist/esm/v6/uniswapV4.d.ts +82 -0
  158. package/dist/esm/v6/uniswapV4.d.ts.map +1 -0
  159. package/dist/esm/v6/uniswapV4.js +318 -0
  160. package/dist/esm/v6/uniswapV4.js.map +1 -0
  161. package/dist/esm/v6/uniswapV4.test.d.ts +2 -0
  162. package/dist/esm/v6/uniswapV4.test.d.ts.map +1 -0
  163. package/dist/esm/v6/uniswapV4.test.js +126 -0
  164. package/dist/esm/v6/uniswapV4.test.js.map +1 -0
  165. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  166. package/dist/tsconfig.tsbuildinfo +1 -1
  167. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { zeroAddress } from "viem";
1
+ import { decodeEventLog, isAddressEqual, zeroAddress, } from "viem";
2
2
  import { NATIVE_TOKEN, NATIVE_TOKEN_DECIMALS } from "../constants.js";
3
3
  import { jbControllerAbi, jbProjectsAbi } from "../generated/juicebox.js";
4
4
  import { BASE_CURRENCY_ETH, tokenCurrencyId } from "./currency.js";
@@ -120,7 +120,8 @@ export function buildRulesetMetadata(overrides) {
120
120
  * shared timestamp so every chain's ruleset is byte-identical.
121
121
  * @param args.duration Seconds the ruleset is locked for. 0 = no duration.
122
122
  * @param args.weight Tokens issued per unit of `baseCurrency` paid, as an
123
- * 18-decimal fixed point (uint112).
123
+ * 18-decimal fixed point (uint112). Later configurations can use the exported
124
+ * `RULESET_WEIGHT_INHERIT` sentinel (1n); zero means genuine zero issuance.
124
125
  * @param args.weightCutPercent Issuance cut applied each cycle, out of 1e9.
125
126
  * @param args.approvalHook A deadline contract queued rulesets must clear.
126
127
  * @param args.metadata Ruleset metadata; see {@link buildRulesetMetadata}.
@@ -173,4 +174,40 @@ export function buildLaunchProjectTx(args) {
173
174
  value: args.creationFee,
174
175
  };
175
176
  }
177
+ /**
178
+ * Decode a v6 `LaunchProject` log emitted by the canonical controller.
179
+ *
180
+ * Checking the emitter matters: unrelated contracts can emit an event with the
181
+ * same signature, and ERC-721 `Transfer` logs in a complex receipt are not a
182
+ * reliable way to identify which mint was the Juicebox project NFT.
183
+ */
184
+ export function decodeLaunchProjectId(log, { chainId }) {
185
+ if (!isAddressEqual(log.address, v6Address("JBController", chainId))) {
186
+ return null;
187
+ }
188
+ try {
189
+ const decoded = decodeEventLog({
190
+ abi: jbControllerAbi,
191
+ eventName: "LaunchProject",
192
+ data: log.data,
193
+ topics: log.topics,
194
+ strict: true,
195
+ });
196
+ return decoded.eventName === "LaunchProject"
197
+ ? decoded.args.projectId
198
+ : null;
199
+ }
200
+ catch {
201
+ return null;
202
+ }
203
+ }
204
+ /** Return the first canonical v6 project id found in a transaction's logs. */
205
+ export function projectIdFromLaunchLogs(logs, args) {
206
+ for (const log of logs) {
207
+ const projectId = decodeLaunchProjectId(log, args);
208
+ if (projectId !== null)
209
+ return projectId;
210
+ }
211
+ return null;
212
+ }
176
213
  //# sourceMappingURL=launch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../../src/v6/launch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../../src/v6/launch.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
- import { decodeFunctionData, encodeFunctionData, parseEther, zeroAddress, } from "viem";
1
+ import { encodeAbiParameters, encodeEventTopics, decodeFunctionData, encodeFunctionData, parseEther, zeroAddress, } from "viem";
2
2
  import { sepolia } from "viem/chains";
3
3
  import { describe, expect, test } from "vitest";
4
4
  import { NATIVE_TOKEN, USDC_ADDRESSES } from "../constants.js";
5
5
  import { jbControllerAbi } from "../generated/juicebox.js";
6
- import { buildAccountingContext, buildLaunchProjectTx, buildRulesetConfiguration, buildRulesetMetadata, buildTerminalConfigurations, getProjectCreationFee, } from "./launch.js";
6
+ import { buildAccountingContext, buildLaunchProjectTx, buildRulesetConfiguration, buildRulesetMetadata, buildTerminalConfigurations, decodeLaunchProjectId, getProjectCreationFee, projectIdFromLaunchLogs, } from "./launch.js";
7
7
  import { v6Address } from "./types.js";
8
8
  const OWNER = "0x000000000000000000000000000000000000dEaD";
9
9
  /** A stub PublicClient that records readContract calls. */
@@ -132,4 +132,29 @@ describe("getProjectCreationFee", () => {
132
132
  });
133
133
  });
134
134
  });
135
+ describe("launch receipt decoding", () => {
136
+ const launchLog = (address = v6Address("JBController", sepolia.id)) => ({
137
+ address,
138
+ topics: encodeEventTopics({
139
+ abi: jbControllerAbi,
140
+ eventName: "LaunchProject",
141
+ }),
142
+ data: encodeAbiParameters([
143
+ { type: "uint256" },
144
+ { type: "uint256" },
145
+ { type: "string" },
146
+ { type: "string" },
147
+ { type: "address" },
148
+ ], [12n, 42n, "ipfs://project", "launched", OWNER]),
149
+ });
150
+ test("decodes only the canonical controller's LaunchProject event", () => {
151
+ const log = launchLog();
152
+ expect(decodeLaunchProjectId(log, { chainId: sepolia.id })).toBe(42n);
153
+ expect(projectIdFromLaunchLogs([log], { chainId: sepolia.id })).toBe(42n);
154
+ expect(decodeLaunchProjectId(launchLog("0x1111111111111111111111111111111111111111"), { chainId: sepolia.id })).toBeNull();
155
+ });
156
+ test("returns null for malformed launch logs", () => {
157
+ expect(decodeLaunchProjectId({ ...launchLog(), data: "0x" }, { chainId: sepolia.id })).toBeNull();
158
+ });
159
+ });
135
160
  //# sourceMappingURL=launch.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"launch.test.js","sourceRoot":"","sources":["../../../src/v6/launch.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"launch.test.js","sourceRoot":"","sources":["../../../src/v6/launch.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ import { Address, Hex, PublicClient } from "viem";
2
+ import { JBChainId } from "../types.js";
3
+ /**
4
+ * App-level sentinel convention used by Juicebox 721 shops for effectively
5
+ * unlimited inventory.
6
+ */
7
+ export declare const TIER_UNLIMITED_SUPPLY = 999999999;
8
+ /**
9
+ * JB721TiersHookStore's `DISCOUNT_DENOMINATOR`: a tier's `discountPercent` is
10
+ * out of 200, so the shopper-facing "% off" is `discountPercent / 2`.
11
+ */
12
+ export declare const DISCOUNT_DENOMINATOR = 200n;
13
+ /** Canonical display fields understood across Juicebox 721 metadata writers. */
14
+ export interface TierMetadata {
15
+ name?: string;
16
+ description?: string;
17
+ image?: string;
18
+ animationUrl?: string;
19
+ mediaType?: string;
20
+ categoryName?: string;
21
+ }
22
+ /** Input accepted by {@link buildTierMetadata}. */
23
+ export interface TierMetadataInput {
24
+ name: string;
25
+ description?: string;
26
+ image?: string;
27
+ animationUrl?: string;
28
+ mediaType?: string;
29
+ categoryName?: string;
30
+ }
31
+ /** JSON shape written for a tier's pinned metadata. */
32
+ export interface StoredTierMetadata {
33
+ name: string;
34
+ description?: string;
35
+ image?: string;
36
+ animation_url?: string;
37
+ mediaType?: string;
38
+ categoryName?: string;
39
+ }
40
+ /**
41
+ * Parse a `data:application/json` tier URI. Invalid, non-object, and non-data
42
+ * values return `null` so callers can fall back to an IPFS metadata fetch.
43
+ */
44
+ export declare function parseTierMetadataJson(uri: string): Record<string, unknown> | null;
45
+ /**
46
+ * Normalize legacy and current tier metadata field names into one display
47
+ * shape. Only non-empty strings are returned.
48
+ */
49
+ export declare function pickTierMetadata(json: Record<string, unknown>): TierMetadata;
50
+ /** Whether a tier media value uses an immutable or browser-loadable URI form. */
51
+ export declare function isSafeTierMediaUri(value: string): boolean;
52
+ /** Build the canonical JSON object pinned for one tier. */
53
+ export declare function buildTierMetadata(input: TierMetadataInput): StoredTierMetadata;
54
+ /**
55
+ * Route IPFS media through a caller-selected gateway base URL. Data URIs and
56
+ * ordinary HTTP URLs pass through unchanged.
57
+ */
58
+ export declare function tierMediaAssetUrl(value: unknown, ipfsGatewayBaseUrl?: string): string | undefined;
59
+ /**
60
+ * Return a browser-renderable tier image URL. SVG data URIs that only wrap an
61
+ * external `<image href>` are unwrapped because browsers block that nested
62
+ * network request when the SVG itself is used as an `<img>` source.
63
+ */
64
+ export declare function tierMediaImageUrl(image: unknown, ipfsGatewayBaseUrl?: string): string | undefined;
65
+ /** Pick and resolve all tier metadata fields in one pass. */
66
+ export declare function tierDisplayMetadata(json: Record<string, unknown>, ipfsGatewayBaseUrl?: string): TierMetadata;
67
+ /** Stable first-seen category ids, with blank categories assigned to 0. */
68
+ export declare function buildTierCategoryPlan(tiers: ReadonlyArray<{
69
+ id: string;
70
+ categoryName?: string;
71
+ }>): {
72
+ categoryByTierId: Record<string, number>;
73
+ storeCategories: Record<string, string>;
74
+ };
75
+ /**
76
+ * A tier's effective (discounted) price, matching the on-chain formula in
77
+ * JB721TiersHookStore: `price - mulDiv(price, discountPercent, 200)` with
78
+ * integer-floor division.
79
+ *
80
+ * @param price The tier's full (undiscounted) price.
81
+ * @param discountPercent The tier's discount, out of 200 (`DISCOUNT_DENOMINATOR`).
82
+ */
83
+ export declare function effectiveTierPrice(price: bigint, discountPercent: number | bigint): bigint;
84
+ /**
85
+ * A single 721 tier a project sells.
86
+ */
87
+ export interface Project721Tier {
88
+ id: number;
89
+ /** Full (undiscounted) price in the shop's pricing terms. */
90
+ price: bigint;
91
+ remainingSupply: number;
92
+ initialSupply: number;
93
+ votingUnits: bigint;
94
+ reserveFrequency: number;
95
+ category: number;
96
+ /** Out of 200 — see {@link DISCOUNT_DENOMINATOR}. */
97
+ discountPercent: number;
98
+ encodedIpfsUri: Hex;
99
+ /** tokenUriResolver output (data URI), or "" if the hook has no resolver. */
100
+ resolvedUri: string;
101
+ }
102
+ /**
103
+ * A project's resolved 721 tiers hook ("shop"): the hook, its store, the
104
+ * metadata id target for pay/cash-out metadata, the pricing context, and tiers.
105
+ */
106
+ export interface Project721Shop {
107
+ /** The project's 721 tiers hook (the ruleset data hook / revnet hook). */
108
+ hook: Address;
109
+ /** The hook's tiers store. */
110
+ store: Address;
111
+ /**
112
+ * The hook's `METADATA_ID_TARGET` (shared implementation address). Pass this
113
+ * to {@link build721PayMetadata} / {@link build721CashOutMetadata}, never the
114
+ * `hook` address.
115
+ */
116
+ metadataIdTarget: Address;
117
+ /** The hook's pricing context: `currency` id and `decimals`. */
118
+ pricing: {
119
+ currency: number;
120
+ decimals: number;
121
+ };
122
+ tiers: Project721Tier[];
123
+ }
124
+ /**
125
+ * Read a JB721 hook's `METADATA_ID_TARGET` — the shared *implementation* address
126
+ * that pay/cash-out metadata ids must key off (a delegatecall clone reports the
127
+ * implementation, not itself). Falls back to `hook` if the read reverts (e.g. an
128
+ * older hook without the getter), which is only correct for a non-clone hook.
129
+ *
130
+ * @param client A viem public client on the given chain.
131
+ * @param args.hook The project's 721 tiers hook (clone) address.
132
+ */
133
+ export declare function get721MetadataIdTarget(client: PublicClient, { hook }: {
134
+ chainId: JBChainId;
135
+ hook: Address;
136
+ }): Promise<Address>;
137
+ /**
138
+ * Resolve a project's 721 tiers hook, its store, metadata id target, pricing
139
+ * context, and tiers in one call.
140
+ *
141
+ * Hook resolution mirrors the app patterns: revnets read
142
+ * `REVOwner.tiered721HookOf`; custom projects read the current ruleset's pay
143
+ * data hook — either the omnichain deployer (the real hook lives in
144
+ * `JBOmnichainDeployer.tiered721HookOf(projectId, rulesetId)`) or the 721 hook
145
+ * itself, verified by probing `STORE()` (a revert means it is not a 721 hook, so
146
+ * the project has no shop).
147
+ *
148
+ * Returns `null` when the project authoritatively has no 721 shop. RPC failures
149
+ * on authoritative reads throw, so a transient error surfaces as an error rather
150
+ * than a false "no shop".
151
+ *
152
+ * @param client A viem public client on the given chain.
153
+ * @param args.projectId The project (or revnet) id.
154
+ * @param args.isRevnet Whether the project is a revnet (changes hook resolution).
155
+ * @param args.tierLimit Max tiers to read from `tiersOf`. Defaults to 100.
156
+ * @param args.categories Tier categories to filter by (empty = all). Defaults to `[]`.
157
+ */
158
+ export declare function getProject721Shop(client: PublicClient, { chainId, projectId, isRevnet, tierLimit, categories, }: {
159
+ chainId: JBChainId;
160
+ projectId: bigint;
161
+ isRevnet: boolean;
162
+ tierLimit?: number;
163
+ categories?: bigint[];
164
+ }): Promise<Project721Shop | null>;
165
+ //# sourceMappingURL=nft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nft.d.ts","sourceRoot":"","sources":["../../../src/v6/nft.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,342 @@
1
+ import { zeroAddress } from "viem";
2
+ import { JBOmnichainDeployerContracts } from "../contracts.js";
3
+ import { jb721TiersHookAbi, jb721TiersHookStoreAbi, jbContractAddress, jbOmnichainDeployerAbi, } from "../generated/juicebox.js";
4
+ import { ipfsAssetPath, isIpfsCid } from "../utils/ipfs.js";
5
+ import { getRevnetTiered721Hook } from "./revnets.js";
6
+ import { getCurrentRuleset } from "./rulesets.js";
7
+ /**
8
+ * App-level sentinel convention used by Juicebox 721 shops for effectively
9
+ * unlimited inventory.
10
+ */
11
+ export const TIER_UNLIMITED_SUPPLY = 999_999_999;
12
+ /**
13
+ * JB721TiersHookStore's `DISCOUNT_DENOMINATOR`: a tier's `discountPercent` is
14
+ * out of 200, so the shopper-facing "% off" is `discountPercent / 2`.
15
+ */
16
+ export const DISCOUNT_DENOMINATOR = 200n;
17
+ function nonEmptyString(value) {
18
+ return typeof value === "string" && value ? value : undefined;
19
+ }
20
+ function decodeBase64Utf8(value) {
21
+ const binary = atob(value);
22
+ return new TextDecoder().decode(Uint8Array.from(binary, (character) => character.charCodeAt(0)));
23
+ }
24
+ /**
25
+ * Parse a `data:application/json` tier URI. Invalid, non-object, and non-data
26
+ * values return `null` so callers can fall back to an IPFS metadata fetch.
27
+ */
28
+ export function parseTierMetadataJson(uri) {
29
+ if (!uri.startsWith("data:application/json"))
30
+ return null;
31
+ const comma = uri.indexOf(",");
32
+ if (comma === -1)
33
+ return null;
34
+ try {
35
+ const header = uri.slice(0, comma);
36
+ const payload = uri.slice(comma + 1);
37
+ const json = JSON.parse(header.split(";").includes("base64")
38
+ ? decodeBase64Utf8(payload)
39
+ : decodeURIComponent(payload));
40
+ return json !== null && typeof json === "object" && !Array.isArray(json)
41
+ ? json
42
+ : null;
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ /**
49
+ * Normalize legacy and current tier metadata field names into one display
50
+ * shape. Only non-empty strings are returned.
51
+ */
52
+ export function pickTierMetadata(json) {
53
+ return {
54
+ name: nonEmptyString(json.productName) ?? nonEmptyString(json.name),
55
+ description: nonEmptyString(json.productDescription) ??
56
+ nonEmptyString(json.description),
57
+ image: nonEmptyString(json.image) ?? nonEmptyString(json.imageUri),
58
+ animationUrl: nonEmptyString(json.animation_url) ?? nonEmptyString(json.animationUrl),
59
+ mediaType: nonEmptyString(json.mediaType) ??
60
+ nonEmptyString(json.animationType) ??
61
+ nonEmptyString(json.mimeType),
62
+ categoryName: nonEmptyString(json.categoryName),
63
+ };
64
+ }
65
+ /** Whether a tier media value uses an immutable or browser-loadable URI form. */
66
+ export function isSafeTierMediaUri(value) {
67
+ const uri = value.trim();
68
+ if (!uri || /\s/.test(uri))
69
+ return false;
70
+ const ipfsPath = ipfsAssetPath(uri);
71
+ if (ipfsPath && isIpfsCid(ipfsPath.split("/")[0]))
72
+ return true;
73
+ if (isIpfsCid(uri.split("/")[0]))
74
+ return true;
75
+ if (/^data:(image|audio|video)\/[a-z0-9.+-]+[;,]/i.test(uri))
76
+ return true;
77
+ try {
78
+ const url = new URL(uri);
79
+ return url.protocol === "https:" || url.protocol === "http:";
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ /** Build the canonical JSON object pinned for one tier. */
86
+ export function buildTierMetadata(input) {
87
+ const name = input.name.trim();
88
+ if (!name)
89
+ throw new Error("Tier name is required.");
90
+ const optional = (value) => value?.trim() || undefined;
91
+ const image = optional(input.image);
92
+ const animationUrl = optional(input.animationUrl);
93
+ const mediaType = optional(input.mediaType);
94
+ if (image && !isSafeTierMediaUri(image)) {
95
+ throw new Error("Tier images must use IPFS, HTTP, HTTPS, or an image data URI.");
96
+ }
97
+ if (animationUrl && !isSafeTierMediaUri(animationUrl)) {
98
+ throw new Error("Tier animations must use IPFS, HTTP, HTTPS, or a media data URI.");
99
+ }
100
+ if (mediaType &&
101
+ !/^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/i.test(mediaType)) {
102
+ throw new Error("Tier media type must be a valid MIME type.");
103
+ }
104
+ return {
105
+ name,
106
+ description: optional(input.description),
107
+ image,
108
+ animation_url: animationUrl,
109
+ mediaType,
110
+ categoryName: optional(input.categoryName),
111
+ };
112
+ }
113
+ /**
114
+ * Route IPFS media through a caller-selected gateway base URL. Data URIs and
115
+ * ordinary HTTP URLs pass through unchanged.
116
+ */
117
+ export function tierMediaAssetUrl(value, ipfsGatewayBaseUrl = "https://ipfs.io/ipfs/") {
118
+ if (typeof value !== "string" || !value)
119
+ return undefined;
120
+ if (value.startsWith("data:"))
121
+ return value;
122
+ const trimmed = value.trim();
123
+ const path = ipfsAssetPath(trimmed) ??
124
+ (isIpfsCid(trimmed.split("/")[0]) ? trimmed : null);
125
+ if (!path)
126
+ return value;
127
+ return `${ipfsGatewayBaseUrl.replace(/\/?$/, "/")}${path}`;
128
+ }
129
+ function svgDataUriMarkup(uri) {
130
+ const match = /^data:image\/svg\+xml([^,]*),([\s\S]*)$/.exec(uri);
131
+ if (!match)
132
+ return null;
133
+ try {
134
+ return match[1].split(";").includes("base64")
135
+ ? decodeBase64Utf8(match[2])
136
+ : decodeURIComponent(match[2]);
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ }
142
+ /**
143
+ * Return a browser-renderable tier image URL. SVG data URIs that only wrap an
144
+ * external `<image href>` are unwrapped because browsers block that nested
145
+ * network request when the SVG itself is used as an `<img>` source.
146
+ */
147
+ export function tierMediaImageUrl(image, ipfsGatewayBaseUrl) {
148
+ if (typeof image !== "string" || !image)
149
+ return undefined;
150
+ const markup = svgDataUriMarkup(image);
151
+ if (markup) {
152
+ const href = /<image[^>]+href=["']([^"']+)["']/.exec(markup)?.[1];
153
+ if (href && !href.startsWith("data:")) {
154
+ return tierMediaAssetUrl(href, ipfsGatewayBaseUrl);
155
+ }
156
+ return image;
157
+ }
158
+ return tierMediaAssetUrl(image, ipfsGatewayBaseUrl);
159
+ }
160
+ /** Pick and resolve all tier metadata fields in one pass. */
161
+ export function tierDisplayMetadata(json, ipfsGatewayBaseUrl) {
162
+ const metadata = pickTierMetadata(json);
163
+ return {
164
+ ...metadata,
165
+ image: tierMediaImageUrl(metadata.image, ipfsGatewayBaseUrl),
166
+ animationUrl: tierMediaAssetUrl(metadata.animationUrl, ipfsGatewayBaseUrl),
167
+ };
168
+ }
169
+ /** Stable first-seen category ids, with blank categories assigned to 0. */
170
+ export function buildTierCategoryPlan(tiers) {
171
+ const categoryIds = new Map();
172
+ const categoryByTierId = {};
173
+ const storeCategories = {};
174
+ for (const tier of tiers) {
175
+ const name = tier.categoryName?.trim() || "";
176
+ if (!name) {
177
+ categoryByTierId[tier.id] = 0;
178
+ continue;
179
+ }
180
+ let category = categoryIds.get(name);
181
+ if (category === undefined) {
182
+ category = categoryIds.size + 1;
183
+ categoryIds.set(name, category);
184
+ storeCategories[String(category)] = name;
185
+ }
186
+ categoryByTierId[tier.id] = category;
187
+ }
188
+ return { categoryByTierId, storeCategories };
189
+ }
190
+ /**
191
+ * A tier's effective (discounted) price, matching the on-chain formula in
192
+ * JB721TiersHookStore: `price - mulDiv(price, discountPercent, 200)` with
193
+ * integer-floor division.
194
+ *
195
+ * @param price The tier's full (undiscounted) price.
196
+ * @param discountPercent The tier's discount, out of 200 (`DISCOUNT_DENOMINATOR`).
197
+ */
198
+ export function effectiveTierPrice(price, discountPercent) {
199
+ let discount = BigInt(discountPercent);
200
+ if (discount <= 0n)
201
+ return price;
202
+ if (discount > DISCOUNT_DENOMINATOR)
203
+ discount = DISCOUNT_DENOMINATOR;
204
+ return price - (price * discount) / DISCOUNT_DENOMINATOR;
205
+ }
206
+ /**
207
+ * Read a JB721 hook's `METADATA_ID_TARGET` — the shared *implementation* address
208
+ * that pay/cash-out metadata ids must key off (a delegatecall clone reports the
209
+ * implementation, not itself). Falls back to `hook` if the read reverts (e.g. an
210
+ * older hook without the getter), which is only correct for a non-clone hook.
211
+ *
212
+ * @param client A viem public client on the given chain.
213
+ * @param args.hook The project's 721 tiers hook (clone) address.
214
+ */
215
+ export async function get721MetadataIdTarget(client, { hook }) {
216
+ return client
217
+ .readContract({
218
+ address: hook,
219
+ abi: jb721TiersHookAbi,
220
+ functionName: "METADATA_ID_TARGET",
221
+ })
222
+ .catch(() => hook);
223
+ }
224
+ /**
225
+ * Resolve a project's 721 tiers hook, its store, metadata id target, pricing
226
+ * context, and tiers in one call.
227
+ *
228
+ * Hook resolution mirrors the app patterns: revnets read
229
+ * `REVOwner.tiered721HookOf`; custom projects read the current ruleset's pay
230
+ * data hook — either the omnichain deployer (the real hook lives in
231
+ * `JBOmnichainDeployer.tiered721HookOf(projectId, rulesetId)`) or the 721 hook
232
+ * itself, verified by probing `STORE()` (a revert means it is not a 721 hook, so
233
+ * the project has no shop).
234
+ *
235
+ * Returns `null` when the project authoritatively has no 721 shop. RPC failures
236
+ * on authoritative reads throw, so a transient error surfaces as an error rather
237
+ * than a false "no shop".
238
+ *
239
+ * @param client A viem public client on the given chain.
240
+ * @param args.projectId The project (or revnet) id.
241
+ * @param args.isRevnet Whether the project is a revnet (changes hook resolution).
242
+ * @param args.tierLimit Max tiers to read from `tiersOf`. Defaults to 100.
243
+ * @param args.categories Tier categories to filter by (empty = all). Defaults to `[]`.
244
+ */
245
+ export async function getProject721Shop(client, { chainId, projectId, isRevnet, tierLimit = 100, categories = [], }) {
246
+ // 1. Resolve the 721 hook.
247
+ let hook = null;
248
+ // A non-authoritative candidate is the ruleset data hook, which might be some
249
+ // other kind of hook; the STORE() probe below decides.
250
+ let authoritative = true;
251
+ if (isRevnet) {
252
+ const revnetHook = await getRevnetTiered721Hook(client, {
253
+ chainId,
254
+ revnetId: projectId,
255
+ });
256
+ hook = revnetHook !== zeroAddress ? revnetHook : null;
257
+ }
258
+ else {
259
+ const { ruleset, metadata } = await getCurrentRuleset(client, {
260
+ chainId,
261
+ projectId,
262
+ });
263
+ const dataHook = metadata.dataHook;
264
+ if (metadata.useDataHookForPay && dataHook && dataHook !== zeroAddress) {
265
+ const omni = jbContractAddress["6"][JBOmnichainDeployerContracts.JBOmnichainDeployer]?.[chainId];
266
+ if (omni && dataHook.toLowerCase() === omni.toLowerCase()) {
267
+ // Omnichain project: the real 721 hook lives in the deployer's
268
+ // per-ruleset mapping.
269
+ const [omniHook] = await client.readContract({
270
+ address: omni,
271
+ abi: jbOmnichainDeployerAbi,
272
+ functionName: "tiered721HookOf",
273
+ args: [projectId, BigInt(ruleset.id)],
274
+ });
275
+ hook = omniHook !== zeroAddress ? omniHook : null;
276
+ }
277
+ else {
278
+ // Single-chain custom project: the data hook may be the 721 hook itself.
279
+ hook = dataHook;
280
+ authoritative = false;
281
+ }
282
+ }
283
+ }
284
+ if (!hook)
285
+ return null;
286
+ // 2. The hook's store. For a non-authoritative candidate a revert means "not a
287
+ // 721 hook" (no shop); for an authoritative one, let failures throw.
288
+ const readStore = () => client.readContract({
289
+ address: hook,
290
+ abi: jb721TiersHookAbi,
291
+ functionName: "STORE",
292
+ });
293
+ const store = authoritative
294
+ ? await readStore()
295
+ : await readStore().catch(() => null);
296
+ if (!store)
297
+ return null;
298
+ // 3. Metadata id target + pricing context. Pricing is meaningless without the
299
+ // hook's exact currency + decimals, so a failure here is an error, not a
300
+ // fallback.
301
+ const [metadataIdTarget, pricingRaw] = await Promise.all([
302
+ get721MetadataIdTarget(client, { chainId, hook }),
303
+ client.readContract({
304
+ address: hook,
305
+ abi: jb721TiersHookAbi,
306
+ functionName: "pricingContext",
307
+ }),
308
+ ]);
309
+ // 4. The tiers, with resolver URIs included so callers can name tiers without
310
+ // a per-tier resolver read.
311
+ const raw = await client.readContract({
312
+ address: store,
313
+ abi: jb721TiersHookStoreAbi,
314
+ functionName: "tiersOf",
315
+ args: [hook, categories, true, 0n, BigInt(tierLimit)],
316
+ });
317
+ const tiers = raw
318
+ .filter((tier) => tier.initialSupply > 0)
319
+ .map((tier) => ({
320
+ id: tier.id,
321
+ price: tier.price,
322
+ remainingSupply: tier.remainingSupply,
323
+ initialSupply: tier.initialSupply,
324
+ votingUnits: tier.votingUnits,
325
+ reserveFrequency: tier.reserveFrequency,
326
+ category: tier.category,
327
+ discountPercent: tier.discountPercent,
328
+ encodedIpfsUri: tier.encodedIpfsUri,
329
+ resolvedUri: tier.resolvedUri ?? "",
330
+ }));
331
+ return {
332
+ hook,
333
+ store,
334
+ metadataIdTarget,
335
+ pricing: {
336
+ currency: Number(pricingRaw[0]),
337
+ decimals: Number(pricingRaw[1]),
338
+ },
339
+ tiers,
340
+ };
341
+ }
342
+ //# sourceMappingURL=nft.js.map