diff --git a/components/ui/TransactionButton.tsx b/components/ui/TransactionButton.tsx index 2ab30541e..1bf87e7c7 100644 --- a/components/ui/TransactionButton.tsx +++ b/components/ui/TransactionButton.tsx @@ -52,7 +52,6 @@ const TransactionButton: FC> = ({ }, [extrinsic, sdk]); const { data: fee } = useExtrinsicFee(extrinsicBase); - const { data: constants } = useChainConstants(); const insufficientFeeBalance = fee?.sufficientBalance === false; @@ -92,7 +91,7 @@ const TransactionButton: FC> = ({ } else if (isUsingVPN) { return "VPN Blocked"; } else if (insufficientFeeBalance) { - return `Insufficient ${constants?.tokenSymbol}`; + return `Insufficient ${fee.symbol}`; } else if (loading) { return (
diff --git a/lib/hooks/queries/useFeePayingAsset.ts b/lib/hooks/queries/useFeePayingAsset.ts index 772f4786f..bf70bbfe4 100644 --- a/lib/hooks/queries/useFeePayingAsset.ts +++ b/lib/hooks/queries/useFeePayingAsset.ts @@ -1,13 +1,13 @@ import { UseQueryResult, useQuery } from "@tanstack/react-query"; - -import { AssetId, IOZtgAssetId, ZTG } from "@zeitgeistpm/sdk"; +import { AssetId, IOForeignAssetId, IOZtgAssetId, ZTG } from "@zeitgeistpm/sdk"; import Decimal from "decimal.js"; +import useFeePayingAssetSelection from "lib/state/fee-paying-asset"; import { useWallet } from "lib/state/wallet"; -import { useAssetMetadata } from "./useAssetMetadata"; -import { useBalance } from "./useBalance"; -import { useChainConstants } from "./useChainConstants"; +import { AssetMetadata, useAllAssetMetadata } from "./useAssetMetadata"; +import { ChainConstants, useChainConstants } from "./useChainConstants"; +import { CurrencyBalance } from "./useCurrencyBalances"; +import { useForeignAssetBalances } from "./useForeignAssetBalances"; import { useZtgBalance } from "./useZtgBalance"; -import useFeePayingAssetSelection from "lib/state/fee-paying-asset"; type FeeAsset = { assetId: AssetId; @@ -26,27 +26,27 @@ export const useFeePayingAsset = ( ): UseQueryResult => { const { activeAccount: activeAccount } = useWallet(); const { data: nativeBalance } = useZtgBalance(activeAccount?.address); + const { data: foreignAssetBalances } = useForeignAssetBalances( + activeAccount?.address, + ); const { data: constants } = useChainConstants(); - - const { data: dotMetadata } = useAssetMetadata({ ForeignAsset: 0 }); - const { data: dotBalance } = useBalance(activeAccount?.address, { - ForeignAsset: 0, - }); + const { data: assetMetadata } = useAllAssetMetadata(); const { assetSelection } = useFeePayingAssetSelection(); const enabled = !!nativeBalance && - !!dotMetadata && + !!foreignAssetBalances && !!activeAccount && - !!dotBalance && - !!baseFee; + !!assetMetadata && + !!baseFee && + !!constants; const query = useQuery( [ feePayingAssetKey, activeAccount?.address, nativeBalance, - dotBalance, + foreignAssetBalances, baseFee, assetSelection, ], @@ -63,26 +63,12 @@ export const useFeePayingAsset = ( }; } - const dotFeeFactor = dotMetadata.feeFactor.div(ZTG); - const dotFee = baseFee.mul(dotFeeFactor).mul(foreignAssetFeeBuffer); - - if (dotBalance.greaterThan(dotFee)) { - return { - assetId: { - ForeignAsset: 0, - }, - symbol: dotMetadata.symbol, - amount: dotFee, - sufficientBalance: true, - }; - } else { - return { - assetId: { Ztg: null }, - symbol: constants?.tokenSymbol ?? "", - amount: baseFee, - sufficientBalance: false, - }; - } + return findBestFeePayingAsset( + foreignAssetBalances, + assetMetadata, + baseFee, + constants, + ); } else { const isNative = IOZtgAssetId.is(assetSelection.value); if (isNative) { @@ -92,17 +78,29 @@ export const useFeePayingAsset = ( amount: baseFee, sufficientBalance: true, }; - } else { - const dotFeeFactor = dotMetadata.feeFactor.div(ZTG); - const dotFee = baseFee.mul(dotFeeFactor).mul(foreignAssetFeeBuffer); - return { - assetId: { - ForeignAsset: 0, - }, - symbol: dotMetadata.symbol, - amount: dotFee, - sufficientBalance: dotBalance.greaterThan(dotFee), - }; + } else if (IOForeignAssetId.is(assetSelection.value)) { + const balance = foreignAssetBalances.find( + (asset) => + IOForeignAssetId.is(assetSelection.value) && + assetSelection.value.ForeignAsset === asset.foreignAssetId, + ); + const metadata = assetMetadata?.find( + (data) => + IOForeignAssetId.is(assetSelection.value) && + assetSelection.value.ForeignAsset === data[0], + )?.[1]; + const feeFactor = metadata?.feeFactor.div(ZTG); + const fee = + feeFactor && baseFee.mul(feeFactor).mul(foreignAssetFeeBuffer); + + if (metadata && fee && balance) { + return { + assetId: assetSelection.value, + symbol: metadata?.symbol, + amount: fee, + sufficientBalance: fee && balance?.balance.greaterThan(fee), + }; + } } } } @@ -115,3 +113,50 @@ export const useFeePayingAsset = ( return query; }; + +const findBestFeePayingAsset = ( + foreignAssetBalances: CurrencyBalance[], + assetMetadata: [number | "Ztg", AssetMetadata][], + baseFee: Decimal, + constants: ChainConstants, +) => { + // find first available asset to pay fee, else just return native asset + const availableAsset = foreignAssetBalances.find((asset) => { + const feeFactor = + availableAsset && findFeeFactor(assetMetadata, availableAsset); + if (feeFactor) { + return asset.balance.greaterThan( + baseFee.mul(feeFactor).mul(foreignAssetFeeBuffer), + ); + } + }); + + if (availableAsset && availableAsset.foreignAssetId != null) { + const feeFactor = + availableAsset && findFeeFactor(assetMetadata, availableAsset); + return { + assetId: { + ForeignAsset: availableAsset.foreignAssetId, + }, + symbol: availableAsset.symbol, + amount: baseFee.mul(feeFactor ?? 1).mul(foreignAssetFeeBuffer), + sufficientBalance: true, + }; + } else { + return { + assetId: { Ztg: null }, + symbol: constants?.tokenSymbol ?? "", + amount: baseFee, + sufficientBalance: false, + }; + } +}; + +const findFeeFactor = ( + assetMetadata: [number | "Ztg", AssetMetadata][], + asset: CurrencyBalance, +) => { + return assetMetadata + .find((data) => asset.foreignAssetId === data[0])?.[1] + .feeFactor.div(ZTG); +}; diff --git a/lib/state/util/web3auth-config.ts b/lib/state/util/web3auth-config.ts index bb55f5f8e..c96c18987 100644 --- a/lib/state/util/web3auth-config.ts +++ b/lib/state/util/web3auth-config.ts @@ -3,7 +3,7 @@ import { CHAIN_NAMESPACES } from "@web3auth/base"; import { Web3Auth } from "@web3auth/modal"; import { atom } from "jotai"; -export const clientId = process.env.NEXT_PUBLIC_WEB3AUTH_CLIENT_ID_ZTG ?? ""; +export const clientId = process.env.NEXT_PUBLIC_WEB3AUTH_CLIENT_ID_ZTG; class Web3AuthWallet extends BaseDotsamaWallet { constructor({ extensionName, title, installUrl, logo }) { @@ -41,28 +41,31 @@ const chainConfig = { ticker: "DOT", tickerName: "Polkadot", }; -export const web3AuthInstance = new Web3Auth({ - clientId, - chainConfig, - web3AuthNetwork: "cyan", - // Settings for whitelabel version of web3auth modal - // uiConfig: { - // loginMethodsOrder: [ - // "google", - // "facebook", - // "twitter", - // "discord", - // "twitch", - // "email_passwordless", - // ], - // appName: "Zeitgeist", - // mode: "dark", - // logoLight: "https://web3auth.io/images/w3a-L-Favicon-1.svg", - // logoDark: "https://web3auth.io/images/w3a-D-Favicon-1.svg", - // defaultLanguage: "en", - // loginGridCol: 3, - // primaryButton: "externalLogin", - // }, -}); +export const web3AuthInstance = + clientId && clientId.length > 0 + ? new Web3Auth({ + clientId, + chainConfig, + web3AuthNetwork: "cyan", + // Settings for whitelabel version of web3auth modal + // uiConfig: { + // loginMethodsOrder: [ + // "google", + // "facebook", + // "twitter", + // "discord", + // "twitch", + // "email_passwordless", + // ], + // appName: "Zeitgeist", + // mode: "dark", + // logoLight: "https://web3auth.io/images/w3a-L-Favicon-1.svg", + // logoDark: "https://web3auth.io/images/w3a-D-Favicon-1.svg", + // defaultLanguage: "en", + // loginGridCol: 3, + // primaryButton: "externalLogin", + // }, + }) + : null; export const web3authAtom = atom(web3AuthInstance); diff --git a/package.json b/package.json index 54388a40a..25acdcd45 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@headlessui/tailwindcss": "^0.1.2", "@notionhq/client": "^2.2.3", "@plaiceholder/next": "^2.5.0", - "@polkadot/api": "^10.9.1", + "@polkadot/api": "^10.10.1", "@polkadot/extension-dapp": "^0.44.6", "@polkadot/ui-keyring": "^2.4.1", "@subsocial/grill-widget": "^0.0.5", diff --git a/yarn.lock b/yarn.lock index 32a628478..5a0287886 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1815,7 +1815,7 @@ __metadata: languageName: node linkType: hard -"@polkadot/api@npm:10.10.1, @polkadot/api@npm:^10.9.1": +"@polkadot/api@npm:10.10.1, @polkadot/api@npm:^10.10.1": version: 10.10.1 resolution: "@polkadot/api@npm:10.10.1" dependencies: @@ -4594,7 +4594,7 @@ __metadata: "@notionhq/client": ^2.2.3 "@plaiceholder/next": ^2.5.0 "@playwright/test": ^1.28.1 - "@polkadot/api": ^10.9.1 + "@polkadot/api": ^10.10.1 "@polkadot/extension-dapp": ^0.44.6 "@polkadot/ui-keyring": ^2.4.1 "@polkadot/wasm-crypto": ^6.3.1