Skip to content

Commit

Permalink
Improve bridge locked amount check (#1381)
Browse files Browse the repository at this point in the history
* check bridge locked amount usinf asset kind

* return bridge history search field

* fix first connection logic

* improve bridge history search
  • Loading branch information
Nikita-Polyakov authored Apr 5, 2024
1 parent 668d704 commit 959554b
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 55 deletions.
6 changes: 3 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -378,13 +378,13 @@ export default class App extends Mixins(mixins.TransactionMixin, NodeErrorMixin)
onReconnect: this.handleNodeConnect,
}),
]);
} catch (error) {
// we handled error using callback, do nothing
} finally {
// Wallet node connection dependent logic
if (!this.isWalletLoaded) {
await initWallet(walletOptions);
}
} catch (error) {
// we handled error using callback, do nothing
}
}
}
Expand Down
11 changes: 3 additions & 8 deletions src/components/mixins/BridgeMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import WalletConnectMixin from '@/components/mixins/WalletConnectMixin';
import { PageNames } from '@/consts';
import router from '@/router';
import { getter, state } from '@/store/decorators';
import { subBridgeApi } from '@/utils/bridge/sub/api';

import type { CodecString } from '@sora-substrate/util';
import type { RegisteredAccountAsset } from '@sora-substrate/util/build/assets/types';
import type { SubNetwork } from '@sora-substrate/util/build/bridgeProxy/sub/types';

@Component
export default class BridgeMixin extends Mixins(mixins.LoadingMixin, WalletConnectMixin) {
Expand All @@ -31,6 +29,7 @@ export default class BridgeMixin extends Mixins(mixins.LoadingMixin, WalletConne
@getter.bridge.recipient recipient!: string;
@getter.bridge.externalNetworkFee externalNetworkFee!: CodecString;
@getter.bridge.isNativeTokenSelected isNativeTokenSelected!: boolean;
@getter.bridge.isSidechainAsset isSidechainAsset!: boolean;
@getter.assets.xor xor!: RegisteredAccountAsset;

get nativeTokenSymbol(): string {
Expand All @@ -45,14 +44,10 @@ export default class BridgeMixin extends Mixins(mixins.LoadingMixin, WalletConne
return FPNumber.fromCodecValue(this.externalTransferFee, this.asset?.externalDecimals);
}

get assetLockedOnSora(): boolean {
return !subBridgeApi.isSoraParachain(this.networkSelected as SubNetwork);
}

get outgoingMaxAmount(): FPNumber | null {
const locks = [this.outgoingMaxLimit];

if (this.assetLockedOnSora) locks.push(this.assetLockedBalance);
if (this.isSidechainAsset) locks.push(this.assetLockedBalance);

const filtered = locks.filter((item) => !!item) as FPNumber[];

Expand All @@ -71,7 +66,7 @@ export default class BridgeMixin extends Mixins(mixins.LoadingMixin, WalletConne
}

get incomingMaxAmount(): FPNumber | null {
if (this.assetLockedOnSora) return null;
if (this.isSidechainAsset) return null;

return this.assetLockedBalance ?? null;
}
Expand Down
3 changes: 1 addition & 2 deletions src/components/pages/Moonpay/BridgeInitMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { MoonpayEVMTransferAssetData, MoonpayApi } from '@/utils/moonpay';

import type { CodecString } from '@sora-substrate/util';
import type { RegisteredAccountAsset, AccountBalance } from '@sora-substrate/util/build/assets/types';
import type { EthAssetKind } from '@sora-substrate/util/build/bridgeProxy/eth/consts';
import type { EthHistory } from '@sora-substrate/util/build/bridgeProxy/eth/types';
import type { EvmNetwork } from '@sora-substrate/util/build/bridgeProxy/evm/types';
import type { BridgeNetworkId } from '@sora-substrate/util/build/bridgeProxy/types';
Expand Down Expand Up @@ -157,7 +156,7 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W

const evmNetworkFee: CodecString = await getEthNetworkFee(
asset,
registeredAsset.kind as EthAssetKind,
registeredAsset.kind,
this.contractAddress,
ethTransferData.amount,
false,
Expand Down
42 changes: 18 additions & 24 deletions src/store/bridge/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { FPNumber } from '@sora-substrate/util';
import { getAssetBalance } from '@sora-substrate/util/build/assets';
import { DAI } from '@sora-substrate/util/build/assets/consts';
import { BridgeTxStatus, BridgeTxDirection, BridgeNetworkType } from '@sora-substrate/util/build/bridgeProxy/consts';
import { EthAssetKind } from '@sora-substrate/util/build/bridgeProxy/eth/consts';
import { DexId } from '@sora-substrate/util/build/dex/consts';
import { api, WALLET_CONSTS } from '@soramitsu/soraneo-wallet-web';
import { defineActions } from 'direct-vuex';
Expand Down Expand Up @@ -142,7 +141,7 @@ async function getEvmNetworkFee(context: ActionContext<any, any>): Promise<void>

fee = await getEthNetworkFee(
asset,
bridgeRegisteredAsset.kind as EthAssetKind,
bridgeRegisteredAsset.kind,
contractAddress,
value,
state.isSoraToEvm,
Expand Down Expand Up @@ -235,33 +234,28 @@ async function updateEthHistory(context: ActionContext<any, any>, clearHistory =

async function updateEthLockedBalance(context: ActionContext<any, any>): Promise<void> {
const { commit, getters, rootGetters, rootState } = bridgeActionContext(context);
const { address, decimals, externalAddress } = getters.asset ?? {};
const { isRegisteredAsset, isSidechainAsset, asset } = getters;
const { address, decimals, externalAddress, externalDecimals } = asset ?? {};
const { networkSelected } = rootState.web3;
const { isValidNetwork, contractAddress } = rootGetters.web3;
const bridgeContractAddress = contractAddress(KnownEthBridgeAsset.Other);

if (address && networkSelected && isValidNetwork && externalAddress && bridgeContractAddress) {
const registeredAsset = rootState.assets.registeredAssets[address];

if (registeredAsset) {
const { kind, decimals: externalDecimals } = registeredAsset;

if (kind === EthAssetKind.Sidechain) {
const [lockedValue, bridgeValue] = await Promise.all([
ethBridgeApi.getLockedAssets(networkSelected as number, address),
ethersUtil.getAccountAssetBalance(bridgeContractAddress, externalAddress),
]);
const balance = FPNumber.min(
FPNumber.fromCodecValue(lockedValue, decimals),
FPNumber.fromCodecValue(bridgeValue, externalDecimals)
);
commit.setAssetLockedBalance(balance);
return;
}
}
}
const hasNetworkData = !!networkSelected && isValidNetwork && !!bridgeContractAddress;
const hasAssetData = !!address && !!externalAddress && isRegisteredAsset;

commit.setAssetLockedBalance();
if (hasNetworkData && hasAssetData && isSidechainAsset) {
const [lockedValue, bridgeValue] = await Promise.all([
ethBridgeApi.getLockedAssets(networkSelected as number, address),
ethersUtil.getAccountAssetBalance(bridgeContractAddress, externalAddress),
]);
const balance = FPNumber.min(
FPNumber.fromCodecValue(lockedValue, decimals),
FPNumber.fromCodecValue(bridgeValue, externalDecimals)
);
commit.setAssetLockedBalance(balance);
} else {
commit.setAssetLockedBalance();
}
}

async function updateBridgeProxyLockedBalance(context: ActionContext<any, any>): Promise<void> {
Expand Down
17 changes: 17 additions & 0 deletions src/store/bridge/getters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Operation } from '@sora-substrate/util';
import { BridgeNetworkType } from '@sora-substrate/util/build/bridgeProxy/consts';
import { EthAssetKind } from '@sora-substrate/util/build/bridgeProxy/eth/consts';
import { SubAssetKind } from '@sora-substrate/util/build/bridgeProxy/sub/consts';
import { defineGetters } from 'direct-vuex';

import { ZeroStringValue } from '@/consts';
Expand Down Expand Up @@ -77,6 +79,21 @@ const getters = defineGetters<BridgeState>()({
return !!asset?.externalAddress;
},

isSidechainAsset(...args): boolean {
const { getters, rootState } = bridgeGetterContext(args);
const { asset, isSubBridge } = getters;
const { registeredAssets } = rootState.assets;

if (!asset) return false;
if (!(asset.address in registeredAssets)) return false;

const registered = registeredAssets[asset.address];
const kind = registered.kind;
const sidechainKind = isSubBridge ? SubAssetKind.Sidechain : EthAssetKind.Sidechain;

return kind === sidechainKind;
},

autoselectedAssetAddress(...args): Nullable<string> {
const { rootState } = bridgeGetterContext(args);
const assetIds = Object.keys(rootState.assets.registeredAssets);
Expand Down
3 changes: 2 additions & 1 deletion src/utils/bridge/eth/classes/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ const getReceiptData = async (externalHash: string) => {
};

const getEvmBlockNumber = (ethereumTx: ethers.TransactionResponse | null) => {
return ethereumTx?.blockNumber;
const blockNumber = ethereumTx?.blockNumber; // could be a string
return blockNumber ? +blockNumber : null;
};

const getEvmBlockId = (ethereumTx: ethers.TransactionResponse | null) => {
Expand Down
4 changes: 2 additions & 2 deletions src/utils/bridge/eth/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ const getEthBridgeIncomingGasLimit = (assetEvmAddress: string): bigint => {

export async function getEthNetworkFee(
asset: RegisteredAccountAsset,
assetKind: EthAssetKind,
assetKind: string,
getContractAddress: (symbol: KnownEthBridgeAsset) => Nullable<string>,
value: string,
isOutgoing: boolean,
Expand All @@ -256,7 +256,7 @@ export async function getEthNetworkFee(
let gasLimitTotal!: bigint;

if (isOutgoing) {
gasLimitTotal = getEthBridgeOutgoingGasLimit(asset.externalAddress, assetKind);
gasLimitTotal = getEthBridgeOutgoingGasLimit(asset.externalAddress, assetKind as EthAssetKind);
} else {
const bridgeContractAddress = getContractAddress(KnownEthBridgeAsset.Other) as string;
const allowance = await ethersUtil.getAllowance(evmAccount, bridgeContractAddress, asset.externalAddress);
Expand Down
48 changes: 33 additions & 15 deletions src/views/BridgeTransactionsHistory.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</generic-page-header>
<s-form class="history-form" :show-message="false">
<search-input
v-if="history.length"
v-if="historyList.length"
v-model="query"
:placeholder="t('bridgeHistory.filterPlaceholder')"
autofocus
Expand Down Expand Up @@ -87,6 +87,20 @@ import { state } from '@/store/decorators';
import type { IBridgeTransaction } from '@sora-substrate/util';
const SearchAttrs = [
'assetAddress',
'symbol',
'hash',
'blockId',
'txId',
'externalBlockId',
'externalHash',
'parachainBlockId',
'parachainHash',
'relaychainBlockId',
'relaychainHash',
];
@Component({
components: {
GenericPageHeader: lazyComponent(Components.GenericPageHeader),
Expand Down Expand Up @@ -154,25 +168,29 @@ export default class BridgeTransactionsHistory extends Mixins(
}
getFilteredHistory(history: Array<IBridgeTransaction>): Array<IBridgeTransaction> {
if (this.query) {
const query = this.query.toLowerCase().trim();
return history.filter(
(item) =>
`${item.assetAddress}`.toLowerCase().includes(query) ||
`${this.registeredAssets[item.assetAddress as string]?.address}`.toLowerCase().includes(query) ||
`${item.symbol}`.toLowerCase().includes(query)
);
}
if (!this.query) return history;
const query = this.query.toLowerCase().trim();
return history;
return history.filter((item) => {
const bridgeRegisteredAsset = this.registeredAssets[item.assetAddress as string];
const criterias = [bridgeRegisteredAsset?.address];
SearchAttrs.forEach((attr) => {
if (attr in item) criterias.push(item[attr]);
});
return criterias.some((criteria) => String(criteria).toLowerCase().includes(query));
});
}
formatAmount(historyItem: IBridgeTransaction, received = false): string {
const amount = received ? historyItem.amount2 ?? historyItem.amount : historyItem.amount;
formatAmount(item: IBridgeTransaction, received = false): string {
const amount = received ? item.amount2 ?? item.amount : item.amount;
if (!historyItem.assetAddress || !amount) return '';
if (!item.assetAddress || !amount) return '';
const decimals = this.registeredAssets?.[historyItem.assetAddress]?.decimals;
const bridgeRegisteredAsset = this.registeredAssets[item.assetAddress];
const decimals = bridgeRegisteredAsset?.decimals;
return this.formatStringValue(amount, decimals);
}
Expand Down

0 comments on commit 959554b

Please sign in to comment.