Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate composables to a provider pattern, so watchers and composables register once. #537

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,283 changes: 703 additions & 580 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"pretty-ms": "^7.0.0",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.4",
"typescript": "~3.9.3",
"vue": "^3.0.0-beta.1",
"vue": "^3.1.4",
"vue-echarts": "^6.0.0-rc.4",
"vue-i18n": "^9.0.0-rc.1",
"vue-query": "^1.6.0",
Expand Down
2 changes: 2 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import WalletSelectModal from '@/components/web3/WalletSelectModal.vue';
import useVueWeb3 from './services/web3/useVueWeb3';
import RpcProviderService from '@/services/rpc-provider/rpc-provider.service';
import { useRoute } from 'vue-router';
// import registerProviders from '@/plugins/providers/registerProviders';

export default defineComponent({
components: {
Expand Down Expand Up @@ -54,6 +55,7 @@ export default defineComponent({

// CALLBACKS
onBeforeMount(() => {
// registerProviders();
store.dispatch('app/init');
providerService.initBlockListener(setBlockNumber);
});
Expand Down
42 changes: 42 additions & 0 deletions src/AppProviders.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script lang="ts">
import { defineComponent, h } from 'vue';

import Provider from '@/plugins/providers/Provider.vue';
import provideTokenStore from '@/plugins/providers/tokenstore.provider';
import provideTokens from '@/plugins/providers/tokens.provider';
import provideAccountBalances from '@/plugins/providers/balances.provider';
import provideAccountAllowances from '@/plugins/providers/allowances.provider';
Comment on lines +4 to +8
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These probably will move to a better home that isn't inside plugins


const providers = [
provideTokenStore,
provideAccountBalances,
provideTokens,
provideAccountAllowances
];

import App from './App.vue';
export default defineComponent({
components: {
App,
Provider
},
render() {
const renderProvider = (providerFunctions: Function[]) => {
if (!providerFunctions.length) {
return h(App, {});
}
const [providerFunction, ...remainder] = providerFunctions;
return h(
Provider,
{ providerFunction: providerFunction as Function },
{
default() {
return [renderProvider(remainder)];
}
}
);
};
return renderProvider(providers);
}
});
</script>
15 changes: 9 additions & 6 deletions src/components/modals/SelectTokenModal/SelectTokenModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@
</template>

<script lang="ts">
import { defineComponent, reactive, toRefs, computed } from 'vue';
import { defineComponent, reactive, toRefs, computed, watch } from 'vue';
import { useStore } from 'vuex';
import { useI18n } from 'vue-i18n';
import { isAddress, getAddress } from '@ethersproject/address';
import useTokenLists from '@/composables/useTokensStore';
import useTokenStore from '@/composables/useTokensStore';
// import useTokenLists2 from '@/composables/useTokenLists2';
import TokenListItem from '@/components/lists/TokenListItem.vue';
import TokenListsListItem from '@/components/lists/TokenListsListItem.vue';
Expand Down Expand Up @@ -147,15 +147,18 @@ export default defineComponent({
isActiveList,
listMap,
activeTokenLists
} = useTokenLists();
const { tokens: tokenMap } = useTokens(data);
const tokens = computed(() => Object.values(tokenMap.value));
} = useTokenStore();

const { tokens: tokenMap } = useTokens(toRefs(data));
const tokens = computed(() => {
return Object.values(tokenMap.value);
});
// const {
// approvedTokenLists,
// toggleList,
// toggled: toggledTokenLists,
// isToggled: isToggledList
// } = useTokenLists2();
// } = useTokenStore2();

// COMPOSABLES
const store = useStore();
Expand Down
87 changes: 9 additions & 78 deletions src/composables/useAccountBalances.ts
Original file line number Diff line number Diff line change
@@ -1,90 +1,21 @@
import getProvider from '@/lib/utils/provider';
import { useQuery } from 'vue-query';
import { computed, reactive } from 'vue';
import { getBalances } from '@/lib/utils/balancer/tokens';
import { formatEther, formatUnits } from '@ethersproject/units';
import { getAddress } from '@ethersproject/address';
import QUERY_KEYS from '@/constants/queryKeys';
import { ETHER } from '@/constants/tokenlists';
import useVueWeb3 from '@/services/web3/useVueWeb3';
import useTokenStore from './useTokensStore';
import {
BalancesProviderPayload,
BalancesProviderSymbol
} from '@/plugins/providers/balances.provider';
import { inject } from 'vue';

// THE CONTENTS OF THIS WILL BE REPLACED/ALTERED WITH THE REGISTRY REFACTOR
export default function useAccountBalances() {
const { account, userNetworkConfig, isWalletReady } = useVueWeb3();
const { allTokens: tokens, isLoading: isLoadingTokens } = useTokenStore();

const isQueryEnabled = computed(
() =>
account.value !== null &&
Object.keys(tokens).length !== 0 &&
isWalletReady.value &&
!isLoadingTokens.value
);

const {
data,
balances,
hasBalance,
error,
isLoading,
isIdle,
isError,
isFetching,
refetch: refetchBalances
} = useQuery(
reactive(QUERY_KEYS.Balances.All(account, userNetworkConfig, tokens)),
() => {
return Promise.all([
getBalances(
String(userNetworkConfig.value?.chainId),
getProvider(userNetworkConfig.value?.key),
account.value,
Object.values(tokens.value)
.map(token => token.address)
.filter(token => token !== ETHER.address)
),
getProvider(userNetworkConfig.value?.key).getBalance(
account.value.toLowerCase()
)
]);
},
reactive({
enabled: isQueryEnabled,
keepPreviousData: isWalletReady
})
);

const balances = computed(() => {
if (data.value) {
const balances = {};
Object.keys(data.value[0]).forEach((tokenAddress: string) => {
const balance = formatUnits(
data.value[0][tokenAddress],
tokens.value[getAddress(tokenAddress)]?.decimals || 18
);
// not concerned with tokens which have a 0 balance
if (balance === '0.0') return;
balances[tokenAddress] = {
balance,
symbol: tokens.value[getAddress(tokenAddress)].symbol,
address: getAddress(tokenAddress)
};
});

// separate case for native ether
balances[ETHER.address.toLowerCase()] = {
balance: formatEther(data.value[1] || 0),
symbol: ETHER.symbol,
address: ETHER.address
};
return balances;
}
return null;
});

function hasBalance(address: string): boolean {
return (balances.value || {})[address];
}

refetchBalances
} = inject(BalancesProviderSymbol) as BalancesProviderPayload;
return {
balances,
hasBalance,
Expand Down
93 changes: 17 additions & 76 deletions src/composables/useAllowances.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,29 @@
import useVueWeb3 from '@/services/web3/useVueWeb3';
import { useQuery } from 'vue-query';
import { getAllowances } from '@/lib/utils/balancer/tokens';
import getProvider from '@/lib/utils/provider';
import { computed, reactive, Ref, ref } from 'vue';
import { ETHER } from '@/constants/tokenlists';
import { isAddress } from 'web3-utils';
import QUERY_KEYS from '@/constants/queryKeys';
import useTokens from './useTokens';
import { inject, onBeforeMount, Ref, watch } from 'vue';
import {
AllowancesProviderSymbol,
AllowancesProviderPayload
} from '@/plugins/providers/allowances.provider';

type UseAccountPayload = {
tokens?: Ref<string[]>;
dstList?: Ref<string[]>;
};

const dstAllowanceMap = ref({});

// THE CONTENTS OF THIS WILL BE REPLACED/ALTERED WITH THE REGISTRY REFACTOR
export default function useAllowances(payload?: UseAccountPayload) {
const { userNetworkConfig, account } = useVueWeb3();
const { tokens: allTokens } = useTokens();
const provider = getProvider(String(userNetworkConfig.value?.chainId));
// filter out ether and any bad addresses
const tokens = computed(() =>
(payload?.tokens?.value || Object.keys(allTokens.value)).filter(
t => t !== ETHER.address && isAddress(t)
)
);
const dstList = computed(() => [
...(payload?.dstList?.value || []),
userNetworkConfig.value?.addresses.vault
]);

const isQueryEnabled = computed(
() => account.value != '' && tokens.value.length > 0
);
const {
data: allowances,
isLoading,
isFetching,
refetch: refetchAllowances
} = useQuery(
QUERY_KEYS.Account.Allowances(userNetworkConfig, account, dstList, tokens),
() =>
Promise.all(
dstList.value.map(async dst =>
getAllowances(
String(userNetworkConfig.value?.chainId),
provider,
account.value,
dst,
tokens.value
)
)
),
reactive({
enabled: isQueryEnabled,
onSuccess: allowances => {
allowances.forEach((allowance, i) => {
dstAllowanceMap.value[dstList.value[i]] = allowance;
});
}
})
);

const isLoadingOrFetching = computed(
() => isLoading.value || isFetching.value
);

const getRequiredAllowances = query => {
const tokens = query.tokens;
const amounts = query.amounts;
const dst = query.dst || userNetworkConfig.value?.addresses.vault;

const requiredAllowances = tokens.filter((token, index) => {
const amount = amounts[index];
if (parseFloat(amount) == 0) return false;
if (!dstAllowanceMap.value) return false;
if (!dstAllowanceMap.value[dst]) return true;
if (!dstAllowanceMap.value[dst][token.toLowerCase()]) return true;
return dstAllowanceMap.value[dst][token.toLowerCase()].lt(amount);
});

return requiredAllowances;
};
allowances,
getRequiredAllowances,
isLoading: isLoadingOrFetching,
refetchAllowances,
updateAllowanceRequest
} = inject(AllowancesProviderSymbol) as AllowancesProviderPayload;

onBeforeMount(() => {
if (payload) {
updateAllowanceRequest(payload);
}
});

return {
allowances,
Expand Down
81 changes: 15 additions & 66 deletions src/composables/useTokens.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,22 @@
import { Token, TokenMap } from '@/types';
import { getAddress } from '@ethersproject/address';
import { keyBy, orderBy, uniqBy } from 'lodash';
import { computed } from 'vue';
import { useStore } from 'vuex';
import useAccountBalances from './useAccountBalances';
import useTokenStore from './useTokensStore';

type TokenRequest = {
query?: string;
queryAddress?: string;
};
import {
TokenRequest,
TokensProviderPayload,
TokensProviderSymbol
} from '@/plugins/providers/tokens.provider';
import { inject, onBeforeMount } from 'vue';

export default function useTokens(request?: TokenRequest) {
const store = useStore();
const prices = computed(() => store.state.market.prices);
const { allTokens: _allTokens } = useTokenStore();
const { balances } = useAccountBalances();

const tokensList = computed(() => {
const _tokens = uniqBy<Token>(
orderBy(
// populate token data into list of tokens
Object.values(_allTokens.value).map(token => {
const balance =
(balances.value || {})[token.address.toLowerCase()]?.balance || '0';
const price = prices.value[token.address.toLowerCase()]?.price || 0;
const value = balance * price;
const price24HChange =
prices.value[token.address.toLowerCase()]?.price24HChange || 0;
const value24HChange = (value / 100) * price24HChange;
return {
...token,
address: getAddress(token.address), // Enforce that we use checksummed addresses
value,
price,
price24HChange,
balance,
value24HChange
};
}),
['value', 'balance'],
['desc', 'desc']
),
'address'
);

if (request?.queryAddress) {
const queryAddressLC = request?.queryAddress?.toLowerCase();

return _tokens.filter(
token => token.address?.toLowerCase() === queryAddressLC
);
}

// search functionality, this can be better
if (request?.query) {
const queryLC = request?.query?.toLowerCase();
const { tokens, updateTokenRequest } = inject(
TokensProviderSymbol
) as TokensProviderPayload;

return _tokens.filter(
token =>
token.name.toLowerCase().includes(queryLC) ||
token.symbol.toLowerCase().includes(queryLC)
);
onBeforeMount(() => {
if (request) {
updateTokenRequest(request);
}

return _tokens;
});

const tokens = computed(() => keyBy(tokensList.value, 'address') as TokenMap);

return { tokens };
return {
tokens
};
}
Loading