Skip to content

Commit

Permalink
fix: Account Unification errors (#1003)
Browse files Browse the repository at this point in the history
* fix: AU errors

* fix: transfer ERC20 tokens from EVM to unitifed Native account

* fix: modified assets link for Shibuya
  • Loading branch information
impelcrypto authored Nov 2, 2023
1 parent 9033aef commit bab1445
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 44 deletions.
2 changes: 2 additions & 0 deletions src/components/assets/Account.vue
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ import { $api } from 'src/boot/api';
import EvmNativeToken from 'src/components/assets/EvmNativeToken.vue';
import NativeAssetList from 'src/components/assets/NativeAssetList.vue';
import ZkAstr from 'src/components/assets/ZkAstr.vue';
import AuIcon from 'src/components/header/modals/account-unification/AuIcon.vue';
import { endpointKey, providerEndpoints } from 'src/config/chainEndpoints';
import { supportWalletObj } from 'src/config/wallets';
import {
Expand All @@ -116,6 +117,7 @@ export default defineComponent({
NativeAssetList,
EvmNativeToken,
ZkAstr,
AuIcon,
},
props: {
ttlErc20Amount: {
Expand Down
7 changes: 6 additions & 1 deletion src/components/assets/XcmCurrency.vue
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,12 @@ export default defineComponent({
const explorerLink = computed<string>(() => {
const astarBalanceUrl = 'https://astar.subscan.io/assets/' + t.value.id;
const shidenBalanceUrl = 'https://shiden.subscan.io/assets/' + t.value.id;
return currentNetworkIdx.value === endpointKey.ASTAR ? astarBalanceUrl : shidenBalanceUrl;
const shibuyaBalanceUrl = 'https://shibuya.subscan.io/assets/' + t.value.id;
return currentNetworkIdx.value === endpointKey.ASTAR
? astarBalanceUrl
: currentNetworkIdx.value === endpointKey.SHIDEN
? shidenBalanceUrl
: shibuyaBalanceUrl;
});
return {
Expand Down
3 changes: 1 addition & 2 deletions src/components/header/modals/account-unification/AuIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
</template>

<script lang="ts">
import { UnifiedAccount } from 'src/store/general/state';
import { defineComponent, PropType } from 'vue';
import { defineComponent } from 'vue';
import Jazzicon from 'vue3-jazzicon/src/components';
export default defineComponent({
Expand Down
40 changes: 32 additions & 8 deletions src/hooks/transfer/useTokenTransfer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
ASTAR_SS58_FORMAT,
SUBSTRATE_SS58_FORMAT,
buildEvmAddress,
getEvmGasCost,
getShortenAddress,
isValidAddressPolkadotAddress,
Expand All @@ -20,7 +19,7 @@ import { Path } from 'src/router';
import { useStore } from 'src/store';
import { container } from 'src/v2/common';
import { Asset } from 'src/v2/models';
import { IAssetsService } from 'src/v2/services';
import { IAccountUnificationService, IAssetsService } from 'src/v2/services';
import { Symbols } from 'src/v2/symbols';
import { Ref, computed, ref, watch, watchEffect } from 'vue';
import { useI18n } from 'vue-i18n';
Expand All @@ -36,7 +35,7 @@ export function useTokenTransfer(selectedToken: Ref<Asset>) {

const store = useStore();
const { t } = useI18n();
const { currentAccount, getSS58Address } = useAccount();
const { currentAccount } = useAccount();
const { accountData } = useBalance(currentAccount);

const transferableBalance = computed<number>(() => {
Expand Down Expand Up @@ -122,7 +121,17 @@ export function useTokenTransfer(selectedToken: Ref<Asset>) {
transferAmt.value = String(selectedToken.value.userBalance);
};

const setErrorMsg = (): void => {
const checkUnifiedAccount = async (): Promise<boolean> => {
const isEvmAddress = isValidEvmAddress(toAddress.value);
const service = container.get<IAccountUnificationService>(Symbols.AccountUnificationService);
if (isH160.value) {
return isEvmAddress ? true : await service.checkIsUnifiedAccount(toAddress.value);
} else {
return isEvmAddress ? await service.checkIsUnifiedAccount(toAddress.value) : true;
}
};

const setErrorMsg = async (): Promise<void> => {
if (isLoading.value) return;
const transferAmtRef = Number(transferAmt.value);
try {
Expand All @@ -132,6 +141,13 @@ export function useTokenTransfer(selectedToken: Ref<Asset>) {
});
} else if (toAddress.value && !isValidDestAddress.value) {
errMsg.value = 'warning.inputtedInvalidDestAddress';
} else if (
isH160.value &&
toAddress.value &&
!isTransferNativeToken.value &&
!(await checkUnifiedAccount())
) {
errMsg.value = 'warning.inputtedNotUnifiedDestAddress';
} else if (transferAmtRef && !transferableBalance.value && !isH160.value) {
errMsg.value = t('warning.insufficientBalance', {
token: nativeTokenSymbol.value,
Expand Down Expand Up @@ -171,11 +187,14 @@ export function useTokenTransfer(selectedToken: Ref<Asset>) {

try {
const assetsService = container.get<IAssetsService>(Symbols.AssetsService);
const accountUnificationService = container.get<IAccountUnificationService>(
Symbols.AccountUnificationService
);

if (isH160.value) {
const receivingAddress = isValidEvmAddress(toAddress)
? toAddress
: buildEvmAddress(toAddress);
: await accountUnificationService.getMappedEvmAddress(toAddress);
const successMessage = t('assets.toast.completedMessage', {
symbol,
transferAmt,
Expand All @@ -192,7 +211,7 @@ export function useTokenTransfer(selectedToken: Ref<Asset>) {
});
} else {
const receivingAddress = isValidEvmAddress(toAddress)
? await getSS58Address(toAddress)
? await accountUnificationService.getMappedNativeAddress(toAddress)
: toAddress;
const successMessage = t('assets.toast.completedMessage', {
symbol,
Expand Down Expand Up @@ -239,16 +258,21 @@ export function useTokenTransfer(selectedToken: Ref<Asset>) {
toAddressBalance.value = 0;
return;
}
const accountUnificationService = container.get<IAccountUnificationService>(
Symbols.AccountUnificationService
);

const isSendToH160 = isValidEvmAddress(toAddress.value);
const destAddress = isSendToH160 ? await getSS58Address(toAddress.value) : toAddress.value;
const destAddress = isSendToH160
? await accountUnificationService.getMappedNativeAddress(toAddress.value)
: toAddress.value;
const srcChainId = evmNetworkIdx.value;

if (isTransferNativeToken.value && !isZkEvm.value) {
toAddressBalance.value = await getNativeTokenBalance(destAddress);
} else if (isH160.value) {
const address = isValidAddressPolkadotAddress(toAddress.value)
? buildEvmAddress(toAddress.value)
? await accountUnificationService.getMappedEvmAddress(toAddress.value)
: toAddress.value;

const balance = await getTokenBal({
Expand Down
16 changes: 0 additions & 16 deletions src/hooks/useAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,21 +129,6 @@ export const useAccount = () => {
}
};

// TODO Move to separate lib, probably update toSS58Address in astar.js
const getSS58Address = async (evmAddress: string): Promise<string> => {
if (isValidEvmAddress(evmAddress)) {
const service = container.get<IAccountUnificationService>(Symbols.AccountUnificationService);
const ss58Pair = await service.getMappedNativeAddress(evmAddress);
if (ss58Pair) {
return ss58Pair;
} else {
return toSS58Address(evmAddress);
}
}

return evmAddress;
};

const showAccountUnificationModal = (): void => {
const eventAggregator = container.get<IEventAggregator>(Symbols.EventAggregator);
eventAggregator.publish(new UnifyAccountMessage());
Expand Down Expand Up @@ -249,7 +234,6 @@ export const useAccount = () => {
isAccountUnification,
isH160Formatted,
disconnectAccount,
getSS58Address,
showAccountUnificationModal,
checkIfUnified,
};
Expand Down
15 changes: 11 additions & 4 deletions src/hooks/wallet/useAccountUnification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
PayloadWithWeight,
getEvmGas,
getIndividualClaimTxs,
toSS58Address,
wait,
} from '@astar-network/astar-sdk-core';
import { SubmittableExtrinsic } from '@polkadot/api/types';
Expand All @@ -24,7 +23,7 @@ import { useStore } from 'src/store';
import { XcmAssets } from 'src/store/assets/state';
import { container } from 'src/v2/common';
import { ExtrinsicStatusMessage, IEventAggregator } from 'src/v2/messaging';
import { Asset, IdentityData } from 'src/v2/models';
import { Asset } from 'src/v2/models';
import { DappCombinedInfo } from 'src/v2/models/DappsStaking';
import { IAccountUnificationService, IDappStakingService, IIdentityService } from 'src/v2/services';
import { Symbols } from 'src/v2/symbols';
Expand Down Expand Up @@ -73,7 +72,9 @@ export const useAccountUnification = () => {
const unifiedAccount = computed<UnifiedAccount | undefined>(
() => store.getters['general/getUnifiedAccount']
);
const isAccountUnified = computed<boolean>(() => unifiedAccount.value !== undefined);
const isAccountUnified = computed<boolean>(() => {
return !!(unifiedAccount.value !== undefined && unifiedAccount.value.name);
});

const setAccountName = (event: any) => {
accountName.value = typeof event === 'string' ? event : event.target.value;
Expand Down Expand Up @@ -118,11 +119,17 @@ export const useAccountUnification = () => {

const checkStakerInfo = async (): Promise<void> => {
if (!selectedEvmAddress.value || !era.value || !dapps.value) return;
const accountUnificationService = container.get<IAccountUnificationService>(
Symbols.AccountUnificationService
);
try {
isLoadingDappStaking.value = true;
let isPendingWithdrawal = false;
let stakingData: MyStakeInfo[] = [];
const mappedSS58Address = toSS58Address(selectedEvmAddress.value);

const mappedSS58Address = await accountUnificationService.getMappedNativeAddress(
selectedEvmAddress.value
);
const dappStakingService = container.get<IDappStakingService>(Symbols.DappStakingService);

// Memo: check if there are any dapps staked
Expand Down
15 changes: 12 additions & 3 deletions src/hooks/xcm/useXcmBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
capitalize,
isValidAddressPolkadotAddress,
isValidEvmAddress,
toSS58Address,
} from '@astar-network/astar-sdk-core';
import { ApiPromise } from '@polkadot/api';
import { ethers } from 'ethers';
Expand Down Expand Up @@ -40,7 +39,12 @@ import { Path } from 'src/router';
import { container } from 'src/v2/common';
import { AstarToken } from 'src/v2/config/xcm/XcmRepositoryConfiguration';
import { IApiFactory } from 'src/v2/integration';
import { IXcmEvmService, IXcmService, IXcmTransfer } from 'src/v2/services';
import {
IAccountUnificationService,
IXcmEvmService,
IXcmService,
IXcmTransfer,
} from 'src/v2/services';
import { Symbols } from 'src/v2/symbols';
import { useRouter } from 'vue-router';
import { castChainName, castXcmEndpoint } from 'src/modules/xcm';
Expand Down Expand Up @@ -337,10 +341,15 @@ export function useXcmBridge(selectedToken: Ref<Asset>) {
) {
return 0;
}
const accountUnificationService = container.get<IAccountUnificationService>(
Symbols.AccountUnificationService
);
if (isDeposit.value) {
// if: SS58 Deposit
const isSendToH160 = isValidEvmAddress(address);
const destAddress = isSendToH160 ? toSS58Address(address) : address;
const destAddress = isSendToH160
? await accountUnificationService.getMappedNativeAddress(address)
: address;
if (isAstarNativeTransfer.value) {
const accountInfo = await $api?.query.system.account<SystemAccount>(address);
const bal = accountInfo!.data.free || '0';
Expand Down
1 change: 1 addition & 0 deletions src/i18n/en-US/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default {
insufficientBalance: 'Insufficient {token} balance',
insufficientFee: 'Warning! Transaction might fail due to insufficient fee',
inputtedInvalidDestAddress: 'Inputted invalid destination address',
inputtedNotUnifiedDestAddress: 'Inputted destination address has not been unified',
blankDestAddress: 'Destination address is blank',
inputtedInvalidAddress: 'Inputted invalid address',
selectedInvalidNetworkInWallet: 'Selected invalid network in your wallet',
Expand Down
9 changes: 5 additions & 4 deletions src/store/dapp-staking/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { StateInterface } from '../index';
import { sign } from './../../hooks/helper/wallet';
import { SubstrateAccount } from './../general/state';
import { DappStateInterface as State, NewDappItem, FileInfo } from './state';
import { IDappStakingService } from 'src/v2/services';
import { IAccountUnificationService, IDappStakingService } from 'src/v2/services';
import { container } from 'src/v2/common';
import { Symbols } from 'src/v2/symbols';
import axios, { AxiosError } from 'axios';
Expand All @@ -25,7 +25,6 @@ import {
TOKEN_API_URL,
DappItem,
isValidEvmAddress,
toSS58Address,
} from '@astar-network/astar-sdk-core';

const showError = (dispatch: Dispatch, message: string): void => {
Expand Down Expand Up @@ -91,14 +90,16 @@ const actions: ActionTree<State, StateInterface> = {
{ commit, dispatch },
{ network, currentAccount }: { network: string; currentAccount: string }
) {
// commit('general/setLoading', true, { root: true });
const accountUnificationService = container.get<IAccountUnificationService>(
Symbols.AccountUnificationService
);

try {
// Fetch dapps
const dappsUrl = `${TOKEN_API_URL}/v1/${network.toLowerCase()}/dapps-staking/dappssimple`;
const service = container.get<IDappStakingService>(Symbols.DappStakingService);
const address = isValidEvmAddress(currentAccount)
? toSS58Address(currentAccount)
? await accountUnificationService.getMappedNativeAddress(currentAccount)
: currentAccount;
const [dapps, combinedInfo] = await Promise.all([
axios.get<DappItem[]>(dappsUrl),
Expand Down
6 changes: 6 additions & 0 deletions src/v2/repositories/IAccountUnificationRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ export interface IAccountUnificationRepository {
*/
getMappedEvmAddress(nativeAddress: string): Promise<string>;

/**
* check if the given address is unified account.
* @param address H160 or SS58 address.
*/
handleCheckIsUnifiedAccount(address: string): Promise<boolean>;

/**
* Gets batch all call to unify accounts and to set the account identity.
* @param nativeAddress Native address to unify.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { buildEvmAddress, isValidEvmAddress, toSS58Address } from '@astar-network/astar-sdk-core';
import { AccountId32, H160 } from '@polkadot/types/interfaces';
import { inject, injectable } from 'inversify';
import { Guard } from 'src/v2/common';
Expand Down Expand Up @@ -29,24 +30,37 @@ export class AccountUnificationRepository implements IAccountUnificationReposito
Guard.ThrowIfUndefined('evmAddress', evmAddress);

const api = await this.api.getApi();
// Todo: update the function name once Shibuya runtime has been updated.
const nativeAddress = api.query.hasOwnProperty('unifiedAccounts')
? await api.query.unifiedAccounts.evmToNative<AccountId32>(evmAddress)
: '';
: toSS58Address(evmAddress);

return nativeAddress.toString();
return nativeAddress.toString() !== '' ? nativeAddress.toString() : toSS58Address(evmAddress);
}

public async getMappedEvmAddress(nativeAddress: string): Promise<string> {
Guard.ThrowIfUndefined('nativeAddress', nativeAddress);

const api = await this.api.getApi();
// Todo: update the function name once Shibuya runtime has been updated.
const evmAddress = api.query.hasOwnProperty('unifiedAccounts')
? await api.query.unifiedAccounts.nativeToEvm<H160>(nativeAddress)
: '';
: buildEvmAddress(nativeAddress);

return evmAddress.toString();
return evmAddress.toString() !== '' ? evmAddress.toString() : buildEvmAddress(nativeAddress);
}

public async handleCheckIsUnifiedAccount(address: string): Promise<boolean> {
Guard.ThrowIfUndefined('address', address);

const api = await this.api.getApi();
const isEvmAddress = isValidEvmAddress(address);
const isRuntimeApplied = api.query.hasOwnProperty('unifiedAccounts');
if (!isRuntimeApplied) return false;

const mappedAddress = isEvmAddress
? await api.query.unifiedAccounts.evmToNative<AccountId32>(address)
: await api.query.unifiedAccounts.nativeToEvm<H160>(address);

return mappedAddress.toString() !== '';
}

public async getUnifyAccountsBatchAllCall(
Expand Down
3 changes: 3 additions & 0 deletions src/v2/repositories/implementations/AssetsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export class AssetsRepository implements IAssetsRepository {
};
}
}

public async getEvmWithdrawCall({
amount,
senderAddress,
Expand All @@ -69,10 +70,12 @@ export class AssetsRepository implements IAssetsRepository {
const h160Addr = buildEvmAddress(senderAddress);
return api.tx.evm.withdraw(h160Addr, amount);
}

public async getVestCall(): Promise<SubmittableExtrinsic<'promise', ISubmittableResult>> {
const api = await this.api.getApi();
return api.tx.vesting.vest();
}

public async getNativeBalance(address: string): Promise<string> {
try {
const api = await this.api.getApi();
Expand Down
1 change: 1 addition & 0 deletions src/v2/services/IAccountUnificationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export interface IAccountUnificationService {
): Promise<boolean>;
getMappedNativeAddress(evmAddress: string): Promise<string>;
getMappedEvmAddress(nativeAddress: string): Promise<string>;
checkIsUnifiedAccount(address: string): Promise<boolean>;
}
Loading

0 comments on commit bab1445

Please sign in to comment.