@ape.swap/bonds-sdk 5.1.49-test.2 → 5.1.49-test.4

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 (46) hide show
  1. package/dist/config/constants/chains.js +1 -1
  2. package/dist/config/constants/chains.js.map +1 -1
  3. package/dist/config/constants/suiCallbacks.d.ts +2 -0
  4. package/dist/config/constants/suiCallbacks.js +17 -0
  5. package/dist/config/constants/suiCallbacks.js.map +1 -0
  6. package/dist/config/constants/suiZapTokens.js +19 -7
  7. package/dist/config/constants/suiZapTokens.js.map +1 -1
  8. package/dist/constants/suiConstants.d.ts +1 -7
  9. package/dist/constants/suiConstants.js +6 -34
  10. package/dist/constants/suiConstants.js.map +1 -1
  11. package/dist/state/bonds/discoverSuiBonds.d.ts +6 -0
  12. package/dist/state/bonds/fetchBondsDataSui.js +38 -11
  13. package/dist/state/bonds/fetchBondsDataSui.js.map +1 -1
  14. package/dist/state/bonds/useBondsData.js +17 -9
  15. package/dist/state/bonds/useBondsData.js.map +1 -1
  16. package/dist/state/bonds/useBondsList.js +22 -22
  17. package/dist/state/bonds/useBondsList.js.map +1 -1
  18. package/dist/state/tokenPrices/useTokenPrices.js +1 -13
  19. package/dist/state/tokenPrices/useTokenPrices.js.map +1 -1
  20. package/dist/state/useSDKConfig.d.ts +2 -0
  21. package/dist/state/useSDKConfig.js +6 -0
  22. package/dist/state/useSDKConfig.js.map +1 -1
  23. package/dist/state/zap/useSuiZapQuote.js +5 -28
  24. package/dist/state/zap/useSuiZapQuote.js.map +1 -1
  25. package/dist/utils/suiHelpers.d.ts +1 -1
  26. package/dist/utils/suiHelpers.js +5 -5
  27. package/dist/utils/suiHelpers.js.map +1 -1
  28. package/dist/views/BuyBond/BuyComponentSui.js +133 -57
  29. package/dist/views/BuyBond/BuyComponentSui.js.map +1 -1
  30. package/dist/views/BuyBond/utils.js +3 -0
  31. package/dist/views/BuyBond/utils.js.map +1 -1
  32. package/dist/views/YourBonds/components/UserBondRow/UserBondRowSui.js +2 -2
  33. package/dist/views/YourBonds/components/UserBondRow/UserBondRowSui.js.map +1 -1
  34. package/dist/views/YourBondsModal/components/Actions/ActionsSui.js +2 -2
  35. package/dist/views/YourBondsModal/components/Actions/ActionsSui.js.map +1 -1
  36. package/dist/views/YourBondsModal/components/TransferBondModal/TransferActionSui.d.ts +9 -0
  37. package/dist/views/YourBondsModal/components/TransferBondModal/TransferActionSui.js +71 -0
  38. package/dist/views/YourBondsModal/components/TransferBondModal/TransferActionSui.js.map +1 -0
  39. package/dist/views/YourBondsModal/components/TransferBondModal/index.js +2 -1
  40. package/dist/views/YourBondsModal/components/TransferBondModal/index.js.map +1 -1
  41. package/package.json +1 -1
  42. package/dist/state/bonds/aptosBondsConfig.js +0 -183
  43. package/dist/state/bonds/aptosBondsConfig.js.map +0 -1
  44. package/dist/state/bonds/suiBondsConfig.d.ts +0 -4
  45. package/dist/state/bonds/suiBondsConfig.js +0 -227
  46. package/dist/state/bonds/suiBondsConfig.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useBondsList.js","sources":["../../../src/state/bonds/useBondsList.ts"],"sourcesContent":["import { QueryClient, useQuery, useQueryClient, UseQueryResult } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport axios from 'axios'\nimport { BillsConfig, ChainId } from '@ape.swap/apeswap-lists'\nimport { reportError } from '../../utils/reportError'\nimport { SDKProps } from '../useSDKConfig'\nimport { getAptosBondsList } from './aptosBondsConfig'\nimport { getSuiBondsList } from './suiBondsConfig'\n\nexport default function useBondsList(): UseQueryResult<BillsConfig[]> {\n const queryClient = useQueryClient()\n return useQuery({\n queryKey: [QUERY_KEYS.BONDS_LIST],\n queryFn: () => getBondsList(queryClient),\n staleTime: Infinity,\n refetchInterval: 300000, // 5 min\n refetchOnWindowFocus: false,\n })\n}\n\nexport const getBondsList = async (queryClient: QueryClient): Promise<BillsConfig[]> => {\n const { urls, customBranch } = queryClient?.getQueryData([QUERY_KEYS.SDK_CONFIG]) as SDKProps\n const realTimeApiURL = urls['realTimeApi']\n const apiUrl = urls['apiV2']\n\n try {\n const response = await axios.get(`${realTimeApiURL}/utils/bonds${customBranch ? `?branch=${customBranch}` : ''}`)\n // TODO remove this fallback, from now on bonds should be fetched from list repo 'feat/sui-aptos' branch. Also remove try-catch\n\n // Always include static Aptos + Sui configs alongside API bonds\n const apiData: BillsConfig[] = response.data ?? []\n const aptosBonds = apiData.some((b) => b.chainId === ChainId.APTOS) ? [] : getAptosBondsList()\n const suiBonds = getSuiBondsList()\n return [...apiData, ...aptosBonds, ...suiBonds]\n } catch (e) {\n reportError({\n apiUrl,\n error: e,\n extraInfo: { type: 'getBondsList', e },\n })\n return [...getAptosBondsList(), ...getSuiBondsList()]\n }\n}\n"],"names":[],"mappings":";;;;;;;;AASc,SAAU,YAAY,GAAA;AAClC,IAAA,MAAM,WAAW,GAAG,cAAc,EAAE;AACpC,IAAA,OAAO,QAAQ,CAAC;AACd,QAAA,QAAQ,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;AACjC,QAAA,OAAO,EAAE,MAAM,YAAY,CAAC,WAAW,CAAC;AACxC,QAAA,SAAS,EAAE,QAAQ;QACnB,eAAe,EAAE,MAAM;AACvB,QAAA,oBAAoB,EAAE,KAAK;AAC5B,KAAA,CAAC;AACJ;MAEa,YAAY,GAAG,OAAO,WAAwB,KAA4B;AACrF,IAAA,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,WAAW,EAAE,YAAY,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAa;AAC7F,IAAA,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC;AAC1C,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;AAE5B,IAAA,IAAI;QACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA,EAAG,cAAc,CAAA,YAAA,EAAe,YAAY,GAAG,CAAA,QAAA,EAAW,YAAY,CAAA,CAAE,GAAG,EAAE,CAAA,CAAE,CAAC;;;AAIjH,QAAA,MAAM,OAAO,GAAkB,QAAQ,CAAC,IAAI,IAAI,EAAE;AAClD,QAAA,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,iBAAiB,EAAE;AAC9F,QAAA,MAAM,QAAQ,GAAG,eAAe,EAAE;QAClC,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ,CAAC;IACjD;IAAE,OAAO,CAAC,EAAE;AACV,QAAA,WAAW,CAAC;YACV,MAAM;AACN,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,SAAS,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE;AACvC,SAAA,CAAC;QACF,OAAO,CAAC,GAAG,iBAAiB,EAAE,EAAE,GAAG,eAAe,EAAE,CAAC;IACvD;AACF;;;;"}
1
+ {"version":3,"file":"useBondsList.js","sources":["../../../src/state/bonds/useBondsList.ts"],"sourcesContent":["import { QueryClient, useQuery, useQueryClient, UseQueryResult } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport axios from 'axios'\nimport { BillsConfig } from '@ape.swap/apeswap-lists'\nimport { SDKProps } from '../useSDKConfig'\n\nexport default function useBondsList(): UseQueryResult<BillsConfig[]> {\n const queryClient = useQueryClient()\n return useQuery({\n queryKey: [QUERY_KEYS.BONDS_LIST],\n queryFn: () => getBondsList(queryClient),\n staleTime: Infinity,\n refetchInterval: 300000, // 5 min\n refetchOnWindowFocus: false,\n })\n}\n\nexport const getBondsList = async (queryClient: QueryClient): Promise<BillsConfig[]> => {\n const { urls, customBranch } = queryClient?.getQueryData([QUERY_KEYS.SDK_CONFIG]) as SDKProps\n const realTimeApiURL = urls['realTimeApi']\n\n const response = await axios.get(`${realTimeApiURL}/utils/bonds${customBranch ? `?branch=${customBranch}` : ''}`)\n return response.data\n //\n // try {\n // const response = await axios.get(`${realTimeApiURL}/utils/bonds${customBranch ? `?branch=${customBranch}` : ''}`)\n // // TODO remove this fallback, from now on bonds should be fetched from list repo 'feat/sui-aptos' branch. Also remove try-catch\n //\n // // Always include static Aptos + discovered Sui configs alongside API bonds\n // const apiData: BillsConfig[] = response.data ?? []\n // const nonSuiApiData = apiData.filter((b) => b.chainId !== ChainId.SUI)\n // const aptosBonds = apiData.some((b) => b.chainId === ChainId.APTOS) ? [] : getAptosBondsList()\n // const suiBonds = await discoverSuiBonds(suiTreasuryAddresses)\n // return [...nonSuiApiData, ...aptosBonds, ...suiBonds]\n // } catch (e) {\n // reportError({\n // apiUrl,\n // error: e,\n // extraInfo: { type: 'getBondsList', e },\n // })\n // const suiBonds = await discoverSuiBonds(suiTreasuryAddresses)\n // return [...getAptosBondsList(), ...suiBonds]\n // }\n}\n"],"names":[],"mappings":";;;;AAMc,SAAU,YAAY,GAAA;AAClC,IAAA,MAAM,WAAW,GAAG,cAAc,EAAE;AACpC,IAAA,OAAO,QAAQ,CAAC;AACd,QAAA,QAAQ,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;AACjC,QAAA,OAAO,EAAE,MAAM,YAAY,CAAC,WAAW,CAAC;AACxC,QAAA,SAAS,EAAE,QAAQ;QACnB,eAAe,EAAE,MAAM;AACvB,QAAA,oBAAoB,EAAE,KAAK;AAC5B,KAAA,CAAC;AACJ;MAEa,YAAY,GAAG,OAAO,WAAwB,KAA4B;AACrF,IAAA,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,WAAW,EAAE,YAAY,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAa;AAC7F,IAAA,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC;IAE1C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA,EAAG,cAAc,CAAA,YAAA,EAAe,YAAY,GAAG,CAAA,QAAA,EAAW,YAAY,CAAA,CAAE,GAAG,EAAE,CAAA,CAAE,CAAC;IACjH,OAAO,QAAQ,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;AAqBtB;;;;"}
@@ -1,10 +1,8 @@
1
1
  import { useQuery } from '@tanstack/react-query';
2
2
  import axios from 'axios';
3
- import { ChainId } from '@ape.swap/apeswap-lists';
4
3
  import { QUERY_KEYS } from '../../config/constants/queryKeys.js';
5
4
  import { useSDKConfig } from '../useSDKConfig.js';
6
5
  import { reportError } from '../../utils/reportError.js';
7
- import { getSuiFallbackPrices } from '../bonds/suiBondsConfig.js';
8
6
 
9
7
  function useTokenPrices() {
10
8
  const SDKConfig = useSDKConfig();
@@ -21,17 +19,7 @@ function useTokenPrices() {
21
19
  const getTokenPrices = async (priceApi, apiv2) => {
22
20
  try {
23
21
  const response = await axios.get(`${priceApi}/realtime/prices`);
24
- const data = response.data ?? {};
25
- // Merge fallback prices for Sui tokens not returned by price-api (e.g. testnet tokens)
26
- const suiKey = ChainId.SUI;
27
- const suiFallback = getSuiFallbackPrices();
28
- const suiApiPrices = data[suiKey] ?? [];
29
- const suiApiAddresses = new Set(suiApiPrices.map((p) => p.tokenAddress.toLowerCase()));
30
- const missingSuiPrices = suiFallback.filter((p) => !suiApiAddresses.has(p.tokenAddress.toLowerCase()));
31
- if (missingSuiPrices.length > 0) {
32
- data[suiKey] = [...suiApiPrices, ...missingSuiPrices];
33
- }
34
- return data;
22
+ return response.data;
35
23
  }
36
24
  catch (error) {
37
25
  reportError({
@@ -1 +1 @@
1
- {"version":3,"file":"useTokenPrices.js","sources":["../../../src/state/tokenPrices/useTokenPrices.ts"],"sourcesContent":["import { useQuery, UseQueryResult } from '@tanstack/react-query'\nimport axios from 'axios'\nimport { ChainId } from '@ape.swap/apeswap-lists'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport { useSDKConfig } from '../useSDKConfig'\nimport { reportError } from '../../utils/reportError'\nimport { getSuiFallbackPrices } from '../bonds/suiBondsConfig'\n\nexport interface TokenPrices {\n chainId: ChainId\n chainName: string\n tokenAddress: string\n name: string\n symbol: string\n price: number\n priceSource: string\n updatedAt: number\n secondsAgoUpdated: number\n error?: string\n}\n\nexport default function useTokenPrices(): UseQueryResult<Partial<Record<ChainId, TokenPrices[]>>> {\n const SDKConfig = useSDKConfig()\n const priceApi = SDKConfig?.urls?.priceApi\n const apiv2 = SDKConfig?.urls?.apiV2\n return useQuery({\n queryKey: [QUERY_KEYS.TOKEN_PRICES],\n queryFn: () => getTokenPrices(priceApi, apiv2),\n refetchInterval: 30000, // 30 sec\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n })\n}\n\nexport const getTokenPrices = async (\n priceApi: string,\n apiv2: string,\n): Promise<Partial<Record<ChainId, TokenPrices[]>>> => {\n try {\n const response = await axios.get(`${priceApi}/realtime/prices`)\n const data: Partial<Record<ChainId, TokenPrices[]>> = response.data ?? {}\n\n // Merge fallback prices for Sui tokens not returned by price-api (e.g. testnet tokens)\n const suiKey = ChainId.SUI\n const suiFallback = getSuiFallbackPrices()\n const suiApiPrices = data[suiKey] ?? []\n const suiApiAddresses = new Set(suiApiPrices.map((p) => p.tokenAddress.toLowerCase()))\n const missingSuiPrices = suiFallback.filter((p) => !suiApiAddresses.has(p.tokenAddress.toLowerCase()))\n if (missingSuiPrices.length > 0) {\n data[suiKey] = [...suiApiPrices, ...missingSuiPrices]\n }\n\n return data\n } catch (error) {\n reportError({\n apiUrl: apiv2,\n error,\n extraInfo: { type: 'getTokenPrices', error },\n })\n throw new Error('Error getting tokens')\n }\n}\n"],"names":[],"mappings":";;;;;;;;AAqBc,SAAU,cAAc,GAAA;AACpC,IAAA,MAAM,SAAS,GAAG,YAAY,EAAE;AAChC,IAAA,MAAM,QAAQ,GAAG,SAAS,EAAE,IAAI,EAAE,QAAQ;AAC1C,IAAA,MAAM,KAAK,GAAG,SAAS,EAAE,IAAI,EAAE,KAAK;AACpC,IAAA,OAAO,QAAQ,CAAC;AACd,QAAA,QAAQ,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QACnC,OAAO,EAAE,MAAM,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC;QAC9C,eAAe,EAAE,KAAK;AACtB,QAAA,cAAc,EAAE,KAAK;AACrB,QAAA,oBAAoB,EAAE,KAAK;AAC5B,KAAA,CAAC;AACJ;AAEO,MAAM,cAAc,GAAG,OAC5B,QAAgB,EAChB,KAAa,KACuC;AACpD,IAAA,IAAI;QACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA,EAAG,QAAQ,CAAA,gBAAA,CAAkB,CAAC;AAC/D,QAAA,MAAM,IAAI,GAA4C,QAAQ,CAAC,IAAI,IAAI,EAAE;;AAGzE,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG;AAC1B,QAAA,MAAM,WAAW,GAAG,oBAAoB,EAAE;QAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;QACvC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;QACtF,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;AACtG,QAAA,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE;YAC/B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,gBAAgB,CAAC;QACvD;AAEA,QAAA,OAAO,IAAI;IACb;IAAE,OAAO,KAAK,EAAE;AACd,QAAA,WAAW,CAAC;AACV,YAAA,MAAM,EAAE,KAAK;YACb,KAAK;AACL,YAAA,SAAS,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE;AAC7C,SAAA,CAAC;AACF,QAAA,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC;IACzC;AACF;;;;"}
1
+ {"version":3,"file":"useTokenPrices.js","sources":["../../../src/state/tokenPrices/useTokenPrices.ts"],"sourcesContent":["import { useQuery, UseQueryResult } from '@tanstack/react-query'\nimport axios from 'axios'\nimport { ChainId } from '@ape.swap/apeswap-lists'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport { useSDKConfig } from '../useSDKConfig'\nimport { reportError } from '../../utils/reportError'\n\nexport interface TokenPrices {\n chainId: ChainId\n chainName: string\n tokenAddress: string\n name: string\n symbol: string\n price: number\n priceSource: string\n updatedAt: number\n secondsAgoUpdated: number\n error?: string\n}\n\nexport default function useTokenPrices(): UseQueryResult<Partial<Record<ChainId, TokenPrices[]>>> {\n const SDKConfig = useSDKConfig()\n const priceApi = SDKConfig?.urls?.priceApi\n const apiv2 = SDKConfig?.urls?.apiV2\n return useQuery({\n queryKey: [QUERY_KEYS.TOKEN_PRICES],\n queryFn: () => getTokenPrices(priceApi, apiv2),\n refetchInterval: 30000, // 30 sec\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n })\n}\n\nexport const getTokenPrices = async (\n priceApi: string,\n apiv2: string,\n): Promise<Partial<Record<ChainId, TokenPrices[]>>> => {\n try {\n const response = await axios.get(`${priceApi}/realtime/prices`)\n return response.data\n } catch (error) {\n reportError({\n apiUrl: apiv2,\n error,\n extraInfo: { type: 'getTokenPrices', error },\n })\n throw new Error('Error getting tokens')\n }\n}\n"],"names":[],"mappings":";;;;;;AAoBc,SAAU,cAAc,GAAA;AACpC,IAAA,MAAM,SAAS,GAAG,YAAY,EAAE;AAChC,IAAA,MAAM,QAAQ,GAAG,SAAS,EAAE,IAAI,EAAE,QAAQ;AAC1C,IAAA,MAAM,KAAK,GAAG,SAAS,EAAE,IAAI,EAAE,KAAK;AACpC,IAAA,OAAO,QAAQ,CAAC;AACd,QAAA,QAAQ,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QACnC,OAAO,EAAE,MAAM,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC;QAC9C,eAAe,EAAE,KAAK;AACtB,QAAA,cAAc,EAAE,KAAK;AACrB,QAAA,oBAAoB,EAAE,KAAK;AAC5B,KAAA,CAAC;AACJ;AAEO,MAAM,cAAc,GAAG,OAC5B,QAAgB,EAChB,KAAa,KACuC;AACpD,IAAA,IAAI;QACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA,EAAG,QAAQ,CAAA,gBAAA,CAAkB,CAAC;QAC/D,OAAO,QAAQ,CAAC,IAAI;IACtB;IAAE,OAAO,KAAK,EAAE;AACd,QAAA,WAAW,CAAC;AACV,YAAA,MAAM,EAAE,KAAK;YACb,KAAK;AACL,YAAA,SAAS,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE;AAC7C,SAAA,CAAC;AACF,QAAA,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC;IACzC;AACF;;;;"}
@@ -18,8 +18,10 @@ export interface SDKPropsDTO {
18
18
  customBranch?: string;
19
19
  highlightedBond?: string;
20
20
  customRPCS?: Partial<Record<ChainId, string[]>>;
21
+ openSuiConnectModal?: () => void;
21
22
  aptosAddress?: string;
22
23
  suiAddress?: string;
24
+ suiTreasuryAddresses?: string[];
23
25
  }
24
26
  export interface SDKProps {
25
27
  referenceId: string;
@@ -3,6 +3,7 @@ import { useQuery } from '@tanstack/react-query';
3
3
  import { QUERY_KEYS } from '../config/constants/queryKeys.js';
4
4
  import { ChainId } from '@ape.swap/apeswap-lists';
5
5
  import { setCustomRPCS } from '../config/constants/networks.js';
6
+ import { setSuiConnectModalOpener } from '../config/constants/suiCallbacks.js';
6
7
 
7
8
  // Prod URLS. Do not make changes here
8
9
  const defaultUrls = {
@@ -43,6 +44,11 @@ const useSDKConfig = (config) => {
43
44
  setCustomRPCS(config.customRPCS);
44
45
  }
45
46
  }, [config?.customRPCS]);
47
+ useEffect(() => {
48
+ if (config?.openSuiConnectModal) {
49
+ setSuiConnectModalOpener(config.openSuiConnectModal);
50
+ }
51
+ }, [config?.openSuiConnectModal]);
46
52
  const { data } = useQuery({
47
53
  queryKey: [QUERY_KEYS.SDK_CONFIG],
48
54
  queryFn: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"useSDKConfig.js","sources":["../../src/state/useSDKConfig.ts"],"sourcesContent":["import { useEffect } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../config/constants/queryKeys'\nimport { ChainId } from '@ape.swap/apeswap-lists'\nimport { setCustomRPCS } from '../config/constants/networks'\n\n// Prod URLS. Do not make changes here\nconst defaultUrls = {\n apiV2: 'https://api.ape.bond',\n realTimeApi: 'https://realtime-api.ape.bond',\n mainUrl: 'https://ape.bond',\n priceApi: 'https://price-api.ape.bond',\n}\n\n// Staging URLS.\nconst stagingUrls = {\n apiV2: 'https://staging-api.ape.bond',\n realTimeApi: 'https://realtime-api-staging.ape.bond',\n mainUrl: 'https://staging.ape.bond',\n priceApi: 'https://price-api.ape.bond',\n}\n\nexport interface SDKPropsDTO {\n referenceId: string\n chains: number[]\n hotBondChains?: number[]\n connector?: 'rainbowkit' | 'appkit' | 'default'\n useHotBonds?: boolean\n useTiers?: boolean\n useTGEBonds?: boolean\n useCardsView?: boolean\n showLowValueBonds?: boolean\n bondPartner?: string\n namingPreference?: 'Discount' | 'Bonus'\n urls?: Partial<Record<URLKeys, string>>\n theme?: any\n highestCompatibleVersion?: string\n blockSales?: boolean\n customBranch?: string\n highlightedBond?: string\n customRPCS?: Partial<Record<ChainId, string[]>>\n aptosAddress?: string\n suiAddress?: string\n}\n\nexport interface SDKProps {\n referenceId: string\n chains: number[]\n hotBondChains: number[]\n connector?: 'rainbowkit' | 'appkit' | 'default'\n useHotBonds: boolean\n useTiers: boolean\n useTGEBonds: boolean\n showLowValueBonds: boolean\n bondPartner?: string\n namingPreference: 'Discount' | 'Bonus'\n urls: Record<URLKeys, string>\n theme?: any\n highestCompatibleVersion?: string\n evmAddress?: string\n solAddress?: string\n aptosAddress?: string\n suiAddress?: string\n useCardsView?: boolean\n blockSales?: boolean\n customBranch?: string\n highlightedBond?: string\n}\n\nexport const useSDKConfig = (config?: SDKPropsDTO): SDKProps => {\n const urls = process.env.NODE_ENV === 'production' ? defaultUrls : stagingUrls\n\n const initialData: SDKProps = {\n referenceId: '',\n chains: [],\n hotBondChains: [ChainId.BSC, ChainId.MATIC],\n useHotBonds: true,\n connector: 'default',\n useTGEBonds: false,\n showLowValueBonds: false,\n bondPartner: undefined,\n namingPreference: 'Bonus',\n useCardsView: false,\n blockSales: false,\n customBranch: '',\n ...config,\n useTiers: config?.namingPreference === 'Discount' ? false : (config?.useTiers ?? false), // for the time being we'll assume discount preference does not want to useTiers\n urls: { ...urls, ...config?.urls },\n highestCompatibleVersion: '2.2.0',\n }\n\n useEffect(() => {\n if (config?.customRPCS) {\n setCustomRPCS(config.customRPCS)\n }\n }, [config?.customRPCS])\n\n const { data } = useQuery({\n queryKey: [QUERY_KEYS.SDK_CONFIG],\n queryFn: () => {\n throw new Error('Just a hotfix for latest versions of react-query that make queryFn a required prop')\n },\n initialData,\n })\n return data as SDKProps\n}\n\nexport type URLKeys = 'apiV2' | 'realTimeApi' | 'mainUrl' | 'priceApi'\n\nexport const useURLByEnvironment = (key: URLKeys) => {\n const config = useSDKConfig()\n return config?.urls?.[key] as string\n}\n"],"names":[],"mappings":";;;;;;AAMA;AACA,MAAM,WAAW,GAAG;AAClB,IAAA,KAAK,EAAE,sBAAsB;AAC7B,IAAA,WAAW,EAAE,+BAA+B;AAC5C,IAAA,OAAO,EAAE,kBAAkB;AAC3B,IAAA,QAAQ,EAAE,4BAA4B;CACvC;AAED;AACA,MAAM,WAAW,GAAG;AAClB,IAAA,KAAK,EAAE,8BAA8B;AACrC,IAAA,WAAW,EAAE,uCAAuC;AACpD,IAAA,OAAO,EAAE,0BAA0B;AACnC,IAAA,QAAQ,EAAE,4BAA4B;CACvC;AAiDM,MAAM,YAAY,GAAG,CAAC,MAAoB,KAAc;AAC7D,IAAA,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,GAAG,WAAW,GAAG,WAAW;AAE9E,IAAA,MAAM,WAAW,GAAa;AAC5B,QAAA,WAAW,EAAE,EAAE;AACf,QAAA,MAAM,EAAE,EAAE;QACV,aAAa,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC;AAC3C,QAAA,WAAW,EAAE,IAAI;AACjB,QAAA,SAAS,EAAE,SAAS;AACpB,QAAA,WAAW,EAAE,KAAK;AAClB,QAAA,iBAAiB,EAAE,KAAK;AACxB,QAAA,WAAW,EAAE,SAAS;AACtB,QAAA,gBAAgB,EAAE,OAAO;AACzB,QAAA,YAAY,EAAE,KAAK;AACnB,QAAA,UAAU,EAAE,KAAK;AACjB,QAAA,YAAY,EAAE,EAAE;AAChB,QAAA,GAAG,MAAM;QACT,QAAQ,EAAE,MAAM,EAAE,gBAAgB,KAAK,UAAU,GAAG,KAAK,IAAI,MAAM,EAAE,QAAQ,IAAI,KAAK,CAAC;QACvF,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE;AAClC,QAAA,wBAAwB,EAAE,OAAO;KAClC;IAED,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,MAAM,EAAE,UAAU,EAAE;AACtB,YAAA,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC;QAClC;AACF,IAAA,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAExB,IAAA,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;AACxB,QAAA,QAAQ,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QACjC,OAAO,EAAE,MAAK;AACZ,YAAA,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC;QACvG,CAAC;QACD,WAAW;AACZ,KAAA,CAAC;AACF,IAAA,OAAO,IAAgB;AACzB;AAIO,MAAM,mBAAmB,GAAG,CAAC,GAAY,KAAI;AAClD,IAAA,MAAM,MAAM,GAAG,YAAY,EAAE;AAC7B,IAAA,OAAO,MAAM,EAAE,IAAI,GAAG,GAAG,CAAW;AACtC;;;;"}
1
+ {"version":3,"file":"useSDKConfig.js","sources":["../../src/state/useSDKConfig.ts"],"sourcesContent":["import { useEffect } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../config/constants/queryKeys'\nimport { ChainId } from '@ape.swap/apeswap-lists'\nimport { setCustomRPCS } from '../config/constants/networks'\nimport { setSuiConnectModalOpener } from '../config/constants/suiCallbacks'\n\n// Prod URLS. Do not make changes here\nconst defaultUrls = {\n apiV2: 'https://api.ape.bond',\n realTimeApi: 'https://realtime-api.ape.bond',\n mainUrl: 'https://ape.bond',\n priceApi: 'https://price-api.ape.bond',\n}\n\n// Staging URLS.\nconst stagingUrls = {\n apiV2: 'https://staging-api.ape.bond',\n realTimeApi: 'https://realtime-api-staging.ape.bond',\n mainUrl: 'https://staging.ape.bond',\n priceApi: 'https://price-api.ape.bond',\n}\n\nexport interface SDKPropsDTO {\n referenceId: string\n chains: number[]\n hotBondChains?: number[]\n connector?: 'rainbowkit' | 'appkit' | 'default'\n useHotBonds?: boolean\n useTiers?: boolean\n useTGEBonds?: boolean\n useCardsView?: boolean\n showLowValueBonds?: boolean\n bondPartner?: string\n namingPreference?: 'Discount' | 'Bonus'\n urls?: Partial<Record<URLKeys, string>>\n theme?: any\n highestCompatibleVersion?: string\n blockSales?: boolean\n customBranch?: string\n highlightedBond?: string\n customRPCS?: Partial<Record<ChainId, string[]>>\n openSuiConnectModal?: () => void\n aptosAddress?: string\n suiAddress?: string\n suiTreasuryAddresses?: string[]\n}\n\nexport interface SDKProps {\n referenceId: string\n chains: number[]\n hotBondChains: number[]\n connector?: 'rainbowkit' | 'appkit' | 'default'\n useHotBonds: boolean\n useTiers: boolean\n useTGEBonds: boolean\n showLowValueBonds: boolean\n bondPartner?: string\n namingPreference: 'Discount' | 'Bonus'\n urls: Record<URLKeys, string>\n theme?: any\n highestCompatibleVersion?: string\n evmAddress?: string\n solAddress?: string\n aptosAddress?: string\n suiAddress?: string\n useCardsView?: boolean\n blockSales?: boolean\n customBranch?: string\n highlightedBond?: string\n}\n\nexport const useSDKConfig = (config?: SDKPropsDTO): SDKProps => {\n const urls = process.env.NODE_ENV === 'production' ? defaultUrls : stagingUrls\n\n const initialData: SDKProps = {\n referenceId: '',\n chains: [],\n hotBondChains: [ChainId.BSC, ChainId.MATIC],\n useHotBonds: true,\n connector: 'default',\n useTGEBonds: false,\n showLowValueBonds: false,\n bondPartner: undefined,\n namingPreference: 'Bonus',\n useCardsView: false,\n blockSales: false,\n customBranch: '',\n ...config,\n useTiers: config?.namingPreference === 'Discount' ? false : (config?.useTiers ?? false), // for the time being we'll assume discount preference does not want to useTiers\n urls: { ...urls, ...config?.urls },\n highestCompatibleVersion: '2.2.0',\n }\n\n useEffect(() => {\n if (config?.customRPCS) {\n setCustomRPCS(config.customRPCS)\n }\n }, [config?.customRPCS])\n\n useEffect(() => {\n if (config?.openSuiConnectModal) {\n setSuiConnectModalOpener(config.openSuiConnectModal)\n }\n }, [config?.openSuiConnectModal])\n\n const { data } = useQuery({\n queryKey: [QUERY_KEYS.SDK_CONFIG],\n queryFn: () => {\n throw new Error('Just a hotfix for latest versions of react-query that make queryFn a required prop')\n },\n initialData,\n })\n return data as SDKProps\n}\n\nexport type URLKeys = 'apiV2' | 'realTimeApi' | 'mainUrl' | 'priceApi'\n\nexport const useURLByEnvironment = (key: URLKeys) => {\n const config = useSDKConfig()\n return config?.urls?.[key] as string\n}\n"],"names":[],"mappings":";;;;;;;AAOA;AACA,MAAM,WAAW,GAAG;AAClB,IAAA,KAAK,EAAE,sBAAsB;AAC7B,IAAA,WAAW,EAAE,+BAA+B;AAC5C,IAAA,OAAO,EAAE,kBAAkB;AAC3B,IAAA,QAAQ,EAAE,4BAA4B;CACvC;AAED;AACA,MAAM,WAAW,GAAG;AAClB,IAAA,KAAK,EAAE,8BAA8B;AACrC,IAAA,WAAW,EAAE,uCAAuC;AACpD,IAAA,OAAO,EAAE,0BAA0B;AACnC,IAAA,QAAQ,EAAE,4BAA4B;CACvC;AAmDM,MAAM,YAAY,GAAG,CAAC,MAAoB,KAAc;AAC7D,IAAA,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,GAAG,WAAW,GAAG,WAAW;AAE9E,IAAA,MAAM,WAAW,GAAa;AAC5B,QAAA,WAAW,EAAE,EAAE;AACf,QAAA,MAAM,EAAE,EAAE;QACV,aAAa,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC;AAC3C,QAAA,WAAW,EAAE,IAAI;AACjB,QAAA,SAAS,EAAE,SAAS;AACpB,QAAA,WAAW,EAAE,KAAK;AAClB,QAAA,iBAAiB,EAAE,KAAK;AACxB,QAAA,WAAW,EAAE,SAAS;AACtB,QAAA,gBAAgB,EAAE,OAAO;AACzB,QAAA,YAAY,EAAE,KAAK;AACnB,QAAA,UAAU,EAAE,KAAK;AACjB,QAAA,YAAY,EAAE,EAAE;AAChB,QAAA,GAAG,MAAM;QACT,QAAQ,EAAE,MAAM,EAAE,gBAAgB,KAAK,UAAU,GAAG,KAAK,IAAI,MAAM,EAAE,QAAQ,IAAI,KAAK,CAAC;QACvF,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE;AAClC,QAAA,wBAAwB,EAAE,OAAO;KAClC;IAED,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,MAAM,EAAE,UAAU,EAAE;AACtB,YAAA,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC;QAClC;AACF,IAAA,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAExB,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,MAAM,EAAE,mBAAmB,EAAE;AAC/B,YAAA,wBAAwB,CAAC,MAAM,CAAC,mBAAmB,CAAC;QACtD;AACF,IAAA,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAEjC,IAAA,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;AACxB,QAAA,QAAQ,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QACjC,OAAO,EAAE,MAAK;AACZ,YAAA,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC;QACvG,CAAC;QACD,WAAW;AACZ,KAAA,CAAC;AACF,IAAA,OAAO,IAAgB;AACzB;AAIO,MAAM,mBAAmB,GAAG,CAAC,GAAY,KAAI;AAClD,IAAA,MAAM,MAAM,GAAG,YAAY,EAAE;AAC7B,IAAA,OAAO,MAAM,EAAE,IAAI,GAAG,GAAG,CAAW;AACtC;;;;"}
@@ -5,8 +5,7 @@ import { useQuery } from '@tanstack/react-query';
5
5
  import { QUERY_KEYS } from '../../config/constants/queryKeys.js';
6
6
  import useDebounce from '../../hooks/useDebounce.js';
7
7
  import axios from 'axios';
8
- import { IS_SUI_MAINNET } from '../../constants/suiConstants.js';
9
- import { getSuiFallbackPrices } from '../bonds/suiBondsConfig.js';
8
+ import '../../constants/suiConstants.js';
10
9
 
11
10
  // =============================================================================
12
11
  // useSuiZapQuote — Aftermath Finance DEX aggregator quote for Sui zap
@@ -54,28 +53,6 @@ const useSuiZapQuote = (typedValue, inputToken, bond, account, slippage = 0.5) =
54
53
  };
55
54
  }, [inputTokenAddress, principalTokenAddress, inputAmountAtomic, account]);
56
55
  // -------------------------------------------------------------------------
57
- // Testnet mock: calculate quote from fallback prices (no DEX available)
58
- // -------------------------------------------------------------------------
59
- const testnetMockQuote = useMemo(() => {
60
- if (IS_SUI_MAINNET || !queryParams)
61
- return null;
62
- const fallbackPrices = getSuiFallbackPrices();
63
- const inputPrice = fallbackPrices.find((p) => p.tokenAddress.toLowerCase() === queryParams.coinInType.toLowerCase())?.price;
64
- const outputPrice = fallbackPrices.find((p) => p.tokenAddress.toLowerCase() === queryParams.coinOutType.toLowerCase())?.price;
65
- if (!inputPrice || !outputPrice || outputPrice === 0)
66
- return null;
67
- const inputHuman = new BigNumber(queryParams.coinInAmount).div(new BigNumber(10).pow(inputDecimals));
68
- const outputHuman = inputHuman.times(inputPrice).div(outputPrice);
69
- const outputAtomic = outputHuman.times(new BigNumber(10).pow(principalDecimals)).integerValue(BigNumber.ROUND_FLOOR);
70
- return {
71
- routes: [],
72
- coinIn: { type: queryParams.coinInType, amount: queryParams.coinInAmount, tradeFee: '0' },
73
- coinOut: { type: queryParams.coinOutType, amount: outputAtomic.toFixed(0), tradeFee: '0' },
74
- spotPrice: inputPrice / outputPrice,
75
- netTradeFeePercentage: 0,
76
- };
77
- }, [queryParams, inputDecimals, principalDecimals]);
78
- // -------------------------------------------------------------------------
79
56
  // Mainnet: fetch real quote from Aftermath
80
57
  // -------------------------------------------------------------------------
81
58
  const fetchAftermathQuote = async () => {
@@ -91,13 +68,13 @@ const useSuiZapQuote = (typedValue, inputToken, bond, account, slippage = 0.5) =
91
68
  queryKey: [QUERY_KEYS.ZAP_TOKEN_QUOTE, 'aftermath-sui', queryParams],
92
69
  queryFn: fetchAftermathQuote,
93
70
  refetchInterval: 60000,
94
- enabled: IS_SUI_MAINNET && !!queryParams,
71
+ enabled: !!queryParams,
95
72
  retry: 1,
96
73
  staleTime: 30000,
97
74
  });
98
75
  // Use testnet mock on testnet, real quote on mainnet
99
- const activeQuote = IS_SUI_MAINNET ? (quoteData ?? null) : testnetMockQuote;
100
- const zapError = IS_SUI_MAINNET ? !!error : false;
76
+ const activeQuote = quoteData ?? null;
77
+ const zapError = !!error;
101
78
  // Convert amounts to human-readable
102
79
  const estimatedDepositAmount = activeQuote?.coinOut?.amount
103
80
  ? new BigNumber(parseAftermathAmount(activeQuote.coinOut.amount))
@@ -111,7 +88,7 @@ const useSuiZapQuote = (typedValue, inputToken, bond, account, slippage = 0.5) =
111
88
  .times(1 - slippage / 100)
112
89
  .toFixed(principalDecimals)
113
90
  : '0';
114
- const zapLoading = IS_SUI_MAINNET ? isLoading || isFetching : false;
91
+ const zapLoading = isLoading || isFetching ;
115
92
  return [zapLoading, activeQuote, estimatedDepositAmount, zapError, minimumDepositAmount];
116
93
  };
117
94
 
@@ -1 +1 @@
1
- {"version":3,"file":"useSuiZapQuote.js","sources":["../../../src/state/zap/useSuiZapQuote.ts"],"sourcesContent":["// =============================================================================\n// useSuiZapQuote — Aftermath Finance DEX aggregator quote for Sui zap\n// =============================================================================\n//\n// Mainnet: fetches a swap quote from Aftermath Finance (Sui DEX aggregator)\n// when the user selects an input token different from the bond's principal token.\n//\n// Testnet: no DEX aggregator supports Sui testnet or our custom test tokens.\n// Returns a mock quote calculated from fallback prices so the full zap UI and\n// two-TX flow (mint → deposit) can be tested end-to-end.\n//\n// Aftermath API: POST https://aftermath.finance/api/router/trade-route\n\nimport { useMemo } from 'react'\nimport BigNumber from 'bignumber.js'\nimport { ChainId } from '@ape.swap/apeswap-lists'\nimport { useQuery } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport { BondsData } from '../../types/bonds'\nimport useDebounce from '../../hooks/useDebounce'\nimport axios from 'axios'\nimport type { SuiZapToken } from '../../config/constants/suiZapTokens'\nimport { IS_SUI_MAINNET } from '../../constants/suiConstants'\nimport { getSuiFallbackPrices } from '../bonds/suiBondsConfig'\n\nconst AFTERMATH_API_URL = 'https://aftermath.finance/api/router/trade-route'\nconst AFTERMATH_TX_API_URL = 'https://aftermath.finance/api/router/transactions/trade'\n\ninterface AftermathCoinInfo {\n type: string\n amount: string // atomic units with BigInt \"n\" suffix, e.g. \"963906n\"\n tradeFee: string\n}\n\nexport interface AftermathTradeRoute {\n routes: Array<{\n paths: Array<Record<string, unknown>>\n portion: string\n coinIn: AftermathCoinInfo\n coinOut: AftermathCoinInfo\n spotPrice: number\n }>\n coinIn: AftermathCoinInfo\n coinOut: AftermathCoinInfo\n spotPrice: number\n netTradeFeePercentage: number\n}\n\n/** Parse Aftermath amount strings — they may have a trailing \"n\" (BigInt notation) */\nconst parseAftermathAmount = (amount: string): string => {\n return amount.replace(/n$/, '')\n}\n\nconst useSuiZapQuote = (\n typedValue: string,\n inputToken: SuiZapToken | undefined,\n bond: BondsData | undefined,\n account?: string,\n slippage = 0.5,\n): [\n loading: boolean,\n response: AftermathTradeRoute | null,\n depositAmount: string,\n error: boolean,\n minimumDepositAmount: string,\n] => {\n const debouncedInput = useDebounce(typedValue, 400)\n\n const principalTokenAddress = bond?.lpToken?.address?.[ChainId.SUI]\n const inputTokenAddress = inputToken?.address\n\n // Aftermath uses atomic units — convert from human-readable\n const inputDecimals = inputToken?.decimals ?? 9\n const inputAmountAtomic = useMemo(() => {\n const val = new BigNumber(debouncedInput ?? '0')\n if (val.isNaN() || val.lte(0)) return '0'\n return val.times(new BigNumber(10).pow(inputDecimals)).integerValue(BigNumber.ROUND_FLOOR).toFixed(0)\n }, [debouncedInput, inputDecimals])\n\n const principalDecimals = bond?.lpToken?.decimals?.[ChainId.SUI] ?? 6\n\n const queryParams = useMemo(() => {\n if (\n !inputTokenAddress ||\n !principalTokenAddress ||\n inputAmountAtomic === '0' ||\n !account ||\n inputTokenAddress.toLowerCase() === principalTokenAddress.toLowerCase()\n ) {\n return null\n }\n\n return {\n coinInType: inputTokenAddress,\n coinOutType: principalTokenAddress,\n coinInAmount: inputAmountAtomic,\n }\n }, [inputTokenAddress, principalTokenAddress, inputAmountAtomic, account])\n\n // -------------------------------------------------------------------------\n // Testnet mock: calculate quote from fallback prices (no DEX available)\n // -------------------------------------------------------------------------\n const testnetMockQuote = useMemo((): AftermathTradeRoute | null => {\n if (IS_SUI_MAINNET || !queryParams) return null\n\n const fallbackPrices = getSuiFallbackPrices()\n const inputPrice = fallbackPrices.find(\n (p) => p.tokenAddress.toLowerCase() === queryParams.coinInType.toLowerCase(),\n )?.price\n const outputPrice = fallbackPrices.find(\n (p) => p.tokenAddress.toLowerCase() === queryParams.coinOutType.toLowerCase(),\n )?.price\n\n if (!inputPrice || !outputPrice || outputPrice === 0) return null\n\n const inputHuman = new BigNumber(queryParams.coinInAmount).div(new BigNumber(10).pow(inputDecimals))\n const outputHuman = inputHuman.times(inputPrice).div(outputPrice)\n const outputAtomic = outputHuman.times(new BigNumber(10).pow(principalDecimals)).integerValue(BigNumber.ROUND_FLOOR)\n\n return {\n routes: [],\n coinIn: { type: queryParams.coinInType, amount: queryParams.coinInAmount, tradeFee: '0' },\n coinOut: { type: queryParams.coinOutType, amount: outputAtomic.toFixed(0), tradeFee: '0' },\n spotPrice: inputPrice / outputPrice,\n netTradeFeePercentage: 0,\n }\n }, [queryParams, inputDecimals, principalDecimals])\n\n // -------------------------------------------------------------------------\n // Mainnet: fetch real quote from Aftermath\n // -------------------------------------------------------------------------\n const fetchAftermathQuote = async (): Promise<AftermathTradeRoute | null> => {\n if (!queryParams) return null\n\n const response = await axios.post<AftermathTradeRoute>(AFTERMATH_API_URL, queryParams)\n const data = response.data\n if (!data?.coinOut?.amount) return null\n return data\n }\n\n const {\n data: quoteData,\n isLoading,\n isFetching,\n error,\n } = useQuery({\n queryKey: [QUERY_KEYS.ZAP_TOKEN_QUOTE, 'aftermath-sui', queryParams],\n queryFn: fetchAftermathQuote,\n refetchInterval: 60000,\n enabled: IS_SUI_MAINNET && !!queryParams,\n retry: 1,\n staleTime: 30000,\n })\n\n // Use testnet mock on testnet, real quote on mainnet\n const activeQuote = IS_SUI_MAINNET ? (quoteData ?? null) : testnetMockQuote\n const zapError = IS_SUI_MAINNET ? !!error : false\n\n // Convert amounts to human-readable\n const estimatedDepositAmount = activeQuote?.coinOut?.amount\n ? new BigNumber(parseAftermathAmount(activeQuote.coinOut.amount))\n .div(new BigNumber(10).pow(principalDecimals))\n .toFixed(principalDecimals)\n : '0'\n\n // Apply slippage for minimum deposit amount\n const minimumDepositAmount = activeQuote?.coinOut?.amount\n ? new BigNumber(parseAftermathAmount(activeQuote.coinOut.amount))\n .div(new BigNumber(10).pow(principalDecimals))\n .times(1 - slippage / 100)\n .toFixed(principalDecimals)\n : '0'\n\n const zapLoading = IS_SUI_MAINNET ? isLoading || isFetching : false\n\n return [zapLoading, activeQuote, estimatedDepositAmount, zapError, minimumDepositAmount]\n}\n\nexport { AFTERMATH_TX_API_URL }\n\nexport default useSuiZapQuote\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useSuiZapQuote.js","sources":["../../../src/state/zap/useSuiZapQuote.ts"],"sourcesContent":["// =============================================================================\n// useSuiZapQuote — Aftermath Finance DEX aggregator quote for Sui zap\n// =============================================================================\n//\n// Mainnet: fetches a swap quote from Aftermath Finance (Sui DEX aggregator)\n// when the user selects an input token different from the bond's principal token.\n//\n// Testnet: no DEX aggregator supports Sui testnet or our custom test tokens.\n// Returns a mock quote calculated from fallback prices so the full zap UI and\n// two-TX flow (mint → deposit) can be tested end-to-end.\n//\n// Aftermath API: POST https://aftermath.finance/api/router/trade-route\n\nimport { useMemo } from 'react'\nimport BigNumber from 'bignumber.js'\nimport { ChainId } from '@ape.swap/apeswap-lists'\nimport { useQuery } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport { BondsData } from '../../types/bonds'\nimport useDebounce from '../../hooks/useDebounce'\nimport axios from 'axios'\nimport type { SuiZapToken } from '../../config/constants/suiZapTokens'\nimport { IS_SUI_MAINNET } from '../../constants/suiConstants'\n\nconst AFTERMATH_API_URL = 'https://aftermath.finance/api/router/trade-route'\nconst AFTERMATH_TX_API_URL = 'https://aftermath.finance/api/router/transactions/trade'\n\ninterface AftermathCoinInfo {\n type: string\n amount: string // atomic units with BigInt \"n\" suffix, e.g. \"963906n\"\n tradeFee: string\n}\n\nexport interface AftermathTradeRoute {\n routes: Array<{\n paths: Array<Record<string, unknown>>\n portion: string\n coinIn: AftermathCoinInfo\n coinOut: AftermathCoinInfo\n spotPrice: number\n }>\n coinIn: AftermathCoinInfo\n coinOut: AftermathCoinInfo\n spotPrice: number\n netTradeFeePercentage: number\n}\n\n/** Parse Aftermath amount strings — they may have a trailing \"n\" (BigInt notation) */\nconst parseAftermathAmount = (amount: string): string => {\n return amount.replace(/n$/, '')\n}\n\nconst useSuiZapQuote = (\n typedValue: string,\n inputToken: SuiZapToken | undefined,\n bond: BondsData | undefined,\n account?: string,\n slippage = 0.5,\n): [\n loading: boolean,\n response: AftermathTradeRoute | null,\n depositAmount: string,\n error: boolean,\n minimumDepositAmount: string,\n] => {\n const debouncedInput = useDebounce(typedValue, 400)\n\n const principalTokenAddress = bond?.lpToken?.address?.[ChainId.SUI]\n const inputTokenAddress = inputToken?.address\n\n // Aftermath uses atomic units — convert from human-readable\n const inputDecimals = inputToken?.decimals ?? 9\n const inputAmountAtomic = useMemo(() => {\n const val = new BigNumber(debouncedInput ?? '0')\n if (val.isNaN() || val.lte(0)) return '0'\n return val.times(new BigNumber(10).pow(inputDecimals)).integerValue(BigNumber.ROUND_FLOOR).toFixed(0)\n }, [debouncedInput, inputDecimals])\n\n const principalDecimals = bond?.lpToken?.decimals?.[ChainId.SUI] ?? 6\n\n const queryParams = useMemo(() => {\n if (\n !inputTokenAddress ||\n !principalTokenAddress ||\n inputAmountAtomic === '0' ||\n !account ||\n inputTokenAddress.toLowerCase() === principalTokenAddress.toLowerCase()\n ) {\n return null\n }\n\n return {\n coinInType: inputTokenAddress,\n coinOutType: principalTokenAddress,\n coinInAmount: inputAmountAtomic,\n }\n }, [inputTokenAddress, principalTokenAddress, inputAmountAtomic, account])\n\n // -------------------------------------------------------------------------\n // Mainnet: fetch real quote from Aftermath\n // -------------------------------------------------------------------------\n const fetchAftermathQuote = async (): Promise<AftermathTradeRoute | null> => {\n if (!queryParams) return null\n\n const response = await axios.post<AftermathTradeRoute>(AFTERMATH_API_URL, queryParams)\n const data = response.data\n if (!data?.coinOut?.amount) return null\n return data\n }\n\n const {\n data: quoteData,\n isLoading,\n isFetching,\n error,\n } = useQuery({\n queryKey: [QUERY_KEYS.ZAP_TOKEN_QUOTE, 'aftermath-sui', queryParams],\n queryFn: fetchAftermathQuote,\n refetchInterval: 60000,\n enabled: IS_SUI_MAINNET && !!queryParams,\n retry: 1,\n staleTime: 30000,\n })\n\n // Use testnet mock on testnet, real quote on mainnet\n const activeQuote = quoteData ?? null\n const zapError = !!error\n\n // Convert amounts to human-readable\n const estimatedDepositAmount = activeQuote?.coinOut?.amount\n ? new BigNumber(parseAftermathAmount(activeQuote.coinOut.amount))\n .div(new BigNumber(10).pow(principalDecimals))\n .toFixed(principalDecimals)\n : '0'\n\n // Apply slippage for minimum deposit amount\n const minimumDepositAmount = activeQuote?.coinOut?.amount\n ? new BigNumber(parseAftermathAmount(activeQuote.coinOut.amount))\n .div(new BigNumber(10).pow(principalDecimals))\n .times(1 - slippage / 100)\n .toFixed(principalDecimals)\n : '0'\n\n const zapLoading = IS_SUI_MAINNET ? isLoading || isFetching : false\n\n return [zapLoading, activeQuote, estimatedDepositAmount, zapError, minimumDepositAmount]\n}\n\nexport { AFTERMATH_TX_API_URL }\n\nexport default useSuiZapQuote\n"],"names":[],"mappings":"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"}
@@ -2,5 +2,5 @@ import { SuiClient } from '@mysten/sui/client';
2
2
  export declare const getSuiClient: () => SuiClient;
3
3
  export declare const toAtomicUnits: (amount: string | number, decimals: number) => string;
4
4
  export declare const fromAtomicUnits: (amount: string | number, decimals: number) => number;
5
- export declare const readFreshTrueBondPrice: (marketObjectId: string) => Promise<bigint>;
5
+ export declare const readFreshTrueBondPrice: (marketObjectId?: string) => Promise<bigint>;
6
6
  export declare const verifySuiTxSuccess: (digest: string) => Promise<void>;
@@ -45,14 +45,16 @@ const valueOfToken = (fromDec, toDec, amount) => {
45
45
  return amount / pow10bi(fromDec - toDec);
46
46
  };
47
47
  const readFreshTrueBondPrice = async (marketObjectId) => {
48
+ if (!marketObjectId) {
49
+ throw new Error('marketObjectId is required');
50
+ }
48
51
  const client = getSuiClient();
49
52
  const obj = await client.getObject({ id: marketObjectId, options: { showContent: true } });
50
53
  if (!obj.data?.content || obj.data.content.dataType !== 'moveObject') {
51
54
  throw new Error(`[Sui] Could not read BondMarket ${marketObjectId}`);
52
55
  }
53
56
  const f = obj.data.content.fields;
54
- const terms = f.terms?.fields ??
55
- f.terms;
57
+ const terms = f.terms?.fields ?? f.terms;
56
58
  const totalDebt = BigInt(String(f.total_debt ?? '0'));
57
59
  const payoutInitialSupply = BigInt(String(f.payout_token_initial_supply ?? '0'));
58
60
  const controlVariable = BigInt(String(terms.control_variable ?? '0'));
@@ -75,9 +77,7 @@ const readFreshTrueBondPrice = async (marketObjectId) => {
75
77
  const currentDebtPayout = valueOfToken(principalDecimals, payoutDecimals, currentDebtU64);
76
78
  const payoutScale = pow10bi(payoutDecimals);
77
79
  const principalScale = pow10bi(principalDecimals);
78
- const debtRatio = payoutInitialSupply > 0n
79
- ? (currentDebtPayout * payoutScale) / payoutInitialSupply
80
- : 0n;
80
+ const debtRatio = payoutInitialSupply > 0n ? (currentDebtPayout * payoutScale) / payoutInitialSupply : 0n;
81
81
  const basePrice = (controlVariable * debtRatio * principalScale) / PRICE_DECIMALS;
82
82
  const price = basePrice < minimumPrice ? minimumPrice : basePrice;
83
83
  // calculate_true_price (includes fee)
@@ -1 +1 @@
1
- {"version":3,"file":"suiHelpers.js","sources":["../../src/utils/suiHelpers.ts"],"sourcesContent":["import { SuiClient } from '@mysten/sui/client'\nimport BigNumber from 'bignumber.js'\nimport { SUI_FULLNODE_URL } from '../constants/suiConstants'\n\n// ---------------------------------------------------------------------------\n// Sui client — lazy singleton\n// ---------------------------------------------------------------------------\nlet _suiClient: SuiClient | undefined\n\nexport const getSuiClient = (): SuiClient => {\n if (_suiClient) return _suiClient\n _suiClient = new SuiClient({ url: SUI_FULLNODE_URL })\n return _suiClient\n}\n\n// ---------------------------------------------------------------------------\n// Unit conversion\n// ---------------------------------------------------------------------------\n// User inputs live in \"whole tokens\" (e.g. \"1.5 SUI\"). The Sui SDK\n// serialises numeric function arguments from strings, so we convert to\n// atomic units and return a stringified BigInt.\nexport const toAtomicUnits = (amount: string | number, decimals: number): string => {\n if (amount === '' || amount == null) return '0'\n const bn = new BigNumber(amount).times(new BigNumber(10).pow(decimals))\n // Floor so we never over-spend what the user typed.\n return bn.integerValue(BigNumber.ROUND_FLOOR).toFixed(0)\n}\n\n// Atomic → human-readable.\nexport const fromAtomicUnits = (amount: string | number, decimals: number): number => {\n if (amount === '' || amount == null) return 0\n return new BigNumber(amount).div(new BigNumber(10).pow(decimals)).toNumber()\n}\n\n// ---------------------------------------------------------------------------\n// Fresh bond price reader — reads the BondMarket object on-chain and\n// computes the current true_price using the same bond_math formulas as\n// the Move contract. Returns the u64 value (scaled 1e8).\n// ---------------------------------------------------------------------------\n\nconst PRICE_DECIMALS = 100_000_000n // 1e8\nconst PERCENTAGE_BASE = 1_000_000n // 1e6\n\nconst pow10bi = (n: number): bigint => 10n ** BigInt(n)\n\nconst valueOfToken = (fromDec: number, toDec: number, amount: bigint): bigint => {\n if (toDec >= fromDec) return amount * pow10bi(toDec - fromDec)\n return amount / pow10bi(fromDec - toDec)\n}\n\nexport const readFreshTrueBondPrice = async (marketObjectId: string): Promise<bigint> => {\n const client = getSuiClient()\n const obj = await client.getObject({ id: marketObjectId, options: { showContent: true } })\n\n if (!obj.data?.content || obj.data.content.dataType !== 'moveObject') {\n throw new Error(`[Sui] Could not read BondMarket ${marketObjectId}`)\n }\n\n const f = obj.data.content.fields as Record<string, unknown>\n const terms = (f.terms as Record<string, unknown>)?.fields as Record<string, unknown> ??\n f.terms as Record<string, unknown>\n\n const totalDebt = BigInt(String(f.total_debt ?? '0'))\n const payoutInitialSupply = BigInt(String(f.payout_token_initial_supply ?? '0'))\n const controlVariable = BigInt(String(terms.control_variable ?? '0'))\n const minimumPrice = BigInt(String(terms.minimum_price ?? '0'))\n const vestingTerm = BigInt(String(terms.vesting_term ?? '1'))\n const lastDecay = BigInt(String(f.last_decay ?? '0'))\n const feeInPrincipal = BigInt(String(f.fee_in_principal ?? '0'))\n const payoutDecimals = Number(f.payout_decimals ?? 9)\n const principalDecimals = Number(f.principal_decimals ?? 9)\n\n // Decay debt client-side (same as contract's decay_debt)\n const nowSeconds = BigInt(Math.floor(Date.now() / 1000))\n let currentDebt = totalDebt\n if (nowSeconds > lastDecay && vestingTerm > 0n) {\n const elapsed = nowSeconds - lastDecay\n const decay = (totalDebt * elapsed) / vestingTerm\n currentDebt = totalDebt > decay ? totalDebt - decay : 0n\n }\n\n // calculate_price — contract casts total_debt (u128) to u64 via `as u64`\n const currentDebtU64 = currentDebt & 0xFFFFFFFFFFFFFFFFn\n const currentDebtPayout = valueOfToken(principalDecimals, payoutDecimals, currentDebtU64)\n const payoutScale = pow10bi(payoutDecimals)\n const principalScale = pow10bi(principalDecimals)\n\n const debtRatio = payoutInitialSupply > 0n\n ? (currentDebtPayout * payoutScale) / payoutInitialSupply\n : 0n\n const basePrice = (controlVariable * debtRatio * principalScale) / PRICE_DECIMALS\n\n const price = basePrice < minimumPrice ? minimumPrice : basePrice\n\n // calculate_true_price (includes fee)\n const denominator = PERCENTAGE_BASE - feeInPrincipal\n const truePrice = denominator > 0n ? (price * PERCENTAGE_BASE) / denominator : price\n\n return truePrice\n}\n\n// ---------------------------------------------------------------------------\n// TX status verification — Sui returns digests for failed TXs too.\n// Call this after waitForTransaction to ensure the TX actually succeeded.\n// ---------------------------------------------------------------------------\n\nexport const verifySuiTxSuccess = async (digest: string): Promise<void> => {\n const client = getSuiClient()\n const txBlock = await client.getTransactionBlock({\n digest,\n options: { showEffects: true },\n })\n const status = txBlock.effects?.status\n if (status?.status !== 'success') {\n const errorMsg = status?.error ?? 'Transaction failed on-chain'\n throw new Error(`Transaction failed: ${errorMsg}`)\n }\n}\n"],"names":[],"mappings":";;;;AAIA;AACA;AACA;AACA,IAAI,UAAiC;AAE9B,MAAM,YAAY,GAAG,MAAgB;AAC1C,IAAA,IAAI,UAAU;AAAE,QAAA,OAAO,UAAU;IACjC,UAAU,GAAG,IAAI,SAAS,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC;AACrD,IAAA,OAAO,UAAU;AACnB;AAEA;AACA;AACA;AACA;AACA;AACA;MACa,aAAa,GAAG,CAAC,MAAuB,EAAE,QAAgB,KAAY;AACjF,IAAA,IAAI,MAAM,KAAK,EAAE,IAAI,MAAM,IAAI,IAAI;AAAE,QAAA,OAAO,GAAG;IAC/C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;;AAEvE,IAAA,OAAO,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1D;AAEA;MACa,eAAe,GAAG,CAAC,MAAuB,EAAE,QAAgB,KAAY;AACnF,IAAA,IAAI,MAAM,KAAK,EAAE,IAAI,MAAM,IAAI,IAAI;AAAE,QAAA,OAAO,CAAC;IAC7C,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE;AAC9E;AAEA;AACA;AACA;AACA;AACA;AAEA,MAAM,cAAc,GAAG,UAAY,CAAA;AACnC,MAAM,eAAe,GAAG,QAAU,CAAA;AAElC,MAAM,OAAO,GAAG,CAAC,CAAS,KAAa,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC;AAEvD,MAAM,YAAY,GAAG,CAAC,OAAe,EAAE,KAAa,EAAE,MAAc,KAAY;IAC9E,IAAI,KAAK,IAAI,OAAO;QAAE,OAAO,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC;IAC9D,OAAO,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;AAC1C,CAAC;MAEY,sBAAsB,GAAG,OAAO,cAAsB,KAAqB;AACtF,IAAA,MAAM,MAAM,GAAG,YAAY,EAAE;IAC7B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;AAE1F,IAAA,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,YAAY,EAAE;AACpE,QAAA,MAAM,IAAI,KAAK,CAAC,mCAAmC,cAAc,CAAA,CAAE,CAAC;IACtE;IAEA,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAiC;AAC5D,IAAA,MAAM,KAAK,GAAI,CAAC,CAAC,KAAiC,EAAE,MAAiC;QACnF,CAAC,CAAC,KAAgC;AAEpC,IAAA,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC;AACrD,IAAA,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B,IAAI,GAAG,CAAC,CAAC;AAChF,IAAA,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC;AACrE,IAAA,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,IAAI,GAAG,CAAC,CAAC;AAC/D,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,GAAG,CAAC,CAAC;AAC7D,IAAA,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC;AACrD,IAAA,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC;IAChE,MAAM,cAAc,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;IACrD,MAAM,iBAAiB,GAAG,MAAM,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC;;AAG3D,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IACxD,IAAI,WAAW,GAAG,SAAS;IAC3B,IAAI,UAAU,GAAG,SAAS,IAAI,WAAW,GAAG,EAAE,EAAE;AAC9C,QAAA,MAAM,OAAO,GAAG,UAAU,GAAG,SAAS;QACtC,MAAM,KAAK,GAAG,CAAC,SAAS,GAAG,OAAO,IAAI,WAAW;AACjD,QAAA,WAAW,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,EAAE;IAC1D;;AAGA,IAAA,MAAM,cAAc,GAAG,WAAW,GAAG,mBAAmB;IACxD,MAAM,iBAAiB,GAAG,YAAY,CAAC,iBAAiB,EAAE,cAAc,EAAE,cAAc,CAAC;AACzF,IAAA,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;AAC3C,IAAA,MAAM,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC;AAEjD,IAAA,MAAM,SAAS,GAAG,mBAAmB,GAAG;AACtC,UAAE,CAAC,iBAAiB,GAAG,WAAW,IAAI;UACpC,EAAE;IACN,MAAM,SAAS,GAAG,CAAC,eAAe,GAAG,SAAS,GAAG,cAAc,IAAI,cAAc;AAEjF,IAAA,MAAM,KAAK,GAAG,SAAS,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS;;AAGjE,IAAA,MAAM,WAAW,GAAG,eAAe,GAAG,cAAc;AACpD,IAAA,MAAM,SAAS,GAAG,WAAW,GAAG,EAAE,GAAG,CAAC,KAAK,GAAG,eAAe,IAAI,WAAW,GAAG,KAAK;AAEpF,IAAA,OAAO,SAAS;AAClB;AAEA;AACA;AACA;AACA;MAEa,kBAAkB,GAAG,OAAO,MAAc,KAAmB;AACxE,IAAA,MAAM,MAAM,GAAG,YAAY,EAAE;AAC7B,IAAA,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC;QAC/C,MAAM;AACN,QAAA,OAAO,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;AAC/B,KAAA,CAAC;AACF,IAAA,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,MAAM;AACtC,IAAA,IAAI,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE;AAChC,QAAA,MAAM,QAAQ,GAAG,MAAM,EAAE,KAAK,IAAI,6BAA6B;AAC/D,QAAA,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAA,CAAE,CAAC;IACpD;AACF;;;;"}
1
+ {"version":3,"file":"suiHelpers.js","sources":["../../src/utils/suiHelpers.ts"],"sourcesContent":["import { SuiClient } from '@mysten/sui/client'\nimport BigNumber from 'bignumber.js'\nimport { SUI_FULLNODE_URL } from '../constants/suiConstants'\n\n// ---------------------------------------------------------------------------\n// Sui client — lazy singleton\n// ---------------------------------------------------------------------------\nlet _suiClient: SuiClient | undefined\n\nexport const getSuiClient = (): SuiClient => {\n if (_suiClient) return _suiClient\n _suiClient = new SuiClient({ url: SUI_FULLNODE_URL })\n return _suiClient\n}\n\n// ---------------------------------------------------------------------------\n// Unit conversion\n// ---------------------------------------------------------------------------\n// User inputs live in \"whole tokens\" (e.g. \"1.5 SUI\"). The Sui SDK\n// serialises numeric function arguments from strings, so we convert to\n// atomic units and return a stringified BigInt.\nexport const toAtomicUnits = (amount: string | number, decimals: number): string => {\n if (amount === '' || amount == null) return '0'\n const bn = new BigNumber(amount).times(new BigNumber(10).pow(decimals))\n // Floor so we never over-spend what the user typed.\n return bn.integerValue(BigNumber.ROUND_FLOOR).toFixed(0)\n}\n\n// Atomic → human-readable.\nexport const fromAtomicUnits = (amount: string | number, decimals: number): number => {\n if (amount === '' || amount == null) return 0\n return new BigNumber(amount).div(new BigNumber(10).pow(decimals)).toNumber()\n}\n\n// ---------------------------------------------------------------------------\n// Fresh bond price reader — reads the BondMarket object on-chain and\n// computes the current true_price using the same bond_math formulas as\n// the Move contract. Returns the u64 value (scaled 1e8).\n// ---------------------------------------------------------------------------\n\nconst PRICE_DECIMALS = 100_000_000n // 1e8\nconst PERCENTAGE_BASE = 1_000_000n // 1e6\n\nconst pow10bi = (n: number): bigint => 10n ** BigInt(n)\n\nconst valueOfToken = (fromDec: number, toDec: number, amount: bigint): bigint => {\n if (toDec >= fromDec) return amount * pow10bi(toDec - fromDec)\n return amount / pow10bi(fromDec - toDec)\n}\n\nexport const readFreshTrueBondPrice = async (marketObjectId?: string): Promise<bigint> => {\n if (!marketObjectId) {\n throw new Error('marketObjectId is required')\n }\n\n const client = getSuiClient()\n const obj = await client.getObject({ id: marketObjectId, options: { showContent: true } })\n\n if (!obj.data?.content || obj.data.content.dataType !== 'moveObject') {\n throw new Error(`[Sui] Could not read BondMarket ${marketObjectId}`)\n }\n\n const f = obj.data.content.fields as Record<string, unknown>\n const terms =\n ((f.terms as Record<string, unknown>)?.fields as Record<string, unknown>) ?? (f.terms as Record<string, unknown>)\n\n const totalDebt = BigInt(String(f.total_debt ?? '0'))\n const payoutInitialSupply = BigInt(String(f.payout_token_initial_supply ?? '0'))\n const controlVariable = BigInt(String(terms.control_variable ?? '0'))\n const minimumPrice = BigInt(String(terms.minimum_price ?? '0'))\n const vestingTerm = BigInt(String(terms.vesting_term ?? '1'))\n const lastDecay = BigInt(String(f.last_decay ?? '0'))\n const feeInPrincipal = BigInt(String(f.fee_in_principal ?? '0'))\n const payoutDecimals = Number(f.payout_decimals ?? 9)\n const principalDecimals = Number(f.principal_decimals ?? 9)\n\n // Decay debt client-side (same as contract's decay_debt)\n const nowSeconds = BigInt(Math.floor(Date.now() / 1000))\n let currentDebt = totalDebt\n if (nowSeconds > lastDecay && vestingTerm > 0n) {\n const elapsed = nowSeconds - lastDecay\n const decay = (totalDebt * elapsed) / vestingTerm\n currentDebt = totalDebt > decay ? totalDebt - decay : 0n\n }\n\n // calculate_price — contract casts total_debt (u128) to u64 via `as u64`\n const currentDebtU64 = currentDebt & 0xffffffffffffffffn\n const currentDebtPayout = valueOfToken(principalDecimals, payoutDecimals, currentDebtU64)\n const payoutScale = pow10bi(payoutDecimals)\n const principalScale = pow10bi(principalDecimals)\n\n const debtRatio = payoutInitialSupply > 0n ? (currentDebtPayout * payoutScale) / payoutInitialSupply : 0n\n const basePrice = (controlVariable * debtRatio * principalScale) / PRICE_DECIMALS\n\n const price = basePrice < minimumPrice ? minimumPrice : basePrice\n\n // calculate_true_price (includes fee)\n const denominator = PERCENTAGE_BASE - feeInPrincipal\n const truePrice = denominator > 0n ? (price * PERCENTAGE_BASE) / denominator : price\n\n return truePrice\n}\n\n// ---------------------------------------------------------------------------\n// TX status verification — Sui returns digests for failed TXs too.\n// Call this after waitForTransaction to ensure the TX actually succeeded.\n// ---------------------------------------------------------------------------\n\nexport const verifySuiTxSuccess = async (digest: string): Promise<void> => {\n const client = getSuiClient()\n const txBlock = await client.getTransactionBlock({\n digest,\n options: { showEffects: true },\n })\n const status = txBlock.effects?.status\n if (status?.status !== 'success') {\n const errorMsg = status?.error ?? 'Transaction failed on-chain'\n throw new Error(`Transaction failed: ${errorMsg}`)\n }\n}\n"],"names":[],"mappings":"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"}
@@ -29,12 +29,80 @@ import Flex from '../../components/uikit-sdk/Flex/index.js';
29
29
  import Text from '../../components/uikit-sdk/Text/index.js';
30
30
  import Button from '../../components/uikit-sdk/Button/Button.js';
31
31
  import SafeHTMLComponent from '../../components/SafeHTMLComponent/index.js';
32
- import { IS_SUI_MAINNET, SUI_PRINCIPAL_TOKEN_ADMIN_TESTNET, SUI_MINT_PRINCIPAL_FUNCTION, SUI_BOND_MARKET, SUI_TREASURY, SUI_BOND_NFT_REGISTRY, SUI_DEPOSIT_FUNCTION } from '../../constants/suiConstants.js';
32
+ import { SUI_DEPOSIT_FUNCTION, SUI_PACKAGE_ID } from '../../constants/suiConstants.js';
33
33
  import { getSuiClient, readFreshTrueBondPrice, verifySuiTxSuccess } from '../../utils/suiHelpers.js';
34
+ import { openSuiConnectModal } from '../../config/constants/suiCallbacks.js';
34
35
  import { useQueryClient } from '@tanstack/react-query';
35
36
  import { QUERY_KEYS } from '../../config/constants/queryKeys.js';
36
37
  import axios from 'axios';
37
38
 
39
+ // ---------------------------------------------------------------------------
40
+ // Helper: extract the bill_id from a confirmed Sui deposit transaction.
41
+ // Logs the full tx block so the bill_id can be located manually if the
42
+ // automatic extraction fails.
43
+ // ---------------------------------------------------------------------------
44
+ const extractSuiBillId = async (digest, suiClient) => {
45
+ const txBlock = await suiClient.getTransactionBlock({
46
+ digest,
47
+ options: {
48
+ showEffects: true,
49
+ showObjectChanges: true,
50
+ showEvents: true,
51
+ },
52
+ });
53
+ console.log('[SUI AFTER-PURCHASE] Full tx block for digest', digest, txBlock);
54
+ console.log('[SUI AFTER-PURCHASE] objectChanges:', txBlock.objectChanges);
55
+ console.log('[SUI AFTER-PURCHASE] events:', txBlock.events);
56
+ // ── Strategy 1: find the created BondNFT in objectChanges ──────────────
57
+ const bondNftType = `${SUI_PACKAGE_ID}::bond_nft::BondNFT`;
58
+ const createdNft = txBlock.objectChanges?.find((change) => change.type === 'created' && 'objectType' in change && change.objectType?.includes(bondNftType));
59
+ console.log('[SUI AFTER-PURCHASE] Created BondNFT objectChange:', createdNft);
60
+ if (createdNft && 'objectId' in createdNft) {
61
+ const nftObjectId = createdNft.objectId;
62
+ console.log('[SUI AFTER-PURCHASE] BondNFT objectId:', nftObjectId);
63
+ try {
64
+ const nftObj = await suiClient.getObject({
65
+ id: nftObjectId,
66
+ options: { showContent: true },
67
+ });
68
+ console.log('[SUI AFTER-PURCHASE] BondNFT full object:', nftObj);
69
+ if (nftObj.data?.content?.dataType === 'moveObject') {
70
+ const fields = nftObj.data.content.fields;
71
+ console.log('[SUI AFTER-PURCHASE] BondNFT fields:', fields);
72
+ const billId = String(fields?.bill_id ?? '');
73
+ if (billId && billId !== 'undefined' && billId !== '') {
74
+ console.log('[SUI AFTER-PURCHASE] ✅ Extracted bill_id from BondNFT object:', billId);
75
+ return billId;
76
+ }
77
+ }
78
+ }
79
+ catch (e) {
80
+ console.warn('[SUI AFTER-PURCHASE] Failed to read BondNFT object:', nftObjectId, e);
81
+ }
82
+ }
83
+ // ── Strategy 2: look for bill_id in emitted Move events ────────────────
84
+ if (txBlock.events && txBlock.events.length > 0) {
85
+ for (const event of txBlock.events) {
86
+ console.log('[SUI AFTER-PURCHASE] Event type:', event.type, 'parsedJson:', event.parsedJson);
87
+ const eventData = event.parsedJson;
88
+ if (eventData?.bill_id !== undefined) {
89
+ const billId = String(eventData.bill_id);
90
+ console.log('[SUI AFTER-PURCHASE] ✅ Extracted bill_id from event:', event.type, billId);
91
+ return billId;
92
+ }
93
+ }
94
+ }
95
+ // ── Strategy 3: log all object changes for manual inspection ──────────
96
+ if (txBlock.objectChanges) {
97
+ for (const change of txBlock.objectChanges) {
98
+ console.log('[SUI AFTER-PURCHASE] objectChange entry:', change);
99
+ }
100
+ }
101
+ console.warn('[SUI AFTER-PURCHASE] ⚠️ Could not extract bill_id automatically from digest:', digest, '— check the logs above to find it manually.');
102
+ // Signal that the tx succeeded but we don't have a bill ID yet.
103
+ // ModalHandler will fall back to a query-refresh-based flow.
104
+ return `digest:${digest}`;
105
+ };
38
106
  const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, setBillId, }) => {
39
107
  const SDKConfig = useSDKConfig();
40
108
  const queryClient = useQueryClient();
@@ -122,7 +190,7 @@ const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, set
122
190
  .times(new BigNumber(10).pow(principalDecimals))
123
191
  .integerValue(BigNumber.ROUND_FLOOR)
124
192
  .toFixed(0);
125
- const market = bondData.contractAddress[bondData.chainId] ?? SUI_BOND_MARKET;
193
+ const market = bondData.contractAddress[bondData.chainId];
126
194
  // Read fresh bond price from chain to avoid stale cache after previous purchases
127
195
  const freshTruePrice = await readFreshTrueBondPrice(market);
128
196
  const atomicMaxPrice = new BigNumber(freshTruePrice.toString())
@@ -157,13 +225,16 @@ const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, set
157
225
  [principalCoin] = tx.splitCoins(tx.object(userCoins.data[0].coinObjectId), [tx.pure.u64(atomicAmount)]);
158
226
  }
159
227
  }
228
+ if (!market || !bondData?.suiTreasuryId || !bondData?.billNnftAddress?.[ChainId.SUI]) {
229
+ return;
230
+ }
160
231
  tx.moveCall({
161
232
  target: SUI_DEPOSIT_FUNCTION,
162
233
  typeArguments: [payoutCoinType, principalCoinType],
163
234
  arguments: [
164
235
  tx.object(market),
165
- tx.object(bondData.suiTreasuryId ?? SUI_TREASURY),
166
- tx.object(SUI_BOND_NFT_REGISTRY),
236
+ tx.object(bondData.suiTreasuryId),
237
+ tx.object(bondData.billNnftAddress[ChainId.SUI]),
167
238
  principalCoin,
168
239
  tx.pure.u64(atomicMaxPrice),
169
240
  tx.pure.address(suiAccount),
@@ -186,13 +257,17 @@ const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, set
186
257
  const suiClient = getSuiClient();
187
258
  await suiClient.waitForTransaction({ digest });
188
259
  await verifySuiTxSuccess(digest);
260
+ // Extract the bill_id from the confirmed transaction.
261
+ // extractSuiBillId logs the full tx block so you can inspect the raw data
262
+ // in case automatic extraction fails.
263
+ const billId = await extractSuiBillId(digest, suiClient);
264
+ console.log('[SUI AFTER-PURCHASE] handleBuyCallback billId:', billId);
189
265
  // Invalidate bonds data so next purchase uses fresh pricing
190
266
  await queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.BONDS_DATA] });
191
267
  // Sui's indexer has a short lag — getOwnedObjects may not return the
192
268
  // new BondNFT immediately. Schedule re-invalidations so the Your Bonds
193
269
  // view picks up the new bond once the indexer catches up.
194
270
  setTimeout(() => queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.USER_BONDS] }), 3000);
195
- setTimeout(() => queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.USER_BONDS] }), 8000);
196
271
  track({
197
272
  event: 'bond',
198
273
  chain: bondChain,
@@ -207,9 +282,7 @@ const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, set
207
282
  },
208
283
  });
209
284
  addToastSuccess(digest, bondChain);
210
- // Sui does not return a bill_id from the tx response easily —
211
- // the frontend will pick it up on the next query refresh.
212
- setBillId?.('');
285
+ setBillId?.(billId);
213
286
  }
214
287
  catch (error) {
215
288
  console.error('[SUI DEBUG] Error during Sui bond purchase:', error);
@@ -247,47 +320,47 @@ const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, set
247
320
  .integerValue(BigNumber.ROUND_FLOOR)
248
321
  .toFixed(0);
249
322
  // TX1: Acquire principal tokens
250
- if (IS_SUI_MAINNET) {
251
- // Mainnet: swap via Aftermath DEX aggregator
252
- const txResponse = await axios.post(AFTERMATH_TX_API_URL, {
253
- walletAddress: suiAccount,
254
- completeRoute: aftermathQuote,
255
- slippage: slippage / 100,
256
- });
257
- const swapTxBytes = txResponse.data;
258
- if (!swapTxBytes)
259
- throw new Error('Aftermath returned no transaction data');
260
- const swapTx = Transaction.from(swapTxBytes);
261
- const swapResponse = await signAndExecuteTransaction({ transaction: swapTx });
262
- const swapDigest = swapResponse?.digest;
263
- if (!swapDigest)
264
- throw new Error('No tx digest returned for swap');
265
- await suiClient.waitForTransaction({ digest: swapDigest });
266
- }
267
- else {
268
- // Testnet: mint principal tokens via test_principal_token::mint
269
- // No DEX aggregator supports Sui testnet or custom test tokens.
270
- const mintTx = new Transaction();
271
- mintTx.moveCall({
272
- target: SUI_MINT_PRINCIPAL_FUNCTION,
273
- arguments: [
274
- mintTx.object(SUI_PRINCIPAL_TOKEN_ADMIN_TESTNET),
275
- mintTx.pure.u64(depositAmountAtomic),
276
- mintTx.pure.address(suiAccount),
277
- ],
278
- });
279
- mintTx.setSender(suiAccount);
280
- mintTx.setGasBudget(50000000);
281
- const builtMint = await mintTx.build({ client: suiClient });
282
- const prebuiltMint = Transaction.from(builtMint);
283
- const mintResponse = await signAndExecuteTransaction({ transaction: prebuiltMint });
284
- const mintDigest = mintResponse?.digest;
285
- if (!mintDigest)
286
- throw new Error('No tx digest returned for testnet mint');
287
- await suiClient.waitForTransaction({ digest: mintDigest });
288
- }
323
+ // if (IS_SUI_MAINNET) {
324
+ // Mainnet: swap via Aftermath DEX aggregator
325
+ const txResponse = await axios.post(AFTERMATH_TX_API_URL, {
326
+ walletAddress: suiAccount,
327
+ completeRoute: aftermathQuote,
328
+ slippage: slippage / 100,
329
+ });
330
+ const swapTxBytes = txResponse.data;
331
+ if (!swapTxBytes)
332
+ throw new Error('Aftermath returned no transaction data');
333
+ const swapTx = Transaction.from(swapTxBytes);
334
+ const swapResponse = await signAndExecuteTransaction({ transaction: swapTx });
335
+ const swapDigest = swapResponse?.digest;
336
+ if (!swapDigest)
337
+ throw new Error('No tx digest returned for swap');
338
+ await suiClient.waitForTransaction({ digest: swapDigest });
339
+ // } else {
340
+ // // Testnet: mint principal tokens via test_principal_token::mint
341
+ // // No DEX aggregator supports Sui testnet or custom test tokens.
342
+ // const mintTx = new Transaction()
343
+ // mintTx.moveCall({
344
+ // target: SUI_MINT_PRINCIPAL_FUNCTION,
345
+ // arguments: [
346
+ // mintTx.object(SUI_PRINCIPAL_TOKEN_ADMIN_TESTNET),
347
+ // mintTx.pure.u64(depositAmountAtomic),
348
+ // mintTx.pure.address(suiAccount),
349
+ // ],
350
+ // })
351
+ //
352
+ // mintTx.setSender(suiAccount)
353
+ // mintTx.setGasBudget(50_000_000)
354
+ // const builtMint = await mintTx.build({ client: suiClient })
355
+ // const prebuiltMint = Transaction.from(builtMint)
356
+ //
357
+ // const mintResponse = await signAndExecuteTransaction({ transaction: prebuiltMint })
358
+ // const mintDigest = mintResponse?.digest
359
+ // if (!mintDigest) throw new Error('No tx digest returned for testnet mint')
360
+ // await suiClient.waitForTransaction({ digest: mintDigest })
361
+ // }
289
362
  // TX2: Deposit into bond with principal tokens
290
- const market = bondData.contractAddress[bondData.chainId] ?? SUI_BOND_MARKET;
363
+ const market = bondData.contractAddress[ChainId.SUI];
291
364
  // Read fresh bond price from chain to avoid stale cache
292
365
  const freshTruePrice = await readFreshTrueBondPrice(market);
293
366
  const atomicMaxPrice = new BigNumber(freshTruePrice.toString())
@@ -322,13 +395,16 @@ const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, set
322
395
  ]);
323
396
  }
324
397
  }
398
+ if (!market || !bondData?.suiTreasuryId || !bondData?.billNnftAddress?.[ChainId.SUI]) {
399
+ return;
400
+ }
325
401
  tx.moveCall({
326
402
  target: SUI_DEPOSIT_FUNCTION,
327
403
  typeArguments: [payoutCoinType, principalCoinType],
328
404
  arguments: [
329
405
  tx.object(market),
330
- tx.object(bondData.suiTreasuryId ?? SUI_TREASURY),
331
- tx.object(SUI_BOND_NFT_REGISTRY),
406
+ tx.object(bondData.suiTreasuryId),
407
+ tx.object(bondData.billNnftAddress[ChainId.SUI]),
332
408
  principalCoin,
333
409
  tx.pure.u64(atomicMaxPrice),
334
410
  tx.pure.address(suiAccount),
@@ -345,11 +421,15 @@ const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, set
345
421
  throw new Error('No tx digest returned for deposit');
346
422
  await suiClient.waitForTransaction({ digest: depositDigest });
347
423
  await verifySuiTxSuccess(depositDigest);
424
+ // Extract the bill_id from the confirmed deposit transaction.
425
+ // extractSuiBillId logs the full tx block so you can inspect the raw data
426
+ // in case automatic extraction fails.
427
+ const billId = await extractSuiBillId(depositDigest, suiClient);
428
+ console.log('[SUI AFTER-PURCHASE] handleZapCallback billId:', billId);
348
429
  // Invalidate bonds data so next purchase uses fresh pricing
349
430
  await queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.BONDS_DATA] });
350
431
  // Sui indexer lag — schedule delayed re-invalidations for user bonds
351
432
  setTimeout(() => queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.USER_BONDS] }), 3000);
352
- setTimeout(() => queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.USER_BONDS] }), 8000);
353
433
  track({
354
434
  event: 'zap',
355
435
  chain: bondChain,
@@ -374,7 +454,7 @@ const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, set
374
454
  },
375
455
  });
376
456
  addToastSuccess(depositDigest, bondChain);
377
- setBillId?.('');
457
+ setBillId?.(billId);
378
458
  }
379
459
  catch (error) {
380
460
  console.error('Error during Sui zap bond purchase:', error);
@@ -438,11 +518,7 @@ const BuyComponentSui = ({ onDismiss, bondAddress, bondChain, isProjectView, set
438
518
  mt: '10px',
439
519
  borderRadius: 'normal',
440
520
  p: '2px 10px',
441
- }, children: jsx(Text, { sx: { fontSize: '12px', fontWeight: 400, display: 'flex', alignItems: 'center', gap: '10px' }, children: jsx(SafeHTMLComponent, { html: bondData?.warningCard }) }) })), jsx(Flex, { className: "modaltable-container button-container", children: jsx(Flex, { className: "button-container buy", children: !suiAccount ? (jsx(Button, { className: "action-button", onClick: () => {
442
- // Sui dapp-kit ConnectModal is managed by the provider —
443
- // consumers should wrap the app in SuiWalletProvider.
444
- // This button is a fallback prompt.
445
- }, sx: { width: '100%', fontSize: ['14px', '14px', '14px', '16px'] }, children: "Connect to Sui" })) : (jsx(Button, { className: "action-button", load: load, disabled: !canBuy, onClick: handleBuy, sx: { width: '100%', fontSize: ['14px', '14px', '14px', '16px'] }, children: SDKConfig.blockSales
521
+ }, children: jsx(Text, { sx: { fontSize: '12px', fontWeight: 400, display: 'flex', alignItems: 'center', gap: '10px' }, children: jsx(SafeHTMLComponent, { html: bondData?.warningCard }) }) })), jsx(Flex, { className: "modaltable-container button-container", children: jsx(Flex, { className: "button-container buy", children: !suiAccount ? (jsx(Button, { className: "action-button", onClick: openSuiConnectModal, sx: { width: '100%', fontSize: ['14px', '14px', '14px', '16px'] }, children: "Connect to Sui" })) : (jsx(Button, { className: "action-button", load: load, disabled: !canBuy, onClick: handleBuy, sx: { width: '100%', fontSize: ['14px', '14px', '14px', '16px'] }, children: SDKConfig.blockSales
446
522
  ? 'Complete KYC to Buy'
447
523
  : zapError
448
524
  ? 'Swap quote failed'