diff --git a/src/plugins/oSnap/Create.vue b/src/plugins/oSnap/Create.vue index df9e4aa2..a7bfe582 100644 --- a/src/plugins/oSnap/Create.vue +++ b/src/plugins/oSnap/Create.vue @@ -17,7 +17,8 @@ import { getGnosisSafeBalances, getGnosisSafeCollectibles, getIsOsnapEnabled, - getModuleAddressForTreasury + getModuleAddressForTreasury, + getNativeAsset } from './utils'; import OsnapMarketingWidget from './components/OsnapMarketingWidget.vue'; @@ -77,21 +78,20 @@ async function fetchBalances(network: Network, safeAddress: string) { } try { const balances = await getGnosisSafeBalances(network, safeAddress); + const balancesWithNative = balances.map(balance => { + if (!balance.tokenAddress || !balance.token) { + return { + ...balance, + token: getNativeAsset(network), + tokenAddress: 'main' + }; + } + return balance; + }); - const uniswapTokensPromise = fetchTokens( - 'https://gateway.ipfs.io/ipns/tokens.uniswap.org' - ); - const snapshotTokensPromise = fetchTokens( - `${import.meta.env.VITE_SIDEKICK_URL}/api/moderation?list=verifiedTokens` - ); - - const tokensLists = await Promise.all([ - uniswapTokensPromise, - snapshotTokensPromise - ]); - const tokens = tokensLists.flat(); + const tokens = await fetchTokens('https://tokens.uniswap.org'); - return enhanceTokensWithBalances(balances, tokens); + return enhanceTokensWithBalances(balancesWithNative, tokens, network); } catch (e) { console.warn('Error fetching balances'); return []; @@ -100,7 +100,8 @@ async function fetchBalances(network: Network, safeAddress: string) { function enhanceTokensWithBalances( balances: Partial[], - tokens: Token[] + tokens: Token[], + network: Network ) { console.log({ balances, tokens }); return balances @@ -108,18 +109,23 @@ function enhanceTokensWithBalances( (balance): balance is BalanceResponse => !!balance.token && !!balance.tokenAddress && !!balance.balance ) - .map(balance => enhanceTokenWithBalance(balance, tokens)) + .map(balance => enhanceTokenWithBalance(balance, tokens, network)) .sort((a, b) => { - if (a.verified && b.verified) return 0; - if (a.verified) return -1; - return 1; + if (a.address === 'main' && b.address !== 'main') return -1; + if (!(a.address === 'main') && b.address === 'main') return 1; + if (a.verified && !b.verified) return -1; + if (!a.verified && b.verified) return +1; + if (!a.balance || !b.balance) return 0; + if (parseFloat(a.balance) > parseFloat(b.balance)) return -1; + return 0; }); } // gets token balances and also determines if the token is verified function enhanceTokenWithBalance( balance: BalanceResponse, - tokens: Token[] + tokens: Token[], + network: Network ): Token { const verifiedToken = getVerifiedToken(balance.tokenAddress, tokens); return { @@ -129,7 +135,7 @@ function enhanceTokenWithBalance( ? formatUnits(balance.balance, balance.token.decimals) : '0', verified: !!verifiedToken, - chainId: verifiedToken ? verifiedToken.chainId : undefined + chainId: network }; } @@ -197,8 +203,9 @@ const update = (newPluginData: OsnapPluginData) => { emit('update', { key: 'oSnap', form: newPluginData }); }; -watch(newPluginData, async () => { +async function loadBalancesAndCollectibles() { if (!newPluginData.value.safe?.safeAddress) return; + isLoading.value = true; tokens.value = await fetchBalances( newPluginData.value.safe.network, newPluginData.value.safe.safeAddress @@ -207,20 +214,26 @@ watch(newPluginData, async () => { newPluginData.value.safe.network, newPluginData.value.safe.safeAddress ); -}); + + isLoading.value = false; +} + +watch( + () => [ + newPluginData.value.safe?.safeAddress, + newPluginData.value.safe?.network + ], + async () => { + await loadBalancesAndCollectibles(); + update(newPluginData.value); + } +); onMounted(async () => { isLoading.value = true; safes.value = await createOsnapEnabledSafes(); newPluginData.value.safe = cloneDeep(safes.value[0]); - tokens.value = await fetchBalances( - newPluginData.value.safe.network, - newPluginData.value.safe.safeAddress - ); - collectables.value = await fetchCollectibles( - newPluginData.value.safe.network, - newPluginData.value.safe.safeAddress - ); + await loadBalancesAndCollectibles(); update(newPluginData.value); isLoading.value = false; }); diff --git a/src/plugins/oSnap/components/TransactionBuilder/TokensModalItem.vue b/src/plugins/oSnap/components/TransactionBuilder/TokensModalItem.vue index af3166eb..75e75f90 100644 --- a/src/plugins/oSnap/components/TransactionBuilder/TokensModalItem.vue +++ b/src/plugins/oSnap/components/TransactionBuilder/TokensModalItem.vue @@ -54,7 +54,7 @@ const exploreUrl = computed(() => {
- + {{ formatNumber( Number(token.balance), diff --git a/src/plugins/oSnap/components/TransactionBuilder/TransferFunds.vue b/src/plugins/oSnap/components/TransactionBuilder/TransferFunds.vue index 8f0f5ea4..ba3c41a8 100644 --- a/src/plugins/oSnap/components/TransactionBuilder/TransferFunds.vue +++ b/src/plugins/oSnap/components/TransactionBuilder/TransferFunds.vue @@ -23,10 +23,9 @@ const emit = defineEmits<{ updateTransaction: [transaction: TransferFundsTransaction]; }>(); -const nativeAsset = getNativeAsset(props.network); const amount = ref(props.transaction.amount ?? ''); const recipient = ref(props.transaction.recipient ?? ''); -const tokens = ref([nativeAsset, ...props.tokens]); +const tokens = ref(props.tokens); const selectedTokenAddress = ref( props.transaction?.token?.address ?? 'main' @@ -35,7 +34,8 @@ const selectedTokenAddress = ref( const selectedToken = computed( () => tokens.value.find(token => token.address === selectedTokenAddress.value) ?? - nativeAsset + tokens.value.find(token => token.address === 'main') ?? + tokens.value[0] ); const isTokenModalOpen = ref(false); diff --git a/src/plugins/oSnap/utils/getters.ts b/src/plugins/oSnap/utils/getters.ts index 4f070aca..331fbb8a 100644 --- a/src/plugins/oSnap/utils/getters.ts +++ b/src/plugins/oSnap/utils/getters.ts @@ -54,7 +54,7 @@ async function callGnosisSafeTransactionApi( */ export const getGnosisSafeBalances = memoize( (network: Network, safeAddress: string) => { - const endpointPath = `/v1/safes/${safeAddress}/balances/`; + const endpointPath = `/v1/safes/${safeAddress}/balances?exclude_spam=true`; return callGnosisSafeTransactionApi[]>( network, endpointPath