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

Substrate bridge incoming transaction tracking #1081

Merged
merged 41 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
9c15073
reset form on network change
Nikita-Polyakov Jun 10, 2023
311d870
fix network name in ui
Nikita-Polyakov Jun 13, 2023
2a2a5ee
update KAR address
Nikita-Polyakov Jun 14, 2023
32070f9
Merge remote-tracking branch 'origin/develop' into feature/substrate-…
Nikita-Polyakov Jun 14, 2023
ce130b1
wip rococo adapter
Nikita-Polyakov Jun 15, 2023
4c3c3e0
merge origin/develop
Nikita-Polyakov Jun 16, 2023
ee103ce
fix yarn.lock
Nikita-Polyakov Jun 16, 2023
166789f
update assets on network change
Nikita-Polyakov Jun 16, 2023
5fb30ac
update balance method for sub
Nikita-Polyakov Jun 19, 2023
5bbee24
fix adapter connection wait
Nikita-Polyakov Jun 19, 2023
fea6f31
refactoring action name
Nikita-Polyakov Jun 21, 2023
900ebb7
Merge remote-tracking branch 'origin/develop' into feature/substrate-…
Nikita-Polyakov Jun 21, 2023
0fa8393
refactoring block number usage
Nikita-Polyakov Jun 21, 2023
e3bff43
update external balance for selected asset
Nikita-Polyakov Jun 21, 2023
a107911
network update fixes
Nikita-Polyakov Jun 22, 2023
af1dcfc
native balance update
Nikita-Polyakov Jun 22, 2023
95e179e
Merge remote-tracking branch 'origin/develop' into feature/substrate-…
Nikita-Polyakov Jun 22, 2023
b4c0e14
update external data after sora block update
Nikita-Polyakov Jun 22, 2023
594ae09
update selectedNetwork data
Nikita-Polyakov Jun 23, 2023
5c1731a
show sender & recepient balance
Nikita-Polyakov Jun 23, 2023
97e2038
fix balance update
Nikita-Polyakov Jun 26, 2023
c2ae052
update env.json
Nikita-Polyakov Jun 26, 2023
6ab7118
update adapters endpoints
Nikita-Polyakov Jun 26, 2023
92c053d
add messageHash from collator as externalHash temporary
Nikita-Polyakov Jun 26, 2023
b5f3624
wait for rococo message
Nikita-Polyakov Jun 27, 2023
48bc3bd
add external links
Nikita-Polyakov Jun 27, 2023
76eb878
fix adapter endpoint reset issue
Nikita-Polyakov Jun 27, 2023
20aec18
refactoring sonar related issues
Nikita-Polyakov Jun 27, 2023
03af231
incoming transaction signing
Nikita-Polyakov Jun 27, 2023
368a3ad
incoming transaction tracking demo
Nikita-Polyakov Jun 28, 2023
631cc39
remove unused update balances
Nikita-Polyakov Jun 29, 2023
9a267d8
fix history remove
Nikita-Polyakov Jun 29, 2023
a81d562
fix BridgeTransaction asset balance & refactoring
Nikita-Polyakov Jun 29, 2023
cbb81cd
sub history update
Nikita-Polyakov Jun 29, 2023
541a958
merga from another branch
Nikita-Polyakov Jun 29, 2023
f9783ce
Merge remote-tracking branch 'origin/develop' into feature/substrate-…
Nikita-Polyakov Jun 29, 2023
60d30f2
disconnect after bridge leave
Nikita-Polyakov Jun 29, 2023
e4808f0
refactoring disconnect
Nikita-Polyakov Jun 30, 2023
3341abe
update wallet
Nikita-Polyakov Jun 30, 2023
400d913
revert env.json
Nikita-Polyakov Jun 30, 2023
1c1fe20
remove console.log9
Nikita-Polyakov Jun 30, 2023
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
},
"dependencies": {
"@metamask/detect-provider": "^2.0.0",
"@soramitsu/soraneo-wallet-web": "1.17.15",
"@soramitsu/soraneo-wallet-web": "1.17.16",
"@walletconnect/web3-provider": "^1.8.0",
"base-64": "^1.0.0",
"core-js": "^3.26.0",
Expand Down
15 changes: 3 additions & 12 deletions public/env.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,9 @@
"CHAIN_GENESIS_HASH": "",
"EVM_NETWORKS_IDS": [97, 1001],
"SUB_NETWORKS": {
"Rococo": {
"addresses": [
"wss://ws.relaychain-node-1.r1.dev.sora2.soramitsu.co.jp",
"wss://ws.relaychain-node-2.r1.dev.sora2.soramitsu.co.jp"
]
},
"Karura": {
"addresses": [
"wss://ws.karura-node-1.c2.dev.sora2.soramitsu.co.jp",
"wss://ws.karura-node-2.c2.dev.sora2.soramitsu.co.jp"
]
}
"Rococo": "wss://ws.relaychain-node-1.r1.dev.sora2.soramitsu.co.jp",
"Karura": "wss://ws.karura-node-1.c2.dev.sora2.soramitsu.co.jp",
"Mainnet": "wss://ws.parachain-collator-1.c1.dev.sora2.soramitsu.co.jp"
},
"PARACHAIN_IDS": {
"Karura": 2000,
Expand Down
2 changes: 1 addition & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ export default class App extends Mixins(mixins.TransactionMixin, NodeErrorMixin)
@mutation.settings.resetBlockNumberSubscription private resetBlockNumberSubscription!: FnWithoutArgs;
@mutation.referrals.unsubscribeFromInvitedUsers private unsubscribeFromInvitedUsers!: FnWithoutArgs;
@mutation.web3.setEvmNetworksApp private setEvmNetworksApp!: (data: EvmNetwork[]) => void;
@mutation.web3.setSubNetworkApps private setSubNetworkApps!: (data: SubNetworkApps) => void;
@mutation.web3.setEthBridgeSettings private setEthBridgeSettings!: (settings: EthBridgeSettings) => Promise<void>;
@mutation.referrals.resetStorageReferrer private resetStorageReferrer!: FnWithoutArgs;

@action.web3.setSubNetworkApps private setSubNetworkApps!: (data: SubNetworkApps) => void;
@action.wallet.settings.setApiKeys private setApiKeys!: (apiKeys: WALLET_TYPES.ApiKeysObject) => Promise<void>;
@action.wallet.subscriptions.resetNetworkSubscriptions private resetNetworkSubscriptions!: AsyncFnWithoutArgs;
@action.wallet.subscriptions.resetInternalSubscriptions private resetInternalSubscriptions!: AsyncFnWithoutArgs;
Expand Down
2 changes: 1 addition & 1 deletion src/components/mixins/BridgeMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default class BridgeMixin extends Mixins(mixins.LoadingMixin, WalletConne

@getter.web3.isValidNetwork isValidNetwork!: boolean;
@getter.bridge.sender sender!: string;
@getter.bridge.recepient recepient!: string;
@getter.bridge.recipient recipient!: string;
@getter.bridge.soraNetworkFee soraNetworkFee!: CodecString;
@getter.bridge.evmNetworkFee evmNetworkFee!: CodecString;
@getter.assets.xor xor!: RegisteredAccountAsset;
Expand Down
54 changes: 42 additions & 12 deletions src/components/mixins/NetworkFormatterMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Component, Mixins } from 'vue-property-decorator';
import { EvmLinkType, EVM_NETWORKS } from '@/consts/evm';
import { SUB_NETWORKS } from '@/consts/sub';
import { state, getter } from '@/store/decorators';
import type { AvailableNetwork } from '@/store/web3/types';
import type { NetworkData } from '@/types/bridge';

import TranslationMixin from './TranslationMixin';
Expand All @@ -17,6 +18,10 @@ import type { BridgeNetworkId } from '@sora-substrate/util/build/bridgeProxy/typ
export default class NetworkFormatterMixin extends Mixins(TranslationMixin) {
@state.wallet.settings.soraNetwork soraNetwork!: Nullable<WALLET_CONSTS.SoraNetwork>;
@getter.web3.selectedNetwork selectedNetwork!: Nullable<NetworkData>;
@getter.web3.availableNetworks availableNetworks!: Record<
BridgeNetworkType,
Partial<Record<BridgeNetworkId, AvailableNetwork>>
>;

readonly EvmLinkType = EvmLinkType;

Expand Down Expand Up @@ -79,26 +84,51 @@ export default class NetworkFormatterMixin extends Mixins(TranslationMixin) {
}
}

// TODO [EVM] check network explorers links
getEvmExplorerLink(hash: string, type: EvmLinkType, networkId: BridgeNetworkId): string {
if (!hash) return '';
getNetworkExplorerLinks(
networkType: BridgeNetworkType,
networkId: BridgeNetworkId,
value: string,
blockHash = '',
type = EvmLinkType.Transaction
) {
if (!value) return [];

const network = EVM_NETWORKS[networkId];
const networkData = this.availableNetworks[networkType][networkId]?.data;

if (!network) {
console.error(`Network id "${networkId}" is not defined in "EVM_NETWORKS"`);
return '';
if (!networkData) {
console.error(`Network data for "${networkId}" is not defined"`);
return [];
}

const explorerUrl = network.blockExplorerUrls[0];
const explorerUrl = networkData.blockExplorerUrls[0];

if (!explorerUrl) {
console.error(`"blockExplorerUrls" is not provided for EVM network id "${networkId}"`);
return '';
console.error(`"blockExplorerUrls" is not provided for network id "${networkId}"`);
return [];
}

const path = type === EvmLinkType.Transaction ? 'tx' : 'address';
if (networkType === BridgeNetworkType.Sub) {
if (type === EvmLinkType.Account) return [];

return `${explorerUrl}/${path}/${hash}`;
if (!blockHash) return [];

const baseLink = `https://polkadot.js.org/apps/?rpc=${explorerUrl}#/explorer/query`;

return [
{
type: WALLET_CONSTS.ExplorerType.Polkadot,
value: `${baseLink}/${blockHash}`,
},
];
} else {
const path = type === EvmLinkType.Transaction ? 'tx' : 'address';

return [
{
type: this.TranslationConsts.Etherscan as WALLET_CONSTS.ExplorerType,
value: `${explorerUrl}/${path}/${value}`,
},
];
}
}
}
3 changes: 2 additions & 1 deletion src/components/mixins/WalletConnectMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,15 @@ export default class WalletConnectMixin extends Mixins(TranslationMixin) {

// update selected evm network without metamask request
@mutation.web3.setSelectedNetwork setSelectedNetwork!: (networkId: BridgeNetworkId) => void;
@mutation.web3.resetProvidedEvmNetwork resetProvidedEvmNetwork!: FnWithoutArgs;
@mutation.web3.resetEvmAddress resetEvmAddress!: FnWithoutArgs;
@mutation.web3.setEvmAddress setEvmAddress!: (address: string) => void;
@mutation.web3.resetProvidedEvmNetwork resetProvidedEvmNetwork!: FnWithoutArgs;
@mutation.web3.setSelectAccountDialogVisibility private setSelectAccountDialogVisibility!: (flag: boolean) => void;

@action.web3.connectEvmAccount private connectEvmAccount!: (provider: Provider) => Promise<void>;
@action.web3.updateNetworkProvided updateNetworkProvided!: AsyncFnWithoutArgs;
@action.web3.connectExternalNetwork connectExternalNetwork!: (networkHex?: string) => Promise<void>;
@action.web3.disconnectExternalNetwork disconnectExternalNetwork!: AsyncFnWithoutArgs;
@action.web3.selectExternalNetwork selectExternalNetwork!: (networkId: BridgeNetworkId) => Promise<void>;

getWalletAddress = getWalletAddress;
Expand Down
11 changes: 4 additions & 7 deletions src/components/pages/Bridge/SelectNetwork.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { Component, Mixins } from 'vue-property-decorator';

import NetworkFormatterMixin from '@/components/mixins/NetworkFormatterMixin';
import { action, getter, mutation, state } from '@/store/decorators';
import type { NetworkData } from '@/types/bridge';
import type { AvailableNetwork } from '@/store/web3/types';

import type { BridgeNetworkId } from '@sora-substrate/util/build/bridgeProxy/types';

Expand All @@ -47,11 +47,6 @@ export default class BridgeSelectNetwork extends Mixins(NetworkFormatterMixin) {
@state.web3.networkSelected private networkSelected!: Nullable<BridgeNetworkId>;
@state.web3.selectNetworkDialogVisibility private selectNetworkDialogVisibility!: boolean;

@getter.web3.availableNetworks availableNetworks!: Record<
BridgeNetworkType,
{ disabled: boolean; data: NetworkData }[]
>;

@mutation.web3.setNetworkType private setNetworkType!: (networkType: BridgeNetworkType) => void;
@mutation.web3.setSelectNetworkDialogVisibility private setSelectNetworkDialogVisibility!: (flag: boolean) => void;

Expand All @@ -67,7 +62,9 @@ export default class BridgeSelectNetwork extends Mixins(NetworkFormatterMixin) {

get networks(): NetworkItem[] {
return Object.entries(this.availableNetworks)
.map(([type, networks]) => {
.map(([type, record]) => {
const networks = Object.values(record) as AvailableNetwork[];

return networks.map(({ disabled, data: { id, name } }) => {
const networkName = type === BridgeNetworkType.EvmLegacy ? `${name} (${this.t('hashiBridgeText')})` : name;

Expand Down
6 changes: 3 additions & 3 deletions src/components/pages/Moonpay/BridgeInitMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W
) => Promise<Nullable<MoonpayEVMTransferAssetData>>;

@action.assets.updateRegisteredAssets private updateRegisteredAssets!: AsyncFnWithoutArgs;
@action.assets.updateExternalBalances private updateExternalBalances!: AsyncFnWithoutArgs;

async prepareEvmNetwork(): Promise<void> {
this.selectExternalNetwork(this.ethBridgeEvmNetwork); // WalletConnectMixin
Expand Down Expand Up @@ -127,7 +126,6 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W
}

await this.updateRegisteredAssets();
await this.updateExternalBalances();

const [soraAddress] =
Object.entries(this.registeredAssets).find(([soraAddress, registeredAsset]) =>
Expand All @@ -143,6 +141,8 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W

const asset = this.assetsDataTable[soraAddress];

const externalBalance = (await ethersUtil.getAccountAssetBalance(ethTransferData.to, asset.externalAddress))
.value;
const evmNetworkFee: CodecString = await ethersUtil.getEvmNetworkFee(soraAddress, false);
const evmNativeBalance = await ethersUtil.getAccountBalance(ethTransferData.to);
const hasEthForFee = !hasInsufficientEvmNativeTokenForFee(evmNativeBalance, evmNetworkFee);
Expand All @@ -151,7 +151,7 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W
throw createError('Insufficient ETH for fee', MoonpayNotifications.FeeError);
}

const maxAmount = getMaxValue(asset, evmNetworkFee, true); // max balance (minus fee if eth asset)
const maxAmount = getMaxValue({ ...asset, externalBalance }, evmNetworkFee, true); // max balance (minus fee if eth asset)
const amount = Math.min(Number(maxAmount), Number(ethTransferData.amount));

if (amount <= 0) {
Expand Down
100 changes: 13 additions & 87 deletions src/store/assets/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,29 @@ import { assetsActionContext } from '@/store/assets';
import type { BridgeAccountAsset } from '@/store/assets/types';
import { ethBridgeApi } from '@/utils/bridge/eth/api';
import { evmBridgeApi } from '@/utils/bridge/evm/api';
import { subConnector } from '@/utils/bridge/sub/classes/adapter';
import ethersUtil from '@/utils/ethers-util';

import type { ActionContext } from 'vuex';

async function getEthRegisteredAssets(context: ActionContext<any, any>): Promise<Record<string, BridgeAccountAsset>[]> {
const { rootDispatch } = assetsActionContext(context);

const networkAssets = await ethBridgeApi.getRegisteredAssets();
const registeredAssets: Record<string, BridgeAccountAsset>[] = [];

for (const asset of networkAssets) {
const soraAddress = asset.address;
const address = asset.externalAddress || (await rootDispatch.web3.getEvmTokenAddressByAssetId(soraAddress));
const decimals = +asset.externalDecimals ?? (await ethersUtil.getAssetDecimals(address));

const registeredAssets = networkAssets.reduce<Record<string, BridgeAccountAsset>[]>((buffer, asset) => {
buffer.push({
[asset.address]: {
address: asset.externalAddress,
registeredAssets.push({
[soraAddress]: {
address,
balance: ZeroStringValue,
decimals: +asset.externalDecimals,
decimals,
},
});
return buffer;
}, []);
}

return registeredAssets;
}
Expand Down Expand Up @@ -113,67 +118,6 @@ async function getRegisteredAssets(context: ActionContext<any, any>): Promise<Re
}
}

async function updateSubBalances(context: ActionContext<any, any>): Promise<Record<string, BridgeAccountAsset>[]> {
const { state, rootCommit, rootState } = assetsActionContext(context);
// fetch balances for current sora account
const accountAddress = rootState.wallet.account.address;

const updated = await Promise.all(
Object.entries(state.registeredAssets).map(async ([soraAddress, asset]) => {
const accountAsset = { ...asset };
const balance = await subConnector.adapter.getTokenBalance(accountAddress, accountAsset.address);
accountAsset.balance = balance;
return { [soraAddress]: accountAsset };
})
);

return updated;
}

async function updateEvmBalances(context: ActionContext<any, any>): Promise<Record<string, BridgeAccountAsset>[]> {
const { state, rootDispatch, rootCommit, rootState } = assetsActionContext(context);

const accountAddress = rootState.web3.evmAddress;

const updated = await Promise.all(
Object.entries(state.registeredAssets).map(async ([soraAddress, asset]) => {
const accountAsset = { ...asset };
try {
if (!accountAsset.address) {
accountAsset.address = await rootDispatch.web3.getEvmTokenAddressByAssetId(soraAddress);
}
if (accountAsset.address) {
const { value, decimals } = await ethersUtil.getAccountAssetBalance(accountAddress, accountAsset.address);

accountAsset.balance = value;
accountAsset.decimals = decimals;
}
} catch (error) {
console.error(error);
}
return { [soraAddress]: accountAsset };
})
);

return updated;
}

async function getRegisteredAssetsBalances(
context: ActionContext<any, any>
): Promise<Record<string, BridgeAccountAsset>[]> {
const { rootState } = assetsActionContext(context);

switch (rootState.web3.networkType) {
case BridgeNetworkType.EvmLegacy:
case BridgeNetworkType.Evm: {
return await updateEvmBalances(context);
}
case BridgeNetworkType.Sub: {
return await updateSubBalances(context);
}
}
}

const actions = defineActions({
// for common usage
async updateRegisteredAssets(context): Promise<void> {
Expand All @@ -192,24 +136,6 @@ const actions = defineActions({
commit.resetRegisteredAssets();
}
},

// for common usage
async updateExternalBalances(context): Promise<void> {
const { commit } = assetsActionContext(context);

commit.setRegisteredAssetsBalancesUpdating(true);

try {
const list = await getRegisteredAssetsBalances(context);
const registeredAssets = list.reduce((buffer, asset) => ({ ...buffer, ...asset }), {});

commit.setRegisteredAssets(registeredAssets);
} catch (error) {
console.error(error);
} finally {
commit.setRegisteredAssetsBalancesUpdating(false);
}
},
});

export default actions;
3 changes: 0 additions & 3 deletions src/store/assets/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ const mutations = defineMutations<AssetsState>()({
state.registeredAssets = {};
state.registeredAssetsFetching = false;
},
setRegisteredAssetsBalancesUpdating(state, flag = false): void {
state.registeredAssetsBalancesUpdating = flag;
},
});

export default mutations;
1 change: 0 additions & 1 deletion src/store/assets/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ function initialState(): AssetsState {
return {
registeredAssets: {},
registeredAssetsFetching: false,
registeredAssetsBalancesUpdating: false,
};
}

Expand Down
1 change: 0 additions & 1 deletion src/store/assets/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@ export type RegisteredAccountAssetObject = {
export type AssetsState = {
registeredAssets: Record<string, BridgeAccountAsset>;
registeredAssetsFetching: boolean;
registeredAssetsBalancesUpdating: boolean;
};
Loading