@bananapus/nana-sdk-react 12.0.0 → 13.0.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 (47) hide show
  1. package/dist/components/NativeTokenValue.d.ts +1 -1
  2. package/dist/components/NativeTokenValue.d.ts.map +1 -1
  3. package/dist/contexts/JBChainContext/JBChainContext.d.ts.map +1 -1
  4. package/dist/contexts/JBContractContext/JBContractContext.d.ts.map +1 -1
  5. package/dist/contexts/JBProjectMetadataContext/JBProjectMetadataContext.d.ts.map +1 -1
  6. package/dist/contexts/JBProjectProvider/JBProjectProvider.d.ts.map +1 -1
  7. package/dist/contexts/JBRulesetContext/JBRulesetContext.d.ts +1 -1
  8. package/dist/contexts/JBRulesetContext/JBRulesetContext.d.ts.map +1 -1
  9. package/dist/contexts/JBTerminalContext/JBPrimaryNativeTerminalProvider.d.ts +1 -1
  10. package/dist/contexts/JBTerminalContext/JBPrimaryNativeTerminalProvider.d.ts.map +1 -1
  11. package/dist/contexts/JBTerminalContext/JBTerminalContext.d.ts +1 -1
  12. package/dist/contexts/JBTerminalContext/JBTerminalContext.d.ts.map +1 -1
  13. package/dist/contexts/JBTokenContext/JBTokenContext.d.ts.map +1 -1
  14. package/dist/hooks/index.d.ts.map +1 -1
  15. package/dist/hooks/jb721Hook/useFind721DataHook.d.ts.map +1 -1
  16. package/dist/hooks/ruleset/useJBRuleset.d.ts +6 -6
  17. package/dist/hooks/ruleset/useJBRuleset.d.ts.map +1 -1
  18. package/dist/hooks/ruleset/useJBUpcomingRuleset.d.ts.map +1 -1
  19. package/dist/hooks/ruleset/useResolveDataHook.d.ts +1 -1
  20. package/dist/hooks/ruleset/useResolveDataHook.d.ts.map +1 -1
  21. package/dist/hooks/shop/useOwnedShopItems.d.ts.map +1 -1
  22. package/dist/hooks/shop/useShopPurchases.d.ts.map +1 -1
  23. package/dist/hooks/suckers/useSuckers.d.ts.map +1 -1
  24. package/dist/hooks/token/useNativeTokenSurplus.d.ts.map +1 -1
  25. package/dist/hooks/token/useNativeTokenSymbol.d.ts.map +1 -1
  26. package/dist/hooks/token/useSuckersCashOutQuote.d.ts +13 -2
  27. package/dist/hooks/token/useSuckersCashOutQuote.d.ts.map +1 -1
  28. package/dist/hooks/token/useSuckersNativeTokenBalance.d.ts.map +1 -1
  29. package/dist/hooks/token/useSuckersTokenCashOutValue.d.ts +5 -1
  30. package/dist/hooks/token/useSuckersTokenCashOutValue.d.ts.map +1 -1
  31. package/dist/hooks/token/useSuckersUserTokenBalance.d.ts.map +1 -1
  32. package/dist/hooks/token/useTokenCashOutQuoteEth.d.ts +26 -0
  33. package/dist/hooks/token/useTokenCashOutQuoteEth.d.ts.map +1 -1
  34. package/dist/hooks/useEtherPrice.d.ts +8 -1
  35. package/dist/hooks/useEtherPrice.d.ts.map +1 -1
  36. package/dist/hooks/useNetwork.d.ts.map +1 -1
  37. package/dist/hooks/usePreparePayMetadata.d.ts.map +1 -1
  38. package/dist/index.d.ts +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +471 -219
  41. package/dist/index.js.map +1 -1
  42. package/dist/lib/bendystraw/getBendystrawUrl.d.ts.map +1 -1
  43. package/dist/lib/bendystraw/useBendystrawQuery.d.ts.map +1 -1
  44. package/dist/lib/relayr/hooks/useGetRelayrTxBundle.d.ts.map +1 -1
  45. package/dist/lib/relayr/hooks/useRequestRelayrQuote.d.ts.map +1 -1
  46. package/dist/lib/relayr/hooks/useSendRelayrTx.d.ts.map +1 -1
  47. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,8 +1,14 @@
1
+ "use client";
2
+ "use client";
3
+
1
4
  // src/components/NativeTokenValue.tsx
2
5
  import { NATIVE_TOKEN_DECIMALS, formatUnits } from "@bananapus/nana-sdk-core";
3
6
 
4
7
  // src/hooks/token/useNativeTokenSymbol.ts
5
- import { DEFAULT_NATIVE_TOKEN_SYMBOL, JB_CHAINS } from "@bananapus/nana-sdk-core";
8
+ import {
9
+ DEFAULT_NATIVE_TOKEN_SYMBOL,
10
+ JB_CHAINS
11
+ } from "@bananapus/nana-sdk-core";
6
12
 
7
13
  // src/contexts/JBChainContext/JBChainContext.tsx
8
14
  import { debug } from "@bananapus/nana-sdk-core";
@@ -25,7 +31,8 @@ var JBChainProvider = ({
25
31
 
26
32
  // src/hooks/token/useNativeTokenSymbol.ts
27
33
  function useNativeTokenSymbol(chainId) {
28
- const _chainId = chainId ?? useJBChainId();
34
+ const contextChainId = useJBChainId();
35
+ const _chainId = chainId ?? contextChainId;
29
36
  if (!_chainId) {
30
37
  return DEFAULT_NATIVE_TOKEN_SYMBOL;
31
38
  }
@@ -34,7 +41,10 @@ function useNativeTokenSymbol(chainId) {
34
41
 
35
42
  // src/components/NativeTokenValue.tsx
36
43
  import { Fragment, jsxs } from "react/jsx-runtime";
37
- function NativeTokenValue({ wei, decimals = 4 }) {
44
+ function NativeTokenValue({
45
+ wei,
46
+ decimals = 4
47
+ }) {
38
48
  const symbol = useNativeTokenSymbol();
39
49
  return /* @__PURE__ */ jsxs(Fragment, { children: [
40
50
  formatUnits(wei, NATIVE_TOKEN_DECIMALS, {
@@ -47,20 +57,28 @@ function NativeTokenValue({ wei, decimals = 4 }) {
47
57
 
48
58
  // src/contexts/JBContractContext/JBContractContext.tsx
49
59
  import {
50
- NATIVE_TOKEN as NATIVE_TOKEN4,
60
+ NATIVE_TOKEN as NATIVE_TOKEN5,
51
61
  debug as debug10,
52
62
  USDC_ADDRESSES,
53
- jbDirectoryAbi,
54
- jbControllerAbi as jbControllerAbi5,
63
+ jbDirectoryAbi as jbDirectoryAbi2,
64
+ jbControllerAbi as jbControllerAbi6,
55
65
  jbContractAddress as jbContractAddress2,
56
- JBCoreContracts as JBCoreContracts3,
57
- getJBContractAddress as getJBContractAddress2
66
+ JBCoreContracts as JBCoreContracts4,
67
+ getJBContractAddress as getJBContractAddress3
58
68
  } from "@bananapus/nana-sdk-core";
59
- import { createContext as createContext8, useCallback, useContext as useContext8, useMemo as useMemo5 } from "react";
69
+ import {
70
+ createContext as createContext8,
71
+ useCallback,
72
+ useContext as useContext8,
73
+ useMemo as useMemo5
74
+ } from "react";
60
75
  import { isAddressEqual as isAddressEqual4, zeroAddress as zeroAddress4 } from "viem";
61
76
 
62
77
  // src/hooks/usePreparePayMetadata.ts
63
- import { DEFAULT_ALLOW_OVERSPENDING, createHookMetadata } from "@bananapus/nana-sdk-core";
78
+ import {
79
+ DEFAULT_ALLOW_OVERSPENDING,
80
+ createHookMetadata
81
+ } from "@bananapus/nana-sdk-core";
64
82
  import { encodeAbiParameters } from "viem";
65
83
 
66
84
  // src/hooks/jb721Hook/helpers.ts
@@ -103,7 +121,10 @@ function encodeJB721HookPayMetadata(metadata) {
103
121
  metadata.allowOverspending ?? DEFAULT_ALLOW_OVERSPENDING,
104
122
  metadata.tierIdsToMint.map(Number)
105
123
  ];
106
- const encoded = encodeAbiParameters([{ type: "bool" }, { type: "uint16[]" }], args);
124
+ const encoded = encodeAbiParameters(
125
+ [{ type: "bool" }, { type: "uint16[]" }],
126
+ args
127
+ );
107
128
  return encoded;
108
129
  }
109
130
  function usePreparePayMetadata({
@@ -222,8 +243,12 @@ function useResolveDataHook({
222
243
  resolvedDataHook = tiered721Hook;
223
244
  } else if (extraDataHook && !isAddressEqual(extraDataHook, zeroAddress)) {
224
245
  resolvedDataHook = extraDataHook;
246
+ } else if (tiered721Hook === void 0 || extraDataHook === void 0) {
247
+ resolvedDataHook = void 0;
225
248
  }
226
- } else if (legacyDataHookQuery.data?.[2]) {
249
+ } else if (legacyDataHookQuery.data === void 0) {
250
+ resolvedDataHook = void 0;
251
+ } else if (legacyDataHookQuery.data[2]) {
227
252
  resolvedDataHook = legacyDataHookQuery.data[2];
228
253
  }
229
254
  }
@@ -254,16 +279,20 @@ function useJBRulesetMetadata() {
254
279
  const { rulesetMetadata } = useJBRulesetContext();
255
280
  return rulesetMetadata;
256
281
  }
257
- var JBRulesetProvider = ({ children }) => {
282
+ var JBRulesetProvider = ({
283
+ children
284
+ }) => {
258
285
  const { contracts, projectId, version } = useJBContractContext();
259
286
  const chainId = useJBChainId();
287
+ const controllerAddress = contracts.controller.data ?? void 0;
260
288
  const { data: ruleset, isLoading } = useReadContract3({
261
289
  chainId,
262
290
  abi: jbControllerAbi,
263
291
  functionName: "currentRulesetOf",
264
- address: contracts.controller.data ?? void 0,
292
+ address: controllerAddress,
265
293
  args: [projectId],
266
294
  query: {
295
+ enabled: !!controllerAddress,
267
296
  select([ruleset2, rulesetMetadata]) {
268
297
  return {
269
298
  data: {
@@ -274,7 +303,9 @@ var JBRulesetProvider = ({ children }) => {
274
303
  metadata: {
275
304
  ...rulesetMetadata,
276
305
  cashOutTaxRate: new CashOutTaxRate(rulesetMetadata.cashOutTaxRate),
277
- reservedPercent: new ReservedPercent(rulesetMetadata.reservedPercent),
306
+ reservedPercent: new ReservedPercent(
307
+ rulesetMetadata.reservedPercent
308
+ ),
278
309
  // v4/v5 store the INVERSE flag (`useTotalSurplusForCashOuts`) in this slot;
279
310
  // normalize to the v6 field's semantics.
280
311
  scopeCashOutsToLocalBalances: version === 6 ? rulesetMetadata.scopeCashOutsToLocalBalances : !rulesetMetadata.scopeCashOutsToLocalBalances
@@ -283,38 +314,31 @@ var JBRulesetProvider = ({ children }) => {
283
314
  }
284
315
  }
285
316
  });
286
- const { resolvedDataHook } = useResolveDataHook({
287
- dataHookAddress: ruleset?.metadata?.dataHook,
288
- projectId,
289
- chainId,
290
- rulesetId: BigInt(ruleset?.data.id ?? 0)
291
- });
292
- const rulesetMetadataWithResolvedDataHook = ruleset?.metadata && {
293
- ...ruleset.metadata,
294
- dataHook: resolvedDataHook
317
+ const { resolvedDataHook, isLoading: isDataHookLoading } = useResolveDataHook(
318
+ {
319
+ dataHookAddress: ruleset?.metadata?.dataHook,
320
+ projectId,
321
+ chainId,
322
+ rulesetId: ruleset?.data.id === void 0 ? void 0 : BigInt(ruleset.data.id)
323
+ }
324
+ );
325
+ const isRulesetLoading = Boolean(isLoading || contracts.controller.isLoading);
326
+ const rulesetMetadataWithResolvedDataHook = ruleset?.metadata && resolvedDataHook ? { ...ruleset.metadata, dataHook: resolvedDataHook } : void 0;
327
+ const rulesetState = { data: ruleset?.data, isLoading: isRulesetLoading };
328
+ const rulesetMetadataState = {
329
+ data: rulesetMetadataWithResolvedDataHook,
330
+ isLoading: Boolean(isRulesetLoading || isDataHookLoading)
295
331
  };
296
332
  debug3("JBRulesetContext", {
297
- ruleset: {
298
- data: ruleset?.data,
299
- isLoading
300
- },
301
- rulesetMetadata: {
302
- data: rulesetMetadataWithResolvedDataHook,
303
- isLoading
304
- }
333
+ ruleset: rulesetState,
334
+ rulesetMetadata: rulesetMetadataState
305
335
  });
306
336
  return /* @__PURE__ */ jsx2(
307
337
  JBRulesetContext.Provider,
308
338
  {
309
339
  value: {
310
- ruleset: {
311
- data: ruleset?.data,
312
- isLoading
313
- },
314
- rulesetMetadata: {
315
- data: rulesetMetadataWithResolvedDataHook,
316
- isLoading
317
- }
340
+ ruleset: rulesetState,
341
+ rulesetMetadata: rulesetMetadataState
318
342
  },
319
343
  children
320
344
  }
@@ -354,7 +378,8 @@ function useFind721DataHook() {
354
378
  const { data } = useJBDataHookContext();
355
379
  const { projectId, version } = useJBContractContext();
356
380
  const { ruleset } = useJBRulesetContext();
357
- const publicClient = usePublicClient();
381
+ const chainId = useJBChainId();
382
+ const publicClient = usePublicClient({ chainId });
358
383
  const rulesetId = ruleset.data?.id;
359
384
  const dataHookAddress = data?.dataHookAddress;
360
385
  debug5("useFind721DataHook::args", {
@@ -364,7 +389,17 @@ function useFind721DataHook() {
364
389
  publicClient
365
390
  });
366
391
  const jb721DataHookQuery = useQuery({
367
- queryKey: ["dataHook", projectId, rulesetId, dataHookAddress],
392
+ // Chain and version are read inputs, and with `staleTime: Infinity` a key
393
+ // that omits them serves one chain's (or version's) hook for another's.
394
+ queryKey: [
395
+ "dataHook",
396
+ chainId,
397
+ version,
398
+ projectId,
399
+ rulesetId,
400
+ dataHookAddress
401
+ ],
402
+ enabled: !!chainId && !!rulesetId && !!dataHookAddress,
368
403
  staleTime: Infinity,
369
404
  queryFn: async () => {
370
405
  if (!rulesetId || !dataHookAddress) return null;
@@ -410,14 +445,19 @@ function JBCurrentDataHookProvider({
410
445
  }
411
446
 
412
447
  // src/contexts/JBProjectMetadataContext/JBProjectMetadataContext.tsx
413
- import { debug as debug7, getProjectMetadata } from "@bananapus/nana-sdk-core";
448
+ import {
449
+ debug as debug7,
450
+ getProjectMetadata
451
+ } from "@bananapus/nana-sdk-core";
414
452
  import { createContext as createContext4, useContext as useContext4 } from "react";
415
453
  import { usePublicClient as usePublicClient2 } from "wagmi";
416
454
  import { useQuery as useQuery2 } from "wagmi/query";
417
455
  import { jsx as jsx5 } from "react/jsx-runtime";
418
- var JBProjectMetadataContext = createContext4({
419
- metadata: AsyncDataNone
420
- });
456
+ var JBProjectMetadataContext = createContext4(
457
+ {
458
+ metadata: AsyncDataNone
459
+ }
460
+ );
421
461
  function useJBProjectMetadataContext() {
422
462
  return useContext4(JBProjectMetadataContext);
423
463
  }
@@ -429,13 +469,18 @@ function useProjectMetadata({
429
469
  const chainId = useJBChainId();
430
470
  const publicClient = usePublicClient2({ chainId });
431
471
  return useQuery2({
472
+ // The chain is part of the read's identity: the same project id resolves to
473
+ // a different project on every chain, so omitting it lets one chain's name
474
+ // and logo be served for another's project.
432
475
  queryKey: [
433
476
  "juice-sdk",
434
477
  "useProjectMetadata",
478
+ chainId,
435
479
  projectId?.toString(),
436
480
  jbControllerAddress,
437
481
  ipfsGatewayHostname
438
482
  ],
483
+ enabled: !!chainId && !!projectId && !!jbControllerAddress,
439
484
  queryFn: async () => {
440
485
  if (!projectId || !jbControllerAddress) return null;
441
486
  if (!publicClient) {
@@ -519,13 +564,19 @@ var JBTokenProvider = ({
519
564
  version,
520
565
  contracts: { controller }
521
566
  } = useJBContractContext();
522
- const { data: tokenAddress } = useReadContract4({
523
- address: getJBContractAddress(JBCoreContracts.JBTokens, version, chainId),
567
+ let jbTokensAddress;
568
+ try {
569
+ jbTokensAddress = chainId ? getJBContractAddress(JBCoreContracts.JBTokens, version, chainId) : void 0;
570
+ } catch {
571
+ jbTokensAddress = void 0;
572
+ }
573
+ const { data: tokenAddress, isLoading: isTokenAddressLoading } = useReadContract4({
574
+ address: jbTokensAddress,
524
575
  abi: jbTokensAbi,
525
576
  functionName: "tokenOf",
526
577
  chainId,
527
578
  args: [projectId],
528
- query: { enabled: !!projectId && !!chainId && !!version }
579
+ query: { enabled: !!projectId && !!jbTokensAddress }
529
580
  });
530
581
  const fetchTokenEnabled = Boolean(
531
582
  tokenAddress && !isAddressEqual2(tokenAddress, zeroAddress2)
@@ -550,10 +601,18 @@ var JBTokenProvider = ({
550
601
  JBTokenContext.Provider,
551
602
  {
552
603
  value: {
553
- token,
604
+ // The ERC-20 read is disabled until `tokenOf` answers, which would
605
+ // otherwise publish `isLoading: false, data: undefined` — "this project
606
+ // has no token" — on every page load.
607
+ token: {
608
+ ...token,
609
+ isLoading: Boolean(token.isLoading || isTokenAddressLoading)
610
+ },
554
611
  totalOutstanding: {
555
612
  data: totalOutstandingData,
556
- isLoading: totalOutstandingRes?.isLoading
613
+ isLoading: Boolean(
614
+ totalOutstandingRes?.isLoading || controller?.isLoading
615
+ )
557
616
  }
558
617
  },
559
618
  children
@@ -567,7 +626,10 @@ import { debug as debug8 } from "@bananapus/nana-sdk-core";
567
626
  // src/contexts/JBTerminalContext/JBTerminalContext.tsx
568
627
  import { jbMultiTerminalAbi } from "@bananapus/nana-sdk-core";
569
628
  import { createContext as createContext6, useContext as useContext6 } from "react";
570
- import { isAddressEqual as isAddressEqual3, zeroAddress as zeroAddress3 } from "viem";
629
+ import {
630
+ isAddressEqual as isAddressEqual3,
631
+ zeroAddress as zeroAddress3
632
+ } from "viem";
571
633
  import { useReadContract as useReadContract5 } from "wagmi";
572
634
  import { jsx as jsx7 } from "react/jsx-runtime";
573
635
  var JBTerminalContext = createContext6({
@@ -578,7 +640,10 @@ var JBTerminalContext = createContext6({
578
640
  function useJBTerminalContext() {
579
641
  return useContext6(JBTerminalContext);
580
642
  }
581
- var JBTerminalProvider = ({ address, children }) => {
643
+ var JBTerminalProvider = ({
644
+ address,
645
+ children
646
+ }) => {
582
647
  const chainId = useJBChainId();
583
648
  const { data: store, isLoading: isStoreLoading } = useReadContract5({
584
649
  abi: jbMultiTerminalAbi,
@@ -617,15 +682,16 @@ function JBPrimaryNativeTerminalProvider({
617
682
  children
618
683
  }) {
619
684
  const { contracts } = useJBContractContext();
620
- const terminalAddress = contracts?.primaryNativeTerminal?.data;
685
+ const terminalAddress = contracts?.primaryNativeTerminal?.data ?? void 0;
621
686
  debug8("JBPrimaryNativeTerminalProvider", { terminalAddress });
622
- if (!terminalAddress) return children;
623
687
  return /* @__PURE__ */ jsx8(JBTerminalProvider, { address: terminalAddress, children });
624
688
  }
625
689
 
626
690
  // src/contexts/JBProjectProvider/JBProjectProvider.tsx
627
691
  import { jsx as jsx9 } from "react/jsx-runtime";
628
- var JBProjectContext = createContext7(void 0);
692
+ var JBProjectContext = createContext7(
693
+ void 0
694
+ );
629
695
  var JBProjectProvider = ({
630
696
  projectId,
631
697
  chainId,
@@ -634,24 +700,43 @@ var JBProjectProvider = ({
634
700
  version,
635
701
  bendystraw
636
702
  }) => {
637
- return /* @__PURE__ */ jsx9(JBProjectContext.Provider, { value: { chainId, projectId, version, bendystraw }, children: /* @__PURE__ */ jsx9(JBChainProvider, { chainId, children: /* @__PURE__ */ jsx9(JBContractProvider, { projectId, version, ...ctxProps?.contract, children: /* @__PURE__ */ jsx9(JBRulesetProvider, { children: /* @__PURE__ */ jsx9(JBProjectMetadataProvider, { ...ctxProps?.metadata, children: /* @__PURE__ */ jsx9(JBCurrentDataHookProvider, { children: /* @__PURE__ */ jsx9(JBPrimaryNativeTerminalProvider, { children: /* @__PURE__ */ jsx9(JBTokenProvider, { ...ctxProps?.token, children }) }) }) }) }) }) }) });
703
+ return /* @__PURE__ */ jsx9(
704
+ JBProjectContext.Provider,
705
+ {
706
+ value: { chainId, projectId, version, bendystraw },
707
+ children: /* @__PURE__ */ jsx9(JBChainProvider, { chainId, children: /* @__PURE__ */ jsx9(
708
+ JBContractProvider,
709
+ {
710
+ projectId,
711
+ version,
712
+ ...ctxProps?.contract,
713
+ children: /* @__PURE__ */ jsx9(JBRulesetProvider, { children: /* @__PURE__ */ jsx9(JBProjectMetadataProvider, { ...ctxProps?.metadata, children: /* @__PURE__ */ jsx9(JBCurrentDataHookProvider, { children: /* @__PURE__ */ jsx9(JBPrimaryNativeTerminalProvider, { children: /* @__PURE__ */ jsx9(JBTokenProvider, { ...ctxProps?.token, children }) }) }) }) })
714
+ }
715
+ ) })
716
+ }
717
+ );
638
718
  };
639
719
  function useJBProject() {
640
- return useContext7(JBProjectContext);
720
+ const context = useContext7(JBProjectContext);
721
+ if (!context) return void 0;
722
+ const { bendystraw: _bendystraw, ...project } = context;
723
+ return project;
641
724
  }
642
725
  function useBendystrawConfig() {
643
726
  return useContext7(JBProjectContext)?.bendystraw;
644
727
  }
645
728
 
646
729
  // src/lib/bendystraw/getBendystrawUrl.ts
647
- import { arbitrum, base, mainnet as mainnet2, optimism } from "viem/chains";
730
+ import { JB_CHAINS as JB_CHAINS2 } from "@bananapus/nana-sdk-core";
648
731
  var bendystrawUrl = "https://bendystraw.xyz";
649
732
  var testnetBendystrawUrl = "https://testnet.bendystraw.xyz";
650
733
  function getBendystrawUrl(chainId, config) {
651
734
  const { url, apiKey } = config;
652
- if (url) return `${url}/${apiKey}`;
653
- const isMainnet = [mainnet2, base, arbitrum, optimism].some((c) => c.id === chainId);
654
- return `${isMainnet ? bendystrawUrl : testnetBendystrawUrl}${apiKey !== "" ? `/${apiKey}` : ""}`;
735
+ const keyPath = apiKey !== "" ? `/${apiKey}` : "";
736
+ if (url) return `${url}${keyPath}`;
737
+ const chain = JB_CHAINS2[chainId]?.chain;
738
+ const isMainnet = chain ? !chain.testnet : false;
739
+ return `${isMainnet ? bendystrawUrl : testnetBendystrawUrl}${keyPath}`;
655
740
  }
656
741
 
657
742
  // src/lib/bendystraw/useBendystrawQuery.ts
@@ -684,21 +769,21 @@ function useBendystrawQuery(document, ...[variables, options]) {
684
769
 
685
770
  // src/hooks/suckers/useSuckers.ts
686
771
  import {
687
- arbitrum as arbitrum2,
772
+ arbitrum,
688
773
  arbitrumSepolia,
689
- base as base2,
774
+ base,
690
775
  baseSepolia,
691
- mainnet as mainnet3,
692
- optimism as optimism2,
776
+ mainnet as mainnet2,
777
+ optimism,
693
778
  optimismSepolia,
694
779
  sepolia
695
780
  } from "viem/chains";
696
781
  import { useMemo as useMemo2 } from "react";
697
782
  var chainOrder = [
698
- mainnet3.id,
699
- base2.id,
700
- optimism2.id,
701
- arbitrum2.id,
783
+ mainnet2.id,
784
+ base.id,
785
+ optimism.id,
786
+ arbitrum.id,
702
787
  sepolia.id,
703
788
  baseSepolia.id,
704
789
  optimismSepolia.id,
@@ -3387,7 +3472,9 @@ function useNativeTokenSurplus({
3387
3472
  version,
3388
3473
  contracts: { primaryNativeTerminal }
3389
3474
  } = useJBContractContext();
3390
- const _chainId = chainId ?? useJBChainId();
3475
+ const contextChainId = useJBChainId();
3476
+ const _chainId = chainId ?? contextChainId;
3477
+ const isContextChain = !!_chainId && _chainId === contextChainId;
3391
3478
  const v6Query = useReadContract6({
3392
3479
  chainId: _chainId,
3393
3480
  abi: jbMultiTerminalAbi2,
@@ -3399,7 +3486,7 @@ function useNativeTokenSurplus({
3399
3486
  BigInt(NATIVE_TOKEN_DECIMALS2),
3400
3487
  BigInt(ETH_CURRENCY_ID)
3401
3488
  ],
3402
- query: { enabled: version === 6 }
3489
+ query: { enabled: version === 6 && isContextChain }
3403
3490
  });
3404
3491
  const legacyQuery = useReadContract6({
3405
3492
  chainId: _chainId,
@@ -3418,7 +3505,7 @@ function useNativeTokenSurplus({
3418
3505
  BigInt(NATIVE_TOKEN_DECIMALS2),
3419
3506
  BigInt(ETH_CURRENCY_ID)
3420
3507
  ],
3421
- query: { enabled: version !== 6 }
3508
+ query: { enabled: version !== 6 && isContextChain }
3422
3509
  });
3423
3510
  return version === 6 ? v6Query : legacyQuery;
3424
3511
  }
@@ -3504,14 +3591,31 @@ function useSuckersNativeTokenSurplus() {
3504
3591
  import {
3505
3592
  applyJbDaoCashOutFee,
3506
3593
  ETH_CURRENCY_ID as ETH_CURRENCY_ID3,
3594
+ getJBContractAddress as getJBContractAddress2,
3507
3595
  getProjectTerminalStore,
3596
+ getTokenCashOutQuoteEth,
3597
+ jbController4_1Abi,
3598
+ jbControllerAbi as jbControllerAbi3,
3599
+ jbControllerV5Abi,
3600
+ JBCoreContracts as JBCoreContracts2,
3601
+ jbDirectoryAbi,
3508
3602
  jbTerminalStoreAbi,
3509
3603
  jbTerminalStoreV5Abi,
3604
+ NATIVE_TOKEN as NATIVE_TOKEN3,
3510
3605
  NATIVE_TOKEN_DECIMALS as NATIVE_TOKEN_DECIMALS4
3511
3606
  } from "@bananapus/nana-sdk-core";
3512
3607
  import { getContract as getContract2 } from "viem";
3513
3608
  import { useConfig as useConfig2 } from "wagmi";
3514
3609
  import { useQuery as useQuery5 } from "wagmi/query";
3610
+ var V6_NATIVE_TOKEN_CURRENCY_ID = Number(BigInt(NATIVE_TOKEN3) & 0xffffffffn);
3611
+ function nativeCurrencyId(version) {
3612
+ return version === 6 ? V6_NATIVE_TOKEN_CURRENCY_ID : ETH_CURRENCY_ID3;
3613
+ }
3614
+ function controllerAbi(version) {
3615
+ if (version === 6) return jbControllerAbi3;
3616
+ if (version === 5) return jbControllerV5Abi;
3617
+ return jbController4_1Abi;
3618
+ }
3515
3619
  function useSuckersCashOutQuote(tokenAmountWei) {
3516
3620
  const config = useConfig2();
3517
3621
  const chainId = useJBChainId();
@@ -3529,41 +3633,86 @@ function useSuckersCashOutQuote(tokenAmountWei) {
3529
3633
  enabled: Boolean(!isLoading && chainId),
3530
3634
  queryFn: async () => {
3531
3635
  if (!chainId) return null;
3532
- const quotes = await Promise.all(
3533
- pairs.map(async ({ peerChainId, projectId: projectId2 }) => {
3534
- return getTokenRedemptionQuote(
3535
- config,
3536
- peerChainId,
3537
- projectId2,
3538
- tokenAmountWei,
3539
- version
3540
- );
3541
- }) ?? []
3542
- );
3543
- return quotes.reduce((acc, quote) => acc + quote, 0n);
3636
+ const members = pairs.length > 0 ? pairs : [{ peerChainId: chainId, projectId }];
3637
+ const [totals, cashOutTaxRate] = await Promise.all([
3638
+ Promise.all(
3639
+ members.map(
3640
+ ({ peerChainId, projectId: projectId2 }) => getChainSurplusAndSupply(
3641
+ config,
3642
+ peerChainId,
3643
+ projectId2,
3644
+ version
3645
+ )
3646
+ )
3647
+ ),
3648
+ getCashOutTaxRate(config, chainId, projectId, version)
3649
+ ]);
3650
+ return getTokenCashOutQuoteEth(tokenAmountWei, {
3651
+ overflowWei: totals.reduce((acc, { surplus }) => acc + surplus, 0n),
3652
+ totalSupply: totals.reduce(
3653
+ (acc, { totalSupply }) => acc + totalSupply,
3654
+ 0n
3655
+ ),
3656
+ cashOutTaxRate,
3657
+ // `totalTokenSupplyWithReservedTokensOf` already includes pending
3658
+ // reserved tokens.
3659
+ tokensReserved: 0n
3660
+ });
3544
3661
  }
3545
3662
  });
3546
- const netTotal = applyJbDaoCashOutFee(suckersQuote.data ?? 0n);
3663
+ const netTotal = suckersQuote.data != null ? applyJbDaoCashOutFee(suckersQuote.data) : void 0;
3547
3664
  return {
3548
3665
  data: netTotal,
3549
3666
  isLoading: suckersQuote.isLoading || isLoading,
3550
3667
  errors: [error, suckersQuote.error].filter(Boolean)
3551
3668
  };
3552
3669
  }
3553
- async function getTokenRedemptionQuote(config, chainId, projectId, tokenAmountWei, version) {
3554
- const contract = getContract2({
3670
+ async function getChainSurplusAndSupply(config, chainId, projectId, version) {
3671
+ const client = config.getClient({ chainId });
3672
+ const terminalStore = getContract2({
3555
3673
  address: getProjectTerminalStore(chainId, version),
3556
3674
  abi: version === 6 ? jbTerminalStoreAbi : jbTerminalStoreV5Abi,
3557
- client: config.getClient({ chainId })
3675
+ client
3558
3676
  });
3559
- return await contract.read.currentReclaimableSurplusOf([
3560
- projectId,
3561
- tokenAmountWei,
3562
- [],
3563
- [],
3564
- BigInt(NATIVE_TOKEN_DECIMALS4),
3565
- BigInt(ETH_CURRENCY_ID3)
3677
+ const [surplus, controller] = await Promise.all([
3678
+ terminalStore.read.currentTotalSurplusOf([
3679
+ projectId,
3680
+ BigInt(NATIVE_TOKEN_DECIMALS4),
3681
+ BigInt(nativeCurrencyId(version))
3682
+ ]),
3683
+ getControllerAddress(config, chainId, projectId, version)
3566
3684
  ]);
3685
+ const totalSupply = await getContract2({
3686
+ address: controller,
3687
+ abi: controllerAbi(version),
3688
+ client
3689
+ }).read.totalTokenSupplyWithReservedTokensOf([projectId]);
3690
+ return { surplus, totalSupply };
3691
+ }
3692
+ async function getCashOutTaxRate(config, chainId, projectId, version) {
3693
+ const controller = await getControllerAddress(
3694
+ config,
3695
+ chainId,
3696
+ projectId,
3697
+ version
3698
+ );
3699
+ const [, metadata] = await getContract2({
3700
+ address: controller,
3701
+ abi: controllerAbi(version),
3702
+ client: config.getClient({ chainId })
3703
+ }).read.currentRulesetOf([projectId]);
3704
+ return Number(metadata.cashOutTaxRate);
3705
+ }
3706
+ async function getControllerAddress(config, chainId, projectId, version) {
3707
+ return await getContract2({
3708
+ address: getJBContractAddress2(
3709
+ JBCoreContracts2.JBDirectory,
3710
+ version,
3711
+ chainId
3712
+ ),
3713
+ abi: jbDirectoryAbi,
3714
+ client: config.getClient({ chainId })
3715
+ }).read.controllerOf([projectId]);
3567
3716
  }
3568
3717
 
3569
3718
  // src/hooks/token/useTokenCashOutQuoteEth.ts
@@ -3580,13 +3729,22 @@ function useTokenCashOutQuoteEth(tokenAmountWei, { chainId }) {
3580
3729
  const { store } = useJBTerminalContext();
3581
3730
  const jbChainId = useJBChainId();
3582
3731
  const _chainId = chainId ?? jbChainId;
3732
+ const isContextChain = !!_chainId && _chainId === jbChainId;
3583
3733
  return useReadContract7({
3584
3734
  abi: version === 6 ? jbTerminalStoreAbi2 : jbTerminalStoreV5Abi2,
3585
3735
  functionName: "currentReclaimableSurplusOf",
3586
3736
  chainId: _chainId,
3587
3737
  address: store.data ?? void 0,
3588
- args: tokenAmountWei ? [projectId, tokenAmountWei, [], [], BigInt(NATIVE_TOKEN_DECIMALS5), BigInt(ETH_CURRENCY_ID4)] : void 0,
3738
+ args: tokenAmountWei ? [
3739
+ projectId,
3740
+ tokenAmountWei,
3741
+ [],
3742
+ [],
3743
+ BigInt(NATIVE_TOKEN_DECIMALS5),
3744
+ BigInt(ETH_CURRENCY_ID4)
3745
+ ] : void 0,
3589
3746
  query: {
3747
+ enabled: isContextChain && !!store.data && !!tokenAmountWei,
3590
3748
  select(data) {
3591
3749
  return applyJbDaoCashOutFee2(data);
3592
3750
  }
@@ -3601,50 +3759,91 @@ import { formatEther } from "viem";
3601
3759
  // src/hooks/useEtherPrice.ts
3602
3760
  import { useQuery as useQuery6 } from "wagmi/query";
3603
3761
  var PRICE_REFRESH_INTERVAL = 60 * 1e3 * 5;
3604
- function useEtherPrice() {
3762
+ var DEFAULT_ETHER_PRICE_ENDPOINT = "https://juicebox.money/api/juicebox/prices/ethusd";
3763
+ function useEtherPrice({
3764
+ endpoint = DEFAULT_ETHER_PRICE_ENDPOINT
3765
+ } = {}) {
3605
3766
  return useQuery6({
3606
- queryKey: ["juice-sdk", "etherPrice"],
3767
+ queryKey: ["juice-sdk", "etherPrice", endpoint],
3607
3768
  queryFn: async () => {
3608
- return fetch("https://juicebox.money/api/juicebox/prices/ethusd").then((res) => res.json()).then((data) => data.price);
3769
+ const response = await fetch(endpoint);
3770
+ if (!response.ok) {
3771
+ throw new Error(`Ether price request failed (${response.status}).`);
3772
+ }
3773
+ const { price } = await response.json();
3774
+ return price;
3609
3775
  },
3610
- staleTime: PRICE_REFRESH_INTERVAL
3776
+ staleTime: PRICE_REFRESH_INTERVAL,
3777
+ // `staleTime` alone only marks the price stale; nothing refetches it on a
3778
+ // page that stays mounted, so the quoted price silently ages.
3779
+ refetchInterval: PRICE_REFRESH_INTERVAL
3611
3780
  });
3612
3781
  }
3613
3782
 
3614
3783
  // src/hooks/token/useSuckersTokenCashOutValue.ts
3615
- function useSuckersTokenCashOutValue({ targetCurrency }) {
3616
- const { data: ethPrice, isLoading: isEthLoading } = useEtherPrice();
3617
- const { data: quote, isLoading: isQuoteLoading, errors } = useSuckersCashOutQuote(ONE_JB_TOKEN);
3784
+ function useSuckersTokenCashOutValue({
3785
+ targetCurrency
3786
+ }) {
3787
+ const {
3788
+ data: ethPrice,
3789
+ isLoading: isEthLoading,
3790
+ error: ethPriceError
3791
+ } = useEtherPrice();
3792
+ const {
3793
+ data: quote,
3794
+ isLoading: isQuoteLoading,
3795
+ errors
3796
+ } = useSuckersCashOutQuote(ONE_JB_TOKEN);
3618
3797
  const loading = isQuoteLoading || isEthLoading;
3619
3798
  if (loading) {
3620
3799
  return { loading: true, data: void 0 };
3621
3800
  }
3622
- const quoteEth = parseFloat(formatEther(quote ?? 0n));
3623
- const data = targetCurrency === "eth" ? quoteEth : quoteEth * (ethPrice ?? 0);
3801
+ if (quote == null) {
3802
+ return { loading, data: void 0, errors };
3803
+ }
3804
+ const quoteEth = parseFloat(formatEther(quote));
3805
+ if (targetCurrency === "eth") {
3806
+ return { loading, data: quoteEth, errors };
3807
+ }
3808
+ const allErrors = ethPriceError ? [...errors, ethPriceError] : errors;
3809
+ if (ethPrice === void 0) {
3810
+ return { loading, data: void 0, errors: allErrors };
3811
+ }
3624
3812
  return {
3625
3813
  loading,
3626
- data,
3627
- errors
3814
+ data: quoteEth * ethPrice,
3815
+ errors: allErrors
3628
3816
  };
3629
3817
  }
3630
3818
 
3631
3819
  // src/hooks/token/useSuckersUserTokenBalance.ts
3632
- import { JBCoreContracts as JBCoreContracts2, JBProjectToken as JBProjectToken2, jbTokensAbi as jbTokensAbi2 } from "@bananapus/nana-sdk-core";
3820
+ import {
3821
+ JBCoreContracts as JBCoreContracts3,
3822
+ JBProjectToken as JBProjectToken2,
3823
+ jbTokensAbi as jbTokensAbi2
3824
+ } from "@bananapus/nana-sdk-core";
3633
3825
  import { getContract as getContract3 } from "viem";
3634
3826
  import { useAccount as useAccount2, useConfig as useConfig3, useReadContract as useReadContract8 } from "wagmi";
3635
3827
  import { useQuery as useQuery7 } from "wagmi/query";
3636
3828
  function useSuckersUserTokenBalance() {
3637
3829
  const config = useConfig3();
3638
3830
  const chainId = useJBChainId();
3639
- const { projectId, contractAddress } = useJBContractContext();
3831
+ const { projectId, version, contractAddress } = useJBContractContext();
3640
3832
  const { address: userAddress } = useAccount2();
3833
+ let jbTokensAddress;
3834
+ try {
3835
+ jbTokensAddress = chainId ? contractAddress(JBCoreContracts3.JBTokens) : void 0;
3836
+ } catch {
3837
+ jbTokensAddress = void 0;
3838
+ }
3641
3839
  const currentChainQuery = useReadContract8({
3642
3840
  abi: jbTokensAbi2,
3643
3841
  functionName: "totalBalanceOf",
3644
- address: contractAddress(JBCoreContracts2.JBTokens),
3842
+ address: jbTokensAddress,
3645
3843
  chainId,
3646
3844
  args: userAddress ? [userAddress, projectId] : void 0,
3647
3845
  query: {
3846
+ enabled: !!userAddress && !!jbTokensAddress,
3648
3847
  select(data) {
3649
3848
  return new JBProjectToken2(data);
3650
3849
  }
@@ -3652,10 +3851,15 @@ function useSuckersUserTokenBalance() {
3652
3851
  });
3653
3852
  const { data: pairs = [], isLoading, isError } = useSuckers();
3654
3853
  const balanceQuery = useQuery7({
3854
+ // The balances are keyed to a wallet and a protocol version as much as to a
3855
+ // project: without them a previous account's (or version's) balances are
3856
+ // served to the next one.
3655
3857
  queryKey: [
3656
3858
  "suckersUserTokenBalance",
3657
3859
  projectId.toString(),
3658
3860
  chainId?.toString(),
3861
+ version,
3862
+ userAddress,
3659
3863
  currentChainQuery.data?.value.toString(),
3660
3864
  pairs?.map((pair) => pair.peerChainId).join(",")
3661
3865
  ],
@@ -3673,11 +3877,14 @@ function useSuckersUserTokenBalance() {
3673
3877
  pairs.map(async (pair) => {
3674
3878
  const { peerChainId, projectId: projectId2 } = pair;
3675
3879
  const contract = getContract3({
3676
- address: contractAddress(JBCoreContracts2.JBTokens, peerChainId),
3880
+ address: contractAddress(JBCoreContracts3.JBTokens, peerChainId),
3677
3881
  abi: jbTokensAbi2,
3678
3882
  client: config.getClient({ chainId: peerChainId })
3679
3883
  });
3680
- const balance = await contract.read.totalBalanceOf([userAddress, projectId2]);
3884
+ const balance = await contract.read.totalBalanceOf([
3885
+ userAddress,
3886
+ projectId2
3887
+ ]);
3681
3888
  return {
3682
3889
  balance: new JBProjectToken2(balance),
3683
3890
  chainId: peerChainId,
@@ -3703,7 +3910,7 @@ import {
3703
3910
  getPrimaryNativeTerminal as getPrimaryNativeTerminal2,
3704
3911
  getProjectTerminalStore as getProjectTerminalStore2,
3705
3912
  jbTerminalStoreAbi as jbTerminalStoreAbi3,
3706
- NATIVE_TOKEN as NATIVE_TOKEN3
3913
+ NATIVE_TOKEN as NATIVE_TOKEN4
3707
3914
  } from "@bananapus/nana-sdk-core";
3708
3915
  import { getContract as getContract4 } from "viem";
3709
3916
  import { useConfig as useConfig4 } from "wagmi";
@@ -3714,10 +3921,13 @@ function useSuckersNativeTokenBalance() {
3714
3921
  const { projectId, version } = useJBContractContext();
3715
3922
  const { data: pairs = [], isLoading, isError } = useSuckers();
3716
3923
  const balanceQuery = useQuery8({
3924
+ // The terminal store address is version-specific, so the version is part of
3925
+ // the read's identity (as it already is in `useSuckersCashOutQuote`).
3717
3926
  queryKey: [
3718
3927
  "suckersNativeTokenBalance",
3719
3928
  projectId.toString(),
3720
3929
  chainId?.toString(),
3930
+ version,
3721
3931
  pairs.map((pair) => pair.peerChainId).join(",")
3722
3932
  ],
3723
3933
  queryFn: async () => {
@@ -3726,13 +3936,22 @@ function useSuckersNativeTokenBalance() {
3726
3936
  const balances = await Promise.all(
3727
3937
  pairs.map(async (pair) => {
3728
3938
  const { peerChainId, projectId: projectId2 } = pair;
3729
- const terminal = await getPrimaryNativeTerminal2(config, peerChainId, projectId2, version);
3939
+ const terminal = await getPrimaryNativeTerminal2(
3940
+ config,
3941
+ peerChainId,
3942
+ projectId2,
3943
+ version
3944
+ );
3730
3945
  const contract = getContract4({
3731
3946
  address: getProjectTerminalStore2(peerChainId, version),
3732
3947
  abi: jbTerminalStoreAbi3,
3733
3948
  client: config.getClient({ chainId: peerChainId })
3734
3949
  });
3735
- const balance = await contract.read.balanceOf([terminal, projectId2, NATIVE_TOKEN3]);
3950
+ const balance = await contract.read.balanceOf([
3951
+ terminal,
3952
+ projectId2,
3953
+ NATIVE_TOKEN4
3954
+ ]);
3736
3955
  return { balance, chainId: peerChainId, projectId: projectId2 };
3737
3956
  })
3738
3957
  );
@@ -3749,7 +3968,7 @@ function useSuckersNativeTokenBalance() {
3749
3968
  // src/hooks/ruleset/useJBRuleset.ts
3750
3969
  import {
3751
3970
  CashOutTaxRate as CashOutTaxRate2,
3752
- jbControllerAbi as jbControllerAbi3,
3971
+ jbControllerAbi as jbControllerAbi4,
3753
3972
  ReservedPercent as ReservedPercent2,
3754
3973
  RulesetWeight as RulesetWeight2,
3755
3974
  WeightCutPercent as WeightCutPercent2
@@ -3762,7 +3981,7 @@ function useJBRuleset({
3762
3981
  const { contracts, version } = useJBContractContext();
3763
3982
  const query = useReadContract9({
3764
3983
  chainId,
3765
- abi: jbControllerAbi3,
3984
+ abi: jbControllerAbi4,
3766
3985
  functionName: "currentRulesetOf",
3767
3986
  address: contracts?.controller?.data ?? void 0,
3768
3987
  args: projectId ? [projectId] : void 0,
@@ -3778,7 +3997,9 @@ function useJBRuleset({
3778
3997
  metadata: {
3779
3998
  ...rulesetMetadata,
3780
3999
  cashOutTaxRate: new CashOutTaxRate2(rulesetMetadata.cashOutTaxRate),
3781
- reservedPercent: new ReservedPercent2(rulesetMetadata.reservedPercent),
4000
+ reservedPercent: new ReservedPercent2(
4001
+ rulesetMetadata.reservedPercent
4002
+ ),
3782
4003
  // v4/v5 store the INVERSE flag (`useTotalSurplusForCashOuts`) in this slot;
3783
4004
  // normalize to the v6 field's semantics.
3784
4005
  scopeCashOutsToLocalBalances: version === 6 ? rulesetMetadata.scopeCashOutsToLocalBalances : !rulesetMetadata.scopeCashOutsToLocalBalances
@@ -3787,26 +4008,35 @@ function useJBRuleset({
3787
4008
  }
3788
4009
  }
3789
4010
  });
3790
- const { resolvedDataHook } = useResolveDataHook({
3791
- dataHookAddress: query.data?.metadata?.dataHook,
3792
- projectId,
3793
- chainId,
3794
- rulesetId: BigInt(query.data?.data?.id ?? 0)
3795
- });
4011
+ const rulesetId = query.data?.data?.id;
4012
+ const { resolvedDataHook, isLoading: isDataHookLoading } = useResolveDataHook(
4013
+ {
4014
+ dataHookAddress: query.data?.metadata?.dataHook,
4015
+ projectId,
4016
+ chainId,
4017
+ // Ruleset 0 is not a ruleset. Passing it as a real id would query the
4018
+ // deployer for a ruleset that cannot exist.
4019
+ rulesetId: rulesetId === void 0 ? void 0 : BigInt(rulesetId)
4020
+ }
4021
+ );
3796
4022
  return {
3797
4023
  ruleset: query.data?.data,
3798
- rulesetMetadata: query.data?.metadata && {
3799
- ...query.data.metadata,
3800
- dataHook: resolvedDataHook
3801
- },
3802
- ...query
4024
+ // Withhold the metadata until the data hook behind the omnichain deployer
4025
+ // is known, rather than publishing the deployer address as the hook.
4026
+ rulesetMetadata: query.data?.metadata && resolvedDataHook ? { ...query.data.metadata, dataHook: resolvedDataHook } : void 0,
4027
+ ...query,
4028
+ // A read disabled while its controller is still resolving reports
4029
+ // `isLoading: false`, which reads as "this project has no ruleset".
4030
+ isLoading: Boolean(
4031
+ query.isLoading || contracts?.controller?.isLoading || isDataHookLoading
4032
+ )
3803
4033
  };
3804
4034
  }
3805
4035
 
3806
4036
  // src/hooks/ruleset/useJBUpcomingRuleset.ts
3807
4037
  import {
3808
4038
  CashOutTaxRate as CashOutTaxRate3,
3809
- jbControllerAbi as jbControllerAbi4,
4039
+ jbControllerAbi as jbControllerAbi5,
3810
4040
  ReservedPercent as ReservedPercent3,
3811
4041
  RulesetWeight as RulesetWeight3,
3812
4042
  WeightCutPercent as WeightCutPercent3
@@ -3817,40 +4047,40 @@ function useJBUpcomingRuleset({
3817
4047
  chainId
3818
4048
  }) {
3819
4049
  const { contracts, version } = useJBContractContext();
4050
+ const controllerAddress = contracts.controller?.data ?? void 0;
3820
4051
  const { data, isLoading } = useReadContract10({
3821
- abi: jbControllerAbi4,
4052
+ abi: jbControllerAbi5,
3822
4053
  functionName: "upcomingRulesetOf",
3823
- address: contracts.controller?.data ?? void 0,
4054
+ address: controllerAddress,
3824
4055
  args: projectId ? [projectId] : void 0,
3825
4056
  chainId
3826
4057
  });
3827
4058
  const _latestUpcomingRuleset = data?.[0];
3828
4059
  const _latestUpcomingRulesetMetadata = data?.[1];
3829
- const { resolvedDataHook } = useResolveDataHook({
3830
- dataHookAddress: _latestUpcomingRulesetMetadata?.dataHook,
3831
- projectId,
3832
- chainId,
3833
- rulesetId: BigInt(_latestUpcomingRuleset?.id ?? 0)
3834
- });
3835
- const upcomingWeight = new RulesetWeight3(_latestUpcomingRuleset?.weight ?? 0n);
3836
- const upcomingWeightCutPercent = new WeightCutPercent3(
3837
- _latestUpcomingRuleset?.weightCutPercent ?? 0
4060
+ const { resolvedDataHook, isLoading: isDataHookLoading } = useResolveDataHook(
4061
+ {
4062
+ dataHookAddress: _latestUpcomingRulesetMetadata?.dataHook,
4063
+ projectId,
4064
+ chainId,
4065
+ // Ruleset 0 is not a ruleset; don't fabricate one for the deployer lookup.
4066
+ rulesetId: _latestUpcomingRuleset?.id === void 0 ? void 0 : BigInt(_latestUpcomingRuleset.id)
4067
+ }
3838
4068
  );
3839
4069
  const latestUpcomingRuleset = _latestUpcomingRuleset ? {
3840
4070
  ..._latestUpcomingRuleset,
3841
- weight: upcomingWeight,
3842
- weightCutPercent: upcomingWeightCutPercent
4071
+ weight: new RulesetWeight3(_latestUpcomingRuleset.weight),
4072
+ weightCutPercent: new WeightCutPercent3(
4073
+ _latestUpcomingRuleset.weightCutPercent
4074
+ )
3843
4075
  } : void 0;
3844
- const upcomingReservedPercent = new ReservedPercent3(
3845
- _latestUpcomingRulesetMetadata?.reservedPercent ?? 0
3846
- );
3847
- const upcomingCashOutTaxRate = new CashOutTaxRate3(
3848
- _latestUpcomingRulesetMetadata?.cashOutTaxRate ?? 0
3849
- );
3850
- const latestUpcomingRulesetMetadata = _latestUpcomingRulesetMetadata ? {
4076
+ const latestUpcomingRulesetMetadata = _latestUpcomingRulesetMetadata && resolvedDataHook ? {
3851
4077
  ..._latestUpcomingRulesetMetadata,
3852
- reservedPercent: upcomingReservedPercent,
3853
- cashOutTaxRate: upcomingCashOutTaxRate,
4078
+ reservedPercent: new ReservedPercent3(
4079
+ _latestUpcomingRulesetMetadata.reservedPercent
4080
+ ),
4081
+ cashOutTaxRate: new CashOutTaxRate3(
4082
+ _latestUpcomingRulesetMetadata.cashOutTaxRate
4083
+ ),
3854
4084
  // v4/v5 store the INVERSE flag (`useTotalSurplusForCashOuts`) in this slot;
3855
4085
  // normalize to the v6 field's semantics.
3856
4086
  scopeCashOutsToLocalBalances: version === 6 ? _latestUpcomingRulesetMetadata.scopeCashOutsToLocalBalances : !_latestUpcomingRulesetMetadata.scopeCashOutsToLocalBalances,
@@ -3859,19 +4089,32 @@ function useJBUpcomingRuleset({
3859
4089
  return {
3860
4090
  ruleset: latestUpcomingRuleset,
3861
4091
  rulesetMetadata: latestUpcomingRulesetMetadata,
3862
- isLoading
4092
+ // A read disabled while its controller is still resolving reports
4093
+ // `isLoading: false`, which reads as "there is no upcoming ruleset".
4094
+ isLoading: Boolean(
4095
+ isLoading || contracts.controller?.isLoading || isDataHookLoading
4096
+ )
3863
4097
  };
3864
4098
  }
3865
4099
 
3866
4100
  // src/contexts/JBContractContext/JBContractContext.tsx
3867
4101
  import { useReadContract as useReadContract11 } from "wagmi";
3868
4102
  import { jsx as jsx10 } from "react/jsx-runtime";
4103
+ function outsideProvider() {
4104
+ throw new Error(
4105
+ "JBContractContext was read outside a JBContractProvider. Wrap the tree in JBProjectProvider or JBContractProvider."
4106
+ );
4107
+ }
3869
4108
  var JBContractContext = createContext8({
3870
4109
  /**
3871
4110
  * The project id of the Juicebox project.
3872
4111
  */
3873
- projectId: 0n,
3874
- version: 5,
4112
+ get projectId() {
4113
+ return outsideProvider();
4114
+ },
4115
+ get version() {
4116
+ return outsideProvider();
4117
+ },
3875
4118
  /**
3876
4119
  * The addresses of the contracts for the project.
3877
4120
  */
@@ -3883,7 +4126,7 @@ var JBContractContext = createContext8({
3883
4126
  tokens: AsyncDataNone,
3884
4127
  splits: AsyncDataNone
3885
4128
  },
3886
- contractAddress: () => zeroAddress4
4129
+ contractAddress: outsideProvider
3887
4130
  });
3888
4131
  function useJBContractContext() {
3889
4132
  return useContext8(JBContractContext);
@@ -3904,7 +4147,9 @@ function useJBProjectId(chainId) {
3904
4147
  if (!chainId || currentChainId === chainId || !suckers) {
3905
4148
  return { projectId: currentProjectId, chainId: currentChainId, version };
3906
4149
  }
3907
- const projectId = suckers.find((suckerPair) => suckerPair.peerChainId === chainId)?.projectId;
4150
+ const projectId = suckers.find(
4151
+ (suckerPair) => suckerPair.peerChainId === chainId
4152
+ )?.projectId;
3908
4153
  return { projectId, chainId, version };
3909
4154
  }
3910
4155
  var JBContractProvider = ({
@@ -3921,28 +4166,38 @@ var JBContractProvider = ({
3921
4166
  },
3922
4167
  [include]
3923
4168
  );
3924
- const jbDirectoryAddress = chainId ? jbContractAddress2[version][JBCoreContracts3.JBDirectory][chainId] : void 0;
4169
+ const jbDirectoryAddress = chainId ? jbContractAddress2[version][JBCoreContracts4.JBDirectory][chainId] : void 0;
3925
4170
  const primaryNativeTerminalEth = useReadContract11({
3926
4171
  address: jbDirectoryAddress,
3927
- abi: jbDirectoryAbi,
4172
+ abi: jbDirectoryAbi2,
3928
4173
  functionName: "primaryTerminalOf",
3929
4174
  chainId,
3930
- args: enabled([1 /* PrimaryNativePaymentTerminal */]) ? [projectId, NATIVE_TOKEN4] : void 0
4175
+ args: enabled([1 /* PrimaryNativePaymentTerminal */]) ? [projectId, NATIVE_TOKEN5] : void 0
3931
4176
  });
4177
+ const usdcAddress = chainId ? USDC_ADDRESSES[chainId] : void 0;
3932
4178
  const primaryNativeTerminalUsdc = useReadContract11({
3933
4179
  address: jbDirectoryAddress,
3934
- abi: jbDirectoryAbi,
4180
+ abi: jbDirectoryAbi2,
3935
4181
  functionName: "primaryTerminalOf",
3936
4182
  chainId,
3937
- args: enabled([1 /* PrimaryNativePaymentTerminal */]) ? [projectId, chainId ? USDC_ADDRESSES[chainId] : zeroAddress4] : void 0
4183
+ args: usdcAddress && enabled([1 /* PrimaryNativePaymentTerminal */]) ? [projectId, usdcAddress] : void 0
3938
4184
  });
3939
4185
  const primaryNativeTerminal = useMemo5(() => {
3940
- return primaryNativeTerminalEth.data !== zeroAddress4 ? primaryNativeTerminalEth : primaryNativeTerminalUsdc;
4186
+ const isTerminal = (address) => address !== void 0 && !isAddressEqual4(address, zeroAddress4);
4187
+ if (isTerminal(primaryNativeTerminalEth.data))
4188
+ return primaryNativeTerminalEth;
4189
+ if (isTerminal(primaryNativeTerminalUsdc.data))
4190
+ return primaryNativeTerminalUsdc;
4191
+ return {
4192
+ ...primaryNativeTerminalEth,
4193
+ data: void 0,
4194
+ isLoading: primaryNativeTerminalEth.isLoading || primaryNativeTerminalUsdc.isLoading
4195
+ };
3941
4196
  }, [primaryNativeTerminalEth, primaryNativeTerminalUsdc]);
3942
4197
  const controller = useReadContract11({
3943
4198
  chainId,
3944
4199
  address: jbDirectoryAddress,
3945
- abi: jbDirectoryAbi,
4200
+ abi: jbDirectoryAbi2,
3946
4201
  functionName: "controllerOf",
3947
4202
  args: [projectId],
3948
4203
  query: {
@@ -3952,82 +4207,79 @@ var JBContractProvider = ({
3952
4207
  });
3953
4208
  const controllerAddress = useMemo5(() => controller.data, [controller.data]);
3954
4209
  const hasController = useMemo5(() => {
3955
- return controllerAddress && !isAddressEqual4(controllerAddress, zeroAddress4);
4210
+ return Boolean(
4211
+ controllerAddress && !isAddressEqual4(controllerAddress, zeroAddress4)
4212
+ );
3956
4213
  }, [controllerAddress]);
3957
- const normalizedControllerAddress = useMemo5(() => {
3958
- return hasController ? controllerAddress : zeroAddress4;
4214
+ const resolvedControllerAddress = useMemo5(() => {
4215
+ return hasController ? controllerAddress : void 0;
3959
4216
  }, [controllerAddress, hasController]);
3960
4217
  const fundAccessLimits = useReadContract11({
3961
4218
  chainId,
3962
- address: normalizedControllerAddress,
3963
- abi: jbControllerAbi5,
4219
+ address: resolvedControllerAddress,
4220
+ abi: jbControllerAbi6,
3964
4221
  functionName: "FUND_ACCESS_LIMITS",
3965
4222
  query: {
3966
- enabled: enabled([0 /* Controller */, 2 /* FundAccessLimits */]),
4223
+ enabled: hasController && enabled([0 /* Controller */, 2 /* FundAccessLimits */]),
3967
4224
  staleTime: Infinity
3968
4225
  }
3969
4226
  });
3970
4227
  const rulesets = useReadContract11({
3971
4228
  chainId,
3972
- address: normalizedControllerAddress,
3973
- abi: jbControllerAbi5,
4229
+ address: resolvedControllerAddress,
4230
+ abi: jbControllerAbi6,
3974
4231
  functionName: "RULESETS",
3975
4232
  query: {
3976
- enabled: enabled([0 /* Controller */, 5 /* Rulesets */]),
4233
+ enabled: hasController && enabled([0 /* Controller */, 5 /* Rulesets */]),
3977
4234
  staleTime: Infinity
3978
4235
  }
3979
4236
  });
3980
4237
  const tokens = useReadContract11({
3981
4238
  chainId,
3982
- address: normalizedControllerAddress,
3983
- abi: jbControllerAbi5,
4239
+ address: resolvedControllerAddress,
4240
+ abi: jbControllerAbi6,
3984
4241
  functionName: "TOKENS",
3985
4242
  query: {
3986
- enabled: enabled([0 /* Controller */, 3 /* Tokens */]),
4243
+ enabled: hasController && enabled([0 /* Controller */, 3 /* Tokens */]),
3987
4244
  staleTime: Infinity
3988
4245
  }
3989
4246
  });
3990
4247
  const splits = useReadContract11({
3991
4248
  chainId,
3992
- address: normalizedControllerAddress,
3993
- abi: jbControllerAbi5,
4249
+ address: resolvedControllerAddress,
4250
+ abi: jbControllerAbi6,
3994
4251
  functionName: "SPLITS",
3995
4252
  query: {
3996
- enabled: enabled([0 /* Controller */, 4 /* Splits */]),
4253
+ enabled: hasController && enabled([0 /* Controller */, 4 /* Splits */]),
3997
4254
  staleTime: Infinity
3998
4255
  }
3999
4256
  });
4257
+ const dependent = (query) => ({
4258
+ ...query,
4259
+ isLoading: Boolean(query.isLoading || controller.isLoading)
4260
+ });
4000
4261
  const contractAddress = useCallback(
4001
4262
  (contract, _chainId) => {
4002
- return getJBContractAddress2(contract, version, _chainId || chainId);
4263
+ return getJBContractAddress3(contract, version, _chainId || chainId);
4003
4264
  },
4004
4265
  [version, chainId]
4005
4266
  );
4006
- debug10("JBContractContext", {
4007
- projectId,
4008
- contracts: {
4009
- controller,
4010
- fundAccessLimits,
4011
- primaryNativeTerminal,
4012
- rulesets,
4013
- tokens,
4014
- splits
4015
- }
4016
- });
4267
+ const contracts = {
4268
+ controller,
4269
+ fundAccessLimits: dependent(fundAccessLimits),
4270
+ primaryNativeTerminal,
4271
+ rulesets: dependent(rulesets),
4272
+ tokens: dependent(tokens),
4273
+ splits: dependent(splits)
4274
+ };
4275
+ debug10("JBContractContext", { projectId, contracts });
4017
4276
  return /* @__PURE__ */ jsx10(
4018
4277
  JBContractContext.Provider,
4019
4278
  {
4020
4279
  value: {
4021
4280
  version,
4022
4281
  projectId,
4023
- contracts: {
4024
- controller,
4025
- fundAccessLimits,
4026
- primaryNativeTerminal,
4027
- rulesets,
4028
- tokens,
4029
- splits
4030
- },
4282
+ contracts,
4031
4283
  contractAddress
4032
4284
  },
4033
4285
  children
@@ -4040,7 +4292,9 @@ var API = "https://api.relayr.ba5ed.com";
4040
4292
  var DASHBOARD = "https://relayr.ba5ed.com";
4041
4293
 
4042
4294
  // src/lib/relayr/hooks/useRequestRelayrQuote.ts
4043
- import { jbContractAddress as jbContractAddress3 } from "@bananapus/nana-sdk-core";
4295
+ import {
4296
+ jbContractAddress as jbContractAddress3
4297
+ } from "@bananapus/nana-sdk-core";
4044
4298
  import { useMutation } from "wagmi/query";
4045
4299
  function useRequestRelayrQuote() {
4046
4300
  const { version: contextVersion } = useJBContractContext();
@@ -4226,7 +4480,9 @@ function useGetRelayrTxBundle() {
4226
4480
  hasFailed,
4227
4481
  uuid,
4228
4482
  response: getRelayrTxBundle.data,
4229
- isPolling: !!uuid && !isComplete && !hasFailed,
4483
+ // A bundle whose fetches keep erroring is not still polling: without the
4484
+ // error term a consumer's spinner never stops.
4485
+ isPolling: !!uuid && !isComplete && !hasFailed && !getRelayrTxBundle.error,
4230
4486
  isFetching: getRelayrTxBundle.isFetching,
4231
4487
  error: getRelayrTxBundle.error
4232
4488
  };
@@ -4241,25 +4497,20 @@ function useSendRelayrTx() {
4241
4497
  const _sendTransaction = useSendTransaction();
4242
4498
  const sendRelayrTx = useCallback3(
4243
4499
  async (chainPayment) => {
4244
- try {
4245
- if (chainId !== chainPayment.chain) {
4246
- try {
4247
- await switchChainAsync({ chainId: chainPayment.chain });
4248
- } catch (e) {
4249
- console.error(e);
4250
- throw new Error("Failed to switch to correct chain");
4251
- }
4500
+ if (chainId !== chainPayment.chain) {
4501
+ try {
4502
+ await switchChainAsync({ chainId: chainPayment.chain });
4503
+ } catch (e) {
4504
+ console.error(e);
4505
+ throw new Error("Failed to switch to correct chain");
4252
4506
  }
4253
- const tx = await _sendTransaction.sendTransactionAsync({
4254
- chainId: chainPayment.chain,
4255
- to: chainPayment.target,
4256
- value: BigInt(chainPayment.amount),
4257
- data: chainPayment.calldata
4258
- });
4259
- return tx;
4260
- } catch (error) {
4261
- throw error;
4262
4507
  }
4508
+ return await _sendTransaction.sendTransactionAsync({
4509
+ chainId: chainPayment.chain,
4510
+ to: chainPayment.target,
4511
+ value: BigInt(chainPayment.amount),
4512
+ data: chainPayment.calldata
4513
+ });
4263
4514
  },
4264
4515
  [_sendTransaction.sendTransactionAsync, chainId, switchChainAsync]
4265
4516
  );
@@ -4274,6 +4525,7 @@ function useSendRelayrTx() {
4274
4525
  export {
4275
4526
  API,
4276
4527
  DASHBOARD,
4528
+ DEFAULT_ETHER_PRICE_ENDPOINT,
4277
4529
  DynamicContract,
4278
4530
  JBChainContext,
4279
4531
  JBChainProvider,