From 28b1d901d7fb20054817f5672dbe8ba6cb697ae9 Mon Sep 17 00:00:00 2001 From: Stefan Popov Date: Fri, 29 Sep 2023 21:18:57 +0200 Subject: [PATCH] Release 1.22.0 (#1184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update wallet 1.13.1 (#918) * deploy trigger removal Signed-off-by: Nikita Zaporozhets * Liiquidity proxy 1.6 (#923) * update wallet with liqudity proxy * update swap view * improve btn loading state (#924) * up wallet version 1.13.4 (#925) * up wallet version * update wallet * up wallet version to 1.13.5 (#926) * up wallet version * update wallet to 1.13.5 * fix ts issues * Feature/x1-widget (#876) * move to separate module * add enabling flag * Update getters.ts * remove route * Update types.ts * x1 widget * redesign * refactor & add X1 * Update RoadMap.vue * improvements in flow & KYC status * remove logs * fixes * take into account different statuses matches * settings & stub * fixes & x1 enabling * add prod settings * wip * organize credentials * change css * Update env.json * css refactoring * Update env.json * fixes * roll out prod widget X1 * remove console.log * refactor & fixes * handle no record response * Update SoraCardIntroPage.vue * Fix/chart precision (#928) * fix precision while loop * improve precision calc * optional fee popup (#919) * add checks * up wallet * use exact version * Update wallet * Update localise files * Update translation files Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * [Remove Liquidity] Show ceres locked liquidity (#922) * show ceres locked liquidity percent * change translation of locked * refactoring rendering * Update translations Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> Co-authored-by: Stefan Popov * Use settingsStorage from wallet (#929) * Use settingsStorage from wallet * Update wallet version * Hide switch on Explore page for !isLoggedIn * Update lokalise Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix search focus behavior (#932) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Add fearless (#934) * Update package.json * Update yarn.lock --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix fearless integration (#936) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix Fearless wallet (#937) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix Fearless link for Mozilla (#938) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * update wallet to TBCD (#940) * Update wallet (#943) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Upgrade PW SDK (#930) * add phone input * Update Phone.vue * implement logic * Update ConfirmationInfo.vue * add disclaimer for X1 * Update ToSDialog.vue * fixes * update wallet 1.15.0 (#945) * fixes (#946) * fixes * typo * Fix styles issues related to card (#948) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * [Explore Page] Hide tokens & pools with zero tvl (#941) * change tokens page data handling * update explore pools * remove console * tokens min liquidity 1 --------- Co-authored-by: Stefan Popov * improve routing (#947) * Add loading state for router * Add setLoading mutation for router * Add comment * Modify goto logic of router * Add links * Add page loader * Improve goTo with additional checks pages by default * Update vue router * Update generateLocaleJson.ts * Fix page loading * Use goTo for separate moonpay page * Update comment * Add Sonar --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> Co-authored-by: Nikita Polyakov <53777036+Nikita-Polyakov@users.noreply.github.com> * fix (#949) * Fix lokalise and SORA Card issues (#950) * Remove sora, evm, pageNotFound * Add polkadot apps link to bridge txs * Update lokalise keys * Improve images * Improve card routing * Update ConfirmationInfo.vue * Fix texts --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix phone and styles for card (#951) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix sora card phone and route (#952) * Fix phone inputs (#953) * Fix phone inputs * Update Email.vue * add const * Update Phone.vue * Update Phone.vue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> Co-authored-by: RustemYuzlibaev * Fix email, first, last name length (#954) * Fix email, first, last name length * Add loader for euro calculations * Update SoraCardIntroPage.vue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * git (#955) * test push * refactor * tmp disable sonar * fix cred name * update wallet to 1.15.2 (#957) * update wallet to 1.15.2 * fix issues after wallet update * update wallet to 1.15.3 * change value * fix json error (#958) * fix path * fix path * switch to tachi * test * revert lib * test values check * fix lib * DAST pipeline update * Update Jenkinsfile-dast * revert lib * fix (#961) * Fix connection disconnected event (#960) * fix disconnected event * update wallet to 1.15.4 * update translations --------- Co-authored-by: Rustem * Update Jenkinsfile-dast * Update Jenkinsfile-dast * Update Jenkinsfile-dast * Update Jenkinsfile-dast * Update Jenkinsfile-dast * Otp resend try fix (#964) * add event * fix OTP resend issue * wipe email before start * low limit * SORA Card translation (#959) * prework * add lang keys * update translations * todo rejection translation * update translations * update translations * Update Jenkinsfile-dast * Free KYC attempts counter (#962) * prework * add lang keys * prework * update translations * todo rejection translation * add flow with new KYC attempt * improve price request * fix * Revert "fix" This reverts commit 18af1f3511db8940308bcab180a5bb4ab3c90a5b. * show pending status when finished KYC * remove price calculation stub * update translations * merge translation PR * show reject reasons * email fix resend (#967) * Update Email.vue * add missing words * Hide LP fee (#968) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix liqudity proxy route and args (#969) * update liquidity-proxy calls * update wallet 1.15.7 * multiple otp send fix (#970) * fix * cancel changes * fixes * update wallet 1.15.9 (#973) * update wallet to 1.15.10 (#974) * Status bar & SORA Card fixes (#882) * Draft * Add subquery & node connection checks * Add node location * Fix imports for App component * Add no internet dialog * Fix location in node model * Add footer popper * Draft * Fix margin * Remove node selection from header * Move all common logic to footer popper * Add interaction with tab * Fix outline * Update SwapTransactionDetails.vue * Use Notification mixin * Fix colors * Fix colors * 2nd Draft * Replace node selection dialog * Remove unused deps * Move SelectNodeDialog * Fix styles for slippage tolerance * Add new const * Update SlippageTolerance.vue * Refactor AppFooter & NoInternetDialog * Update statistics dialog * Finilize colors for Statistics statuses * Update library * Update yarn.lock * Update StatisticsDialog.vue * Add scss/css variables * Update en.json * Update translations * Update en.json * Update translations * Fix displayRegions * Fix styles in StatisticsDialog * Keep selected node details up to date * Add TODO * Fix imports * Fix SORA Card issues * Translate blacklisted countries * Fix SORA Card translations * Handle case when `navigator.connection` isn't supported * Update StatisticsDialog.vue * Update App.vue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Update Jenkinsfile * Reduce bundle size (#942) * Reduce bundle size * Update vue.config.js --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Feature/network stats (#931) * refactoring styles * refactoring letter-spacing * network-stats-row * improve network stats adaptive * refactoring columns data * change group data logic * tvl chart wip * add ChartSkeleton component * handle chart error & update tooltip * add volume chart example * refactoring specs * refactoring components folder structure * wip refactoring folders structure * refactoring components folders * wip fees chart * fix charts fetching * data fetching for supply chart * add token-dropdown to supply chart * skeleton fixes * fixes * fix error * refactoring * fix imports * update network stats components * refactoring charts data fetching * update translations * test * revert lib * refactoring imports * refactoring MarketAlgorithm paths * fix weekly stats, legend, x axis overlap * SimpleNotification from wallet * update according qa * update translations * network stats chart fixes * supply bar chart * update supply color, explore method --------- Co-authored-by: Stefan Popov Co-authored-by: Pavel Varfolomeev * Update Jenkinsfile-dast * Move disclaimer to front page (#965) * Update SoraCardIntroPage.vue * add to front page & fix translations * add flow with not found number * add missing translations * remove debug actions * remove unused css * Fix/bridge select asset (#976) * fix bridge select asset * fix bridge history request * fix transaction-details arrow * upfate wallet 1.15.11 (#977) * move disclaimer (#914) * Update AppHeaderMenu.vue * add popover * store value * remove old disclaimer * add translation keys * fix type * use css variables * add defined box-shadow * update translation * force user to make decision * Update storage.ts * show disclaimer if no approve * set disclaimer * fix * wait until loading * add translations * fix margins * fix width --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * fix (#980) * Fix max limit speed for internet connection (#975) * Fix max limit speed for internet connection * Fix issues * Fix tab issues * Fix issue with negative left values --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Add Token Velocity column to Tokens Page (#979) * add velocity columns * add en translation * update translations * fix css * remove symbol column from tokens page --------- Co-authored-by: Stefan Popov * remove keys (#981) Co-authored-by: Stefan Popov Co-authored-by: Nikita Polyakov <53777036+Nikita-Polyakov@users.noreply.github.com> * Demeter dialogs bottom padding adding (#982) Co-authored-by: Rustem Co-authored-by: Stefan Popov * update wallet 1.15.12 (#983) * Add routing for pairs (#971) * Add routing for pairs * Fix * Update index.ts * Finilise routing flow * Update SelectedTokensRouteMixin.ts * Update SubscriptionsMixin.ts --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix release issues (#984) * Fix action button styles in status bar * Fix z-index * Fix outline styles --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Move disclaimer to App Header (#986) * Move disclaimer to App Header * Update AppHeaderMenu.vue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Move disclaimer to App Header (#986) * Move disclaimer to App Header * Update AppHeaderMenu.vue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * fix swap container and chart align (#987) * fix supply chart axis label (#989) * Fix release issues (#990) * Fix SWAP route issue * Fix outline styles * Add online/offline consts * Remove translation keys for online/offline --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Update Jenkinsfile to use PR-generator SecretStore bot secret Signed-off-by: BAStos525 * Fix flag (#992) * Fix flag * Update AppFooter.vue * Update countryFlagEmoji.ts --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix styles (#994) * Update card.ts (#997) * add formula to velocity tooltip (#996) Co-authored-by: Rustem * apply suggestions Signed-off-by: BAStos525 * Reuse subscriptions in SubscriptionsMixin (#998) * reuse subscriptions in SUbscriptionsMixin * change variable name * update router config (#999) * Improve sora card styles (#1000) * Improve sora card styles * Remove logs * Update Widget.vue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix seo logo (#1001) * fix camera translation (#1002) * fix (#1003) * fix subscription hooks (#1004) * add DialogTitle component (#1005) Co-authored-by: Stefan Popov * Add nodes location for prod (#1006) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * change text from accounts to new accounts (#1010) * try fix Signed-off-by: BAStos525 * try fix Signed-off-by: BAStos525 * try fix Signed-off-by: BAStos525 * try fix Signed-off-by: BAStos525 * try fix Signed-off-by: BAStos525 * update polkadot deps and fix account length (#1014) * Update polkadot js deps * Fix wallet --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Explore page improvements (#1012) * change pagination of explore page * simplify query & change velocity calc * freeze components external data * remove unused code * refactoring demeter pages * up version * refactoring token approve (#1008) Co-authored-by: Stefan Popov * update wallet to 1.16.2 (#1017) * Refactoring getters (#1018) * move some getters to components * refactoring select-token component * remove getter * Update crowdloans (#1022) * update crowdloan rewards * update wallet * css fixes * change request * update private modifiers * use rw bot Signed-off-by: BAStos525 --------- Signed-off-by: BAStos525 Co-authored-by: BAStos525 * up wallet (#1024) * update wallet for crowdloans fixes (#1025) * update crowdloans in actions * ypdate yarn.lock * fix type * Update xst swaps (#1027) * update swap view * update wallet init * update genesis hash check (#1028) * Update env.json (#1029) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Update env.json (#1030) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Google wallet (#978) * wip integration * remove isDesktop flag * add en translation keys * update dialogs paddings * update wallet 1.16.0-beta.2 * experiment with secretScannerExclusion * secretScannerExclusion regex experiment * add empty keys to prod env.json * fix bridge tx signing * update wallet 1.16.0-beta.4 * small css fixes * update wallet to 1.16.0-beta.5 * update wallet * update translations * update wallet * filter zero tvl snapshots (#1033) * remove unused contracts (#1034) * fix Jenkinsfile PR-generator part Signed-off-by: BAStos525 * add downstreamJob (#1042) * Add fearless (#1038) * Add fearless for SORA card * Fix route params * Update SoraCard.vue * Add message * Update KycView.vue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * price alerts (#1013) * prework * use wallet store * add translations * add translation & update wallet & fix * Update en.json * fix double dialog overlay * add delta percent calculation * adjust * use rw bot for PR-generation Signed-off-by: BAStos525 * fix PR-generation var Signed-off-by: BAStos525 * add typings * update PR-generation vars Signed-off-by: BAStos525 * write logic for display of low cost assets * switch to false when not granted * annotate params * take into account abnormal setup * up wallet * add translations * add translations from localise * fix wiped translations * fixes * fixes * format --------- Signed-off-by: BAStos525 Co-authored-by: BAStos525 * Trustless EVM Bridge support (#792) * refactoring utils bridge folder structure & exports * update wallet integration * import EthBridgeStates from wallet * add eth hashi bridge translations * transfer updateEthBridgeHistory function to settings * wip web3 refactoring * wip update registered assets * change network in metamask * wip network select & change * select network dialog refactoring * evmAddress evmNetwork in storage * update bridge confirm dialog * wip update bridge view * prepare history item creation * wip BridgeTransaction view * wip Bridge class * wip evm bridge transaction handler * wip outgoing reducer * subscribe on tx details * update BridgeHistory view * add evm hash container * update TransferNotification * update network selection * update select network dialog for history usage * add select network to bridge history * show history from network * update transfer flow * update history sync logic * refactoring sync * wip bug fixes * refactoring state * improve removing local history * update Moonpay integration * mock incoming reducer * change selected evm network on moonpay history * fix async process * refactoring BridgeContainer * add some chains to list * refactoring chain names * fix hashi bridge history restoration * update network changing for hashi bridge restoration * resolve SelectToken conflicts * remove merge conflicts * fix merge conflicts * add sepolia to config * update with library imports * remove merge conflicts * fix messages file * fix merge conflicts * fix components names * wip select network * resolve ts issues * return eth bridge settings * update registered assets for network types * update history params * refactoring bridge classes * refactoring bridge interfaces * return eth bridge sign actions * fix select asset mixin * wip update bridge history * update history actions * start up bridge transaction * update bridge getters * fix network switch * update history states * refactoring bridge types * refactoring eth reducers * return approve from dev * return blocks left message * refactoring translations * update external history * update select network dialog & icons * history refactoring * networks disabled state * improve bridge transaction view * change eth bridge storage key * update wallet, remove unused translations * refactoring bridge types * update translations from localise * update translations * remove some todo * refactoring eth history class * dont restore evm address * reduce method complexity * reduce complexity * fetch balances right after account connec * remove unnecessary code from bridge reducers * fix bug when restored transaction overrides in process * fix history restoration * revert transactions fetching logic * refactoring tx date * update prod config * refactoring getRegisteredAssets * improve getRegisteredAssets update * fix bug with lost balance * remove console.log * refactoring block production time usage * update wallet * refactoring network icon * fixes after review * remove unused method * fix network change detection * improve evm network switch * refactoring smart contracts usage * remove unused imports * fix allowance check * fix approve btn message * refactoring getRegisteredAssets * update external balances * update translations (#1047) * remove tilda sign (#1045) * Update AppDisclaimer.vue * add translations * add missing * fix pw sdk & add countries (#1044) * fix pw sdk & add countries * extend interval * remove camera access when applied * add more countries * add css var * switch branche of jenkins library * switch to master branch for jenkins library * handle X1 unavailability * Update X1Dialog.vue * cancel remove camera access * refactor * remove unused package --------- Co-authored-by: Aleksey Kazakov Co-authored-by: Stefan Popov * Create hideFromSearchEngine.sh (#1046) * Create hideFromSearchEngine.sh * Update hideFromSearchEngine.sh * add noindex * revert lib * delete script --------- Co-authored-by: Pavel Varfolomeev * Improve ext connection and linting (#1053) * Improve extensions connection * Improve linting * Update deps * Update yarn.lock * Improve config * Exec lint --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * fix trailing char (#1056) * Fix synths (#1057) * Substrate bridge outgoing (#1059) * update imports * add substrate networks to select * fix available sub networks * wip list assets * update bridge view * add sub reducer * update bridge transaction view * update external history * fix history reset * add bridge select account dialog * refactoring bridge select account * update SelectAccount ui * wip select account directions * update bridge change direction * update env.json * update sub reducer * update sub history * update translations & wallet * use lint config from dev * set outgoung direction for sub bridge * Fix/disclaimer btn show (#1058) * fix trailing char * Update AppDisclaimer.vue * Update AppDisclaimer.vue * make button out of scroll area * adjust timeouts * add error case * remove duplicates * remove class * Fix Sub bridge issues (#1060) * reset form on network change * fix network name in ui * update KAR address * update wallet * add text for scroll (#1064) * Fix bridge network update from metamask (#1065) * fix bridge network change detection * fix polkadot.js link * Add fee multiplier support (#1066) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * change welcome text (#1069) * Fix/substrate outgoing network select (#1076) * reset form on network change * fix network name in ui * update KAR address * wip rococo adapter * fix yarn.lock * update assets on network change * update balance method for sub * fix adapter connection wait * refactoring action name * refactoring block number usage * update external balance for selected asset * network update fixes * native balance update * Set up coverage * separate prod and stage * fix var * add pre branch * fix var * revert lib * Update actions.ts (#1078) * Substrate bridge incoming transaction tracking (#1081) * reset form on network change * fix network name in ui * update KAR address * wip rococo adapter * fix yarn.lock * update assets on network change * update balance method for sub * fix adapter connection wait * refactoring action name * refactoring block number usage * update external balance for selected asset * network update fixes * native balance update * update external data after sora block update * update selectedNetwork data * show sender & recepient balance * fix balance update * update env.json * update adapters endpoints * add messageHash from collator as externalHash temporary * wait for rococo message * add external links * fix adapter endpoint reset issue * refactoring sonar related issues * incoming transaction signing * incoming transaction tracking demo * remove unused update balances * fix history remove * fix BridgeTransaction asset balance & refactoring * sub history update * disconnect after bridge leave * refactoring disconnect * update wallet * revert env.json * remove console.log9 * fix (#1082) * fix * Update AlertList.vue * fix ru * Fix sub assets fetching & hashi bridge issues (#1083) * fix hashi bridge * fetch sub bridgeassets * update wallet * fix external account check * remove unnecessary codeline * remove console.log * Change jenkins lib * Update KycView.vue (#1084) * Fix bridge account link (#1085) * fix bridge account link * wait for external balances fetching * refactoring bridge fees & balances fetching * fix sonar issues * fix sub tx trancking * fix transaction link style * Fix xst & sorting on explore page (#1075) * Update Wallet.vue * Fix regexp * Refactor tokens page * Add default sorting for tokens page * Update Tokens.vue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix issues 1.17 (#1086) * Hide 'show only synths' * Update CERES endpoint for status bar --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Check changes for errors * Revert * Fix notification links (#1092) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Add params * Merge fixes from release 1.17.0 (#1097) * Fix transaction view balance check (#1095) * fix ui checks * fix computed * Fix bridge external decimals (#1096) * fix ui checks * fix computed * fix check * Fix evm expected fee (#1091) * update evm gas price * improve gas fee calculation * remove mainnet from evm networks ids * update gasLimits * add external fee warning * refactoring externalBalance * update locales * update translations from localisr * fix merge conflict * Save sub bridge transaction fees in runtime tx processing (#1088) * fix hashi bridge * fetch sub bridgeassets * update wallet * fix external account check * remove unnecessary codeline * remove console.log * demo for fetching extrinsic fee * fix merge conflict * save tx fee & xcm fee * remove duplicated code from bridge reducers * improve network restoration * refactoring external native token balance * refactoring registered asset naming * update evm gas price * update evm gas price * improve gas fee calculation * remove mainnet from evm networks ids * update gasLimits * add external fee warning * refactoring externalBalance * update locales * update translations from localisr * impove outgoing tracking * wip locked balance * use locked balance in bridge calculations * refactoring * update BridgeTransaction asset locked balance check * refactoring event search * get bridge contract asset locked balance * remove Karura from config * refactoring before wallet update * update wallet 1.18.1 * calc evm fee based on asset kind * fix sonar issues * fix naming * Bridge balances refactoring (#1100) * update store balances * remove externalBalance from sort method * refactoring balance update * bridge route params * Change jenkins lib * spam reminder & bridge fee fix (#1103) * address book (#1099) * bump wallet * add lang * Update KycView.vue * bump wallet * update wallet 1.18.5 (#1106) * [SORA Card]: change camera access request (#1107) * add functionality * add translations * add css vars * Update KycView.vue * Update KycView.vue * Update SECURITY.md (#1105) * Update SECURITY.md Quick grammar fixes to security policy * Update SECURITY.md * Update SECURITY.md * Update SECURITY.md --------- Co-authored-by: Rustem * [Swap] Show loss warning dialog (#1108) * update value-status-wrapper * add loss warning dialog * update translations * fix loss translation argument * update wallet 1.18.8 (#1110) * Fix sub bridge tracking issues (#1104) * fix incoming tracking first steps * improve rococo incomplete transaction tracking * update retry button * refactoring namings in sub reducer * return env.json * parachain data tracking * add sora parachain hash to transaction ui * improve incoming failed tx tracking * refactor to pass sonar * add block height & blocks left in ui * update wallet 1.18.6 * refactoring adapter usage * wip adapters usage * try to refactor complexity * replace adapters in reducer * add beforeSign to bridge reducer * move sora sign to reducers * refactoring signExternal * try to pass sonar * refactoring complexity * refactoring duplicated code * fix incoming tracking & transfer notification modal * [Bridge UI] Use xcm fee in amount calculations (#1112) * fix incoming tracking first steps * improve rococo incomplete transaction tracking * update retry button * refactoring namings in sub reducer * return env.json * parachain data tracking * add sora parachain hash to transaction ui * improve incoming failed tx tracking * refactor to pass sonar * add block height & blocks left in ui * update wallet 1.18.6 * refactoring adapter usage * wip adapters usage * try to refactor complexity * replace adapters in reducer * add beforeSign to bridge reducer * move sora sign to reducers * refactoring signExternal * try to pass sonar * refactoring complexity * refactoring duplicated code * fix incoming tracking & transfer notification modal * add externalTransferFee to store * rename evm to external fee * get transfer fee from const * update bridge main form & logic * fix bridge formatted fee * native token decimals * revert BridgeInitMixin changes * Fix node name in status bar (#1113) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Add soramitsu node (#1114) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * update wallet 1.18.9 (#1115) * Update nodes names (#1116) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * [Tech] Testing workflow (#1111) * Update card.ts * fix sr lang * add Auth and KYC SDK creds * fix typo * use dev price oracle * Update X1Dialog.vue * Update X1Dialog.vue * Update X1Dialog.vue * Update X1Dialog.vue * check url * change images * remove mentions * Update sr.json * Update X1Dialog.vue * switch to prod endpoint * Update KycView.vue * Update X1Dialog.vue * Update card.ts * debug * Update KycView.vue * Update X1Dialog.vue * Update X1Dialog.vue * Fix todo-s comments * make silent * fix typo * debug referenceNumber * Fix soraNetwork issues * Update KycView.vue * Fix types issue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * remove sora parachain xcm fee, update rococo event (#1120) * update wallet with google login (#1121) * Get blacklisted countries from ipfs (#1122) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * update wallet with google seed fix (#1124) * Sub history restoration update (#1127) * remove sora parachain xcm fee, update rococo event * wip history restoration * add parachain data for history restoration * show parachain block id instead of extrinsic hash * wip outgoing tx restoration * sub history incoming restoration * unify bridge history actions * refactoring sub history restoration * update wallet 1.19 * update TransactionView external hash placeholder * refactoring sub history * fix decimals in locked balance check (#1128) * Update KycView.vue (#1131) * Fix release 1.19 (#1134) * Update mainnet config * Update zh_CN.json * Improve translations * Update wallet version --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * fix decimals usage (#1136) * Use address book in sub bridge (#1133) * use address book in sub bridge * update wallet & fix BridgeTransaction vie * Fix release 1.20 (#1141) * Fix types & remove brackets for fiat difference * Set 10% as the default error status for fiat difference/price impact * Fix issues with Cyrillic character * Add synths filter --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * added wallet translations for swap transfer batch extrinsic * Vue 2.7.14 & update packages (#1145) * remove vue-svg-loader * remove cache-loader from vue-loader * rewrite vue.config.js * update wallet * css fixes * remove sass warnings * fix spacing * add alt attrs to RoadMap * remove some todo * fix calculator btn * Pools & Explore pages default sort (#1146) * remove vue-svg-loader * remove cache-loader from vue-loader * rewrite vue.config.js * update wallet * css fixes * remove sass warnings * fix spacing * add alt attrs to RoadMap * remove some todo * explore pages default sort * add pools default sort * add default sort to demeter staking * refactor tokens items * send sora card refresh token (#1140) Co-authored-by: Stefan Popov * Refactoring (#1148) * refactoring * await, fix types * unify payment systems (#1048) * refactor X1 * refactor payment system * resolve imports issues * add eth icon * debug * debug * add connect wallet buttons * debug * remove debug * debug info * improve icons * remove unused icon * add margin * fixes * adjust icons for ads * add translations * adjust pop-ups of ads * add missing translation * add delay * add other langs * update langs * adjust footer * disable x1 * Update env.json * Update env.json * show XST ad with higher probability * add const * update prod env.json * update env.json * show when logged in * make button pressed * Update X1Dialog.vue * add prod creds * improve ads * Update AppAd.vue * improve texts and remove MC icon * Update ethers library to v6 (#1147) * remove vue-svg-loader * remove cache-loader from vue-loader * rewrite vue.config.js * update wallet * css fixes * remove sass warnings * fix spacing * add alt attrs to RoadMap * remove some todo * update ethers usage * refactoring ethers utils * add type annotaions * small fixes * wip external fee * refactoring adapter to remove hardcoded networks usage * add prefix for external fee * history restoration console info * fix sub bridge max btn * remove external network fee getter * refactoring * fix sonar issues * refactoring bridge utils * update api.query usage * improve tracking * refactoring sub reducers * improve sub history restoration * sonar issue refactoring * wip external fiat values * add nativeTOken getter to bridge * fix BridgeTransaction address * refactoring balance utils * remove bridgeApi from getters * fix transaction view prefix * update wallet 1.21.2 * remove unused variable * ADAR name is const now * updated localize for adar * Update swap subscription (#1150) * remove vue-svg-loader * remove cache-loader from vue-loader * rewrite vue.config.js * update wallet * css fixes * remove sass warnings * fix spacing * add alt attrs to RoadMap * remove some todo * update ethers usage * refactoring ethers utils * add type annotaions * small fixes * wip external fee * refactoring adapter to remove hardcoded networks usage * add prefix for external fee * history restoration console info * fix sub bridge max btn * remove external network fee getter * refactoring * fix sonar issues * refactoring bridge utils * update api.query usage * improve tracking * refactoring sub reducers * improve sub history restoration * sonar issue refactoring * wip external fiat values * add nativeTOken getter to bridge * fix BridgeTransaction address * refactoring balance utils * remove bridgeApi from getters * fix transaction view prefix * update wallet 1.21.2 * remove unused variable * prepare for subscription update * update wallet 1.21.5 * Fix dev branch issues (#1152) * fix json import (#1153) Co-authored-by: Stefan Popov * bump wallet version and update yarn lock * Swap quote subscription (#1156) * initial changes * update types * update accessors * remove unused imports * add try catch to subscriptions (#1157) * update wallet 1.21.8 (#1158) * allow select node while node is connecting (#1159) * revise & dashboard (#1129) * KYC revise & dashboard * refactor code * remove test data from build * Update env.json * fix appearance bug * do not hide iban * create translations and refactor icons * add translation * notification prework * css refactoring * fix sonarCube issues * add support for kyc count * plural forms * add pools subscription to calc balance * fix fetching * update langs * fix * Update SoraCard.vue * fixes * Update Dashboard.vue * Fix release 1.21 issues (#1160) * Update address book input props * Replace toPromise * Update wallet lib * Update translations * Update referral system strings --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Remove synths blockers from Add LP (#1162) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Add synthetic switcher to select asset (#1161) * add synthetic switcher to select asset * fix check in create alert * update add liquidity select token --------- Co-authored-by: Stefan Popov * Improve ads (#1163) * Add first version of dynamic ads * Add responsive * Fix sora card progress bar styles * Add screenBreakpointClass * Make header responsive * Make FiatDeposit view responsive * Fix names & remove unused svg-s * Update AppAd.vue --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Add debounce to resize event (#1164) * Add debounce to resize event * Fix names * Fix images size --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix content bottom margin (#1165) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Update App.vue (#1167) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Merge master (#1168) * Release 0.1.2 (#80) * Add base project files * Add About page * Add unit tests * Remove unused files * Update library version * Moved images to img folder. * Refactored some styles, added normalize css. * Fixed article card header font weight. * Fix About snapshot * Fix styles and its imports * PSS-132: Token list store * Add env.json and readme * PSS-134 DevOps: Develop CI and CD processes for Polkaswap web project (#5) * add ci cd Signed-off-by: Bulat Saifullin * fix Dockerfile Signed-off-by: Bulat Saifullin * add pull_request_template.md Signed-off-by: Bulat Saifullin * fix template Signed-off-by: Bulat Saifullin * PSS-132: Select token screen * PSS-132: Refactoring * PSS-132: Change short name to symbol * PSS-132: Add i18n to select token * PSS-132: Add unit tests * PSS-132: Remove elements from tests * Added Swap Interface draft (#4) * Swap Interface: Added screen, Unit Tests, Updated UI Lib version. * PSS-132: Create pair * PSS-132: Fixes for select token * PSS-132: Fix title style * PSS-132: UPdate snaphots * PSS-132: Fix shadow * PSS-132: Fix variable style using * Swap Interface Confirmation Screens (#8) * Added Transaction Submit dialog. * Swap Interface: Moved some variables to store for better relations between different screens and dialogs. * Confirm Swap Dialog: Fixed dialog opening, added confirmation flag to the store. * Added token default logo image, refactored translation call for liquidity. * Added SelectToken dialog on click. * PSS-126: Confirm supply modal * Confirmation screens for create pair * Design fixes * Update ui lib * PSS-126: Logo component * Update tests * Wallet integration and styles issues (#10) * Wallet integration * Fix routing issues * Update UI library version * Refactor all styles * Fix wallet connected state * Update tests * Update test * Update Dockerfile (#12) * PSS-129: Add and remove liquidity page * Design fixes * Token logo check fixes * Refactoring and fixes * Add pair token logo for add liquidity * Settings implementation (#15) * Add settings dialog * Add tests * Update tests * Fix titles for info card * Pool Interface Start Screens (#11) * Pool Interface: Added Start Screen. * Refactored components due to UI Lib updates: set size and border-radius of elements. * Created Dialog wrapper component, refactored dialogs, added fixed top position, fixed close behaviour. * Refactored components imports. * Converted logo icon to link to the home page. * Fixed error in console for Create pair component. * Added Back link behaviour for several components. * Updated unit tests. * PSS-172: Dynamic Page Title (#14) * Added dynamic page title. * PSS-128: Add confirmation screens for pool (#16) * PSS-128: Add confirmation screens for pool Co-authored-by: alexnatalia * Mocks for pool screen * Refactoring * Update tests * Add liquidity button for pairs * Design Fixes and Refactoring (#17) * Refactored TokenLogo and PairTokenLogo components, fixed some bugs, updated unit tests. Refactored components headers. * Added Popper class for info tooltips. Fixed default prop value for Object types. Updated Unit tests. * Design Issues Fix (#19) * Updated configuration variables and Exchange tabs styles. * Updated About page images and styles, Header styles and Menu colors settings. Hid unused links and buttons in header. * Updeted typography variables and Font Styles: Updated Font Size, Line Height and Font Weight Configuration. * Updated Create Pair button styles. Updated Ui Lib version. * Fixed tokens icons for Pool screen. * Updated tooltips to one consistent style. Fixed Pool screen bug. * Refactored: Created special component for Generic Header. Fixed Back icon. * Updated some fonts and Pool screen styles. * Added Empty icon for Select token popup. * Added First Liquidity Provider message to Create a Pair screen. * Hid tooltip for Slider element on Settings screen, hid tooltips for Swap Confirmation. * Updated unit tests. * PSS-205: Remove liquidity: everything should be clickable and with recalculation * Update tests * Fix set remove part to 0 * Inpur for remove part * Fixes * Price container fixes * Update tests * PS-223: Fix remove liquidity in safari * PSS-205: Design Review Issues (#21) * Fixed titles case. Updated buttons with text and icons. Updated typography styles. * Update wallet version & add blockchain integration (#23) * Update wallet version & add blockchain integration * Commented out unit tests. Co-authored-by: alexnatalia * PSS-123: Select token integration * Fix async behavior for dexApi (#25) * Fix async behavior for dexApi * Update .eslintrc.js * PSS-247: Custom Slippage Tolerance Fix (#27) * Updated STab styles. * Updated UI Lib and Wallet versions and styles according to UI Lib fixes. * PSS-129: Add liquiditiy integration * PSS-74 Swap Interface Integration (#26) * Hid swap info for not connected wallet. * Updated SelectToken search by name, added check for translation existance. * Added Swap Integration. * Refactored formatNumber calls. * Hid swap info under buttons for zero amount. * Fixed Header Menu colors. * Fixed swap from Wallet assets. * Updated tooltips. * Updated About page text and Main menu links order. * Fixed Card title color for About page. * Updated Default token setting. * Updated Wallet version. * Hid Transaction Deadline area for Settings. * Removed unneeded tooltip from Settings dialog. * Added validation for Settings. * Added validation for Insufficient Amount error from server. * Added loading while not conencted, changed store to not strict mode, updated tokens setting in store. * Fixed focused behaviour for Swap input fields. * Fix wallet connection & select token behavior * Fixed Min Received format. Co-authored-by: Stefan Popov * Swap result calculation for non connected mode (#28) * Fixed Swap result calculation for non connected mode. * Fixed About page text and styles. * Fix i18n (#30) * Updated Swap input width and Max swap behaviour. Updated Swap Info styles. (#29) * PSS-271: Medium and GitHub links (#31) * Added Github and Medium links for About page. * Upated the Wallet version. * Fixed wallet button color on hover. * Calculate total suply * PSS-216: Design Issues Fixing (#32) * Updated content primary color. * Fixed Price and Token areas horizontal alignment. * Updated tooltips. * Updated Generic Header tooltip. * Updated Token item height for Select Token dialog. * Added Token icons. * Updated token icons names. * PSS-129: Create pair integration * Remove mocks * Refactoring * Add network fee calculation * Fixes * PSS-281: Recalculate Input Values On Select Token (#33) * Added util method to check isNumber value. Removed Max button from token To area. * Added Max sold for reversed swap. * Updated Swap Integration. * Updated UI Lib version. * Added recalc on Select Token. * Fixed Swap for Polkadot.js * Updated isExchangeB param in methods. * Hid Node Address area for Settings popup. * Added Network Fee field to Swap component. * Updated Custom slippage tolerance for Settings. * Fixed paste string value to Swap fields. * Updated Network Fee calls, updated Wallet version, fixed swap tokens balance. * Added isExchangeB parameter to swap call. * Refactoring * fix total supply * PSS-129: Share of pool * Remove share of pool mock * Fix get asset symbol * Hide add liquidity Fix slippage tolerance for add liquidity Fix share of pool Fix unsupprted assets error message * Disable max button for add liquidity Reset values after change tokens * Fixes * Updated Tokens Icons, added PAL icon. (#35) * Wallet connection issues (#38) * Fix wallet connection issues * Fix styles * Update wallet version * Update favicon.ico * PSS-297: check fee on max amount * PSS-295: Added Insufficient Balance Checking (#37) * Added Insufficient balance checking. * Updated FPNumber parameters. * Removed formatNumber usage from Swap screens. * Fixed focus and placeholders values for Swap. * Updated some styles for huge number values. * Refactored due to PR comments. * Result Dialog Styles Fix (#41) * Fixed Result Dialog button styles. * Renamed USD icon. * Update library * Fix swap, liquidity behavior * Update index.ts * TODO: Revert this commit after PSS-309 * Updated wallet version. Co-authored-by: Stefan Popov * PSS-273: WEB UI: Connect Wallet - Close button leads always on Exchange page, not to the previous page (#42) * Fix routing issue * Update wallet version * PSS-295: Confirm Swap Insufficient Balance Checking (#43) * Fixed console error on tokens switch. * Added Is Insufficient Balance checking for Confirm Swap dialog. * Updated Confirm Swap styles. * Updated Swap info after Swap, added max button to init screen. (#44) * Update ui library version (#46) * Update ui library version * Update wallet * BP-312: Fixes for pool * Fix icons position (#47) * Fix icons position * Fix logo * PSS-287: Swap Amount Fields Formatting (#45) * Added Swap fields formatter. * Fixed Slippage Tolerance editing and Swap fields formatting. * Updated wallet version. * Change toString to toFixed * Change formatNumber to toFixed * Fix remove liquidity price * Move back toFixed to toString * Fixed estimated label existence for zero values (#50) * Refactored, added some comments, fixed estimated label existence for zero values. * Modify env config file (#49) Co-authored-by: Bulat Saifullin * Add custom notifications & notification tracking service (#51) * Add custom notifications & notification tracking service * Update notifications & strings according to latest changes * Update api * Update soramitsu-variables.scss * PSS-335: Designer Feedback Fixes FE (#53) * Fixed functionality and layout bugs. * Added draft component to fix layout behaviour. * Fixed Settings behaviour. * Swap: removed Result dialog, edited Network Fee tooltip. * Fixed translation bugs. * Account info implementation & fix loading state (#54) * Add account info * Fix styles * Hide test assets (#55) * Update connection * Remove usdt mock * Add liquidity issues & update notifications (#56) * Add missing notifications * Update RemoveLiquidity * Fix add liquidity screen * Add async loading of liquidity * Fix pool issues * Updated not connected pool interface message. (#60) * PSS-300: Swap confirmation dialog message update (#61) * Updated Swap confirmation dialog message. * Confirm Swap Dialog: Updated message for max sold behaviour. * Swap screen: Fixed Min Received/Max Sold area asset symbol. (#62) * PSS-379: WEB UI. Add liquidity. Click MAX button on 0 balance of XOR (#59) * Updated wallet version. Swap, Add Liquidity, Create Pair components: Updated Max button availability, refactored. * Refactored due to PR comments. * Swap, Add Liquidity: Fixed negative amount after max. Updated wallet version. * Create pair implementation & fix liquidity issues (#63) * Add create pair implementation & fix logic for add liquidity * PSS-297: WEB UI: Restrict Adding liquidity if balance is insufficient (#64) * Add Liquidity: Refactored Insufficient Balance. * Create Pair, Remove Liquidity: Updated Max functionality. * Add insufficient liquidity message for swap (#66) * link @soramitsu/soraneo-wallet-web 0.4.6 * return network address * use wallet routes in app.vue to correctly handle wallet icon click * set changePage method as private * removed local model for inputs: createPairModel * refactoring CreatePair methods * add input maxlength check * fix inputMaxLength method * improve formatNumberField method * refactoring inputMaxLength method * refactoring AddLiquidity view * create TokenPair mixin * wip refactoring * add maxlength to removeLiquidity view inputs * create TokenInputMixin * add input handlers on removeLiquidity view * handle swap inputs * return commented line * PSS-400: WEB UI. Minimum receive/Maximum sold token not changed (#69) * Fixed min received/max sold symbol. * Update wallet & api version (#70) * fixes after review * add store state interfaces * PSS-467: On the swap screen user should be able to select all tokens excecpt pool tokens (#71) * Update wallet & api version * Fix swap with assets created by user * Update wallet & api version * add watcher for slippageTolerance in Swap.vue * remove console lgos * use state types in store mutations & getters * apply transaction mixin changes from wallet * update @soramitsu/soraneo-wallet-web dependency * navigate to wallet connection view on wallet click (#75) * PSS-419: restrict precision in inputs (#74) * add TokenInput component * use TokenInput in Swap.vue * add ConfirmDialogMixin * prepare to refactoring modals * remove comments * remove unneccessary actions * add TODO comments * fix TokenInput handler * link js-ui-library with input fix * PSS-398: WEB UI. Multiple click on Confirm - create multiple transactions. (#76) * Fix multiple confirm for operations * Fix notifications view * Update env.json * PSS-364: reuse s-float-input component (#77) * prepare TokenInput component for export * use s-float-input instead of TokenInput * refactoring Settings component * refactoring RemoveLiquidity * Update wallet (#79) Co-authored-by: alexnatalia Co-authored-by: Aleksandr Makhnev Co-authored-by: Bulat Saifullin Co-authored-by: Alex Natalia <38787212+alexnatalia@users.noreply.github.com> Co-authored-by: Dmitriy Creed Co-authored-by: alexnatalia Co-authored-by: Nikita Polyakov Co-authored-by: Nikita-Polyakov Co-authored-by: Nikita Polyakov <53777036+Nikita-Polyakov@users.noreply.github.com> * Release 0.1.3 (#97) * Add base project files * Add About page * Add unit tests * Remove unused files * Update library version * Moved images to img folder. * Refactored some styles, added normalize css. * Fixed article card header font weight. * Fix About snapshot * Fix styles and its imports * PSS-132: Token list store * Add env.json and readme * PSS-134 DevOps: Develop CI and CD processes for Polkaswap web project (#5) * add ci cd Signed-off-by: Bulat Saifullin * fix Dockerfile Signed-off-by: Bulat Saifullin * add pull_request_template.md Signed-off-by: Bulat Saifullin * fix template Signed-off-by: Bulat Saifullin * PSS-132: Select token screen * PSS-132: Refactoring * PSS-132: Change short name to symbol * PSS-132: Add i18n to select token * PSS-132: Add unit tests * PSS-132: Remove elements from tests * Added Swap Interface draft (#4) * Swap Interface: Added screen, Unit Tests, Updated UI Lib version. * PSS-132: Create pair * PSS-132: Fixes for select token * PSS-132: Fix title style * PSS-132: UPdate snaphots * PSS-132: Fix shadow * PSS-132: Fix variable style using * Swap Interface Confirmation Screens (#8) * Added Transaction Submit dialog. * Swap Interface: Moved some variables to store for better relations between different screens and dialogs. * Confirm Swap Dialog: Fixed dialog opening, added confirmation flag to the store. * Added token default logo image, refactored translation call for liquidity. * Added SelectToken dialog on click. * PSS-126: Confirm supply modal * Confirmation screens for create pair * Design fixes * Update ui lib * PSS-126: Logo component * Update tests * Wallet integration and styles issues (#10) * Wallet integration * Fix routing issues * Update UI library version * Refactor all styles * Fix wallet connected state * Update tests * Update test * Update Dockerfile (#12) * PSS-129: Add and remove liquidity page * Design fixes * Token logo check fixes * Refactoring and fixes * Add pair token logo for add liquidity * Settings implementation (#15) * Add settings dialog * Add tests * Update tests * Fix titles for info card * Pool Interface Start Screens (#11) * Pool Interface: Added Start Screen. * Refactored components due to UI Lib updates: set size and border-radius of elements. * Created Dialog wrapper component, refactored dialogs, added fixed top position, fixed close behaviour. * Refactored components imports. * Converted logo icon to link to the home page. * Fixed error in console for Create pair component. * Added Back link behaviour for several components. * Updated unit tests. * PSS-172: Dynamic Page Title (#14) * Added dynamic page title. * PSS-128: Add confirmation screens for pool (#16) * PSS-128: Add confirmation screens for pool Co-authored-by: alexnatalia * Mocks for pool screen * Refactoring * Update tests * Add liquidity button for pairs * Design Fixes and Refactoring (#17) * Refactored TokenLogo and PairTokenLogo components, fixed some bugs, updated unit tests. Refactored components headers. * Added Popper class for info tooltips. Fixed default prop value for Object types. Updated Unit tests. * Design Issues Fix (#19) * Updated configuration variables and Exchange tabs styles. * Updated About page images and styles, Header styles and Menu colors settings. Hid unused links and buttons in header. * Updeted typography variables and Font Styles: Updated Font Size, Line Height and Font Weight Configuration. * Updated Create Pair button styles. Updated Ui Lib version. * Fixed tokens icons for Pool screen. * Updated tooltips to one consistent style. Fixed Pool screen bug. * Refactored: Created special component for Generic Header. Fixed Back icon. * Updated some fonts and Pool screen styles. * Added Empty icon for Select token popup. * Added First Liquidity Provider message to Create a Pair screen. * Hid tooltip for Slider element on Settings screen, hid tooltips for Swap Confirmation. * Updated unit tests. * PSS-205: Remove liquidity: everything should be clickable and with recalculation * Update tests * Fix set remove part to 0 * Inpur for remove part * Fixes * Price container fixes * Update tests * PS-223: Fix remove liquidity in safari * PSS-205: Design Review Issues (#21) * Fixed titles case. Updated buttons with text and icons. Updated typography styles. * Update wallet version & add blockchain integration (#23) * Update wallet version & add blockchain integration * Commented out unit tests. Co-authored-by: alexnatalia * PSS-123: Select token integration * Fix async behavior for dexApi (#25) * Fix async behavior for dexApi * Update .eslintrc.js * PSS-247: Custom Slippage Tolerance Fix (#27) * Updated STab styles. * Updated UI Lib and Wallet versions and styles according to UI Lib fixes. * PSS-129: Add liquiditiy integration * PSS-74 Swap Interface Integration (#26) * Hid swap info for not connected wallet. * Updated SelectToken search by name, added check for translation existance. * Added Swap Integration. * Refactored formatNumber calls. * Hid swap info under buttons for zero amount. * Fixed Header Menu colors. * Fixed swap from Wallet assets. * Updated tooltips. * Updated About page text and Main menu links order. * Fixed Card title color for About page. * Updated Default token setting. * Updated Wallet version. * Hid Transaction Deadline area for Settings. * Removed unneeded tooltip from Settings dialog. * Added validation for Settings. * Added validation for Insufficient Amount error from server. * Added loading while not conencted, changed store to not strict mode, updated tokens setting in store. * Fixed focused behaviour for Swap input fields. * Fix wallet connection & select token behavior * Fixed Min Received format. Co-authored-by: Stefan Popov * Swap result calculation for non connected mode (#28) * Fixed Swap result calculation for non connected mode. * Fixed About page text and styles. * Fix i18n (#30) * Updated Swap input width and Max swap behaviour. Updated Swap Info styles. (#29) * PSS-271: Medium and GitHub links (#31) * Added Github and Medium links for About page. * Upated the Wallet version. * Fixed wallet button color on hover. * Calculate total suply * PSS-216: Design Issues Fixing (#32) * Updated content primary color. * Fixed Price and Token areas horizontal alignment. * Updated tooltips. * Updated Generic Header tooltip. * Updated Token item height for Select Token dialog. * Added Token icons. * Updated token icons names. * PSS-129: Create pair integration * Remove mocks * Refactoring * Add network fee calculation * Fixes * PSS-281: Recalculate Input Values On Select Token (#33) * Added util method to check isNumber value. Removed Max button from token To area. * Added Max sold for reversed swap. * Updated Swap Integration. * Updated UI Lib version. * Added recalc on Select Token. * Fixed Swap for Polkadot.js * Updated isExchangeB param in methods. * Hid Node Address area for Settings popup. * Added Network Fee field to Swap component. * Updated Custom slippage tolerance for Settings. * Fixed paste string value to Swap fields. * Updated Network Fee calls, updated Wallet version, fixed swap tokens balance. * Added isExchangeB parameter to swap call. * Refactoring * fix total supply * PSS-129: Share of pool * Remove share of pool mock * Fix get asset symbol * Hide add liquidity Fix slippage tolerance for add liquidity Fix share of pool Fix unsupprted assets error message * Disable max button for add liquidity Reset values after change tokens * Fixes * Updated Tokens Icons, added PAL icon. (#35) * Wallet connection issues (#38) * Fix wallet connection issues * Fix styles * Update wallet version * Update favicon.ico * PSS-297: check fee on max amount * PSS-295: Added Insufficient Balance Checking (#37) * Added Insufficient balance checking. * Updated FPNumber parameters. * Removed formatNumber usage from Swap screens. * Fixed focus and placeholders values for Swap. * Updated some styles for huge number values. * Refactored due to PR comments. * Result Dialog Styles Fix (#41) * Fixed Result Dialog button styles. * Renamed USD icon. * Update library * Fix swap, liquidity behavior * Update index.ts * TODO: Revert this commit after PSS-309 * Updated wallet version. Co-authored-by: Stefan Popov * PSS-273: WEB UI: Connect Wallet - Close button leads always on Exchange page, not to the previous page (#42) * Fix routing issue * Update wallet version * PSS-295: Confirm Swap Insufficient Balance Checking (#43) * Fixed console error on tokens switch. * Added Is Insufficient Balance checking for Confirm Swap dialog. * Updated Confirm Swap styles. * Updated Swap info after Swap, added max button to init screen. (#44) * Update ui library version (#46) * Update ui library version * Update wallet * BP-312: Fixes for pool * Fix icons position (#47) * Fix icons position * Fix logo * PSS-287: Swap Amount Fields Formatting (#45) * Added Swap fields formatter. * Fixed Slippage Tolerance editing and Swap fields formatting. * Updated wallet version. * Change toString to toFixed * Change formatNumber to toFixed * Fix remove liquidity price * Move back toFixed to toString * Fixed estimated label existence for zero values (#50) * Refactored, added some comments, fixed estimated label existence for zero values. * Modify env config file (#49) Co-authored-by: Bulat Saifullin * Add custom notifications & notification tracking service (#51) * Add custom notifications & notification tracking service * Update notifications & strings according to latest changes * Update api * Update soramitsu-variables.scss * PSS-335: Designer Feedback Fixes FE (#53) * Fixed functionality and layout bugs. * Added draft component to fix layout behaviour. * Fixed Settings behaviour. * Swap: removed Result dialog, edited Network Fee tooltip. * Fixed translation bugs. * Account info implementation & fix loading state (#54) * Add account info * Fix styles * Hide test assets (#55) * Update connection * Remove usdt mock * Add liquidity issues & update notifications (#56) * Add missing notifications * Update RemoveLiquidity * Fix add liquidity screen * Add async loading of liquidity * Fix pool issues * Updated not connected pool interface message. (#60) * PSS-300: Swap confirmation dialog message update (#61) * Updated Swap confirmation dialog message. * Confirm Swap Dialog: Updated message for max sold behaviour. * Swap screen: Fixed Min Received/Max Sold area asset symbol. (#62) * PSS-379: WEB UI. Add liquidity. Click MAX button on 0 balance of XOR (#59) * Updated wallet version. Swap, Add Liquidity, Create Pair components: Updated Max button availability, refactored. * Refactored due to PR comments. * Swap, Add Liquidity: Fixed negative amount after max. Updated wallet version. * Create pair implementation & fix liquidity issues (#63) * Add create pair implementation & fix logic for add liquidity * PSS-297: WEB UI: Restrict Adding liquidity if balance is insufficient (#64) * Add Liquidity: Refactored Insufficient Balance. * Create Pair, Remove Liquidity: Updated Max functionality. * Add insufficient liquidity message for swap (#66) * link @soramitsu/soraneo-wallet-web 0.4.6 * return network address * use wallet routes in app.vue to correctly handle wallet icon click * set changePage method as private * removed local model for inputs: createPairModel * refactoring CreatePair methods * add input maxlength check * fix inputMaxLength method * improve formatNumberField method * refactoring inputMaxLength method * refactoring AddLiquidity view * create TokenPair mixin * wip refactoring * add maxlength to removeLiquidity view inputs * create TokenInputMixin * add input handlers on removeLiquidity view * handle swap inputs * return commented line * PSS-400: WEB UI. Minimum receive/Maximum sold token not changed (#69) * Fixed min received/max sold symbol. * Update wallet & api version (#70) * fixes after review * add store state interfaces * PSS-467: On the swap screen user should be able to select all tokens excecpt pool tokens (#71) * Update wallet & api version * Fix swap with assets created by user * Update wallet & api version * add watcher for slippageTolerance in Swap.vue * remove console lgos * use state types in store mutations & getters * apply transaction mixin changes from wallet * update @soramitsu/soraneo-wallet-web dependency * navigate to wallet connection view on wallet click (#75) * PSS-419: restrict precision in inputs (#74) * add TokenInput component * use TokenInput in Swap.vue * add ConfirmDialogMixin * prepare to refactoring modals * remove comments * remove unneccessary actions * add TODO comments * fix TokenInput handler * link js-ui-library with input fix * PSS-398: WEB UI. Multiple click on Confirm - create multiple transactions. (#76) * Fix multiple confirm for operations * Fix notifications view * Update env.json * PSS-364: reuse s-float-input component (#77) * prepare TokenInput component for export * use s-float-input instead of TokenInput * refactoring Settings component * refactoring RemoveLiquidity * Update wallet (#79) * SFloatInput Fixes (#82) * Reseted values and tokens for Add Liquidity and Create Pair components, added placeholders for all SFloatInput elements. * PSS-378: WEB UI. Remove liquidity. Troubles with entering of amount manually (#83) * Reseted values and tokens for Add Liquidity and Create Pair components, added placeholders for all SFloatInput elements. * Remove liquidity: fixed fields editing and insufficient balance calculation. * Remove Liquidity: Fixed editing behaviour. * Updated due to PR comments. * PSS-486: reset vuex values after transaction (#81) * PSS-351: Show balance in select token dialog (#84) * wip assetList * fixes in swap * fix types * remove unused imports * Refactoring Modals: add ConfirmTokenPairDialog component (#78) * add ConfirmTokenPairDialog component * add modal props fix and throw error on create pair failure * fix openSelectTokenDialog method in Swap.vue(#86) * PSS-350: Add clear button to select token search input (#85) * add clear button * refactoring mixin * remove global style in SelectToken * use global style for input button * Update wallet (#87) * Update wallet * Change s-form-item to div in SelectToken dialog (#88) * remove s-form-item * change wrapper classname * Refactoring swap view (#89) * wip * remove formModel * add reset fields method * wip swap values * refactoring minMaxRecieved calls * wip refactoring * use exchangeB as source of truth * use isExchangeB instead of activeField * disable switch during values calculation * recounting check * use promise all for parallel calculation * update ui library * discarding env.json * fixes after revie * Hide balance in SelectToken dialog, if wallet not connected (#91) * Add license (#92) * PSS-248 Web UI: Settings - Problems with input in Custom field (#90) * allow type any value * fix error * add local model * PSS-418: Precision management (#93) * Create NumberFormatterMixin.ts * Improve precision management for pool * Improve precision management for swap operation * Improve precision management for select token dialog * Update AddLiquidity.vue * Improve precision management for remove liquidity operation * Update todo sections * Fix issues * Update wallet & api versions * Add balance updates * Add zero string const * update wallet (#94) * PSS-351 Select Token fixes (#95) * select-token fixes * show 0 balance as - Co-authored-by: alexnatalia Co-authored-by: Aleksandr Makhnev Co-authored-by: Bulat Saifullin Co-authored-by: Alex Natalia <38787212+alexnatalia@users.noreply.github.com> Co-authored-by: Dmitriy Creed Co-authored-by: alexnatalia Co-authored-by: Nikita Polyakov Co-authored-by: Nikita-Polyakov Co-authored-by: Nikita Polyakov <53777036+Nikita-Polyakov@users.noreply.github.com> * Release 0.1.3 (#100) * PSS-516: WEB UI. Can go to remove liquidity page without liquidity on account (#96) * Added Page Not Found Draft. * Fixed Add and Remove Liquidity router bags, hid some screens for unauthorized access. Added redirect to exchange for Page Not Found error. * Disabled selects for existed liquidity addition. * Update Swap.vue (#99) * Release 0.1.4 (#126) * Add base project files * Add About page * Add unit tests * Remove unused files * Update library version * Moved images to img folder. * Refactored some styles, added normalize css. * Fixed article card header font weight. * Fix About snapshot * Fix styles and its imports * PSS-132: Token list store * Add env.json and readme * PSS-134 DevOps: Develop CI and CD processes for Polkaswap web project (#5) * add ci cd Signed-off-by: Bulat Saifullin * fix Dockerfile Signed-off-by: Bulat Saifullin * add pull_request_template.md Signed-off-by: Bulat Saifullin * fix template Signed-off-by: Bulat Saifullin * PSS-132: Select token screen * PSS-132: Refactoring * PSS-132: Change short name to symbol * PSS-132: Add i18n to select token * PSS-132: Add unit tests * PSS-132: Remove elements from tests * Added Swap Interface draft (#4) * Swap Interface: Added screen, Unit Tests, Updated UI Lib version. * PSS-132: Create pair * PSS-132: Fixes for select token * PSS-132: Fix title style * PSS-132: UPdate snaphots * PSS-132: Fix shadow * PSS-132: Fix variable style using * Swap Interface Confirmation Screens (#8) * Added Transaction Submit dialog. * Swap Interface: Moved some variables to store for better relations between different screens and dialogs. * Confirm Swap Dialog: Fixed dialog opening, added confirmation flag to the store. * Added token default logo image, refactored translation call for liquidity. * Added SelectToken dialog on click. * PSS-126: Confirm supply modal * Confirmation screens for create pair * Design fixes * Update ui lib * PSS-126: Logo component * Update tests * Wallet integration and styles issues (#10) * Wallet integration * Fix routing issues * Update UI library version * Refactor all styles * Fix wallet connected state * Update tests * Update test * Update Dockerfile (#12) * PSS-129: Add and remove liquidity page * Design fixes * Token logo check fixes * Refactoring and fixes * Add pair token logo for add liquidity * Settings implementation (#15) * Add settings dialog * Add tests * Update tests * Fix titles for info card * Pool Interface Start Screens (#11) * Pool Interface: Added Start Screen. * Refactored components due to UI Lib updates: set size and border-radius of elements. * Created Dialog wrapper component, refactored dialogs, added fixed top position, fixed close behaviour. * Refactored components imports. * Converted logo icon to link to the home page. * Fixed error in console for Create pair component. * Added Back link behaviour for several components. * Updated unit tests. * PSS-172: Dynamic Page Title (#14) * Added dynamic page title. * PSS-128: Add confirmation screens for pool (#16) * PSS-128: Add confirmation screens for pool Co-authored-by: alexnatalia * Mocks for pool screen * Refactoring * Update tests * Add liquidity button for pairs * Design Fixes and Refactoring (#17) * Refactored TokenLogo and PairTokenLogo components, fixed some bugs, updated unit tests. Refactored components headers. * Added Popper class for info tooltips. Fixed default prop value for Object types. Updated Unit tests. * Design Issues Fix (#19) * Updated configuration variables and Exchange tabs styles. * Updated About page images and styles, Header styles and Menu colors settings. Hid unused links and buttons in header. * Updeted typography variables and Font Styles: Updated Font Size, Line Height and Font Weight Configuration. * Updated Create Pair button styles. Updated Ui Lib version. * Fixed tokens icons for Pool screen. * Updated tooltips to one consistent style. Fixed Pool screen bug. * Refactored: Created special component for Generic Header. Fixed Back icon. * Updated some fonts and Pool screen styles. * Added Empty icon for Select token popup. * Added First Liquidity Provider message to Create a Pair screen. * Hid tooltip for Slider element on Settings screen, hid tooltips for Swap Confirmation. * Updated unit tests. * PSS-205: Remove liquidity: everything should be clickable and with recalculation * Update tests * Fix set remove part to 0 * Inpur for remove part * Fixes * Price container fixes * Update tests * PS-223: Fix remove liquidity in safari * PSS-205: Design Review Issues (#21) * Fixed titles case. Updated buttons with text and icons. Updated typography styles. * Update wallet version & add blockchain integration (#23) * Update wallet version & add blockchain integration * Commented out unit tests. Co-authored-by: alexnatalia * PSS-123: Select token integration * Fix async behavior for dexApi (#25) * Fix async behavior for dexApi * Update .eslintrc.js * PSS-247: Custom Slippage Tolerance Fix (#27) * Updated STab styles. * Updated UI Lib and Wallet versions and styles according to UI Lib fixes. * PSS-129: Add liquiditiy integration * PSS-74 Swap Interface Integration (#26) * Hid swap info for not connected wallet. * Updated SelectToken search by name, added check for translation existance. * Added Swap Integration. * Refactored formatNumber calls. * Hid swap info under buttons for zero amount. * Fixed Header Menu colors. * Fixed swap from Wallet assets. * Updated tooltips. * Updated About page text and Main menu links order. * Fixed Card title color for About page. * Updated Default token setting. * Updated Wallet version. * Hid Transaction Deadline area for Settings. * Removed unneeded tooltip from Settings dialog. * Added validation for Settings. * Added validation for Insufficient Amount error from server. * Added loading while not conencted, changed store to not strict mode, updated tokens setting in store. * Fixed focused behaviour for Swap input fields. * Fix wallet connection & select token behavior * Fixed Min Received format. Co-authored-by: Stefan Popov * Swap result calculation for non connected mode (#28) * Fixed Swap result calculation for non connected mode. * Fixed About page text and styles. * Fix i18n (#30) * Updated Swap input width and Max swap behaviour. Updated Swap Info styles. (#29) * PSS-271: Medium and GitHub links (#31) * Added Github and Medium links for About page. * Upated the Wallet version. * Fixed wallet button color on hover. * Calculate total suply * PSS-216: Design Issues Fixing (#32) * Updated content primary color. * Fixed Price and Token areas horizontal alignment. * Updated tooltips. * Updated Generic Header tooltip. * Updated Token item height for Select Token dialog. * Added Token icons. * Updated token icons names. * PSS-129: Create pair integration * Remove mocks * Refactoring * Add network fee calculation * Fixes * PSS-281: Recalculate Input Values On Select Token (#33) * Added util method to check isNumber value. Removed Max button from token To area. * Added Max sold for reversed swap. * Updated Swap Integration. * Updated UI Lib version. * Added recalc on Select Token. * Fixed Swap for Polkadot.js * Updated isExchangeB param in methods. * Hid Node Address area for Settings popup. * Added Network Fee field to Swap component. * Updated Custom slippage tolerance for Settings. * Fixed paste string value to Swap fields. * Updated Network Fee calls, updated Wallet version, fixed swap tokens balance. * Added isExchangeB parameter to swap call. * Refactoring * fix total supply * PSS-129: Share of pool * Remove share of pool mock * Fix get asset symbol * Hide add liquidity Fix slippage tolerance for add liquidity Fix share of pool Fix unsupprted assets error message * Disable max button for add liquidity Reset values after change tokens * Fixes * Updated Tokens Icons, added PAL icon. (#35) * Wallet connection issues (#38) * Fix wallet connection issues * Fix styles * Update wallet version * Update favicon.ico * PSS-297: check fee on max amount * PSS-295: Added Insufficient Balance Checking (#37) * Added Insufficient balance checking. * Updated FPNumber parameters. * Removed formatNumber usage from Swap screens. * Fixed focus and placeholders values for Swap. * Updated some styles for huge number values. * Refactored due to PR comments. * Result Dialog Styles Fix (#41) * Fixed Result Dialog button styles. * Renamed USD icon. * Update library * Fix swap, liquidity behavior * Update index.ts * TODO: Revert this commit after PSS-309 * Updated wallet version. Co-authored-by: Stefan Popov * PSS-273: WEB UI: Connect Wallet - Close button leads always on Exchange page, not to the previous page (#42) * Fix routing issue * Update wallet version * PSS-295: Confirm Swap Insufficient Balance Checking (#43) * Fixed console error on tokens switch. * Added Is Insufficient Balance checking for Confirm Swap dialog. * Updated Confirm Swap styles. * Updated Swap info after Swap, added max button to init screen. (#44) * Update ui library version (#46) * Update ui library version * Update wallet * BP-312: Fixes for pool * Fix icons position (#47) * Fix icons position * Fix logo * PSS-287: Swap Amount Fields Formatting (#45) * Added Swap fields formatter. * Fixed Slippage Tolerance editing and Swap fields formatting. * Updated wallet version. * Change toString to toFixed * Change formatNumber to toFixed * Fix remove liquidity price * Move back toFixed to toString * Fixed estimated label existence for zero values (#50) * Refactored, added some comments, fixed estimated label existence for zero values. * Modify env config file (#49) Co-authored-by: Bulat Saifullin * Add custom notifications & notification tracking service (#51) * Add custom notifications & notification tracking service * Update notifications & strings according to latest changes * Update api * Update soramitsu-variables.scss * PSS-335: Designer Feedback Fixes FE (#53) * Fixed functionality and layout bugs. * Added draft component to fix layout behaviour. * Fixed Settings behaviour. * Swap: removed Result dialog, edited Network Fee tooltip. * Fixed translation bugs. * Account info implementation & fix loading state (#54) * Add account info * Fix styles * Hide test assets (#55) * Update connection * Remove usdt mock * Add liquidity issues & update notifications (#56) * Add missing notifications * Update RemoveLiquidity * Fix add liquidity screen * Add async loading of liquidity * Fix pool issues * Updated not connected pool interface message. (#60) * PSS-300: Swap confirmation dialog message update (#61) * Updated Swap confirmation dialog message. * Confirm Swap Dialog: Updated message for max sold behaviour. * Swap screen: Fixed Min Received/Max Sold area asset symbol. (#62) * PSS-379: WEB UI. Add liquidity. Click MAX button on 0 balance of XOR (#59) * Updated wallet version. Swap, Add Liquidity, Create Pair components: Updated Max button availability, refactored. * Refactored due to PR comments. * Swap, Add Liquidity: Fixed negative amount after max. Updated wallet version. * Create pair implementation & fix liquidity issues (#63) * Add create pair implementation & fix logic for add liquidity * PSS-297: WEB UI: Restrict Adding liquidity if balance is insufficient (#64) * Add Liquidity: Refactored Insufficient Balance. * Create Pair, Remove Liquidity: Updated Max functionality. * Add insufficient liquidity message for swap (#66) * link @soramitsu/soraneo-wallet-web 0.4.6 * return network address * use wallet routes in app.vue to correctly handle wallet icon click * set changePage method as private * removed local model for inputs: createPairModel * refactoring CreatePair methods * add input maxlength check * fix inputMaxLength method * improve formatNumberField method * refactoring inputMaxLength method * refactoring AddLiquidity view * create TokenPair mixin * wip refactoring * add maxlength to removeLiquidity view inputs * create TokenInputMixin * add input handlers on removeLiquidity view * handle swap inputs * return commented line * PSS-400: WEB UI. Minimum receive/Maximum sold token not changed (#69) * Fixed min received/max sold symbol. * Update wallet & api version (#70) * fixes after review * add store state interfaces * PSS-467: On the swap screen user should be able to select all tokens excecpt pool tokens (#71) * Update wallet & api version * Fix swap with assets created by user * Update wallet & api version * add watcher for slippageTolerance in Swap.vue * remove console lgos * use state types in store mutations & getters * apply transaction mixin changes from wallet * update @soramitsu/soraneo-wallet-web dependency * navigate to wallet connection view on wallet click (#75) * PSS-419: restrict precision in inputs (#74) * add TokenInput component * use TokenInput in Swap.vue * add ConfirmDialogMixin * prepare to refactoring modals * remove comments * remove unneccessary actions * add TODO comments * fix TokenInput handler * link js-ui-library with input fix * PSS-398: WEB UI. Multiple click on Confirm - create multiple transactions. (#76) * Fix multiple confirm for operations * Fix notifications view * Update env.json * PSS-364: reuse s-float-input component (#77) * prepare TokenInput component for export * use s-float-input instead of TokenInput * refactoring Settings component * refactoring RemoveLiquidity * Update wallet (#79) * SFloatInput Fixes (#82) * Reseted values and tokens for Add Liquidity and Create Pair components, added placeholders for all SFloatInput elements. * PSS-378: WEB UI. Remove liquidity. Troubles with entering of amount manually (#83) * Reseted values and tokens for Add Liquidity and Create Pair components, added placeholders for all SFloatInput elements. * Remove liquidity: fixed fields editing and insufficient balance calculation. * Remove Liquidity: Fixed editing behaviour. * Updated due to PR comments. * PSS-486: reset vuex values after transaction (#81) * PSS-351: Show balance in select token dialog (#84) * wip assetList * fixes in swap * fix types * remove unused imports * Refactoring Modals: add ConfirmTokenPairDialog component (#78) * add ConfirmTokenPairDialog component * add modal props fix and throw error on create pair failure * fix openSelectTokenDialog method in Swap.vue(#86) * PSS-350: Add clear button to select token search input (#85) * add clear button * refactoring mixin * remove global style in SelectToken * use global style for input button * Update wallet (#87) * Update wallet * Change s-form-item to div in SelectToken dialog (#88) * remove s-form-item * change wrapper classname * Refactoring swap view (#89) * wip * remove formModel * add reset fields method * wip swap values * refactoring minMaxRecieved calls * wip refactoring * use exchangeB as source of truth * use isExchangeB instead of activeField * disable switch during values calculation * recounting check * use promise all for parallel calculation * update ui library * discarding env.json * fixes after revie * Hide balance in SelectToken dialog, if wallet not connected (#91) * Add license (#92) * PSS-248 Web UI: Settings - Problems with input in Custom field (#90) * allow type any value * fix error * add local model * PSS-418: Precision management (#93) * Create NumberFormatterMixin.ts * Improve precision management for pool * Improve precision management for swap operation * Improve precision management for select token dialog * Update AddLiquidity.vue * Improve precision management for remove liquidity operation * Update todo sections * Fix issues * Update wallet & api versions * Add balance updates * Add zero string const * update wallet (#94) * PSS-351 Select Token fixes (#95) * select-token fixes * show 0 balance as - * PSS-516: WEB UI. Can go to remove liquidity page without liquidity on account (#96) * Added Page Not Found Draft. * Fixed Add and Remove Liquidity router bags, hid some screens for unauthorized access. Added redirect to exchange for Page Not Found error. * Disabled selects for existed liquidity addition. * Update Swap.vue (#99) * Add namespace & types for swap (#101) * Fix price and swap info (#104) * Fix price calculations * Update SwapInfo.vue * Update wallet & api (#105) * Fix swap links (#106) * Fix swap links * Update wallet * Update api (#111) * up wallet version (#112) * Updated wallet version to 0.6.3 (#113) * Updated wallet version to 0.6.4. (#114) * Polkaswap layout redesign (#98) (#102) * Polkaswap layout redesign (#98) * pss-498 header redesign * wip pss-496 * style fixes * add HelpDialog component * reexport package.json * exchange routing fix * add Rewards stub with coming soon text * refactoring SidebarItemContent * refactoring styles * add FAUCET_URL to env.json * fixes after review * fix sidebar item hover css * fix disabled item css * Move bridge functionality (#103) * pss-498 header redesign * wip pss-496 * style fixes * add HelpDialog component * reexport package.json * exchange routing fix * add Rewards stub with coming soon text * refactoring SidebarItemContent * refactoring styles * add FAUCET_URL to env.json * fixes after review * Move bridge functionality Co-authored-by: Nikita-Polyakov * Update wallet & api * PSS-524: Bridge (#107) * pss-498 header redesign * wip pss-496 * style fixes * add HelpDialog component * reexport package.json * exchange routing fix * add Rewards stub with coming soon text * refactoring SidebarItemContent * refactoring styles * add FAUCET_URL to env.json * fixes after review * Move bridge functionality * Bridge: Updated unauthorized routes. * Updated Generic Page Header, updated Bridge screens. * Fixed token icons. * Bridge: Updated styles. * Updated tooltips. * Removed unused token images. * Refactored due to PR comments. Co-authored-by: Nikita-Polyakov Co-authored-by: Stefan Popov * Fix/pss 539 metamsk lock issue (#108) * improve subscribers * add check account is connected * Fix/balance flickering (#109) * wip update balance flow * refactoring views and store modules * remove unused code * fixes after review * Update yarn.lock * Updated wallet version. * Updated wallet version to 0.6.4. * Updated wallet version to 0.6.5. * PSS-540: Add Pending Transactions to Bridge History (#115) * pss-498 header redesign * wip pss-496 * style fixes * add HelpDialog component * reexport package.json * exchange routing fix * add Rewards stub with coming soon text * refactoring SidebarItemContent * refactoring styles * add FAUCET_URL to env.json * fixes after review * Move bridge functionality * Bridge: Updated unauthorized routes. * Updated Generic Page Header, updated Bridge screens. * Fixed token icons. * Bridge: Updated styles. * Updated tooltips. * Removed btc icon. * Updated due to PR comments. * Updated due to PR comments. * Reverted formatAddress changes. * Added pending state. * Updated wallet version. * Fix bridge functionality Co-authored-by: Nikita-Polyakov Co-authored-by: Stefan Popov Co-authored-by: Alex Natalia * Select dialog updates (#118) * Modify select dialog * Remove all symbol dependencies * PSS-502: Swap And Pool Redesign (#117) * Separated Swap and Pool. * Changed assets filter from symbol to address. * Updated wallet version to 0.7.1. * Fixed assets addresses behaviour for bridge. * Reverted previous version of the wallet, fixed some places due to PR comments. Co-authored-by: Alex Natalia * Update styles and icons (#119) * Fix styles and icons * Update BrandedTooltip.vue * Update wallet & ui library versions * Update LICENSE * Update package.json * Fix issues Co-authored-by: Stefan Popov Co-authored-by: Alex Natalia <38787212+alexnatalia@users.noreply.github.com> Co-authored-by: Alex Natalia * Redesign Updates (#120) * Refactored buttons styles, changed some translation to common one. * Updated tooltips, screens info area. * Updated info blocks. * Updated info blocks in confirmation and pool screens. * Combined input area styles. * Update About.vue * GenericPageHeader: Changed default prop of tooltip placement. Signed-off-by: alexnatalia Co-authored-by: Stefan Popov * update wallet to 0.7.4 (#121) * remove getAssets from select-token dialog (#123) * PSS-573 WEB UI. MAX button for bridge work incorrect. (#124) * fix calc max value * remove console.log * update wallet 0.7.7 & hide farming in menu * refactoring (#122) * Fix issues (#125) * Remove default values from props * Fix issues Co-authored-by: alexnatalia Co-authored-by: Aleksandr Makhnev Co-authored-by: Bulat Saifullin Co-authored-by: Alex Natalia <38787212+alexnatalia@users.noreply.github.com> Co-authored-by: Dmitriy Creed Co-authored-by: alexnatalia Co-authored-by: Nikita Polyakov Co-authored-by: Nikita-Polyakov Co-authored-by: Nikita Polyakov <53777036+Nikita-Polyakov@users.noreply.github.com> Co-authored-by: Alex Natalia * Release 0.1.5 (#158) * Release 0.1.5 (#161) * Release 0.1.6 (#170) * Release 0.1.6 (#174) * Release 0.1.7 (#190) * Release 0.1.8 (#200) * Release 0.1.9 (#206) * Release 1.0.0 (#208) * Update styles * Update wallet * Fix wait message for bridge eth->sora flow * Fix page amount for bridge * Fix bridge icons * Fix swap checks for XOR output without XOR or with XOR balance < network fee * Release 1.0.0 (#212) * Release 1.0.0 (#215) * Release 1.0.0 (#219) * Release 1.0.1 (#226) * Release 1.0.2 (#234) * Release 1.1.0 (#244) * PSS-281: Recalculate Input Values On Select Token (#33) * Added util method to check isNumber value. Removed Max button from token To area. * Added Max sold for reversed swap. * Updated Swap Integration. * Updated UI Lib version. * Added recalc on Select Token. * Fixed Swap for Polkadot.js * Updated isExchangeB param in methods. * Hid Node Address area for Settings popup. * Added Network Fee field to Swap component. * Updated Custom slippage tolerance for Settings. * Fixed paste string value to Swap fields. * Updated Network Fee calls, updated Wallet version, fixed swap tokens balance. * Added isExchangeB parameter to swap call. * Refactoring * fix total supply * PSS-129: Share of pool * Remove share of pool mock * Fix get asset symbol * Hide add liquidity Fix slippage tolerance for add liquidity Fix share of pool Fix unsupprted assets error message * Disable max button for add liquidity Reset values after change tokens * Fixes * Updated Tokens Icons, added PAL icon. (#35) * Wallet connection issues (#38) * Fix wallet connection issues * Fix styles * Update wallet version * Update favicon.ico * PSS-297: check fee on max amount * PSS-295: Added Insufficient Balance Checking (#37) * Added Insufficient balance checking. * Updated FPNumber parameters. * Removed formatNumber usage from Swap screens. * Fixed focus and placeholders values for Swap. * Updated some styles for huge number values. * Refactored due to PR comments. * Result Dialog Styles Fix (#41) * Fixed Result Dialog button styles. * Renamed USD icon. * Update library * Fix swap, liquidity behavior * Update index.ts * TODO: Revert this commit after PSS-309 * Updated wallet version. Co-authored-by: Stefan Popov * PSS-273: WEB UI: Connect Wallet - Close button leads always on Exchange page, not to the previous page (#42) * Fix routing issue * Update wallet version * PSS-295: Confirm Swap Insufficient Balance Checking (#43) * Fixed console error on tokens switch. * Added Is Insufficient Balance checking for Confirm Swap dialog. * Updated Confirm Swap styles. * Updated Swap info after Swap, added max button to init screen. (#44) * Update ui library version (#46) * Update ui library version * Update wallet * BP-312: Fixes for pool * Fix icons position (#47) * Fix icons position * Fix logo * PSS-287: Swap Amount Fields Formatting (#45) * Added Swap fields formatter. * Fixed Slippage Tolerance editing and Swap fields formatting. * Updated wallet version. * Change toString to toFixed * Change formatNumber to toFixed * Fix remove liquidity price * Move back toFixed to toString * Fixed estimated label existence for zero values (#50) * Refactored, added some comments, fixed estimated label existence for zero values. * Modify env config file (#49) Co-authored-by: Bulat Saifullin * Add custom notifications & notification tracking service (#51) * Add custom notifications & notification tracking service * Update notifications & strings according to latest changes * Update api * Update soramitsu-variables.scss * PSS-335: Designer Feedback Fixes FE (#53) * Fixed functionality and layout bugs. * Added draft component to fix layout behaviour. * Fixed Settings behaviour. * Swap: removed Result dialog, edited Network Fee tooltip. * Fixed translation bugs. * Account info implementation & fix loading state (#54) * Add account info * Fix styles * Hide test assets (#55) * Update connection * Remove usdt mock * Add liquidity issues & update notifications (#56) * Add missing notifications * Update RemoveLiquidity * Fix add liquidity screen * Add async loading of liquidity * Fix pool issues * Updated not connected pool interface message. (#60) * PSS-300: Swap confirmation dialog message update (#61) * Updated Swap confirmation dialog message. * Confirm Swap Dialog: Updated message for max sold behaviour. * Swap screen: Fixed Min Received/Max Sold area asset symbol. (#62) * PSS-379: WEB UI. Add liquidity. Click MAX button on 0 balance of XOR (#59) * Updated wallet version. Swap, Add Liquidity, Create Pair components: Updated Max button availability, refactored. * Refactored due to PR comments. * Swap, Add Liquidity: Fixed negative amount after max. Updated wallet version. * Create pair implementation & fix liquidity issues (#63) * Add create pair implementation & fix logic for add liquidity * PSS-297: WEB UI: Restrict Adding liquidity if balance is insufficient (#64) * Add Liquidity: Refactored Insufficient Balance. * Create Pair, Remove Liquidity: Updated Max functionality. * Add insufficient liquidity message for swap (#66) * link @soramitsu/soraneo-wallet-web 0.4.6 * return network address * use wallet routes in app.vue to correctly handle wallet icon click * set changePage method as private * removed local model for inputs: createPairModel * refactoring CreatePair methods * add input maxlength check * fix inputMaxLength method * improve formatNumberField method * refactoring inputMaxLength method * refactoring AddLiquidity view * create TokenPair mixin * wip refactoring * add maxlength to removeLiquidity view inputs * create TokenInputMixin * add input handlers on removeLiquidity view * handle swap inputs * return commented line * PSS-400: WEB UI. Minimum receive/Maximum sold token not changed (#69) * Fixed min received/max sold symbol. * Update wallet & api version (#70) * fixes after review * add store state interfaces * PSS-467: On the swap screen user should be able to select all tokens excecpt pool tokens (#71) * Update wallet & api version * Fix swap with assets created by user * Update wallet & api version * add watcher for slippageTolerance in Swap.vue * remove console lgos * use state types in store mutations & getters * apply transaction mixin changes from wallet * update @soramitsu/soraneo-wallet-web dependency * navigate to wallet connection view on wallet click (#75) * PSS-419: restrict precision in inputs (#74) * add TokenInput component * use TokenInput in Swap.vue * add ConfirmDialogMixin * prepare to refactoring modals * remove comments * remove unneccessary actions * add TODO comments * fix TokenInput handler * link js-ui-library with input fix * PSS-398: WEB UI. Multiple click on Confirm - create multiple transactions. (#76) * Fix multiple confirm for operations * Fix notifications view * Update env.json * PSS-364: reuse s-float-input component (#77) * prepare TokenInput component for export * use s-float-input instead of TokenInput * refactoring Settings component * refactoring RemoveLiquidity * Update wallet (#79) * SFloatInput Fixes (#82) * Reseted values and tokens for Add Liquidity and Create Pair components, added placeholders for all SFloatInput elements. * PSS-378: WEB UI. Remove liquidity. Troubles with entering of amount manually (#83) * Reseted values and tokens for Add Liquidity and Create Pair components, added placeholders for all SFloatInput elements. * Remove liquidity: fixed fields editing and insufficient balance calculation. * Remove Liquidity: Fixed editing behaviour. * Updated due to PR comments. * PSS-486: reset vuex values after transaction (#81) * PSS-351: Show balance in select token dialog (#84) * wip assetList * fixes in swap * fix types * remove unused imports * Refactoring Modals: add ConfirmTokenPairDialog component (#78) * add ConfirmTokenPairDialog component * add modal props fix and throw error on create pair failure * fix openSelectTokenDialog method in Swap.vue(#86) * PSS-350: Add clear button to select token search input (#85) * add clear button * refactoring mixin * remove global style in SelectToken * use global style for input button * Update wallet (#87) * Update wallet * Change s-form-item to div in SelectToken dialog (#88) * remove s-form-item * change wrapper classname * Refactoring swap view (#89) * wip * remove formModel * add reset fields method * wip swap values * refactoring minMaxRecieved calls * wip refactoring * use exchangeB as source of truth * use isExchangeB instead of activeField * disable switch during values calculation * recounting check * use promise all for parallel calculation * update ui library * discarding env.json * fixes after revie * Hide balance in SelectToken dialog, if wallet not connected (#91) * Add license (#92) * PSS-248 Web UI: Settings - Problems with input in Custom field (#90) * allow type any value * fix error * add local model * PSS-418: Precision management (#93) * Create NumberFormatterMixin.ts * Improve precision management for pool * Improve precision management for swap operation * Improve precision management for select token dialog * Update AddLiquidity.vue * Improve precision management for remove liquidity operation * Update todo sections * Fix issues * Update wallet & api versions * Add balance updates * Add zero string const * update wallet (#94) * PSS-351 Select Token fixes (#95) * select-token fixes * show 0 balance as - * PSS-516: WEB UI. Can go to remove liquidity page without liquidity on account (#96) * Added Page Not Found Draft. * Fixed Add and Remove Liquidity router bags, hid some screens for unauthorized access. Added redirect to exchange for Page Not Found error. * Disabled selects for existed liquidity addition. * Update Swap.vue (#99) * Add namespace & types for swap (#101) * Fix price and swap info (#104) * Fix price calculations * Update SwapInfo.vue * Update wallet & api (#105) * Fix swap links (#106) * Fix swap links * Update wallet * Update api (#111) * up wallet version (#112) * Updated wallet version to 0.6.3 (#113) * Updated wallet version to 0.6.4. (#114) * Polkaswap layout redesign (#98) (#102) * Polkaswap layout redesign (#98) * pss-498 header redesign * w… * fix (#1172) * Fix release 1.21 issues (#1175) * Bump version * Demeter dialog remove extra padding * Update yarn.lock --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> Co-authored-by: shlavik * Enable supply chart for all tokens (#1170) * Enable supply chart for all tokens * Update package.json --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> Co-authored-by: Nikita Polyakov <53777036+Nikita-Polyakov@users.noreply.github.com> * [Bridge] Add Min & Max limits (#1151) * remove vue-svg-loader * remove cache-loader from vue-loader * rewrite vue.config.js * update wallet * css fixes * remove sass warnings * fix spacing * add alt attrs to RoadMap * remove some todo * update ethers usage * refactoring ethers utils * add type annotaions * small fixes * wip external fee * refactoring adapter to remove hardcoded networks usage * add prefix for external fee * history restoration console info * fix sub bridge max btn * remove external network fee getter * refactoring * fix sonar issues * refactoring bridge utils * update api.query usage * improve tracking * refactoring sub reducers * improve sub history restoration * sonar issue refactoring * wip external fiat values * add nativeTOken getter to bridge * fix BridgeTransaction address * refactoring balance utils * remove bridgeApi from getters * fix transaction view prefix * update wallet 1.21.2 * add asset limit subscription * rework asset transfer limit update * update bridge subscription logic * bridge view computed * remove unused variable * prepare for subscription update * asset max limit subscription * update bridge transaction view * add min limit fetching * add getters to bridge views * add bridge limit card * update translations * replace relayChainBlockNumber call * bridge ui fixes * reset bridge form, fix network change * connection additional checks * await isReady promises * open sora parachain connection after select network * refactoring sub networks connector * refactoring web3 store * improve loading states & refactoring actions * fix bridge loading logix * refactoring bridge balances fetching * fix sub network fee & bridge container * update bridge quote * update bridge quote * fix bridge loading state * fix bridge actions promise.all reject * fix connection open * fix locked balance calc * rename web3 method * change CodecString to FPNumber in store balances * refactoring sonar issues * fix bridge amount decimals in form * update eth bridge locked balance * update wallet 1.22.0 * refactoring sonar issues * update filter fn * Fix sub bridge address issues (#1180) * fix address format checks * format sub bridge account address in ss58 * improve externalAccount usage * update wallet 1.22.1 * add xcm fee info * Remove ~ sign (#1179) * Remove ~ sign * Remove not used component * fix address format in hsitory restoration --------- Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> Co-authored-by: Nikita Polyakov <53777036+Nikita-Polyakov@users.noreply.github.com> Co-authored-by: Nikita-Polyakov * Fix assets sorting order in swap and bridge (#1181) * fix assets sorting order in swap and bridge * improve sortByBalance * Add scroll into view (#1182) Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> * Fix sub bridge sora fee & fix eth history restoration (#1183) * update bridge sora fee & history restoration * update message, remove bad util fn * sore fee update optimization * update translations * Delete TokenSelectDropdown.vue --------- Signed-off-by: Nikita Zaporozhets Signed-off-by: BAStos525 Co-authored-by: Nikita Polyakov <53777036+Nikita-Polyakov@users.noreply.github.com> Co-authored-by: Nikita Zaporozhets Co-authored-by: Nikita Zaporozhets <95526886+f33r0@users.noreply.github.com> Co-authored-by: Rustem Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com> Co-authored-by: Pavel Varfolomeev Co-authored-by: wpi86 <86880521+wpi86@users.noreply.github.com> Co-authored-by: frodan Co-authored-by: Daniil Fronts Co-authored-by: Viacheslav Co-authored-by: BAStos525 Co-authored-by: BAStos525 <66615487+BAStos525@users.noreply.github.com> Co-authored-by: Aleksey Kazakov Co-authored-by: C4tWithShell Co-authored-by: Dmitriy Creed Co-authored-by: Vladimir Shelkovnikov <99356504+C4tWithShell@users.noreply.github.com> Co-authored-by: William Richter <88400283+WRRicht3r@users.noreply.github.com> Co-authored-by: Timofey Trepalin Co-authored-by: Maksim Baranov <33489381+MaksimBaranov98@users.noreply.github.com> Co-authored-by: timofeytrepalin <97504184+timofeytrepalin@users.noreply.github.com> Co-authored-by: alexnatalia Co-authored-by: Aleksandr Makhnev Co-authored-by: Bulat Saifullin Co-authored-by: Alex Natalia <38787212+alexnatalia@users.noreply.github.com> Co-authored-by: alexnatalia Co-authored-by: Nikita Polyakov Co-authored-by: Nikita-Polyakov Co-authored-by: Alex Natalia Co-authored-by: Pavel Golovkin Co-authored-by: Pavel Co-authored-by: Pobepto Co-authored-by: Tarmo Vannas Co-authored-by: 武宮誠 Co-authored-by: Denis Nikiforov <45266099+DenisNikiforov@users.noreply.github.com> Co-authored-by: Ahmed Elkashef Co-authored-by: sunlucky163 Co-authored-by: sunlucky163 <44086186+sunlucky163@users.noreply.github.com> Co-authored-by: Bao Tran Co-authored-by: Bao Nguyen Tran Co-authored-by: Pavel Varfolomeev Co-authored-by: German Vechtomov <89127595+ox7a59@users.noreply.github.com> --- package.json | 4 +- .../Language/SelectLanguageDialog.vue | 11 +- src/components/mixins/BridgeMixin.ts | 56 ++- src/components/mixins/SelectAssetMixin.ts | 3 +- src/components/mixins/TranslationMixin.ts | 1 + src/components/mixins/WalletConnectMixin.ts | 17 +- src/components/pages/Bridge/LimitCard.vue | 62 +++ src/components/pages/Bridge/SelectAccount.vue | 14 +- src/components/pages/Bridge/SelectAsset.vue | 4 +- src/components/pages/Bridge/SelectNetwork.vue | 19 +- .../pages/Bridge/TransactionDetails.vue | 24 +- .../pages/Moonpay/BridgeInitMixin.ts | 28 +- .../pages/Moonpay/MoonpayHistory.vue | 8 +- src/components/pages/Stats/SupplyChart.vue | 31 +- .../Dialog/ConfirmBridgeTransaction.vue | 3 + .../shared/Input/TokenSelectDropdown.vue | 40 -- .../shared/SelectAsset/SelectToken.vue | 4 +- src/consts/index.ts | 4 +- src/consts/sub.ts | 6 + src/lang/cs.json | 4 +- src/lang/de.json | 4 +- src/lang/en.json | 4 +- src/lang/es.json | 4 +- src/lang/fr.json | 4 +- src/lang/hr.json | 4 +- src/lang/hu.json | 4 +- src/lang/hy.json | 4 +- src/lang/id.json | 4 +- src/lang/it.json | 4 +- src/lang/messages.ts | 8 + src/lang/nl.json | 4 +- src/lang/no.json | 4 +- src/lang/pl.json | 4 +- src/lang/ru.json | 4 +- src/lang/sk.json | 4 +- src/lang/sr.json | 4 +- src/lang/sv.json | 4 +- src/lang/vi.json | 4 +- src/lang/yo.json | 4 +- src/lang/zh_CN.json | 4 +- .../components/CalculatorDialog.vue | 2 +- src/router/index.ts | 2 +- src/store/assets/actions.ts | 2 +- src/store/bridge/actions.ts | 467 ++++++++++-------- src/store/bridge/getters.ts | 45 +- src/store/bridge/mutations.ts | 48 +- src/store/bridge/state.ts | 12 +- src/store/bridge/types.ts | 15 +- src/store/moonpay/actions.ts | 6 +- src/store/moonpay/types.ts | 6 +- src/store/web3/actions.ts | 88 ++-- src/store/web3/getters.ts | 12 +- src/store/web3/mutations.ts | 4 + src/store/web3/state.ts | 6 +- src/store/web3/types.ts | 1 + src/utils/bridge/common/utils.ts | 40 +- src/utils/bridge/eth/api.ts | 2 +- src/utils/bridge/eth/classes/history.ts | 29 +- src/utils/bridge/eth/classes/reducers.ts | 39 +- src/utils/bridge/eth/index.ts | 10 +- src/utils/bridge/eth/utils.ts | 21 +- src/utils/bridge/evm/classes/reducers.ts | 17 +- src/utils/bridge/sub/classes/adapter.ts | 75 ++- src/utils/bridge/sub/classes/history.ts | 75 +-- src/utils/bridge/sub/classes/reducers.ts | 104 ++-- src/utils/bridge/sub/utils.ts | 18 +- src/utils/ethers-util.ts | 15 +- src/utils/index.ts | 2 +- src/views/Bridge.vue | 282 ++++++----- src/views/BridgeContainer.vue | 68 +-- src/views/BridgeTransaction.vue | 95 ++-- src/views/BridgeTransactionsHistory.vue | 2 +- src/views/Explore/Demeter.vue | 10 +- src/views/Explore/Pools.vue | 11 +- src/views/FiatDepositOptions.vue | 4 +- yarn.lock | 84 ++-- 76 files changed, 1227 insertions(+), 919 deletions(-) create mode 100644 src/components/pages/Bridge/LimitCard.vue delete mode 100644 src/components/shared/Input/TokenSelectDropdown.vue diff --git a/package.json b/package.json index c4a94cd06..d7f115660 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "polkaswap-exchange-web", - "version": "1.21.1", + "version": "1.22.0", "repository": { "type": "git", "url": "https://github.com/sora-xor/polkaswap-exchange-web.git" @@ -24,7 +24,7 @@ }, "dependencies": { "@metamask/detect-provider": "^2.0.0", - "@soramitsu/soraneo-wallet-web": "1.21.12", + "@soramitsu/soraneo-wallet-web": "1.22.2", "@walletconnect/web3-provider": "^1.8.0", "core-js": "^3.26.0", "country-code-emoji": "^2.3.0", diff --git a/src/components/App/Settings/Language/SelectLanguageDialog.vue b/src/components/App/Settings/Language/SelectLanguageDialog.vue index 476d61e7f..57d7e59d3 100644 --- a/src/components/App/Settings/Language/SelectLanguageDialog.vue +++ b/src/components/App/Settings/Language/SelectLanguageDialog.vue @@ -10,7 +10,7 @@ size="medium" class="select-language-list__item s-flex" > -
+
{{ lang.value }}
@@ -26,7 +26,7 @@ + + diff --git a/src/components/pages/Bridge/SelectAccount.vue b/src/components/pages/Bridge/SelectAccount.vue index 50e2443be..d37e90536 100644 --- a/src/components/pages/Bridge/SelectAccount.vue +++ b/src/components/pages/Bridge/SelectAccount.vue @@ -20,7 +20,7 @@ import { api, mixins, components } from '@soramitsu/soraneo-wallet-web'; import { Component, Mixins, Watch } from 'vue-property-decorator'; import TranslationMixin from '@/components/mixins/TranslationMixin'; -import { action, state, mutation } from '@/store/decorators'; +import { state, mutation } from '@/store/decorators'; @Component({ components: { @@ -32,7 +32,7 @@ export default class BridgeSelectAccount extends Mixins(mixins.LoadingMixin, Tra @state.web3.subAddress private subAddress!: string; @state.web3.selectAccountDialogVisibility private selectAccountDialogVisibility!: boolean; @mutation.web3.setSelectAccountDialogVisibility private setSelectAccountDialogVisibility!: (flag: boolean) => void; - @action.web3.connectSubAccount private connectSubAccount!: (address: string) => Promise; + @mutation.web3.setSubAddress private setSubAddress!: (address: string) => Promise; address = ''; @@ -50,11 +50,17 @@ export default class BridgeSelectAccount extends Mixins(mixins.LoadingMixin, Tra } get validAddress(): boolean { - return !!this.address && api.validateAddress(this.address); + if (!(this.address && api.validateAddress(this.address))) return false; + try { + api.formatAddress(this.address); + return true; // if it can be formatted -> it's correct + } catch { + return false; // EVM account address + } } handleSelectAddress(): void { - this.connectSubAccount(this.address); + this.setSubAddress(this.address); this.visibility = false; } } diff --git a/src/components/pages/Bridge/SelectAsset.vue b/src/components/pages/Bridge/SelectAsset.vue index 29e781aab..7d2baf83a 100644 --- a/src/components/pages/Bridge/SelectAsset.vue +++ b/src/components/pages/Bridge/SelectAsset.vue @@ -65,8 +65,10 @@ export default class BridgeSelectAsset extends Mixins(TranslationMixin, SelectAs get assetsList(): Array { const assetsAddresses = Object.keys(this.registeredAssets); const excludeAddress = this.asset?.address; + const list = this.getAssetsWithBalances(assetsAddresses, excludeAddress); + const orderedList = [...list].sort(this.sortByBalance); - return this.getAssetsWithBalances(assetsAddresses, excludeAddress).sort(this.sortByBalance); + return orderedList; } get filteredAssets(): Array { diff --git a/src/components/pages/Bridge/SelectNetwork.vue b/src/components/pages/Bridge/SelectNetwork.vue index 96b3548ab..ec1214899 100644 --- a/src/components/pages/Bridge/SelectNetwork.vue +++ b/src/components/pages/Bridge/SelectNetwork.vue @@ -25,6 +25,7 @@ import NetworkFormatterMixin from '@/components/mixins/NetworkFormatterMixin'; import { action, mutation, state } from '@/store/decorators'; import type { AvailableNetwork } from '@/store/web3/types'; +import type { SubNetwork } from '@sora-substrate/util/build/bridgeProxy/sub/consts'; import type { BridgeNetworkId } from '@sora-substrate/util/build/bridgeProxy/types'; type NetworkItem = { @@ -47,10 +48,12 @@ export default class BridgeSelectNetwork extends Mixins(NetworkFormatterMixin) { @state.web3.networkSelected private networkSelected!: Nullable; @state.web3.selectNetworkDialogVisibility private selectNetworkDialogVisibility!: boolean; - @mutation.web3.setNetworkType private setNetworkType!: (networkType: BridgeNetworkType) => void; @mutation.web3.setSelectNetworkDialogVisibility private setSelectNetworkDialogVisibility!: (flag: boolean) => void; - @action.web3.selectExternalNetwork selectExternalNetwork!: (networkId: BridgeNetworkId) => void; + @action.web3.selectExternalNetwork selectExternalNetwork!: (network: { + id: BridgeNetworkId; + type: BridgeNetworkType; + }) => void; get visibility(): boolean { return this.selectNetworkDialogVisibility; @@ -66,7 +69,7 @@ export default class BridgeSelectNetwork extends Mixins(NetworkFormatterMixin) { const networks = Object.values(record) as AvailableNetwork[]; return networks.reduce((buffer, { available, disabled, data: { id, name } }) => { - const networkName = type === BridgeNetworkType.EvmLegacy ? `${name} (${this.t('hashiBridgeText')})` : name; + const networkName = type === BridgeNetworkType.Eth ? `${name} (${this.t('hashiBridgeText')})` : name; if (available) { buffer.push({ @@ -92,10 +95,12 @@ export default class BridgeSelectNetwork extends Mixins(NetworkFormatterMixin) { set selectedNetworkTuple(value: string) { const [networkType, networkSelected] = value.split(DELIMETER); - const networkFormatted = - networkType === BridgeNetworkType.Sub ? (networkSelected as BridgeNetworkId) : Number(networkSelected); - this.setNetworkType(networkType as BridgeNetworkType); - this.selectExternalNetwork(networkFormatted); + + const type = networkType as BridgeNetworkType; + const id = type === BridgeNetworkType.Sub ? (networkSelected as SubNetwork) : Number(networkSelected); + + this.selectExternalNetwork({ id, type }); + this.visibility = false; } } diff --git a/src/components/pages/Bridge/TransactionDetails.vue b/src/components/pages/Bridge/TransactionDetails.vue index 8de39204a..500e208a5 100644 --- a/src/components/pages/Bridge/TransactionDetails.vue +++ b/src/components/pages/Bridge/TransactionDetails.vue @@ -17,9 +17,18 @@ is-formatted > + @@ -29,7 +38,7 @@ import { components, mixins } from '@soramitsu/soraneo-wallet-web'; import { Component, Mixins, Prop } from 'vue-property-decorator'; import TranslationMixin from '@/components/mixins/TranslationMixin'; -import { Components, ZeroStringValue } from '@/consts'; +import { Components, ZeroStringValue, ApproximateSign } from '@/consts'; import { lazyComponent } from '@/router'; import type { CodecString } from '@sora-substrate/util'; @@ -43,12 +52,19 @@ import type { RegisteredAccountAsset } from '@sora-substrate/util/build/assets/t }) export default class BridgeTransactionDetails extends Mixins(mixins.FormattedAmountMixin, TranslationMixin) { readonly XOR = XOR; + readonly ApproximateSign = ApproximateSign; + @Prop({ default: () => null, type: Object }) readonly asset!: Nullable; @Prop({ default: () => null, type: Object }) readonly nativeToken!: Nullable; + @Prop({ default: ZeroStringValue, type: String }) readonly externalTransferFee!: CodecString; @Prop({ default: ZeroStringValue, type: String }) readonly externalNetworkFee!: CodecString; @Prop({ default: ZeroStringValue, type: String }) readonly soraNetworkFee!: CodecString; @Prop({ default: '', type: String }) readonly networkName!: string; + get assetSymbol(): string { + return this.asset?.symbol ?? ''; + } + get nativeTokenSymbol(): string { return this.nativeToken?.symbol ?? ''; } @@ -60,5 +76,9 @@ export default class BridgeTransactionDetails extends Mixins(mixins.FormattedAmo get isExternalFeeNotZero(): boolean { return this.externalNetworkFee !== ZeroStringValue; } + + get isExternalTransferFeeNotZero(): boolean { + return this.externalTransferFee !== ZeroStringValue; + } } diff --git a/src/components/pages/Moonpay/BridgeInitMixin.ts b/src/components/pages/Moonpay/BridgeInitMixin.ts index e696c31cd..0e40dd99a 100644 --- a/src/components/pages/Moonpay/BridgeInitMixin.ts +++ b/src/components/pages/Moonpay/BridgeInitMixin.ts @@ -13,9 +13,11 @@ import ethersUtil from '@/utils/ethers-util'; import type { MoonpayTransaction } from '@/utils/moonpay'; import { MoonpayEVMTransferAssetData, MoonpayApi } from '@/utils/moonpay'; -import type { CodecString, BridgeHistory } from '@sora-substrate/util'; +import type { CodecString } from '@sora-substrate/util'; import type { Asset, AccountBalance } from '@sora-substrate/util/build/assets/types'; +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'; import type { WALLET_CONSTS } from '@soramitsu/soraneo-wallet-web'; const createError = (text: string, notification: MoonpayNotifications) => { @@ -27,7 +29,7 @@ const createError = (text: string, notification: MoonpayNotifications) => { @Component export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, WalletConnectMixin) { @state.moonpay.api moonpayApi!: MoonpayApi; - @state.moonpay.bridgeTransactionData bridgeTransactionData!: Nullable; + @state.moonpay.bridgeTransactionData bridgeTransactionData!: Nullable; @state.web3.ethBridgeEvmNetwork ethBridgeEvmNetwork!: EvmNetwork; @state.wallet.settings.soraNetwork soraNetwork!: Nullable; @state.assets.registeredAssets private registeredAssets!: Record; @@ -40,12 +42,20 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W @mutation.moonpay.setNotificationKey setNotificationKey!: (key: string) => void; @mutation.moonpay.setBridgeTxData setBridgeTxData!: (options?: BridgeTxData) => void; + @action.web3.selectExternalNetwork selectExternalNetwork!: (network: { + id: BridgeNetworkId; + type: BridgeNetworkType; + }) => Promise; + @action.moonpay.getTransactionTranserData private getTransactionTranserData!: ( hash: string ) => Promise>; async prepareEvmNetwork(): Promise { - await this.selectExternalNetwork(this.ethBridgeEvmNetwork); // WalletConnectMixin + await this.selectExternalNetwork({ + id: this.ethBridgeEvmNetwork, + type: BridgeNetworkType.Eth, + }); // WalletConnectMixin } initMoonpayApi(): void { @@ -64,7 +74,7 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W } } - async getBridgeMoonpayTransaction(): Promise { + async getBridgeMoonpayTransaction(): Promise { if (!this.bridgeTransactionData) { throw new Error('bridgeTransactionData is empty'); } @@ -76,18 +86,18 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W if (!tx) { const historyItem = await this.generateHistoryItem(this.bridgeTransactionData); - return historyItem as BridgeHistory; + return historyItem as EthHistory; } return tx; } - getBridgeHistoryItemByMoonpayId(moonpayId: string): Nullable { + getBridgeHistoryItemByMoonpayId(moonpayId: string): Nullable { const externalHash = this.moonpayApi.accountRecords?.[moonpayId]; if (!externalHash) return null; - return Object.values(this.history).find((item) => item.externalHash === externalHash) as Nullable; + return Object.values(this.history).find((item) => item.externalHash === externalHash) as Nullable; } async startBridgeForMoonpayTransaction(): Promise { @@ -100,7 +110,7 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W * @param transaction moonpay transaction data * @returns string - bridge history item id */ - async prepareBridgeHistoryItemData(transaction: MoonpayTransaction): Promise { + async prepareBridgeHistoryItemData(transaction: MoonpayTransaction): Promise { return await this.withLoading(async () => { // this is not really good, but we should change evm network before fetching transaction data await this.prepareEvmNetwork(); @@ -173,7 +183,7 @@ export default class MoonpayBridgeInitMixin extends Mixins(BridgeHistoryMixin, W soraNetworkFee: this.networkFees[Operation.EthBridgeIncoming], externalNetworkFee: evmNetworkFee, externalNetwork: this.ethBridgeEvmNetwork, - externalNetworkType: BridgeNetworkType.EvmLegacy, + externalNetworkType: BridgeNetworkType.Eth, to: ethTransferData.to, payload: { moonpayId: transaction.id, diff --git a/src/components/pages/Moonpay/MoonpayHistory.vue b/src/components/pages/Moonpay/MoonpayHistory.vue index d0dbbdfeb..fd4d4b662 100644 --- a/src/components/pages/Moonpay/MoonpayHistory.vue +++ b/src/components/pages/Moonpay/MoonpayHistory.vue @@ -84,7 +84,7 @@ import ethersUtil from '../../../utils/ethers-util'; import { MoonpayTransactionStatus } from '../../../utils/moonpay'; import type { MoonpayTransaction, MoonpayCurrency, MoonpayCurrenciesById } from '../../../utils/moonpay'; -import type { BridgeHistory } from '@sora-substrate/util'; +import type { EthHistory } from '@sora-substrate/util/build/bridgeProxy/eth/types'; import type Theme from '@soramitsu/soramitsu-js-ui/lib/types/Theme'; const HistoryView = 'history'; @@ -135,7 +135,7 @@ export default class MoonpayHistory extends Mixins(mixins.PaginationSearchMixin, } }, onNetworkChange: (networkHex: string) => { - this.connectExternalNetwork(networkHex); + this.updateProvidedEvmNetwork(networkHex); }, onDisconnect: () => { this.resetProvidedEvmNetwork(); @@ -209,7 +209,7 @@ export default class MoonpayHistory extends Mixins(mixins.PaginationSearchMixin, return `${this.selectedItem.returnUrl}?${query}`; } - get bridgeTxToSora(): Nullable { + get bridgeTxToSora(): Nullable { if (!this.selectedItem.id) return undefined; return this.getBridgeHistoryItemByMoonpayId(this.selectedItem.id); @@ -291,7 +291,7 @@ export default class MoonpayHistory extends Mixins(mixins.PaginationSearchMixin, if (!this.selectedItem.id) return; if (!this.isValidNetwork) { - this.updateNetworkProvided(); + this.changeEvmNetworkProvided(); } else if (this.bridgeTxToSora?.id) { await this.prepareEvmNetwork(); // MoonpayBridgeInitMixin await this.showHistory(this.bridgeTxToSora.id); // MoonpayBridgeInitMixin diff --git a/src/components/pages/Stats/SupplyChart.vue b/src/components/pages/Stats/SupplyChart.vue index 27b1edf6e..985e488e8 100644 --- a/src/components/pages/Stats/SupplyChart.vue +++ b/src/components/pages/Stats/SupplyChart.vue @@ -12,16 +12,16 @@ + @@ -119,7 +120,8 @@ const parse = (node: AssetSnapshotEntity): ChartData => { PriceChange: lazyComponent(Components.PriceChange), StatsCard: lazyComponent(Components.StatsCard), StatsFilter: lazyComponent(Components.StatsFilter), - TokenSelectDropdown: lazyComponent(Components.TokenSelectDropdown), + TokenSelectButton: lazyComponent(Components.TokenSelectButton), + SelectToken: lazyComponent(Components.SelectToken), FormattedAmount: components.FormattedAmount, }, }) @@ -131,11 +133,24 @@ export default class StatsSupplyChart extends Mixins(mixins.LoadingMixin, ChartS filter: SnapshotFilter = ASSET_SUPPLY_LINE_FILTERS[0]; token = XOR; + showSelectTokenDialog = false; data: readonly ChartData[] = []; isFetchingError = false; + get areActionsDisabled(): boolean { + return this.parentLoading || this.loading; + } + + get selectTokenIcon(): Nullable { + return !this.areActionsDisabled ? 'chevron-down-rounded-16' : undefined; + } + + get tokenTabIndex(): number { + return !this.areActionsDisabled ? 0 : -1; + } + get firstValue(): FPNumber { return new FPNumber(first(this.data)?.value ?? 0); } @@ -275,6 +290,10 @@ export default class StatsSupplyChart extends Mixins(mixins.LoadingMixin, ChartS }; } + handleSelectToken(): void { + this.showSelectTokenDialog = true; + } + changeFilter(filter: SnapshotFilter): void { this.filter = filter; this.updateData(); diff --git a/src/components/shared/Dialog/ConfirmBridgeTransaction.vue b/src/components/shared/Dialog/ConfirmBridgeTransaction.vue index f49064bbf..4c0b0af45 100644 --- a/src/components/shared/Dialog/ConfirmBridgeTransaction.vue +++ b/src/components/shared/Dialog/ConfirmBridgeTransaction.vue @@ -25,7 +25,9 @@
null, type: Object }) readonly asset!: Nullable; @Prop({ default: () => null, type: Object }) readonly nativeToken!: Nullable; + @Prop({ default: ZeroStringValue, type: String }) readonly externalTransferFee!: CodecString; @Prop({ default: ZeroStringValue, type: String }) readonly externalNetworkFee!: CodecString; @Prop({ default: ZeroStringValue, type: String }) readonly soraNetworkFee!: CodecString; @Prop({ default: true, type: Boolean }) readonly isSoraToEvm!: boolean; diff --git a/src/components/shared/Input/TokenSelectDropdown.vue b/src/components/shared/Input/TokenSelectDropdown.vue deleted file mode 100644 index 9dc8e9680..000000000 --- a/src/components/shared/Input/TokenSelectDropdown.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/src/components/shared/SelectAsset/SelectToken.vue b/src/components/shared/SelectAsset/SelectToken.vue index 5fe13a5c0..d37e92b86 100644 --- a/src/components/shared/SelectAsset/SelectToken.vue +++ b/src/components/shared/SelectAsset/SelectToken.vue @@ -155,8 +155,10 @@ export default class SelectToken extends Mixins(TranslationMixin, SelectAssetMix const assetsAddresses = whiteList.map((asset) => asset.address); const excludeAddress = this.asset?.address; + const list = this.getAssetsWithBalances(assetsAddresses, excludeAddress); + const orderedList = [...list].sort(this.sortByBalance); - return this.getAssetsWithBalances(assetsAddresses, excludeAddress).sort(this.sortByBalance); + return orderedList; } get filteredWhitelistTokens(): Array { diff --git a/src/consts/index.ts b/src/consts/index.ts index a083e9566..e121656ff 100644 --- a/src/consts/index.ts +++ b/src/consts/index.ts @@ -90,6 +90,8 @@ export const ObjectInit = () => null; export const ZeroStringValue = '0'; +export const ApproximateSign = '~'; + export const MetamaskCancellationCode = 4001; export const DefaultSlippageTolerance = '0.5'; @@ -188,6 +190,7 @@ export enum Components { BridgeSelectNetwork = 'pages/Bridge/SelectNetwork', BridgeSelectAccount = 'pages/Bridge/SelectAccount', BridgeLinksDropdown = 'pages/Bridge/LinksDropdown', + BridgeLimitCard = 'pages/Bridge/LimitCard', // Moonpay Page Moonpay = 'pages/Moonpay/Moonpay', MoonpayNotification = 'pages/Moonpay/Notification', @@ -229,7 +232,6 @@ export enum Components { // Shared Input TokenInput = 'shared/Input/TokenInput', TokenSelectButton = 'shared/Input/TokenSelectButton', - TokenSelectDropdown = 'shared/Input/TokenSelectDropdown', // Shared Dialogs ConfirmBridgeTransactionDialog = 'shared/Dialog/ConfirmBridgeTransaction', NetworkFeeWarningDialog = 'shared/Dialog/NetworkFeeWarning', diff --git a/src/consts/sub.ts b/src/consts/sub.ts index ef0321d5c..f1c3e1e3d 100644 --- a/src/consts/sub.ts +++ b/src/consts/sub.ts @@ -74,4 +74,10 @@ export const SUB_TRANSFER_FEES: SubNetworksFees = { [BridgeTxDirection.Incoming]: '0', }, }, + [SubNetwork.Kusama]: { + KSM: { + [BridgeTxDirection.Outgoing]: '10124190', // [TODO] check in real transfer + [BridgeTxDirection.Incoming]: '0', + }, + }, }; diff --git a/src/lang/cs.json b/src/lang/cs.json index 4fc69664b..c30fb7bd0 100644 --- a/src/lang/cs.json +++ b/src/lang/cs.json @@ -545,7 +545,9 @@ "copy": "Zkopírujte síťovou adresu", "soraAddress": "{Sora} adresa", "ethereumAddress": "{Ethereum} adresa", - "limitMessage": "V současné době existuje {type} {amount} {symbol} pro přemostění, aby byla zajištěna stabilita a bezpečnost sítě {Sora}. Děkujeme za pochopení." + "limitMessage": "V současné době existuje {type} {amount} {symbol} pro přemostění, aby byla zajištěna stabilita a bezpečnost sítě {Sora}. Děkujeme za pochopení.", + "externalTransferFee": "{network} poplatek {XCM}", + "externalTransferFeeTooltip": "Když odešlete překlenovací transakci do sítě {network} , z částky, kterou převádíte, se strhne menší poplatek" }, "selectRegisteredAsset": { "title": "Vyberte token", diff --git a/src/lang/de.json b/src/lang/de.json index c1af17242..2454e2aa2 100644 --- a/src/lang/de.json +++ b/src/lang/de.json @@ -545,7 +545,9 @@ "copy": "Netzwerkadresse kopieren", "soraAddress": "{Sora} Adresse", "ethereumAddress": "{Ethereum} Adresse", - "limitMessage": "Derzeit gibt es ein {type} {amount} {symbol} für Bridging, um die Stabilität und Sicherheit des {Sora}-Netzwerks zu gewährleisten. Vielen Dank für Ihr Verständnis." + "limitMessage": "Derzeit gibt es ein {type} {amount} {symbol} für Bridging, um die Stabilität und Sicherheit des {Sora}-Netzwerks zu gewährleisten. Vielen Dank für Ihr Verständnis.", + "externalTransferFee": "{network} {XCM} -Gebühr", + "externalTransferFeeTooltip": "Wenn Sie eine Bridge-Transaktion an das Netzwerk {network} senden, wird eine geringe Gebühr von dem Betrag erhoben, den Sie überweisen" }, "selectRegisteredAsset": { "title": "Wähle ein Token", diff --git a/src/lang/en.json b/src/lang/en.json index 318ca66fc..86d733f63 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -545,7 +545,9 @@ "copy": "Copy network address", "soraAddress": "{Sora} address", "ethereumAddress": "{Ethereum} address", - "limitMessage": "Currently, there's a {type} {amount} {symbol} for bridging to ensure the stability and security of the {Sora} Network. We appreciate your understanding." + "limitMessage": "Currently, there's a {type} {amount} {symbol} for bridging to ensure the stability and security of the {Sora} Network. We appreciate your understanding.", + "externalTransferFee": "{network} {XCM} fee", + "externalTransferFeeTooltip": "When you send a bridge transaction to the {network} network, a minor fee is taken from the amount you are transferring" }, "selectRegisteredAsset": { "title": "Select a token", diff --git a/src/lang/es.json b/src/lang/es.json index 1c77b7886..f8f64d029 100644 --- a/src/lang/es.json +++ b/src/lang/es.json @@ -545,7 +545,9 @@ "copy": "Copiar dirección de red", "soraAddress": "Dirección de {Sora}", "ethereumAddress": "dirección {Ethereum}", - "limitMessage": "Actualmente, existe un {type} {amount} {symbol} para establecer puentes para garantizar la estabilidad y seguridad de la red {Sora} . apreciamos su comprensión." + "limitMessage": "Actualmente, existe un {type} {amount} {symbol} para establecer puentes para garantizar la estabilidad y seguridad de la red {Sora} . apreciamos su comprensión.", + "externalTransferFee": "tarifa de {network} {XCM}", + "externalTransferFeeTooltip": "Cuando envía una transacción puente a la red {network} , se deduce una tarifa menor del monto que está transfiriendo" }, "selectRegisteredAsset": { "title": "Seleccione un Token", diff --git a/src/lang/fr.json b/src/lang/fr.json index bf47f81e5..7be0fea00 100644 --- a/src/lang/fr.json +++ b/src/lang/fr.json @@ -545,7 +545,9 @@ "copy": "Copier l'adresse réseau", "soraAddress": "{Sora} adresse", "ethereumAddress": "{Ethereum} adresse", - "limitMessage": "Actuellement, il existe un {type} {amount} {symbol} pour le pontage afin de garantir la stabilité et la sécurité du réseau {Sora}. Nous apprécions votre compréhension." + "limitMessage": "Actuellement, il existe un {type} {amount} {symbol} pour le pontage afin de garantir la stabilité et la sécurité du réseau {Sora}. Nous apprécions votre compréhension.", + "externalTransferFee": "Frais {network} {XCM}", + "externalTransferFeeTooltip": "Lorsque vous envoyez une transaction relais vers le réseau {network} , des frais mineurs sont prélevés sur le montant que vous transférez" }, "selectRegisteredAsset": { "title": "Sélectionnez un jeton", diff --git a/src/lang/hr.json b/src/lang/hr.json index 8bbe88bbd..9c11328a8 100644 --- a/src/lang/hr.json +++ b/src/lang/hr.json @@ -545,7 +545,9 @@ "copy": "Kopiraj mrežnu adresu", "soraAddress": "{Sora} adresa", "ethereumAddress": "{Ethereum} adresa", - "limitMessage": "Trenutno postoji {type} {amount} {symbol} za premošćivanje kako bi se osigurala stabilnost i sigurnost {Sora} mreže. Cijenimo vaše razumijevanje." + "limitMessage": "Trenutno postoji {type} {amount} {symbol} za premošćivanje kako bi se osigurala stabilnost i sigurnost {Sora} mreže. Cijenimo vaše razumijevanje.", + "externalTransferFee": "{network} {XCM} naknada", + "externalTransferFeeTooltip": "Kada pošaljete premosnu transakciju na mrežu {network} , od iznosa koji prenosite uzima se manja naknada" }, "selectRegisteredAsset": { "title": "Odaberite token", diff --git a/src/lang/hu.json b/src/lang/hu.json index 7b76f6d38..16db88753 100644 --- a/src/lang/hu.json +++ b/src/lang/hu.json @@ -545,7 +545,9 @@ "copy": "Hálózati cím másolása", "soraAddress": "{Sora} cím", "ethereumAddress": "{Ethereum} cím", - "limitMessage": "Jelenleg létezik egy {type} {amount} {symbol} áthidalás, amely biztosítja a {Sora} hálózat stabilitását és biztonságát. Köszönjük megértését." + "limitMessage": "Jelenleg létezik egy {type} {amount} {symbol} áthidalás, amely biztosítja a {Sora} hálózat stabilitását és biztonságát. Köszönjük megértését.", + "externalTransferFee": "{network} {XCM} díj", + "externalTransferFeeTooltip": "Ha hídtranzakciót küld a {network} hálózatra, az átutalt összegből egy kisebb díjat számítanak fel" }, "selectRegisteredAsset": { "title": "Token kiválasztása", diff --git a/src/lang/hy.json b/src/lang/hy.json index 4f8341ead..b15adcd4f 100644 --- a/src/lang/hy.json +++ b/src/lang/hy.json @@ -545,7 +545,9 @@ "copy": "Պատճենել ցանցի հասցեն", "soraAddress": "{Sora} հասցե", "ethereumAddress": "{Ethereum} հասցե", - "limitMessage": "Ներկայումս {Sora} ցանցի կայունությունն ու անվտանգությունն ապահովելու համար կամրջելու համար կա {type} {amount} {symbol} : Մենք գնահատում ենք ձեր ըմբռնումը:" + "limitMessage": "Ներկայումս {Sora} ցանցի կայունությունն ու անվտանգությունն ապահովելու համար կամրջելու համար կա {type} {amount} {symbol} : Մենք գնահատում ենք ձեր ըմբռնումը:", + "externalTransferFee": "{network} {XCM} վճար", + "externalTransferFeeTooltip": "Երբ դուք կամուրջ գործարք եք ուղարկում {network} ցանցին, ձեր փոխանցվող գումարից փոքր վճար է վերցվում" }, "selectRegisteredAsset": { "title": "Ընտրեք տոկեն", diff --git a/src/lang/id.json b/src/lang/id.json index 5511e3948..ab1a53813 100644 --- a/src/lang/id.json +++ b/src/lang/id.json @@ -545,7 +545,9 @@ "copy": "Salin alamat jaringan", "soraAddress": "{Sora} alamat", "ethereumAddress": "{Ethereum} alamat", - "limitMessage": "Saat ini, ada {type} {amount} {symbol} untuk menjembatani guna memastikan stabilitas dan keamanan Jaringan {Sora} . Kami menghargai pengertian Anda." + "limitMessage": "Saat ini, ada {type} {amount} {symbol} untuk menjembatani guna memastikan stabilitas dan keamanan Jaringan {Sora} . Kami menghargai pengertian Anda.", + "externalTransferFee": "biaya {network} {XCM}", + "externalTransferFeeTooltip": "Saat Anda mengirim transaksi jembatan ke jaringan {network} , sedikit biaya akan diambil dari jumlah yang Anda transfer" }, "selectRegisteredAsset": { "title": "Pilih token", diff --git a/src/lang/it.json b/src/lang/it.json index 74b499b35..ba8981cd3 100644 --- a/src/lang/it.json +++ b/src/lang/it.json @@ -545,7 +545,9 @@ "copy": "Copia l'indirizzo di rete", "soraAddress": "{Sora} indirizzo", "ethereumAddress": "{Ethereum} indirizzo", - "limitMessage": "Attualmente, esiste un {type} {amount} {symbol} per il bridging per garantire la stabilità e la sicurezza della rete {Sora} . Apprezziamo la tua comprensione." + "limitMessage": "Attualmente, esiste un {type} {amount} {symbol} per il bridging per garantire la stabilità e la sicurezza della rete {Sora} . Apprezziamo la tua comprensione.", + "externalTransferFee": "Tariffa {network} {XCM}", + "externalTransferFeeTooltip": "Quando invii una transazione bridge alla rete {network} , viene trattenuta una commissione minore dall'importo che stai trasferendo" }, "selectRegisteredAsset": { "title": "Seleziona un token", diff --git a/src/lang/messages.ts b/src/lang/messages.ts index 5127c869e..1d709fcb0 100644 --- a/src/lang/messages.ts +++ b/src/lang/messages.ts @@ -395,6 +395,9 @@ export default { connectWallets: 'Connect wallets to view respective transaction history.', soraNetworkFee: '{Sora} Network Fee', ethereumNetworkFee: '{Ethereum} Network Fee', + externalTransferFee: '{network} {XCM} fee', + externalTransferFeeTooltip: + 'When you send a bridge transaction to the {network} network, a minor fee is taken from the amount you are trasferring', tooltipValue: '@:comingSoonText', total: 'Total', viewHistory: 'View transactions history', @@ -406,6 +409,8 @@ export default { copy: 'Copy network address', soraAddress: '{Sora} address', ethereumAddress: '{Ethereum} address', + limitMessage: + "Currently, there's a {type} {amount} {symbol} for bridging to ensure the stability and security of the {Sora} Network. We appreciate your understanding.", }, selectRegisteredAsset: { title: 'Select a token', @@ -858,4 +863,7 @@ export default { btnGoToSettings: 'Go to settings', btnAllow: 'Allow access', }, + minAmountText: 'min. amount', + maxAmountText: 'max. amount', + exceededAmountText: '{amount} exceeded', }; diff --git a/src/lang/nl.json b/src/lang/nl.json index 772292e37..a2aef3bbd 100644 --- a/src/lang/nl.json +++ b/src/lang/nl.json @@ -545,7 +545,9 @@ "copy": "Netwerkadres kopiëren", "soraAddress": "{Sora} adres", "ethereumAddress": "{Ethereum} adres", - "limitMessage": "Momenteel is er een {type} {amount} {symbol} voor overbrugging om de stabiliteit en veiligheid van het {Sora}-netwerk te garanderen. We waarderen je begrip." + "limitMessage": "Momenteel is er een {type} {amount} {symbol} voor overbrugging om de stabiliteit en veiligheid van het {Sora}-netwerk te garanderen. We waarderen je begrip.", + "externalTransferFee": "{network} {XCM} kosten", + "externalTransferFeeTooltip": "Wanneer u een overbruggingstransactie naar het {network} -netwerk verzendt, wordt er een kleine vergoeding in rekening gebracht op het bedrag dat u overdraagt" }, "selectRegisteredAsset": { "title": "Kies een token", diff --git a/src/lang/no.json b/src/lang/no.json index a72ae903a..4666b15e4 100644 --- a/src/lang/no.json +++ b/src/lang/no.json @@ -545,7 +545,9 @@ "copy": "Kopier nettverksadressen", "soraAddress": "{Sora} adresse", "ethereumAddress": "{Ethereum} adresse", - "limitMessage": "For øyeblikket er det en {type} {amount} {symbol} for brobygging for å sikre stabiliteten og sikkerheten til {Sora} -nettverket. Vi setter pris på din forståelse." + "limitMessage": "For øyeblikket er det en {type} {amount} {symbol} for brobygging for å sikre stabiliteten og sikkerheten til {Sora} -nettverket. Vi setter pris på din forståelse.", + "externalTransferFee": "{network} {XCM} gebyr", + "externalTransferFeeTooltip": "Når du sender en brotransaksjon til {network} -nettverket, tas et mindre gebyr fra beløpet du overfører" }, "selectRegisteredAsset": { "title": "Velg token", diff --git a/src/lang/pl.json b/src/lang/pl.json index dc957e1bd..0e39cb773 100644 --- a/src/lang/pl.json +++ b/src/lang/pl.json @@ -545,7 +545,9 @@ "copy": "Skopiuj adres sieciowy", "soraAddress": "{Sora} adres", "ethereumAddress": "{Ethereum} adres", - "limitMessage": "Obecnie istnieje {type} {amount} {symbol} do mostkowania, aby zapewnić stabilność i bezpieczeństwo sieci {Sora} . Doceniamy twoje zrozumienie." + "limitMessage": "Obecnie istnieje {type} {amount} {symbol} do mostkowania, aby zapewnić stabilność i bezpieczeństwo sieci {Sora} . Doceniamy twoje zrozumienie.", + "externalTransferFee": "Opłata {network} {XCM}", + "externalTransferFeeTooltip": "Kiedy wysyłasz transakcję pomostową do sieci {network} , od kwoty przelewu pobierana jest niewielka opłata" }, "selectRegisteredAsset": { "title": "Wybierz token", diff --git a/src/lang/ru.json b/src/lang/ru.json index c4ff16173..52a3b4d15 100644 --- a/src/lang/ru.json +++ b/src/lang/ru.json @@ -545,7 +545,9 @@ "copy": "Скопировать адрес сети", "soraAddress": "{Sora} адрес", "ethereumAddress": "{Ethereum} адрес", - "limitMessage": "В настоящее время существует {type} {amount} {symbol} для моста, обеспечивающая стабильность и безопасность сети {Sora}. Мы ценим ваше понимание." + "limitMessage": "В настоящее время существует {type} {amount} {symbol} для моста, обеспечивающая стабильность и безопасность сети {Sora}. Мы ценим ваше понимание.", + "externalTransferFee": "{network} комиссия {XCM}", + "externalTransferFeeTooltip": "Когда вы отправляете транзакцию моста в сеть {network}, из суммы перевода взимается небольшая комиссия." }, "selectRegisteredAsset": { "title": "Выбрать токен", diff --git a/src/lang/sk.json b/src/lang/sk.json index aa646f7bd..bbe108b56 100644 --- a/src/lang/sk.json +++ b/src/lang/sk.json @@ -545,7 +545,9 @@ "copy": "Skopírujte sieťovú adresu", "soraAddress": "{Sora} adresa", "ethereumAddress": "{Ethereum} adresa", - "limitMessage": "V súčasnosti existuje {type} {amount} {symbol} na premostenie na zaistenie stability a bezpečnosti siete {Sora}. Ďakujeme za pochopenie." + "limitMessage": "V súčasnosti existuje {type} {amount} {symbol} na premostenie na zaistenie stability a bezpečnosti siete {Sora}. Ďakujeme za pochopenie.", + "externalTransferFee": "{network} poplatok {XCM}", + "externalTransferFeeTooltip": "Keď odošlete preklenovaciu transakciu do siete {network} , zo sumy, ktorú prenášate, sa účtuje malý poplatok" }, "selectRegisteredAsset": { "title": "Vybrať token", diff --git a/src/lang/sr.json b/src/lang/sr.json index 2d920aefe..42924cc2f 100644 --- a/src/lang/sr.json +++ b/src/lang/sr.json @@ -545,7 +545,9 @@ "copy": "Копирајте мрежну адресу", "soraAddress": "{Sora} adresa", "ethereumAddress": "{Ethereum} adresa", - "limitMessage": "Тренутно постоји {type} {amount} {symbol} за премошћавање да би се обезбедила стабилност и безбедност мреже {Sora} . Ценимо ваше разумевање." + "limitMessage": "Тренутно постоји {type} {amount} {symbol} за премошћавање да би се обезбедила стабилност и безбедност мреже {Sora} . Ценимо ваше разумевање.", + "externalTransferFee": "{network} {XCM} накнада", + "externalTransferFeeTooltip": "Када пошаљете бридге трансакцију на мрежу {network} , од износа који преносите узима се мања накнада" }, "selectRegisteredAsset": { "title": "Изаберите токен", diff --git a/src/lang/sv.json b/src/lang/sv.json index dfbc8b891..4d731d32e 100644 --- a/src/lang/sv.json +++ b/src/lang/sv.json @@ -545,7 +545,9 @@ "copy": "Kopiera nätverksadress", "soraAddress": "{Sora} adress", "ethereumAddress": "{Ethereum} adress", - "limitMessage": "För närvarande finns det en {type} {amount} {symbol} för överbryggning för att säkerställa stabiliteten och säkerheten i {Sora} -nätverket. Vi uppskattar din förståelse." + "limitMessage": "För närvarande finns det en {type} {amount} {symbol} för överbryggning för att säkerställa stabiliteten och säkerheten i {Sora} -nätverket. Vi uppskattar din förståelse.", + "externalTransferFee": "{network} {XCM} avgift", + "externalTransferFeeTooltip": "När du skickar en bryggtransaktion till {network} -nätverket tas en mindre avgift från beloppet du överför" }, "selectRegisteredAsset": { "title": "Välj en token", diff --git a/src/lang/vi.json b/src/lang/vi.json index 76d8f225d..03f8497c0 100644 --- a/src/lang/vi.json +++ b/src/lang/vi.json @@ -545,7 +545,9 @@ "copy": "Sao chép địa chỉ mạng", "soraAddress": "địa chỉ {Sora}", "ethereumAddress": "địa chỉ {Ethereum}", - "limitMessage": "Hiện tại, có một {type} {amount} {symbol} để kết nối nhằm đảm bảo tính ổn định và bảo mật của Mạng {Sora} . Chúng tôi đánh giá cao sự hiểu biết của bạn." + "limitMessage": "Hiện tại, có một {type} {amount} {symbol} để kết nối nhằm đảm bảo tính ổn định và bảo mật của Mạng {Sora} . Chúng tôi đánh giá cao sự hiểu biết của bạn.", + "externalTransferFee": "Phí {network} {XCM}", + "externalTransferFeeTooltip": "Khi bạn gửi giao dịch bắc cầu tới mạng {network} , số tiền bạn chuyển sẽ bị tính một khoản phí nhỏ" }, "selectRegisteredAsset": { "title": "Chọn token", diff --git a/src/lang/yo.json b/src/lang/yo.json index 8d1575299..8fbb054de 100644 --- a/src/lang/yo.json +++ b/src/lang/yo.json @@ -545,7 +545,9 @@ "copy": "Daakọ adirẹsi nẹtiwọki", "soraAddress": "{Sora} adirẹsi", "ethereumAddress": "{Ethereum} adirẹsi", - "limitMessage": "Lọwọlọwọ, {type} {amount} {symbol} wa fun sisọpọ lati rii daju iduroṣinṣin ati aabo ti Nẹtiwọọki {Sora} . A dupe oye rẹ." + "limitMessage": "Lọwọlọwọ, {type} {amount} {symbol} wa fun sisọpọ lati rii daju iduroṣinṣin ati aabo ti Nẹtiwọọki {Sora} . A dupe oye rẹ.", + "externalTransferFee": "{network} {XCM} ọya", + "externalTransferFeeTooltip": "Nigbati o ba fi iṣowo afara ranṣẹ si netiwọki {network} , owo kekere kan yoo gba lati iye ti o n gbe" }, "selectRegisteredAsset": { "title": "Yan Tokini kan", diff --git a/src/lang/zh_CN.json b/src/lang/zh_CN.json index f895c757a..0feb699fd 100644 --- a/src/lang/zh_CN.json +++ b/src/lang/zh_CN.json @@ -545,7 +545,9 @@ "copy": "复制网络地址", "soraAddress": "{Sora} 地址", "ethereumAddress": "{Ethereum} 地址", - "limitMessage": "目前,有一个{type} {amount} {symbol}用于桥接,以确保 {Sora} 网络的稳定性和安全性。我们感谢您的理解。" + "limitMessage": "目前,有一个{type} {amount} {symbol}用于桥接,以确保 {Sora} 网络的稳定性和安全性。我们感谢您的理解。", + "externalTransferFee": "{network} {XCM}费用", + "externalTransferFeeTooltip": "当您向{network}网络发送桥接交易时,将从您传输的金额中收取少量费用" }, "selectRegisteredAsset": { "title": "选择一个代币", diff --git a/src/modules/demeterFarming/components/CalculatorDialog.vue b/src/modules/demeterFarming/components/CalculatorDialog.vue index 2b1512017..76672a3b8 100644 --- a/src/modules/demeterFarming/components/CalculatorDialog.vue +++ b/src/modules/demeterFarming/components/CalculatorDialog.vue @@ -160,7 +160,7 @@ export default class CalculatorDialog extends Mixins(PoolCardMixin, mixins.Dialo } get calculatedRewardsFormatted(): string { - return '~' + this.calculatedRewards.toLocaleString(); + return this.calculatedRewards.toLocaleString(); } get calculatedRewardsFiat(): Nullable { diff --git a/src/router/index.ts b/src/router/index.ts index d05c20a78..43cf17e84 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -270,7 +270,7 @@ router.beforeEach((to, from, next) => { } } if (to.matched.some((record) => record.meta.requiresAuth)) { - if (BridgeChildPages.includes(current) && isLoggedIn && !store.getters.web3.externalAccount) { + if (BridgeChildPages.includes(current) && isLoggedIn && !store.getters.bridge.externalAccount) { setRoute(PageNames.Bridge); return; } diff --git a/src/store/assets/actions.ts b/src/store/assets/actions.ts index 3199ac301..0e48d8523 100644 --- a/src/store/assets/actions.ts +++ b/src/store/assets/actions.ts @@ -80,7 +80,7 @@ async function getRegisteredAssets(context: ActionContext): Promise => { + const accountBalance = await getAssetBalance(api.api, accountAddress, asset.address, asset.decimals); + return accountBalance.transferable; +}; + +const getExternalBalance = async ( + accountAddress: string, + asset: RegisteredAccountAsset, + isSub: boolean +): Promise => { + return isSub + ? await subBridgeConnector.networkAdapter.getTokenBalance(accountAddress, asset?.externalAddress) + : await ethersUtil.getAccountAssetBalance(accountAddress, asset?.externalAddress); +}; + +const getAccountBridgeBalance = async ( + accountAddress: string, + asset: Nullable, + isSora: boolean, + isSub: boolean +): Promise => { + if (!(asset?.address && accountAddress)) return ZeroStringValue; + + try { + return isSora + ? await getSoraBalance(accountAddress, asset) + : await getExternalBalance(accountAddress, asset, isSub); + } catch { + return ZeroStringValue; + } +}; + function getBridgeApi(context: ActionContext) { const { getters } = bridgeActionContext(context); @@ -47,43 +86,6 @@ function checkEvmNetwork(context: ActionContext): void { } } -async function evmTxDataToHistory( - assetDataByAddress: (address: string) => Nullable, - tx: BridgeTransactionData -): Promise { - const id = tx.soraHash; - const asset = assetDataByAddress(tx.soraAssetAddress); - const transactionState = tx.status; - const isOutgoing = tx.direction === BridgeTxDirection.Outgoing; - const blockHeight = isOutgoing ? tx.startBlock : tx.endBlock; - const externalBlockHeight = isOutgoing ? tx.endBlock : tx.startBlock; - const blockId = await api.system.getBlockHash(blockHeight); - const startTime = await api.system.getBlockTimestamp(blockId); - - return { - id, - txId: id, - blockId, - blockHeight, - type: isOutgoing ? Operation.EvmOutgoing : Operation.EvmIncoming, - hash: tx.soraHash, - transactionState, - externalBlockHeight, - externalNetwork: tx.externalNetwork as EvmNetwork, - externalNetworkType: BridgeNetworkType.Evm, - // for now we don't know it - externalHash: '', - amount: FPNumber.fromCodecValue(tx.amount, asset?.decimals).toString(), - assetAddress: asset?.address, - symbol: asset?.symbol, - from: tx.soraAccount, - to: tx.externalAccount, - // for now we only know sora block, assume what this is start & end times - startTime: startTime, - endTime: startTime, - }; -} - function bridgeDataToHistoryItem( context: ActionContext, { date = Date.now(), payload = {}, ...params } = {} @@ -93,7 +95,7 @@ function bridgeDataToHistoryItem( const transactionState = isEthBridge ? WALLET_CONSTS.ETH_BRIDGE_STATES.INITIAL : BridgeTxStatus.Pending; const externalNetwork = rootState.web3.networkSelected as BridgeNetworkId as any; const externalNetworkType = isEthBridge - ? BridgeNetworkType.EvmLegacy + ? BridgeNetworkType.Eth : isEvmBridge ? BridgeNetworkType.Evm : BridgeNetworkType.Sub; @@ -106,46 +108,46 @@ function bridgeDataToHistoryItem( assetAddress: (params as any).assetAddress ?? getters.asset?.address, startTime: date, endTime: date, - status: '', - hash: '', transactionState, - soraNetworkFee: (params as any).soraNetworkFee ?? getters.soraNetworkFee, + soraNetworkFee: (params as any).soraNetworkFee ?? state.soraNetworkFee, externalNetworkFee: (params as any).externalNetworkFee, externalNetwork, externalNetworkType, - to: (params as any).to ?? rootGetters.web3.externalAccount, + to: (params as any).to ?? getters.externalAccountFormatted, payload, }; } async function getEvmNetworkFee(context: ActionContext): Promise { - const { commit, state, rootState } = bridgeActionContext(context); + const { commit, getters, state, rootState } = bridgeActionContext(context); let fee = ZeroStringValue; - const address = state.assetAddress; - const registeredAsset = address ? rootState.assets.registeredAssets[address] : null; + if (getters.asset && getters.isRegisteredAsset) { + const bridgeRegisteredAsset = rootState.assets.registeredAssets[getters.asset.address]; - if (registeredAsset) { - fee = await ethersUtil.getEvmNetworkFee(registeredAsset.address, registeredAsset.kind, state.isSoraToEvm); + fee = await ethersUtil.getEvmNetworkFee( + bridgeRegisteredAsset.address, + bridgeRegisteredAsset.kind, + state.isSoraToEvm + ); } commit.setExternalNetworkFee(fee); } async function getSubNetworkFee(context: ActionContext): Promise { - const { commit } = bridgeActionContext(context); - + const { commit, getters } = bridgeActionContext(context); let fee = ZeroStringValue; - if (subConnector.networkAdapter) { - fee = await subConnector.networkAdapter.getNetworkFee(); + if (getters.asset && getters.isRegisteredAsset) { + fee = await subBridgeConnector.networkAdapter.getNetworkFee(getters.asset); } commit.setExternalNetworkFee(fee); } -async function getExternalNetworkFee(context: ActionContext): Promise { +async function updateExternalNetworkFee(context: ActionContext): Promise { const { getters } = bridgeActionContext(context); if (getters.isSubBridge) { @@ -155,39 +157,26 @@ async function getExternalNetworkFee(context: ActionContext): Promise< } } +async function updateExternalLockedBalance(context: ActionContext): Promise { + const { getters } = bridgeActionContext(context); + + if (getters.isEthBridge) { + await updateEthLockedBalance(context); + } else { + await updateBridgeProxyLockedBalance(context); + } +} + async function updateEvmBalances(context: ActionContext): Promise { const { commit, getters, state } = bridgeActionContext(context); - const { sender, recipient, asset } = getters; + const { sender, recipient, asset, nativeToken } = getters; const { isSoraToEvm } = state; - const spender = isSoraToEvm ? recipient : sender; - const getSenderBalance = async () => { - if (!(asset?.address && sender)) return ZeroStringValue; - - return isSoraToEvm - ? (await getAssetBalance(api.api, sender, asset.address, asset.decimals)).transferable - : await ethersUtil.getAccountAssetBalance(sender, asset?.externalAddress); - }; - - const getRecipientBalance = async () => { - if (!(asset?.address && recipient)) return ZeroStringValue; - - return isSoraToEvm - ? await ethersUtil.getAccountAssetBalance(recipient, asset?.externalAddress) - : (await getAssetBalance(api.api, recipient, asset.address, asset.decimals)).transferable; - }; - - const getSpenderBalance = async () => { - if (!(asset?.address && spender)) return ZeroStringValue; - - return await ethersUtil.getAccountBalance(spender); - }; - const [senderBalance, recipientBalance, nativeBalance] = await Promise.all([ - getSenderBalance(), - getRecipientBalance(), - getSpenderBalance(), + getAccountBridgeBalance(sender, asset, isSoraToEvm, false), + getAccountBridgeBalance(recipient, asset, !isSoraToEvm, false), + getAccountBridgeBalance(spender, nativeToken, false, false), ]); commit.setAssetSenderBalance(senderBalance); @@ -197,35 +186,14 @@ async function updateEvmBalances(context: ActionContext): Promise): Promise { const { commit, getters, state } = bridgeActionContext(context); - const { sender, recipient, asset } = getters; + const { sender, recipient, asset, nativeToken } = getters; const { isSoraToEvm } = state; - - const getSenderBalance = async () => { - if (!(asset?.address && sender)) return ZeroStringValue; - - return isSoraToEvm - ? (await getAssetBalance(api.api, sender, asset.address, asset.decimals)).transferable - : await subConnector.networkAdapter.getTokenBalance(sender, asset?.externalAddress); - }; - - const getRecipientBalance = async () => { - if (!(asset?.address && recipient)) return ZeroStringValue; - - return isSoraToEvm - ? await subConnector.networkAdapter.getTokenBalance(recipient, asset?.externalAddress) - : (await getAssetBalance(api.api, recipient, asset.address, asset.decimals)).transferable; - }; - - const getSpenderBalance = async () => { - if (!(asset?.address && sender)) return ZeroStringValue; - - return await subConnector.networkAdapter.getTokenBalance(sender); - }; + const spender = sender; const [senderBalance, recipientBalance, nativeBalance] = await Promise.all([ - getSenderBalance(), - getRecipientBalance(), - getSpenderBalance(), + getAccountBridgeBalance(sender, asset, isSoraToEvm, true), + getAccountBridgeBalance(recipient, asset, !isSoraToEvm, true), + getAccountBridgeBalance(spender, nativeToken, false, true), ]); commit.setAssetSenderBalance(senderBalance); @@ -247,46 +215,30 @@ async function updateEthHistory(context: ActionContext, clearHistory = await updateHistoryFn(clearHistory, dispatch.updateInternalHistory); } -async function updateEvmHistory(context: ActionContext): Promise { - const { commit, dispatch, state, rootState, rootGetters } = bridgeActionContext(context); - const externalNetwork = rootState.web3.networkSelected; - - if (!externalNetwork) return; - - const accountAddress = rootState.wallet.account.address; - const transactions = await evmBridgeApi.getUserTransactions(accountAddress, externalNetwork as EvmNetwork); - const externalHistory = {}; - - // [TODO]: update later - for (const txData of transactions) { - const tx = await evmTxDataToHistory(rootGetters.assets.assetDataByAddress, txData); - - if (tx.id) { - const inProgress = state.inProgressIds[tx.id]; - - if (!inProgress) { - externalHistory[tx.id] = tx; - - await dispatch.removeHistory({ tx, force: false }); - } - } - } - - commit.setExternalHistory(externalHistory); -} - async function updateEthLockedBalance(context: ActionContext): Promise { const { commit, getters, rootGetters, rootState } = bridgeActionContext(context); - const { address, externalAddress } = getters.asset || {}; + const { address, decimals, externalAddress } = getters.asset ?? {}; + const { networkSelected } = rootState.web3; const bridgeContractAddress = rootGetters.web3.contractAddress(KnownEthBridgeAsset.Other); - if (address && externalAddress && bridgeContractAddress) { - const assetKind = rootState.assets.registeredAssets[address]?.kind; - - if (assetKind === BridgeRequestAssetKind.Sidechain) { - const value = await ethersUtil.getAccountAssetBalance(bridgeContractAddress, externalAddress); - commit.setAssetLockedBalance(value); - return; + if (address && networkSelected && 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; + } } } @@ -295,20 +247,21 @@ async function updateEthLockedBalance(context: ActionContext): Promise async function updateBridgeProxyLockedBalance(context: ActionContext): Promise { const { commit, getters, rootState } = bridgeActionContext(context); - const { address } = getters.asset || {}; - const { networkSelected, networkType } = rootState.web3; + const { address, decimals } = getters.asset ?? {}; + const { networkSelected } = rootState.web3; - if (address && networkSelected && networkType) { - const bridgeApi = getBridgeApi(context) as typeof evmBridgeApi | typeof subBridgeApi; - const data = await bridgeApi.getLockedAssets(networkSelected as never, address); - const balance = data.toString(); + if (address && networkSelected) { + const bridgeApi = getBridgeApi(context); + const value = await bridgeApi.getLockedAssets(networkSelected as never, address); + const balance = FPNumber.fromCodecValue(value, decimals); commit.setAssetLockedBalance(balance); + return; } commit.setAssetLockedBalance(); } -async function getExternalTransferFee(context: ActionContext): Promise { +async function updateExternalTransferFee(context: ActionContext): Promise { const { commit, getters, state, rootState } = bridgeActionContext(context); let fee = ZeroStringValue; @@ -324,6 +277,96 @@ async function getExternalTransferFee(context: ActionContext): Promise commit.setExternalTransferFee(fee); } +function calculateMaxLimit( + limitAsset: string, + referenceAsset: string, + usdLimit: CodecString, + quote: SwapQuote +): FPNumber { + const outgoingLimitUSD = FPNumber.fromCodecValue(usdLimit); + + if (outgoingLimitUSD.isZero() || limitAsset === referenceAsset) return outgoingLimitUSD; + + try { + const { + result: { amount }, + } = quote(limitAsset, referenceAsset, 1, false, [], false); + + const assetPriceUSD = FPNumber.fromCodecValue(amount); + + if (!assetPriceUSD.isFinity() || assetPriceUSD.isZero()) return FPNumber.ZERO; + + return outgoingLimitUSD.div(assetPriceUSD); + } catch (error) { + console.error(error); + return FPNumber.ZERO; + } +} + +async function updateExternalBlockNumber(context: ActionContext): Promise { + const { getters, commit } = bridgeActionContext(context); + try { + const blockNumber = getters.isSubBridge + ? await subBridgeConnector.networkAdapter.getBlockNumber() + : await (await ethersUtil.getEthersInstance()).getBlockNumber(); + + commit.setExternalBlockNumber(blockNumber); + } catch (error) { + console.error(error); + commit.setExternalBlockNumber(0); + } +} + +async function updateFeesAndLockedFunds(context: ActionContext, withSora = false): Promise { + const { commit } = bridgeActionContext(context); + + commit.setFeesAndLockedFundsFetching(true); + + const promises = [ + updateExternalLockedBalance(context), + updateExternalNetworkFee(context), + updateExternalTransferFee(context), + ]; + + if (withSora) { + promises.push(updateSoraNetworkFee(context)); + } + + await Promise.allSettled(promises); + + commit.setFeesAndLockedFundsFetching(false); +} + +async function updateSoraNetworkFee(context: ActionContext): Promise { + const { commit, state, getters, rootState } = bridgeActionContext(context); + const { asset, operation } = getters; + const { + web3: { networkSelected }, + wallet: { + settings: { networkFees }, + }, + } = rootState; + + let fee = ZeroStringValue; + + if (networkSelected && asset && state.isSoraToEvm) { + if (getters.isEthBridge) { + fee = networkFees[operation]; + } else { + const bridgeApi = getBridgeApi(context) as typeof subBridgeApi | typeof evmBridgeApi; + fee = await bridgeApi.getNetworkFee(asset, networkSelected as never); + } + } + + commit.setSoraNetworkFee(fee); +} + +async function updateBalancesAndFees(context: ActionContext, withSora = false): Promise { + const { dispatch } = bridgeActionContext(context); + + await Promise.allSettled([dispatch.updateExternalBalance(), updateFeesAndLockedFunds(context, withSora)]); +} + const actions = defineActions({ setSendedAmount(context, value?: string) { const { commit, state, getters } = bridgeActionContext(context); @@ -361,14 +404,10 @@ const actions = defineActions({ } }, - async updateBalancesAndFees(context): Promise { + async resetBridgeForm(context): Promise { const { dispatch } = bridgeActionContext(context); - await Promise.all([ - dispatch.updateExternalBalance(), - dispatch.updateExternalLockedBalance(), - dispatch.updateExternalFees(), - ]); + await Promise.allSettled([dispatch.setAssetAddress(), dispatch.setSendedAmount()]); }, async switchDirection(context): Promise { @@ -378,7 +417,7 @@ const actions = defineActions({ commit.setAssetSenderBalance(); commit.setAssetRecipientBalance(); - await dispatch.updateBalancesAndFees(); + await updateBalancesAndFees(context, true); if (state.focusedField === FocusedField.Received) { await dispatch.setSendedAmount(state.amountReceived); @@ -394,23 +433,17 @@ const actions = defineActions({ commit.setAssetSenderBalance(); commit.setAssetRecipientBalance(); - await dispatch.updateBalancesAndFees(); - }, - - async updateExternalFees(context): Promise { - const { commit } = bridgeActionContext(context); - - commit.setExternalNetworkFeeFetching(true); - - await Promise.all([getExternalNetworkFee(context), getExternalTransferFee(context)]); - - commit.setExternalNetworkFeeFetching(false); + await Promise.allSettled([ + dispatch.updateOutgoingMaxLimit(), + dispatch.updateIncomingMinLimit(), + updateBalancesAndFees(context, true), + ]); }, async updateExternalBalance(context): Promise { const { commit, getters } = bridgeActionContext(context); - commit.setExternalBalancesFetching(true); + commit.setBalancesFetching(true); if (getters.isSubBridge) { await updateSubBalances(context); @@ -418,42 +451,78 @@ const actions = defineActions({ await updateEvmBalances(context); } - commit.setExternalBalancesFetching(false); + commit.setBalancesFetching(false); }, - async updateExternalLockedBalance(context): Promise { + async updateIncomingMinLimit(context): Promise { const { commit, getters } = bridgeActionContext(context); - commit.setAssetLockedBalanceFetching(true); - - if (getters.isEthBridge) { - await updateEthLockedBalance(context); - } else { - await updateBridgeProxyLockedBalance(context); + let minLimit = FPNumber.ZERO; + + if (getters.isSubBridge && getters.asset && getters.isRegisteredAsset) { + try { + const value = await subBridgeApi.soraParachainApi.getAssetMinimumAmount( + getters.asset.address, + subBridgeConnector.parachainAdapter.api + ); + minLimit = FPNumber.fromCodecValue(value, getters.asset.externalDecimals); + } catch (error) { + console.error(error); + } } - commit.setAssetLockedBalanceFetching(false); + commit.setIncomingMinLimit(minLimit); }, - async updateExternalBlockNumber(context): Promise { - const { getters, commit } = bridgeActionContext(context); + async updateOutgoingMaxLimit(context): Promise { + const { state, commit } = bridgeActionContext(context); - try { - const blockNumber = getters.isSubBridge - ? await subConnector.networkAdapter.getBlockNumber() - : await (await ethersUtil.getEthersInstance()).getBlockNumber(); + const limitAsset = state.assetAddress; - commit.setExternalBlockNumber(blockNumber); - } catch { - commit.setExternalBlockNumber(0); - } + commit.resetOutgoingMaxLimitSubscription(); + + if (!limitAsset) return; + + const hasOutgoingLimit = await api.bridgeProxy.isAssetTransferLimited(limitAsset); + + if (!hasOutgoingLimit) return; + + const referenceAsset = DAI.address; + const sources = [LiquiditySourceTypes.XYKPool, LiquiditySourceTypes.XSTPool]; + const limitObservable = api.bridgeProxy.getCurrentTransferLimitObservable(); + const quoteObservable = await api.swap.getSwapQuoteObservable(referenceAsset, limitAsset, sources, DexId.XOR); + + let subscription!: Subscription; + + await new Promise((resolve) => { + subscription = combineLatest([limitObservable, quoteObservable]).subscribe(([usdLimit, { quote }]) => { + const outgoingMaxLimit = calculateMaxLimit(limitAsset, referenceAsset, usdLimit, quote); + commit.setOutgoingMaxLimit(outgoingMaxLimit); + resolve(); + }); + }); + + commit.setOutgoingMaxLimitSubscription(subscription); + }, + + async subscribeOnBlockUpdates(context): Promise { + const { commit } = bridgeActionContext(context); + + commit.resetBlockUpdatesSubscription(); + + const subscription = api.system.updated.subscribe(() => { + updateExternalBlockNumber(context); + updateBalancesAndFees(context); + }); + + commit.setBlockUpdatesSubscription(subscription); }, async generateHistoryItem(context, playground): Promise { const { dispatch } = bridgeActionContext(context); const historyData = bridgeDataToHistoryItem(context, playground); const bridgeApi = getBridgeApi(context); - const historyItem = bridgeApi.generateHistoryItem(historyData as any); + const historyItem = bridgeApi.generateHistoryItem(historyData as never); if (!historyItem) { throw new Error('[Bridge]: "generateHistoryItem" failed'); @@ -481,18 +550,18 @@ const actions = defineActions({ if (getters.isEthBridge) { await updateEthHistory(context, clearHistory); } - if (getters.isEvmBridge) { - await updateEvmHistory(context); - } if (getters.isSubBridge) { await updateSubHistory(context, clearHistory); } + if (getters.isEvmBridge) { + console.info('Evm history not implemented'); + } commit.setHistoryLoading(false); }, removeHistory(context, { tx, force = false }: { tx: Partial; force: boolean }): void { - const { commit, dispatch, getters, state, rootState } = bridgeActionContext(context); + const { commit, dispatch, state, rootState } = bridgeActionContext(context); const { id, hash } = tx; @@ -555,7 +624,7 @@ const actions = defineActions({ async signEthBridgeOutgoingEvm(context, id: string): Promise { const { rootState, rootGetters } = bridgeActionContext(context); - const tx = ethBridgeApi.getHistory(id) as Nullable; + const tx = ethBridgeApi.getHistory(id) as Nullable; if (!tx?.hash) throw new Error('TX ID cannot be empty!'); if (!tx.amount) throw new Error('TX amount cannot be empty!'); @@ -582,11 +651,11 @@ const actions = defineActions({ const contractInstance = new ethers.Contract(contractAddress, contract.abi, signer); const method = isValOrXor ? 'mintTokensByPeers' - : request.currencyType === BridgeCurrencyType.TokenAddress + : request.currencyType === EthCurrencyType.TokenAddress ? 'receiveByEthereumAssetAddress' : 'receiveBySidechainAssetId'; const methodArgs: Array = [ - isValOrXor || request.currencyType === BridgeCurrencyType.TokenAddress + isValOrXor || request.currencyType === EthCurrencyType.TokenAddress ? asset.externalAddress // address tokenAddress OR : asset.address, // bytes32 assetId new FPNumber(tx.amount, asset.externalDecimals).toCodecString(), // uint256 amount diff --git a/src/store/bridge/getters.ts b/src/store/bridge/getters.ts index 7d04cb598..4bf8c4fab 100644 --- a/src/store/bridge/getters.ts +++ b/src/store/bridge/getters.ts @@ -4,6 +4,7 @@ import { defineGetters } from 'direct-vuex'; import { ZeroStringValue } from '@/consts'; import { bridgeGetterContext } from '@/store/bridge'; +import { formatSubAddress } from '@/utils/bridge/sub/utils'; import type { BridgeState } from './types'; import type { IBridgeTransaction, CodecString } from '@sora-substrate/util'; @@ -59,26 +60,56 @@ const getters = defineGetters()({ return !!asset?.externalAddress; }, + externalAccount(...args): string { + const { getters, rootState } = bridgeGetterContext(args); + const { evmAddress, subAddress } = rootState.web3; + + if (getters.isSubBridge) { + return subAddress; + } else { + return evmAddress; + } + }, + + externalAccountFormatted(...args): string { + const { getters, state, rootState } = bridgeGetterContext(args); + const { subSS58 } = rootState.web3; + + if (getters.isSubBridge && state.isSoraToEvm && getters.externalAccount) { + return formatSubAddress(getters.externalAccount, subSS58); + } else { + return getters.externalAccount; + } + }, + sender(...args): string { const { state, rootState, getters } = bridgeGetterContext(args); + const { address: soraAddress } = rootState.wallet.account; + const { evmAddress, subSS58 } = rootState.web3; - if (getters.isSubBridge) return rootState.wallet.account.address; + if (getters.isSubBridge) { + return !state.isSoraToEvm && soraAddress ? formatSubAddress(soraAddress, subSS58) : soraAddress; + } - return state.isSoraToEvm ? rootState.wallet.account.address : rootState.web3.evmAddress; + return state.isSoraToEvm ? soraAddress : evmAddress; }, recipient(...args): string { const { state, rootState, getters } = bridgeGetterContext(args); + const { address: soraAddress } = rootState.wallet.account; + const { evmAddress, subAddress, subSS58 } = rootState.web3; - if (getters.isSubBridge) return rootState.web3.subAddress; + if (getters.isSubBridge) { + return state.isSoraToEvm && subAddress ? formatSubAddress(subAddress, subSS58) : subAddress; + } - return state.isSoraToEvm ? rootState.web3.evmAddress : rootState.wallet.account.address; + return state.isSoraToEvm ? evmAddress : soraAddress; }, isEthBridge(...args): boolean { const { rootState } = bridgeGetterContext(args); - return rootState.web3.networkType === BridgeNetworkType.EvmLegacy; + return rootState.web3.networkType === BridgeNetworkType.Eth; }, isEvmBridge(...args): boolean { const { rootState } = bridgeGetterContext(args); @@ -100,10 +131,6 @@ const getters = defineGetters()({ return state.isSoraToEvm ? Operation.SubstrateOutgoing : Operation.SubstrateIncoming; } }, - soraNetworkFee(...args): CodecString { - const { getters, rootState } = bridgeGetterContext(args); - return rootState.wallet.settings.networkFees[getters.operation] ?? ZeroStringValue; - }, externalNetworkFee(...args): CodecString { const { state, getters } = bridgeGetterContext(args); diff --git a/src/store/bridge/mutations.ts b/src/store/bridge/mutations.ts index 7458d9bf7..8ef9f2a9e 100644 --- a/src/store/bridge/mutations.ts +++ b/src/store/bridge/mutations.ts @@ -2,7 +2,8 @@ import { defineMutations } from 'direct-vuex'; import omit from 'lodash/fp/omit'; import type { BridgeState, FocusedField } from './types'; -import type { IBridgeTransaction, CodecString } from '@sora-substrate/util'; +import type { FPNumber, IBridgeTransaction, CodecString } from '@sora-substrate/util'; +import type { Subscription } from 'rxjs'; const mutations = defineMutations()({ setSoraToEvm(state, isSoraToEvm: boolean): void { @@ -21,18 +22,39 @@ const mutations = defineMutations()({ state.assetRecipientBalance = balance; }, - setAssetLockedBalance(state, balance: Nullable = null): void { + setAssetLockedBalance(state, balance: Nullable = null): void { state.assetLockedBalance = balance; }, - setAssetLockedBalanceFetching(state, flag: boolean): void { - state.assetLockedBalanceFetching = flag; - }, setExternalBalance(state, balance: Nullable = null): void { state.externalNativeBalance = balance; }, - setExternalBalancesFetching(state, flag: boolean): void { - state.externalBalancesFetching = flag; + + setIncomingMinLimit(state, amount: FPNumber): void { + state.incomingMinLimit = amount; + }, + + setOutgoingMaxLimit(state, amount: Nullable): void { + state.outgoingMaxLimit = amount; + }, + + setOutgoingMaxLimitSubscription(state, subscription: Subscription): void { + state.outgoingMaxLimitSubscription = subscription; + }, + + resetOutgoingMaxLimitSubscription(state): void { + state.outgoingMaxLimitSubscription?.unsubscribe(); + state.outgoingMaxLimitSubscription = null; + state.outgoingMaxLimit = null; + }, + + setBlockUpdatesSubscription(state, subscription: Subscription): void { + state.blockUpdatesSubscription = subscription; + }, + + resetBlockUpdatesSubscription(state): void { + state.blockUpdatesSubscription?.unsubscribe(); + state.blockUpdatesSubscription = null; }, setAmountSend(state, value?: string): void { @@ -47,8 +69,12 @@ const mutations = defineMutations()({ state.focusedField = field; }, - setExternalNetworkFeeFetching(state, flag: boolean): void { - state.externalNetworkFeeFetching = flag; + setBalancesFetching(state, flag: boolean): void { + state.balancesFetching = flag; + }, + + setFeesAndLockedFundsFetching(state, flag: boolean): void { + state.feesAndLockedFundsFetching = flag; }, setExternalNetworkFee(state, fee: CodecString): void { @@ -59,6 +85,10 @@ const mutations = defineMutations()({ state.externalTransferFee = fee; }, + setSoraNetworkFee(state, fee: CodecString) { + state.soraNetworkFee = fee; + }, + /** * Set bridge transactions from localstorage (ethBridgeApi or evmBridgeApi) */ diff --git a/src/store/bridge/state.ts b/src/store/bridge/state.ts index f6c0074f4..6bf0fbf09 100644 --- a/src/store/bridge/state.ts +++ b/src/store/bridge/state.ts @@ -1,3 +1,5 @@ +import { FPNumber } from '@sora-substrate/util'; + import { ZeroStringValue } from '@/consts'; import type { BridgeState } from './types'; @@ -9,15 +11,19 @@ function initialState(): BridgeState { assetSenderBalance: null, // balance for sora assetRecipientBalance: null, // balance for bridge network assetLockedBalance: null, // asset balance locked on bridge - assetLockedBalanceFetching: false, + incomingMinLimit: FPNumber.ZERO, // incoming min limit in asset amount + outgoingMaxLimit: null, // outgoing max limit in asset amount + outgoingMaxLimitSubscription: null, + blockUpdatesSubscription: null, amountSend: '', amountReceived: '', focusedField: null, + soraNetworkFee: ZeroStringValue, externalTransferFee: ZeroStringValue, // fee for transfer between networks (xcm message fee for substrate network) externalNetworkFee: ZeroStringValue, // fee for transaction execution - externalNetworkFeeFetching: false, + balancesFetching: false, + feesAndLockedFundsFetching: false, externalNativeBalance: ZeroStringValue, // balance for external native token (like ETH) - externalBalancesFetching: false, externalBlockNumber: 0, // history sources historyInternal: {}, // localstorage history diff --git a/src/store/bridge/types.ts b/src/store/bridge/types.ts index 2ba335fde..1a6ce8c83 100644 --- a/src/store/bridge/types.ts +++ b/src/store/bridge/types.ts @@ -1,4 +1,5 @@ -import type { CodecString, IBridgeTransaction } from '@sora-substrate/util'; +import type { FPNumber, CodecString, IBridgeTransaction } from '@sora-substrate/util'; +import type { Subscription } from 'rxjs'; export enum FocusedField { Sended = 'Sended', @@ -10,16 +11,20 @@ export type BridgeState = { assetAddress: string; assetSenderBalance: Nullable; assetRecipientBalance: Nullable; - assetLockedBalance: Nullable; - assetLockedBalanceFetching: boolean; + assetLockedBalance: Nullable; + incomingMinLimit: FPNumber; + outgoingMaxLimit: Nullable; + outgoingMaxLimitSubscription: Nullable; + blockUpdatesSubscription: Nullable; amountSend: string; amountReceived: string; focusedField: Nullable; + soraNetworkFee: CodecString; externalTransferFee: CodecString; externalNetworkFee: CodecString; - externalNetworkFeeFetching: boolean; + balancesFetching: boolean; + feesAndLockedFundsFetching: boolean; externalNativeBalance: Nullable; - externalBalancesFetching: boolean; externalBlockNumber: number; // history sources (unsynced localstorage & network) historyInternal: Record; diff --git a/src/store/moonpay/actions.ts b/src/store/moonpay/actions.ts index 899c27973..c99b4b9a1 100644 --- a/src/store/moonpay/actions.ts +++ b/src/store/moonpay/actions.ts @@ -93,10 +93,8 @@ const actions = defineActions({ if (!decodedInput) throw new Error(`Unable to parse transaction data: "${tx.data}"`); const address = tx.to ?? ''; // asset address - const { - value, // BigNumber - to = '', // ethereum address - } = decodedInput.args; + const value = decodedInput.args.getValue('value'); // BigNumber + const to = decodedInput.args.getValue('to'); // ethereum address const amount = new FPNumber(value).toString(); // transferred amount return { diff --git a/src/store/moonpay/types.ts b/src/store/moonpay/types.ts index 6c28fa6ac..e1d615ff1 100644 --- a/src/store/moonpay/types.ts +++ b/src/store/moonpay/types.ts @@ -1,7 +1,7 @@ import type { MoonpayNotifications } from '@/components/pages/Moonpay/consts'; import type { MoonpayApi, MoonpayCurrency, MoonpayTransaction } from '@/utils/moonpay'; -import type { BridgeHistory } from '@sora-substrate/util'; +import type { EthHistory } from '@sora-substrate/util/build/bridgeProxy/eth/types'; export type MoonpayState = { api: MoonpayApi; @@ -12,12 +12,12 @@ export type MoonpayState = { pollingTimestamp: number; transactions: Array; transactionsFetching: boolean; - bridgeTransactionData: Nullable; + bridgeTransactionData: Nullable; startBridgeButtonVisibility: boolean; currencies: Array; }; export type BridgeTxData = Partial<{ - data: Nullable; + data: Nullable; startBridgeButtonVisibility: boolean; }>; diff --git a/src/store/web3/actions.ts b/src/store/web3/actions.ts index e905bed96..483881886 100644 --- a/src/store/web3/actions.ts +++ b/src/store/web3/actions.ts @@ -6,83 +6,60 @@ import { ethers } from 'ethers'; import { KnownEthBridgeAsset, SmartContracts, SmartContractType } from '@/consts/evm'; import { web3ActionContext } from '@/store/web3'; -import { subConnector } from '@/utils/bridge/sub/classes/adapter'; +import { SubNetworksConnector, subBridgeConnector } from '@/utils/bridge/sub/classes/adapter'; import ethersUtil from '@/utils/ethers-util'; -import type { Provider } from '@/utils/ethers-util'; import type { SubNetworkApps } from './types'; import type { SubNetwork } from '@sora-substrate/util/build/bridgeProxy/sub/consts'; import type { ActionContext } from 'vuex'; -async function connectEvmNetwork(context: ActionContext, networkHex?: string): Promise { - const { commit } = web3ActionContext(context); - const evmNetwork = networkHex ? ethersUtil.hexToNumber(networkHex) : await ethersUtil.getEvmNetworkId(); - commit.setProvidedEvmNetwork(evmNetwork); -} - async function connectSubNetwork(context: ActionContext): Promise { - const { getters } = web3ActionContext(context); + const { getters, commit } = web3ActionContext(context); const subNetwork = getters.selectedNetwork; if (!subNetwork) return; - await subConnector.open(subNetwork.id as SubNetwork); + await subBridgeConnector.open(subNetwork.id as SubNetwork); + + const ss58 = subBridgeConnector.networkAdapter.api.registry.chainSS58; + + if (ss58) commit.setSubSS58(ss58); } const actions = defineActions({ - async connectEvmAccount(context, provider: Provider): Promise { + async updateProvidedEvmNetwork(context, networkHex?: string): Promise { const { commit } = web3ActionContext(context); - const address = await ethersUtil.onConnect({ provider }); - commit.setEvmAddress(address); + const evmNetwork = networkHex ? ethersUtil.hexToNumber(networkHex) : await ethersUtil.getEvmNetworkId(); + commit.setProvidedEvmNetwork(evmNetwork); }, - async connectSubAccount(context, address: string): Promise { - const { commit, rootDispatch } = web3ActionContext(context); - commit.setSubAddress(address); - - await rootDispatch.bridge.updateExternalBalance(); + async disconnectExternalNetwork(context): Promise { + await subBridgeConnector.stop(); }, - async connectExternalNetwork(context, network?: string): Promise { - const { dispatch, state, rootDispatch } = web3ActionContext(context); + async selectExternalNetwork(context, { id, type }: { id: BridgeNetworkId; type: BridgeNetworkType }): Promise { + const { commit, dispatch, rootDispatch } = web3ActionContext(context); - await dispatch.disconnectExternalNetwork(); + dispatch.disconnectExternalNetwork(); - if (state.networkType === BridgeNetworkType.Sub) { - await connectSubNetwork(context); - } else { - await connectEvmNetwork(context, network); - } + commit.setNetworkType(type); + commit.setSelectedNetwork(id); - await Promise.all([rootDispatch.assets.updateRegisteredAssets(), rootDispatch.bridge.updateBalancesAndFees()]); - }, + rootDispatch.assets.updateRegisteredAssets(); - async disconnectExternalNetwork(context): Promise { - const { commit } = web3ActionContext(context); - - await subConnector.stop(); - - commit.resetProvidedEvmNetwork(); - }, - - async selectExternalNetwork(context, network: BridgeNetworkId): Promise { - const { commit, dispatch } = web3ActionContext(context); - commit.setSelectedNetwork(network); - await dispatch.updateNetworkProvided(); + if (type === BridgeNetworkType.Sub) { + await connectSubNetwork(context); + } }, - async updateNetworkProvided(context): Promise { - const { dispatch, getters, state } = web3ActionContext(context); + async changeEvmNetworkProvided(context): Promise { + const { getters, state } = web3ActionContext(context); const { selectedNetwork } = getters; const { networkType } = state; - if (!selectedNetwork) return; - - if (networkType !== BridgeNetworkType.Sub) { + if (selectedNetwork && networkType !== BridgeNetworkType.Sub) { await ethersUtil.switchOrAddChain(selectedNetwork); } - - await dispatch.connectExternalNetwork(); }, async getSupportedApps(context): Promise { @@ -95,15 +72,15 @@ const actions = defineActions({ const { commit } = web3ActionContext(context); // update apps in store commit.setSubNetworkApps(apps); - // update endpoints in subConnector - subConnector.endpoints = apps; + // update endpoints in SubNetworksConnector class + SubNetworksConnector.endpoints = apps; }, /** - * Restore selected by user network & network type (EVMLegacy, EVM, Sub) + * Restore selected by user network & network type (Eth, EVM, Sub) */ async restoreSelectedNetwork(context): Promise { - const { commit, state, getters } = web3ActionContext(context); + const { dispatch, state, getters } = web3ActionContext(context); const [type, id] = [ethersUtil.getSelectedBridgeType(), ethersUtil.getSelectedNetwork()]; @@ -111,14 +88,15 @@ const actions = defineActions({ const networkData = getters.availableNetworks[type]?.[id]; if (!!networkData && !networkData.disabled) { - commit.setNetworkType(type); - commit.setSelectedNetwork(id); + await dispatch.selectExternalNetwork({ id, type }); return; } } - commit.setNetworkType(BridgeNetworkType.EvmLegacy); - commit.setSelectedNetwork(state.ethBridgeEvmNetwork); + await dispatch.selectExternalNetwork({ + id: state.ethBridgeEvmNetwork, + type: BridgeNetworkType.Eth, + }); }, async getEvmTokenAddressByAssetId(context, soraAssetId: string): Promise { diff --git a/src/store/web3/getters.ts b/src/store/web3/getters.ts index b57d16250..2061ad99b 100644 --- a/src/store/web3/getters.ts +++ b/src/store/web3/getters.ts @@ -13,16 +13,6 @@ import type { Web3State, AvailableNetwork } from './types'; import type { BridgeNetworkId } from '@sora-substrate/util/build/bridgeProxy/types'; const getters = defineGetters()({ - externalAccount(...args): string { - const { state } = web3GetterContext(args); - - if (state.networkType === BridgeNetworkType.Sub) { - return state.subAddress; - } else { - return state.evmAddress; - } - }, - availableNetworks(...args): Record>> { const { state } = web3GetterContext(args); @@ -75,7 +65,7 @@ const getters = defineGetters()({ }, {}); return { - [BridgeNetworkType.EvmLegacy]: hashi, + [BridgeNetworkType.Eth]: hashi, [BridgeNetworkType.Evm]: evm, [BridgeNetworkType.Sub]: sub, }; diff --git a/src/store/web3/mutations.ts b/src/store/web3/mutations.ts index 660838a75..30b7113f0 100644 --- a/src/store/web3/mutations.ts +++ b/src/store/web3/mutations.ts @@ -22,6 +22,10 @@ const mutations = defineMutations()({ state.subAddress = address; }, + setSubSS58(state, prefix: number) { + state.subSS58 = prefix; + }, + setEvmNetworksApp(state, networksIds: EvmNetwork[]): void { state.evmNetworkApps = networksIds; }, diff --git a/src/store/web3/state.ts b/src/store/web3/state.ts index febd3e895..7ff579007 100644 --- a/src/store/web3/state.ts +++ b/src/store/web3/state.ts @@ -1,15 +1,13 @@ import { BridgeNetworkType } from '@sora-substrate/util/build/bridgeProxy/consts'; import { EvmNetworkId } from '@sora-substrate/util/build/bridgeProxy/evm/consts'; -import { ZeroStringValue } from '@/consts'; -import ethersUtil from '@/utils/ethers-util'; - import type { Web3State } from './types'; export function initialState(): Web3State { return { evmAddress: '', // external evm address subAddress: '', // external sub address + subSS58: 69, // external sub network ss58 prefix (sora by default) networkType: null, // network type for selected network networkSelected: null, // network selected by user @@ -19,7 +17,7 @@ export function initialState(): Web3State { subNetworkApps: {}, // sub netowrks from app config supportedApps: { - [BridgeNetworkType.EvmLegacy]: {}, + [BridgeNetworkType.Eth]: {}, [BridgeNetworkType.Evm]: {}, [BridgeNetworkType.Sub]: [], }, // supported apps from chain diff --git a/src/store/web3/types.ts b/src/store/web3/types.ts index 1d3681a06..d43f74076 100644 --- a/src/store/web3/types.ts +++ b/src/store/web3/types.ts @@ -29,6 +29,7 @@ export type AvailableNetwork = { export type Web3State = { evmAddress: string; subAddress: string; + subSS58: number; networkType: Nullable; networkSelected: Nullable; diff --git a/src/utils/bridge/common/utils.ts b/src/utils/bridge/common/utils.ts index 7351fa98d..3e073f486 100644 --- a/src/utils/bridge/common/utils.ts +++ b/src/utils/bridge/common/utils.ts @@ -1,4 +1,4 @@ -import { Operation, isBridgeOperation, isEvmOperation, isSubstrateOperation } from '@sora-substrate/util'; +import { Operation, isEthOperation, isEvmOperation, isSubstrateOperation } from '@sora-substrate/util'; import { api as soraApi } from '@soramitsu/soraneo-wallet-web'; import { ethers } from 'ethers'; @@ -8,7 +8,8 @@ import { isUnsignedTx as isUnsignedSubTx } from '@/utils/bridge/sub/utils'; import ethersUtil from '@/utils/ethers-util'; import type { ApiPromise } from '@polkadot/api'; -import type { IBridgeTransaction, BridgeHistory } from '@sora-substrate/util'; +import type { IBridgeTransaction } from '@sora-substrate/util'; +import type { EthHistory } from '@sora-substrate/util/build/bridgeProxy/eth/types'; import type { EvmHistory } from '@sora-substrate/util/build/bridgeProxy/evm/types'; import type { SubHistory } from '@sora-substrate/util/build/bridgeProxy/sub/types'; @@ -64,39 +65,26 @@ export const getEvmTransactionRecieptByHash = async ( } }; +export const getBlockEventsByTxIndex = async (blockHash: string, index: number, api: ApiPromise) => { + const blockEvents = await soraApi.system.getBlockEvents(blockHash, api); + const transactionEvents = blockEvents.filter( + ({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.toNumber() === index + ); + + return transactionEvents; +}; + export const getTransactionEvents = async (blockHash: string, transactionHash: string, api: ApiPromise) => { const extrinsics = await soraApi.system.getExtrinsicsFromBlock(blockHash, api); const extrinsicIndex = extrinsics.findIndex((ext) => ext.hash.toString() === transactionHash); if (extrinsicIndex === -1) throw new Error(`Unable to find extrinsic "${transactionHash}" in block "${blockHash}"`); - const blockEvents = await soraApi.system.getBlockEvents(blockHash, api); - const transactionEvents = blockEvents.filter( - ({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.toNumber() === extrinsicIndex - ); + const transactionEvents = await getBlockEventsByTxIndex(blockHash, extrinsicIndex, api); return transactionEvents; }; -export const findEventInBlock = async ({ - api, - blockId, - section, - method, -}: { - api: ApiPromise; - blockId: string; - section: string; - method: string; -}) => { - const blockEvents = await soraApi.system.getBlockEvents(blockId, api); - const event = blockEvents.find(({ event }) => event.section === section && event.method === method); - - if (!event) throw new Error('Event not found'); - - return event.event.data; -}; - export const isOutgoingTransaction = (transaction: Nullable): boolean => { if (!transaction?.type) return false; @@ -106,7 +94,7 @@ export const isOutgoingTransaction = (transaction: Nullable) export const isUnsignedTx = (transaction: Nullable): boolean => { if (!transaction?.type) return true; - if (isBridgeOperation(transaction.type)) return isUnsignedEthTx(transaction as BridgeHistory); + if (isEthOperation(transaction.type)) return isUnsignedEthTx(transaction as EthHistory); if (isEvmOperation(transaction.type)) return isUnsignedEvmTx(transaction as EvmHistory); if (isSubstrateOperation(transaction.type)) return isUnsignedSubTx(transaction as SubHistory); diff --git a/src/utils/bridge/eth/api.ts b/src/utils/bridge/eth/api.ts index ab5dd794d..366271557 100644 --- a/src/utils/bridge/eth/api.ts +++ b/src/utils/bridge/eth/api.ts @@ -1,3 +1,3 @@ import { api } from '@soramitsu/soraneo-wallet-web'; -export const ethBridgeApi = api.bridge; +export const ethBridgeApi = api.bridgeProxy.eth; diff --git a/src/utils/bridge/eth/classes/history.ts b/src/utils/bridge/eth/classes/history.ts index 5a534c801..242c570b9 100644 --- a/src/utils/bridge/eth/classes/history.ts +++ b/src/utils/bridge/eth/classes/history.ts @@ -1,5 +1,5 @@ -import { BridgeTxStatus, Operation } from '@sora-substrate/util'; -import { BridgeNetworkType } from '@sora-substrate/util/build/bridgeProxy/consts'; +import { Operation } from '@sora-substrate/util'; +import { BridgeNetworkType, BridgeTxStatus } from '@sora-substrate/util/build/bridgeProxy/consts'; import { api, historyElementsFilter, @@ -19,8 +19,9 @@ import { getEvmTransactionRecieptByHash, isOutgoingTransaction } from '@/utils/b import { ethBridgeApi } from '@/utils/bridge/eth/api'; import ethersUtil from '@/utils/ethers-util'; -import type { BridgeHistory, NetworkFeesObject } from '@sora-substrate/util'; +import type { NetworkFeesObject } from '@sora-substrate/util'; import type { RegisteredAccountAsset } from '@sora-substrate/util/build/assets/types'; +import type { EthHistory } from '@sora-substrate/util/build/bridgeProxy/eth/types'; import type { ActionContext } from 'vuex'; export default class EtherscanHistoryProvider extends EtherscanProvider { @@ -44,7 +45,7 @@ const BRIDGE_INTERFACE = new ethers.Interface([ const { ETH_BRIDGE_STATES } = WALLET_CONSTS; -const isLocalHistoryItem = (item: BridgeHistory, txId: string, isOutgoing: boolean, requestHash: string) => { +const isLocalHistoryItem = (item: EthHistory, txId: string, isOutgoing: boolean, requestHash: string) => { if (item.txId === txId) return true; return isOutgoing ? item.hash === requestHash : item.externalHash === requestHash; @@ -92,7 +93,7 @@ const getTransactionState = (isOutgoing: boolean, soraPartCompleted: boolean, ex } }; -const hasFinishedState = (item: Nullable) => { +const hasFinishedState = (item: Nullable) => { if (!item) return false; const isOutgoing = isOutgoingTransaction(item); @@ -232,12 +233,14 @@ export class EthBridgeHistory { for (const tx of Object.values(transactions)) { try { - const decodedInput = BRIDGE_INTERFACE.parseTransaction(tx); + const data = (tx as any).input; // 'data' is named as 'input' + const decodedInput = BRIDGE_INTERFACE.parseTransaction({ data }); - if (decodedInput?.args.txHash.toLowerCase() === hash.toLowerCase()) { + if (decodedInput?.args.getValue('txHash').toLowerCase() === hash.toLowerCase()) { return tx; } } catch (err) { + console.info(err); continue; } } @@ -294,7 +297,7 @@ export class EthBridgeHistory { if (!historyElements.length) return; - const currentHistory = ethBridgeApi.historyList as BridgeHistory[]; + const currentHistory = ethBridgeApi.historyList as EthHistory[]; const { externalNetwork } = this; @@ -307,7 +310,7 @@ export class EthBridgeHistory { const { id: txId, blockHash: blockId, blockHeight, data: historyElementData } = historyElement; const { requestHash, amount, assetId: assetAddress, sidechainAddress } = historyElementData as HistoryElementData; - const localHistoryItem = currentHistory.find((item: BridgeHistory) => + const localHistoryItem = currentHistory.find((item: EthHistory) => isLocalHistoryItem(item, txId, isOutgoing, requestHash) ); @@ -354,16 +357,16 @@ export class EthBridgeHistory { externalBlockId, externalBlockHeight, externalNetwork, - externalNetworkType: BridgeNetworkType.EvmLegacy, + externalNetworkType: BridgeNetworkType.Eth, externalNetworkFee, to, }; // update or create local history item if (localHistoryItem) { - ethBridgeApi.saveHistory({ ...localHistoryItem, ...historyItemData } as BridgeHistory); + ethBridgeApi.saveHistory({ ...localHistoryItem, ...historyItemData } as EthHistory); } else { - ethBridgeApi.generateHistoryItem(historyItemData as BridgeHistory); + ethBridgeApi.generateHistoryItem(historyItemData as EthHistory); } await updateCallback?.(); @@ -395,7 +398,7 @@ export const updateEthBridgeHistory = bridge: { inProgressIds }, } = rootState; - const networkData = rootGetters.web3.availableNetworks[BridgeNetworkType.EvmLegacy][ethBridgeEvmNetwork]; + const networkData = rootGetters.web3.availableNetworks[BridgeNetworkType.Eth][ethBridgeEvmNetwork]; if (!networkData) { throw new Error( diff --git a/src/utils/bridge/eth/classes/reducers.ts b/src/utils/bridge/eth/classes/reducers.ts index dcc9454ec..935a0565c 100644 --- a/src/utils/bridge/eth/classes/reducers.ts +++ b/src/utils/bridge/eth/classes/reducers.ts @@ -1,20 +1,20 @@ -import { api, SUBQUERY_TYPES, WALLET_CONSTS } from '@soramitsu/soraneo-wallet-web'; -import { ethers } from 'ethers'; +import { SUBQUERY_TYPES, WALLET_CONSTS } from '@soramitsu/soraneo-wallet-web'; import first from 'lodash/fp/first'; import { BridgeReducer } from '@/utils/bridge/common/classes'; import type { IBridgeReducerOptions, GetBridgeHistoryInstance, SignExternal } from '@/utils/bridge/common/types'; import { getEvmTransactionRecieptByHash, - findEventInBlock, + getTransactionEvents, waitForEvmTransactionMined, } from '@/utils/bridge/common/utils'; import { ethBridgeApi } from '@/utils/bridge/eth/api'; import type { EthBridgeHistory } from '@/utils/bridge/eth/classes/history'; import { getTransaction, waitForApprovedRequest, waitForIncomingRequest } from '@/utils/bridge/eth/utils'; -import type { BridgeHistory, IBridgeTransaction } from '@sora-substrate/util'; +import type { IBridgeTransaction } from '@sora-substrate/util'; import type { RegisteredAccountAsset } from '@sora-substrate/util/build/assets/types'; +import type { EthHistory } from '@sora-substrate/util/build/bridgeProxy/eth/types'; const { ETH_BRIDGE_STATES } = WALLET_CONSTS; @@ -24,12 +24,12 @@ type EthBridgeReducerOptions = IBridgeReducerOptio signExternalIncoming: SignExternal; }; -export class EthBridgeReducer extends BridgeReducer { +export class EthBridgeReducer extends BridgeReducer { protected readonly getBridgeHistoryInstance!: GetBridgeHistoryInstance; protected readonly signExternalOutgoing!: SignExternal; protected readonly signExternalIncoming!: SignExternal; - constructor(options: EthBridgeReducerOptions) { + constructor(options: EthBridgeReducerOptions) { super(options); this.getBridgeHistoryInstance = options.getBridgeHistoryInstance; @@ -53,7 +53,7 @@ export class EthBridgeReducer extends BridgeReducer { ); } - // In BridgeHistory 'blockHeight' will store evm block number + // In EthHistory 'blockHeight' will store evm block number this.updateTransactionParams(id, { externalNetworkFee: fee, externalBlockHeight: blockNumber, @@ -97,7 +97,7 @@ export class EthBridgeReducer extends BridgeReducer { } export class EthBridgeOutgoingReducer extends EthBridgeReducer { - async changeState(transaction: BridgeHistory): Promise { + async changeState(transaction: EthHistory): Promise { if (!transaction.id) throw new Error('[Bridge]: TX ID cannot be empty'); switch (transaction.transactionState) { @@ -122,7 +122,7 @@ export class EthBridgeOutgoingReducer extends EthBridgeReducer { if (!tx.txId) { await this.beforeSign(id); const asset = this.getAssetByAddress(tx.assetAddress as string) as RegisteredAccountAsset; - await ethBridgeApi.transferToEth(asset, tx.to as string, tx.amount as string, id); + await ethBridgeApi.transfer(asset, tx.to as string, tx.amount as string, id); } // signed sora transaction has to be parsed by subquery @@ -153,18 +153,17 @@ export class EthBridgeOutgoingReducer extends EthBridgeReducer { await this.waitForTransactionStatus(id); await this.waitForTransactionBlockId(id); - const { blockId } = this.getTransaction(id); + const { blockId, txId, hash: soraHash } = this.getTransaction(id); - const eventData = await findEventInBlock({ - api: api.api, - blockId: blockId as string, - section: 'ethBridge', - method: 'RequestRegistered', - }); + if (!soraHash) { + const transactionEvents = await getTransactionEvents(blockId as string, txId as string, ethBridgeApi.api); + const requestEvent = transactionEvents.find((e) => + ethBridgeApi.api.events.ethBridge.RequestRegistered.is(e.event) + ); + const hash = requestEvent.event.data[0].toString(); - const hash = eventData[0].toString(); - - this.updateTransactionParams(id, { hash }); + this.updateTransactionParams(id, { hash }); + } const tx = this.getTransaction(id); @@ -205,7 +204,7 @@ export class EthBridgeOutgoingReducer extends EthBridgeReducer { } export class EthBridgeIncomingReducer extends EthBridgeReducer { - async changeState(transaction: BridgeHistory): Promise { + async changeState(transaction: EthHistory): Promise { if (!transaction.id) throw new Error('[Bridge]: TX ID cannot be empty'); switch (transaction.transactionState) { diff --git a/src/utils/bridge/eth/index.ts b/src/utils/bridge/eth/index.ts index 20befd17c..7ffa79ca0 100644 --- a/src/utils/bridge/eth/index.ts +++ b/src/utils/bridge/eth/index.ts @@ -9,13 +9,13 @@ import { EthBridgeOutgoingReducer, EthBridgeIncomingReducer } from '@/utils/brid import type { EthBridgeReducer } from '@/utils/bridge/eth/classes/reducers'; import { getTransaction, updateTransaction } from '@/utils/bridge/eth/utils'; -import type { BridgeHistory } from '@sora-substrate/util'; +import type { EthHistory } from '@sora-substrate/util/build/bridgeProxy/eth/types'; -interface EthBridgeConstructorOptions extends IBridgeConstructorOptions { +interface EthBridgeConstructorOptions extends IBridgeConstructorOptions { getBridgeHistoryInstance: GetBridgeHistoryInstance; } -type EthBridge = Bridge; +type EthBridge = Bridge; const { ETH_BRIDGE_STATES } = WALLET_CONSTS; @@ -41,11 +41,11 @@ const ethBridge: EthBridge = new Bridge({ getTransaction, updateTransaction, // ui integration - showNotification: (tx: BridgeHistory) => store.commit.bridge.setNotificationData(tx as any), + showNotification: (tx: EthHistory) => store.commit.bridge.setNotificationData(tx as any), addTransactionToProgress: (id: string) => store.commit.bridge.addTxIdInProgress(id), removeTransactionFromProgress: (id: string) => store.commit.bridge.removeTxIdFromProgress(id), updateHistory: () => store.dispatch.bridge.updateInternalHistory(), - getActiveTransaction: () => store.getters.bridge.historyItem as BridgeHistory, + getActiveTransaction: () => store.getters.bridge.historyItem as EthHistory, // transaction signing beforeTransactionSign: () => store.dispatch.wallet.transactions.beforeTransactionSign(), // custom diff --git a/src/utils/bridge/eth/utils.ts b/src/utils/bridge/eth/utils.ts index 0e5b1f40e..9906fd366 100644 --- a/src/utils/bridge/eth/utils.ts +++ b/src/utils/bridge/eth/utils.ts @@ -1,11 +1,12 @@ -import { Operation, BridgeTxStatus } from '@sora-substrate/util'; +import { Operation } from '@sora-substrate/util'; +import { BridgeTxStatus } from '@sora-substrate/util/build/bridgeProxy/consts'; import { ethBridgeApi } from '@/utils/bridge/eth/api'; -import type { BridgeHistory, BridgeApprovedRequest } from '@sora-substrate/util'; +import type { EthHistory, EthApprovedRequest } from '@sora-substrate/util/build/bridgeProxy/eth/types'; import type { Subscription } from 'rxjs'; -export const isUnsignedFromPart = (tx: BridgeHistory): boolean => { +export const isUnsignedFromPart = (tx: EthHistory): boolean => { if (tx.type === Operation.EthBridgeOutgoing) { return !tx.blockId && !tx.txId; } else if (tx.type === Operation.EthBridgeIncoming) { @@ -15,7 +16,7 @@ export const isUnsignedFromPart = (tx: BridgeHistory): boolean => { } }; -export const isUnsignedToPart = (tx: BridgeHistory): boolean => { +export const isUnsignedToPart = (tx: EthHistory): boolean => { if (tx.type === Operation.EthBridgeOutgoing) { return !tx.externalHash; } else if (tx.type === Operation.EthBridgeIncoming) { @@ -25,12 +26,12 @@ export const isUnsignedToPart = (tx: BridgeHistory): boolean => { } }; -export const isUnsignedTx = (tx: BridgeHistory): boolean => { +export const isUnsignedTx = (tx: EthHistory): boolean => { return isUnsignedFromPart(tx); }; -export const getTransaction = (id: string): BridgeHistory => { - const tx = ethBridgeApi.getHistory(id) as BridgeHistory; +export const getTransaction = (id: string): EthHistory => { + const tx = ethBridgeApi.getHistory(id) as EthHistory; if (!tx) throw new Error(`[Bridge]: Transaction is not exists: ${id}`); @@ -42,7 +43,7 @@ export const updateTransaction = async (id: string, params = {}) => { ethBridgeApi.saveHistory({ ...tx, ...params }); }; -export const waitForApprovedRequest = async (tx: BridgeHistory): Promise => { +export const waitForApprovedRequest = async (tx: EthHistory): Promise => { if (!tx.hash) throw new Error(`[Bridge]: Tx hash cannot be empty`); if (!Number.isFinite(tx.externalNetwork)) throw new Error(`[Bridge]: Tx externalNetwork should be a number, ${tx.externalNetwork} received`); @@ -54,6 +55,7 @@ export const waitForApprovedRequest = async (tx: BridgeHistory): Promise => { +export const waitForIncomingRequest = async (tx: EthHistory): Promise<{ hash: string; blockId: string }> => { if (!tx.externalHash) throw new Error('[Bridge]: externalHash cannot be empty!'); if (!Number.isFinite(tx.externalNetwork)) throw new Error(`[Bridge]: Tx externalNetwork should be a number, ${tx.externalNetwork} received`); @@ -81,6 +83,7 @@ export const waitForIncomingRequest = async (tx: BridgeHistory): Promise<{ hash: switch (request.status) { case BridgeTxStatus.Failed: case BridgeTxStatus.Frozen: + case BridgeTxStatus.Broken: reject(new Error('[Bridge]: Transaction was failed or canceled')); break; case BridgeTxStatus.Done: diff --git a/src/utils/bridge/evm/classes/reducers.ts b/src/utils/bridge/evm/classes/reducers.ts index fbffa42bc..3c91e6b5f 100644 --- a/src/utils/bridge/evm/classes/reducers.ts +++ b/src/utils/bridge/evm/classes/reducers.ts @@ -2,7 +2,7 @@ import { BridgeTxStatus } from '@sora-substrate/util/build/bridgeProxy/consts'; import { BridgeReducer } from '@/utils/bridge/common/classes'; import type { RemoveTransactionByHash, IBridgeReducerOptions } from '@/utils/bridge/common/types'; -import { findEventInBlock } from '@/utils/bridge/common/utils'; +import { getTransactionEvents } from '@/utils/bridge/common/utils'; import { evmBridgeApi } from '@/utils/bridge/evm/api'; import type { RegisteredAccountAsset } from '@sora-substrate/util/build/assets/types'; @@ -97,14 +97,13 @@ export class EvmBridgeOutgoingReducer extends EvmBridgeReducer { if (tx.hash) return tx.hash; - const eventData = await findEventInBlock({ - api: evmBridgeApi.api, - blockId: tx.blockId as string, - section: 'bridgeProxy', - method: 'RequestStatusUpdate', - }); - - const hash = eventData[0].toString(); + const blockHash = tx.blockId as string; + const transactionHash = tx.txId as string; + const transactionEvents = await getTransactionEvents(blockHash, transactionHash, evmBridgeApi.api); + const requestEvent = transactionEvents.find((e) => + evmBridgeApi.api.events.bridgeProxy.RequestStatusUpdate.is(e.event) + ); + const hash = requestEvent.event.data[0].toString(); this.updateTransactionParams(id, { hash }); diff --git a/src/utils/bridge/sub/classes/adapter.ts b/src/utils/bridge/sub/classes/adapter.ts index 21f8cebcc..19b423720 100644 --- a/src/utils/bridge/sub/classes/adapter.ts +++ b/src/utils/bridge/sub/classes/adapter.ts @@ -34,7 +34,7 @@ export class SubAdapter { } get connected(): boolean { - return this.connection.opened; + return !!this.api?.isConnected; } public setEndpoint(endpoint: string): void { @@ -44,6 +44,7 @@ export class SubAdapter { public async connect(): Promise { if (!this.connected && this.endpoint) { await this.connection.open(this.endpoint); + await this.api.isReady; } } @@ -53,8 +54,12 @@ export class SubAdapter { } } + public getSoraParachainNetwork(): SubNetwork { + return subBridgeApi.getSoraParachain(this.subNetwork); + } + public getSoraParachainId(): number | undefined { - const soraParachain = subBridgeApi.getSoraParachain(this.subNetwork); + const soraParachain = this.getSoraParachainNetwork(); const soraParachainId = subBridgeApi.parachainIds[soraParachain]; return soraParachainId; @@ -63,6 +68,8 @@ export class SubAdapter { public async getBlockNumber(): Promise { if (!this.connected) return 0; + await this.api.isReady; + const result = await this.api.query.system.number(); return result.toNumber(); @@ -71,6 +78,8 @@ export class SubAdapter { protected async getAccountBalance(accountAddress: string): Promise { if (!(this.connected && accountAddress)) return ZeroStringValue; + await this.api.isReady; + const accountInfo = await this.api.query.system.account(accountAddress); const accountBalance = formatBalance(accountInfo.data); const balance = accountBalance.transferable; @@ -100,9 +109,13 @@ export class SubAdapter { } /* [Substrate 5] Runtime call transactionPaymentApi */ - public async getNetworkFee(): Promise { + public async getNetworkFee(asset: RegisteredAsset): Promise { + if (!this.connected) return ZeroStringValue; + + await this.api.isReady; + const decimals = this.api.registry.chainDecimals[0]; - const tx = this.getTransferExtrinsic({} as RegisteredAsset, '', ZeroStringValue); + const tx = this.getTransferExtrinsic(asset, '', ZeroStringValue); const res = await tx.paymentInfo(''); return new FPNumber(res.partialFee, decimals).toCodecString(); @@ -162,9 +175,9 @@ class KusamaAdapter extends SubAdapter { } /* Throws error until Substrate 5 migration */ - public async getNetworkFee(): Promise { + public async getNetworkFee(asset: RegisteredAsset): Promise { try { - return await super.getNetworkFee(); + return await super.getNetworkFee(asset); } catch { // Hardcoded value for Kusama - 0.0007 KSM return '700000000'; @@ -189,7 +202,15 @@ class KusamaAdapter extends SubAdapter { } } -class SubConnector { +export class SubNetworksConnector { + public network!: SubNetwork; + public parachainNetwork!: SubNetwork; + public networkAdapter!: SubAdapter; + public parachainAdapter!: SubAdapter; + public parachainId!: number; + + public static endpoints: SubNetworkApps = {}; + public readonly adapters = { [SubNetwork.Rococo]: () => new KusamaAdapter(SubNetwork.Rococo), [SubNetwork.Kusama]: () => new KusamaAdapter(SubNetwork.Kusama), @@ -197,19 +218,14 @@ class SubConnector { [SubNetwork.KusamaSora]: () => new SubAdapter(SubNetwork.KusamaSora), }; - public endpoints: SubNetworkApps = {}; - - /** Adapter for Substrate network. Used for network selected in app */ - public networkAdapter!: SubAdapter; - public getAdapterForNetwork(network: SubNetwork): SubAdapter { if (!(network in this.adapters)) { throw new Error(`[${this.constructor.name}] Adapter for "${network}" network not implemented`); } - if (!(network in this.endpoints)) { + if (!(network in SubNetworksConnector.endpoints)) { throw new Error(`[${this.constructor.name}] Endpoint for "${network}" network is not defined`); } - const endpoint = this.endpoints[network]; + const endpoint = SubNetworksConnector.endpoints[network]; const adapter = this.adapters[network](); adapter.setEndpoint(endpoint); @@ -217,24 +233,39 @@ class SubConnector { return adapter; } + public async init(network: SubNetwork): Promise { + this.network = network; + this.networkAdapter = this.getAdapterForNetwork(this.network); + this.parachainNetwork = this.networkAdapter.getSoraParachainNetwork(); + this.parachainAdapter = this.getAdapterForNetwork(this.parachainNetwork); + this.parachainId = this.parachainAdapter.getSoraParachainId() as number; + } + /** - * Open main connection with Substrate network + * Open main connection with Substrate network & Sora parachain */ public async open(network: SubNetwork): Promise { - // stop current adapter connection + // stop current connections await this.stop(); // set adapter for network arg - this.networkAdapter = this.getAdapterForNetwork(network); - // open adapter connection - await this.networkAdapter.connect(); + await this.init(network); + // open adapters connections + await this.start(); + } + + /** + * Connect to Substrate network & Sora parachain + */ + public async start(): Promise { + await Promise.all([this.networkAdapter.connect(), this.parachainAdapter.connect()]); } /** - * Close main connection to selected Substrate network + * Close connections to Substrate network & Sora parachain */ public async stop(): Promise { - await this.networkAdapter?.stop(); + await Promise.all([this.networkAdapter?.stop(), this.parachainAdapter?.stop()]); } } -export const subConnector = new SubConnector(); +export const subBridgeConnector = new SubNetworksConnector(); diff --git a/src/utils/bridge/sub/classes/history.ts b/src/utils/bridge/sub/classes/history.ts index 8a0f7f959..739606d3d 100644 --- a/src/utils/bridge/sub/classes/history.ts +++ b/src/utils/bridge/sub/classes/history.ts @@ -4,15 +4,10 @@ import { api } from '@soramitsu/soraneo-wallet-web'; import { ZeroStringValue } from '@/consts'; import { rootActionContext } from '@/store'; -import { findEventInBlock } from '@/utils/bridge/common/utils'; +import { getBlockEventsByTxIndex } from '@/utils/bridge/common/utils'; import { subBridgeApi } from '@/utils/bridge/sub/api'; -import { subConnector } from '@/utils/bridge/sub/classes/adapter'; -import type { SubAdapter } from '@/utils/bridge/sub/classes/adapter'; -import { - getRelayChainBlockNumber, - getMessageAcceptedNonces, - isMessageDispatchedNonces, -} from '@/utils/bridge/sub/utils'; +import { SubNetworksConnector } from '@/utils/bridge/sub/classes/adapter'; +import { getMessageAcceptedNonces, isMessageDispatchedNonces, formatSubAddress } from '@/utils/bridge/sub/utils'; import type { ApiPromise } from '@polkadot/api'; import type { NetworkFeesObject } from '@sora-substrate/util'; @@ -56,35 +51,17 @@ const findTxInBlock = async (blockHash: string, soraHash: string) => { return { hash: txHash, events: txEvents }; }; -class SubBridgeHistory { - private externalNetwork!: SubNetwork; - private parachainNetwork!: SubNetwork; - private externalNetworkAdapter!: SubAdapter; - private parachainNetworkAdapter!: SubAdapter; - private parachainId!: number; - - public async init(externalNetwork: SubNetwork): Promise { - this.externalNetwork = externalNetwork; - this.parachainNetwork = subBridgeApi.getSoraParachain(this.externalNetwork); - this.externalNetworkAdapter = subConnector.getAdapterForNetwork(this.externalNetwork); - this.parachainNetworkAdapter = subConnector.getAdapterForNetwork(this.parachainNetwork); - this.parachainId = subBridgeApi.parachainIds[this.parachainNetwork] as number; - } - +class SubBridgeHistory extends SubNetworksConnector { get soraApi(): ApiPromise { return subBridgeApi.api; } get parachainApi(): ApiPromise { - return this.parachainNetworkAdapter.api; + return this.parachainAdapter.api; } get externalApi(): ApiPromise { - return this.externalNetworkAdapter.api; - } - - private async connect() { - await Promise.all([this.externalNetworkAdapter.connect(), this.parachainNetworkAdapter.connect()]); + return this.networkAdapter.api; } public async clearHistory(updateCallback?: FnWithoutArgs | AsyncFnWithoutArgs): Promise { @@ -100,7 +77,7 @@ class SubBridgeHistory { updateCallback?: FnWithoutArgs | AsyncFnWithoutArgs ): Promise { try { - const transactions = await subBridgeApi.getUserTransactions(address, this.externalNetwork); + const transactions = await subBridgeApi.getUserTransactions(address, this.network); if (!transactions.length) return; @@ -114,7 +91,7 @@ class SubBridgeHistory { if ((localHistoryItem?.id as string) in inProgressIds) continue; if (hasFinishedState(localHistoryItem)) continue; - await this.connect(); + await this.start(); const historyItemData = await this.txDataToHistory(tx, networkFees, assetDataByAddress); @@ -130,8 +107,7 @@ class SubBridgeHistory { await updateCallback?.(); } } finally { - this.externalNetworkAdapter.stop(); - this.parachainNetworkAdapter.stop(); + this.stop(); } } @@ -153,7 +129,6 @@ class SubBridgeHistory { const asset = assetDataByAddress(tx.soraAssetAddress); const amount = FPNumber.fromCodecValue(tx.amount, asset?.decimals).toString(); const type = getType(isOutgoing); - const soraNetworkFee = networkFees[type] ?? ZeroStringValue; const history: SubHistory = { id, @@ -162,12 +137,11 @@ class SubBridgeHistory { hash: id, transactionState: tx.status, parachainBlockHeight, - externalNetwork: this.externalNetwork, + externalNetwork: this.network, externalNetworkType: BridgeNetworkType.Sub, amount, assetAddress: asset?.address, symbol: asset?.symbol, - soraNetworkFee, from: tx.soraAccount, }; @@ -182,7 +156,7 @@ class SubBridgeHistory { const [{ hash, events }, startTime, relayChainBlockNumber] = await Promise.all([ findTxInBlock(blockId, id), api.system.getBlockTimestamp(blockId, this.soraApi), - getRelayChainBlockNumber(parachainBlockId, this.parachainApi), + subBridgeApi.soraParachainApi.getRelayChainBlockNumber(parachainBlockId, this.parachainApi), ]); history.txId = hash; @@ -223,6 +197,7 @@ class SubBridgeHistory { asset: Nullable; events: any[]; }): Promise { + const soraFeeEvent = events.find((e) => this.soraApi.events.transactionPayment.TransactionFeePaid.is(e.event)); // sended from sora nonces const [soraBatchNonce, soraMessageNonce] = getMessageAcceptedNonces(events, this.soraApi); const parachainEvents = await api.system.getBlockEvents(parachainBlockId, this.parachainApi); @@ -264,11 +239,12 @@ class SubBridgeHistory { ); const received = balancesDepositEvent.event.data.amount.toString(); + history.soraNetworkFee = soraFeeEvent.event.data[1].toString(); history.externalNetworkFee = ZeroStringValue; history.externalBlockId = blockId; history.externalBlockHeight = n; history.amount2 = FPNumber.fromCodecValue(received, asset?.externalDecimals).toString(); - history.to = to; + history.to = formatSubAddress(tx.externalAccount, this.externalApi.registry.chainSS58 as number); break; } catch { continue; @@ -291,7 +267,7 @@ class SubBridgeHistory { const blockId = await api.system.getBlockHash(n, this.externalApi); const extrinsics = await api.system.getExtrinsicsFromBlock(blockId, this.externalApi); - for (const extrinsic of extrinsics) { + for (const [extrinsicIndex, extrinsic] of extrinsics.entries()) { try { if (!(extrinsic.method.section === 'xcmPallet' && extrinsic.method.method === 'reserveTransferAssets')) continue; @@ -300,21 +276,22 @@ class SubBridgeHistory { const parachainId = (dest as any).asV3.interior.asX1.asParachain.toNumber(); const accountId = (beneficiary as any).asV3.interior.asX1.asAccountId32.id.toString(); const receiver = subBridgeApi.formatAddress(accountId); + const from = subBridgeApi.formatAddress(history.from as string); - if (!(parachainId === this.parachainId && receiver === history.from)) continue; + if (!(parachainId === this.parachainId && receiver === from)) continue; - const feeData = await findEventInBlock({ - api: this.externalApi, - blockId, - section: 'transactionPayment', - method: 'TransactionFeePaid', - }); + const signer = extrinsic.signer.toString(); + const extrinsicEvents = await getBlockEventsByTxIndex(blockId, extrinsicIndex, this.externalApi); + const feeEvent = extrinsicEvents.find((e) => + this.externalApi.events.transactionPayment.TransactionFeePaid.is(e.event) + ); - history.externalNetworkFee = feeData[1].toString(); + history.soraNetworkFee = ZeroStringValue; + history.externalNetworkFee = feeEvent.event.data[1].toString(); history.externalBlockId = blockId; history.externalBlockHeight = n; - history.to = subBridgeApi.formatAddress(extrinsic.signer.toString()); - break; + history.to = formatSubAddress(signer, this.externalApi.registry.chainSS58 as number); + return; } catch { continue; } diff --git a/src/utils/bridge/sub/classes/reducers.ts b/src/utils/bridge/sub/classes/reducers.ts index 5c7bc581c..e0bc6b479 100644 --- a/src/utils/bridge/sub/classes/reducers.ts +++ b/src/utils/bridge/sub/classes/reducers.ts @@ -8,37 +8,32 @@ import { ZeroStringValue } from '@/consts'; import { BridgeReducer } from '@/utils/bridge/common/classes'; import { getTransactionEvents } from '@/utils/bridge/common/utils'; import { subBridgeApi } from '@/utils/bridge/sub/api'; -import { subConnector } from '@/utils/bridge/sub/classes/adapter'; -import type { SubAdapter } from '@/utils/bridge/sub/classes/adapter'; +import { SubNetworksConnector } from '@/utils/bridge/sub/classes/adapter'; import { getMessageAcceptedNonces, isMessageDispatchedNonces, isAssetAddedToChannel } from '@/utils/bridge/sub/utils'; -import type { ApiPromise } from '@polkadot/api'; +import type { ApiPromise, ApiRx } from '@polkadot/api'; import type { RegisteredAccountAsset } from '@sora-substrate/util/build/assets/types'; import type { SubHistory } from '@sora-substrate/util/build/bridgeProxy/sub/types'; import type { Subscription } from 'rxjs'; export class SubBridgeReducer extends BridgeReducer { - protected subNetworkAdapter!: SubAdapter; - protected soraParachainAdapter!: SubAdapter; - protected asset!: RegisteredAccountAsset; + protected connector!: SubNetworksConnector; - createConnections(id: string): void { + initConnector(id: string): void { const { externalNetwork } = this.getTransaction(id); if (!externalNetwork) throw new Error(`[${this.constructor.name}]: Transaction "externalNetwork" is not defined`); - const soraParachainNetwork = subBridgeApi.getSoraParachain(externalNetwork); - - this.subNetworkAdapter = subConnector.getAdapterForNetwork(externalNetwork); - this.soraParachainAdapter = subConnector.getAdapterForNetwork(soraParachainNetwork); + this.connector = new SubNetworksConnector(); + this.connector.init(externalNetwork); } - async closeConnections(): Promise { - await Promise.all([this.subNetworkAdapter?.stop(), this.soraParachainAdapter?.stop()]); + async closeConnector(): Promise { + await this.connector.stop(); } - async getHashesByBlockNumber(adapter: SubAdapter, blockHeight: number) { + async getHashesByBlockNumber(blockHeight: number, apiRx: ApiRx) { let blockId = ''; if (Number.isFinite(blockHeight)) { @@ -46,7 +41,7 @@ export class SubBridgeReducer extends BridgeReducer { try { await new Promise((resolve) => { - subscription = api.system.getBlockHashObservable(blockHeight, adapter.apiRx).subscribe((hash) => { + subscription = api.system.getBlockHashObservable(blockHeight, apiRx).subscribe((hash) => { if (hash) { blockId = hash; resolve(); @@ -87,7 +82,7 @@ export class SubBridgeIncomingReducer extends SubBridgeReducer { handler: async (id: string) => { try { this.beforeSubmit(id); - this.createConnections(id); + this.initConnector(id); this.updateTransactionParams(id, { transactionState: BridgeTxStatus.Pending }); await this.checkTxId(id); @@ -96,7 +91,7 @@ export class SubBridgeIncomingReducer extends SubBridgeReducer { await this.waitSoraBlockByHash(id); await this.onComplete(id); } finally { - this.closeConnections(); + this.closeConnector(); } }, }); @@ -121,11 +116,11 @@ export class SubBridgeIncomingReducer extends SubBridgeReducer { // transaction not signed await this.beforeSign(id); // open connections - await Promise.all([this.subNetworkAdapter.connect(), this.soraParachainAdapter.connect()]); + await this.connector.start(); // sign transaction - await this.subNetworkAdapter.transfer(asset, tx.to as string, tx.amount as string, id); + await this.connector.networkAdapter.transfer(asset, tx.to as string, tx.amount as string, id); // store sora parachain block number when tx was signed in external network - const parachainStartBlock = (await this.soraParachainAdapter.api.query.system.number()).toNumber(); + const parachainStartBlock = (await this.connector.parachainAdapter.api.query.system.number()).toNumber(); // update history to change tx status in ui this.updateTransactionParams(id, { payload: { @@ -148,12 +143,12 @@ export class SubBridgeIncomingReducer extends SubBridgeReducer { private async updateTxExternalData(id: string): Promise { const tx = this.getTransaction(id); - await this.subNetworkAdapter.connect(); + await this.connector.networkAdapter.connect(); if (!tx.externalBlockHeight) { const externalBlockHeight = await api.system.getBlockNumber( tx.externalBlockId as string, - this.subNetworkAdapter.api + this.connector.networkAdapter.api ); this.updateTransactionParams(id, { @@ -163,12 +158,14 @@ export class SubBridgeIncomingReducer extends SubBridgeReducer { const blockHash = tx.externalBlockId as string; const transactionHash = tx.externalHash as string; - const transactionEvents = await getTransactionEvents(blockHash, transactionHash, this.subNetworkAdapter.api); + const transactionEvents = await getTransactionEvents(blockHash, transactionHash, this.connector.networkAdapter.api); const feeEvent = transactionEvents.find((e) => - this.subNetworkAdapter.api.events.transactionPayment.TransactionFeePaid.is(e.event) + this.connector.networkAdapter.api.events.transactionPayment.TransactionFeePaid.is(e.event) + ); + const xcmEvent = transactionEvents.find((e) => + this.connector.networkAdapter.api.events.xcmPallet.Attempted.is(e.event) ); - const xcmEvent = transactionEvents.find((e) => this.subNetworkAdapter.api.events.xcmPallet.Attempted.is(e.event)); if (feeEvent) { const externalNetworkFee = feeEvent.event.data[1].toString(); @@ -204,11 +201,11 @@ export class SubBridgeIncomingReducer extends SubBridgeReducer { let blockNumber!: number; try { - await this.soraParachainAdapter.connect(); + await this.connector.parachainAdapter.connect(); await new Promise((resolve, reject) => { - const eventsObservable = api.system.getEventsObservable(this.soraParachainAdapter.apiRx); - const blockNumberObservable = api.system.getBlockNumberObservable(this.soraParachainAdapter.apiRx); + const eventsObservable = api.system.getEventsObservable(this.connector.parachainAdapter.apiRx); + const blockNumberObservable = api.system.getBlockNumberObservable(this.connector.parachainAdapter.apiRx); subscription = combineLatest([eventsObservable, blockNumberObservable]).subscribe( ([eventsVec, blockHeight]) => { @@ -221,13 +218,13 @@ export class SubBridgeIncomingReducer extends SubBridgeReducer { const events = [...eventsVec.toArray()].reverse(); const downwardMessagesProcessedEvent = events.find((e) => - this.soraParachainAdapter.api.events.parachainSystem.DownwardMessagesProcessed.is(e.event) + this.connector.parachainAdapter.api.events.parachainSystem.DownwardMessagesProcessed.is(e.event) ); if (!downwardMessagesProcessedEvent) return; const assetAddedToChannelEventIndex = events.findIndex((e) => - isAssetAddedToChannel(e, this.asset, to, sended, this.soraParachainAdapter.api) + isAssetAddedToChannel(e, this.asset, to, sended, this.connector.parachainAdapter.api) ); if (assetAddedToChannelEventIndex === -1) { @@ -238,7 +235,7 @@ export class SubBridgeIncomingReducer extends SubBridgeReducer { blockNumber = blockHeight; [batchNonce, messageNonce] = getMessageAcceptedNonces( events.slice(assetAddedToChannelEventIndex), - this.soraParachainAdapter.api + this.connector.parachainAdapter.api ); resolve(); @@ -252,14 +249,16 @@ export class SubBridgeIncomingReducer extends SubBridgeReducer { subscription.unsubscribe(); // run non blocking process promise - this.getHashesByBlockNumber(this.soraParachainAdapter, blockNumber) + this.getHashesByBlockNumber(blockNumber, this.connector.parachainAdapter.apiRx) .then(({ blockHeight, blockId }) => this.updateTransactionParams(id, { parachainBlockHeight: blockHeight, // parachain block number parachainBlockId: blockId, // parachain block hash }) ) - .finally(() => this.closeConnections()); + .finally(() => { + this.closeConnector(); + }); } const { payload: prevPayload } = this.getTransaction(id); @@ -359,7 +358,7 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { handler: async (id: string) => { try { this.beforeSubmit(id); - this.createConnections(id); + this.initConnector(id); this.updateTransactionParams(id, { transactionState: BridgeTxStatus.Pending }); await this.checkTxId(id); @@ -370,7 +369,7 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { await this.waitForDestinationMessageHash(id); await this.onComplete(id); } finally { - this.closeConnections(); + this.closeConnector(); } }, }); @@ -432,11 +431,11 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { let blockNumber!: number; try { - await this.soraParachainAdapter.connect(); + await this.connector.parachainAdapter.connect(); await new Promise((resolve, reject) => { - const eventsObservable = api.system.getEventsObservable(this.soraParachainAdapter.apiRx); - const blockNumberObservable = api.system.getBlockNumberObservable(this.soraParachainAdapter.apiRx); + const eventsObservable = api.system.getEventsObservable(this.connector.parachainAdapter.apiRx); + const blockNumberObservable = api.system.getBlockNumberObservable(this.connector.parachainAdapter.apiRx); subscription = combineLatest([eventsObservable, blockNumberObservable]).subscribe( ([eventsVec, blockHeight]) => { @@ -447,7 +446,7 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { tx.payload.batchNonce, tx.payload.messageNonce, e, - this.soraParachainAdapter.api + this.connector.parachainAdapter.api ) ); @@ -457,7 +456,7 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { const parachainSystemEvent = events .slice(substrateDispatchEventIndex) - .find((e) => this.soraParachainAdapter.api.events.parachainSystem.UpwardMessageSent.is(e.event)); + .find((e) => this.connector.parachainAdapter.api.events.parachainSystem.UpwardMessageSent.is(e.event)); if (!parachainSystemEvent) { throw new Error(`[${this.constructor.name}]: Unable to find "parachainSystem.UpwardMessageSent" event`); @@ -476,14 +475,16 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { subscription.unsubscribe(); // run non blocking proccess promise - this.getHashesByBlockNumber(this.soraParachainAdapter, blockNumber) + this.getHashesByBlockNumber(blockNumber, this.connector.parachainAdapter.apiRx) .then(({ blockHeight, blockId }) => this.updateTransactionParams(id, { parachainBlockHeight: blockHeight, // parachain block number parachainBlockId: blockId, // parachain block hash }) ) - .finally(() => this.soraParachainAdapter.stop()); + .finally(() => { + this.connector.parachainAdapter.stop(); + }); } const payload = { ...tx.payload, messageHash }; @@ -502,11 +503,11 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { let amount!: string; try { - await this.subNetworkAdapter.connect(); + await this.connector.networkAdapter.connect(); await new Promise((resolve, reject) => { - const eventsObservable = api.system.getEventsObservable(this.subNetworkAdapter.apiRx); - const blockNumberObservable = api.system.getBlockNumberObservable(this.subNetworkAdapter.apiRx); + const eventsObservable = api.system.getEventsObservable(this.connector.networkAdapter.apiRx); + const blockNumberObservable = api.system.getBlockNumberObservable(this.connector.networkAdapter.apiRx); subscription = combineLatest([eventsObservable, blockNumberObservable]).subscribe( ([eventsVec, blockHeight]) => { @@ -514,7 +515,7 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { const events = [...eventsVec.toArray()].reverse(); const messageQueueProcessedEventIndex = events.findIndex( (e) => - this.subNetworkAdapter.api.events.messageQueue.Processed.is(e.event) && + this.connector.networkAdapter.api.events.messageQueue.Processed.is(e.event) && e.event.data[0].toString() === messageHash ); @@ -527,8 +528,9 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { .slice(messageQueueProcessedEventIndex) .find( (e) => - this.subNetworkAdapter.api.events.balances.Deposit.is(e.event) && - subBridgeApi.formatAddress(e.event.data.who.toString()) === tx.to + this.connector.networkAdapter.api.events.balances.Deposit.is(e.event) && + subBridgeApi.formatAddress(e.event.data.who.toString()) === + subBridgeApi.formatAddress(tx.to as string) ); if (!balancesDepositEvent) @@ -547,14 +549,16 @@ export class SubBridgeOutgoingReducer extends SubBridgeReducer { subscription.unsubscribe(); // run blocking process promise - await this.getHashesByBlockNumber(this.subNetworkAdapter, blockNumber) + await this.getHashesByBlockNumber(blockNumber, this.connector.networkAdapter.apiRx) .then(({ blockHeight, blockId }) => this.updateTransactionParams(id, { externalBlockHeight: blockHeight, // parachain block number externalBlockId: blockId, // parachain block hash }) ) - .finally(() => this.subNetworkAdapter.stop()); + .finally(() => { + this.connector.networkAdapter.stop(); + }); } const received = FPNumber.fromCodecValue(amount, this.asset.externalDecimals); diff --git a/src/utils/bridge/sub/utils.ts b/src/utils/bridge/sub/utils.ts index db508d9d9..19ab78010 100644 --- a/src/utils/bridge/sub/utils.ts +++ b/src/utils/bridge/sub/utils.ts @@ -1,3 +1,5 @@ +import { decodeAddress, encodeAddress } from '@polkadot/util-crypto'; + import { subBridgeApi } from '@/utils/bridge/sub/api'; import type { ApiPromise } from '@polkadot/api'; @@ -23,13 +25,6 @@ export const updateTransaction = (id: string, params = {}): void => { subBridgeApi.saveHistory(data); }; -export const getRelayChainBlockNumber = async (blockHash: string, api: ApiPromise): Promise => { - const apiInstanceAtBlock = await api.at(blockHash); - const blockNumber = await apiInstanceAtBlock.query.parachainSystem.lastRelayChainBlockNumber(); - - return Number(blockNumber.toString()); -}; - export const getMessageAcceptedNonces = (events: Array, api: ApiPromise): [number, number] => { const messageAcceptedEvent = events.find((e) => api.events.substrateBridgeOutboundChannel.MessageAccepted.is(e.event) @@ -78,7 +73,7 @@ export const isAssetAddedToChannel = ( const { amount, assetId, recipient } = e.event.data[0].asTransfer; // address check - if (subBridgeApi.formatAddress(recipient.toString()) !== to) return false; + if (subBridgeApi.formatAddress(recipient.toString()) !== subBridgeApi.formatAddress(to)) return false; // asset check if (assetId.toString() !== asset.address) return false; // amount check @@ -87,3 +82,10 @@ export const isAssetAddedToChannel = ( return true; }; + +// [TECH] move to js-lib +export const formatSubAddress = (address: string, ss58: number): string => { + const publicKey = decodeAddress(address, false); + + return encodeAddress(publicKey, ss58); +}; diff --git a/src/utils/ethers-util.ts b/src/utils/ethers-util.ts index 39481f795..23445ffba 100644 --- a/src/utils/ethers-util.ts +++ b/src/utils/ethers-util.ts @@ -1,7 +1,8 @@ import detectEthereumProvider from '@metamask/detect-provider'; import { decodeAddress } from '@polkadot/util-crypto'; -import { FPNumber, BridgeRequestAssetKind } from '@sora-substrate/util'; +import { FPNumber } from '@sora-substrate/util'; import { BridgeNetworkType } from '@sora-substrate/util/build/bridgeProxy/consts'; +import { EthAssetKind } from '@sora-substrate/util/build/bridgeProxy/eth/consts'; import WalletConnectProvider from '@walletconnect/web3-provider'; import { ethers } from 'ethers'; @@ -44,14 +45,14 @@ const gasLimit = { /** * It's in gwei. */ -const getEthBridgeGasLimit = (assetEvmAddress: string, kind: BridgeRequestAssetKind, isSoraToEvm: boolean) => { +const getEthBridgeGasLimit = (assetEvmAddress: string, kind: EthAssetKind, isSoraToEvm: boolean) => { if (isSoraToEvm) { switch (kind) { - case BridgeRequestAssetKind.SidechainOwned: + case EthAssetKind.SidechainOwned: return gasLimit.mintTokensByPeers; - case BridgeRequestAssetKind.Thischain: + case EthAssetKind.Thischain: return gasLimit.receiveBySidechainAssetId; - case BridgeRequestAssetKind.Sidechain: + case EthAssetKind.Sidechain: return isNativeEvmTokenAddress(assetEvmAddress) ? gasLimit.receiveByEthereumAssetAddress.ETH : gasLimit.receiveByEthereumAssetAddress.OTHER; @@ -309,7 +310,7 @@ async function getEvmNetworkFee( const ethersInstance = await getEthersInstance(); const { maxFeePerGas } = await ethersInstance.getFeeData(); const gasPrice = maxFeePerGas ?? BigInt(0); - const gasLimit = BigInt(getEthBridgeGasLimit(assetEvmAddress, assetKind as BridgeRequestAssetKind, isSoraToEvm)); + const gasLimit = BigInt(getEthBridgeGasLimit(assetEvmAddress, assetKind as EthAssetKind, isSoraToEvm)); const fee = calcEvmFee(gasPrice, gasLimit); return fee; @@ -339,7 +340,7 @@ async function getEvmTransactionReceipt(hash: string): Promise { const ethersInstance = await getEthersInstance(); - const block = await ethersInstance.getBlock(number); + const block = await ethersInstance.getBlock(Number(number)); return block; } diff --git a/src/utils/index.ts b/src/utils/index.ts index ca79c69c1..6ada87f47 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -66,7 +66,7 @@ export const isMaxButtonAvailable = ( return !FPNumber.eq(fpMaxBalance, fpAmount) && !hasInsufficientXorForFee(xorAsset, fee, isXorOutputSwap); }; -const getMaxBalance = ( +export const getMaxBalance = ( asset: AssetWithBalance, fee: CodecString, { isExternalBalance = false, isExternalNative = false, isBondedBalance = false } = {} diff --git a/src/views/Bridge.vue b/src/views/Bridge.vue index c0ffd2d45..b67c7e3bc 100644 --- a/src/views/Bridge.vue +++ b/src/views/Bridge.vue @@ -12,7 +12,7 @@
-
+
-
+
@@ -317,13 +332,13 @@ import { hasInsufficientBalance, hasInsufficientXorForFee, hasInsufficientNativeTokenForFee, - getMaxValue, + getMaxBalance, getAssetBalance, asZeroValue, delay, } from '@/utils'; -import type { IBridgeTransaction } from '@sora-substrate/util'; +import type { IBridgeTransaction, CodecString } from '@sora-substrate/util'; import type { AccountAsset, RegisteredAccountAsset } from '@sora-substrate/util/build/assets/types'; @Component({ @@ -332,6 +347,7 @@ import type { AccountAsset, RegisteredAccountAsset } from '@sora-substrate/util/ BridgeSelectNetwork: lazyComponent(Components.BridgeSelectNetwork), BridgeSelectAccount: lazyComponent(Components.BridgeSelectAccount), BridgeTransactionDetails: lazyComponent(Components.BridgeTransactionDetails), + BridgeLimitCard: lazyComponent(Components.BridgeLimitCard), GenericPageHeader: lazyComponent(Components.GenericPageHeader), ConfirmBridgeTransactionDialog: lazyComponent(Components.ConfirmBridgeTransactionDialog), NetworkFeeWarningDialog: lazyComponent(Components.NetworkFeeWarningDialog), @@ -356,13 +372,13 @@ export default class Bridge extends Mixins( readonly KnownSymbols = KnownSymbols; readonly FocusedField = FocusedField; - @state.bridge.externalNetworkFeeFetching private externalNetworkFeeFetching!: boolean; - @state.bridge.externalBalancesFetching private externalBalancesFetching!: boolean; - @state.bridge.assetLockedBalanceFetching private assetLockedBalanceFetching!: boolean; + @state.bridge.externalTransferFee private externalTransferFee!: CodecString; + @state.bridge.balancesFetching private balancesFetching!: boolean; + @state.bridge.feesAndLockedFundsFetching private feesAndLockedFundsFetching!: boolean; + @state.assets.registeredAssetsFetching private registeredAssetsFetching!: boolean; @state.bridge.amountSend amountSend!: string; @state.bridge.amountReceived amountReceived!: string; @state.bridge.isSoraToEvm isSoraToEvm!: boolean; - @state.assets.registeredAssetsFetching registeredAssetsFetching!: boolean; @getter.bridge.isRegisteredAsset isRegisteredAsset!: boolean; @getter.bridge.operation private operation!: Operation; @@ -371,6 +387,7 @@ export default class Bridge extends Mixins( @mutation.bridge.setSoraToEvm private setSoraToEvm!: (value: boolean) => void; @mutation.bridge.setHistoryId private setHistoryId!: (id?: string) => void; @mutation.bridge.setFocusedField setFocusedField!: (field: FocusedField) => void; + @mutation.web3.setSelectNetworkDialogVisibility private setSelectNetworkDialogVisibility!: (flag: boolean) => void; @action.bridge.setSendedAmount setSendedAmount!: (value?: string) => void; @action.bridge.setReceivedAmount setReceivedAmount!: (value?: string) => void; @@ -400,7 +417,7 @@ export default class Bridge extends Mixins( return await this.waitOnExternalFeeWarningConfirmation(); } - get areNetworksConnected(): boolean { + get areAccountsConnected(): boolean { return !!this.sender && !!this.recipient; } @@ -442,35 +459,31 @@ export default class Bridge extends Mixins( if (!(this.asset && this.isRegisteredAsset)) return ZeroStringValue; const fee = this.isSoraToEvm ? this.soraNetworkFee : this.externalNetworkFee; - const maxBalance = getMaxValue(this.asset, fee, { + const maxBalance = getMaxBalance(this.asset, fee, { isExternalBalance: !this.isSoraToEvm, isExternalNative: this.isNativeTokenSelected, }); - if (this.assetLockedBalance && this.isSoraToEvm) { - const fpBalance = this.getFPNumber(maxBalance, this.asset.decimals); - const fpLocked = this.getFPNumberFromCodec(this.assetLockedBalance, this.asset.externalDecimals); - - if (FPNumber.gt(fpBalance, fpLocked)) return fpLocked.toString(); + if (this.isSoraToEvm && this.outgoingMaxAmount) { + if (FPNumber.gt(maxBalance, this.outgoingMaxAmount)) return this.outgoingMaxAmount.toString(); } - return maxBalance; + return maxBalance.toString(); } get isMaxAvailable(): boolean { - if (!(this.asset && this.isRegisteredAsset && this.areNetworksConnected && !asZeroValue(this.maxValue))) + if (!(this.asset && this.isRegisteredAsset && this.areAccountsConnected && !asZeroValue(this.maxValue))) return false; return this.maxValue !== this.amountSend; } - get isInsufficientLiquidity(): boolean { - if (!(this.asset && this.assetLockedBalance && this.isSoraToEvm)) return false; - - const fpAmount = new FPNumber(this.amountSend, this.asset.decimals); - const fpLocked = FPNumber.fromCodecValue(this.assetLockedBalance, this.asset.externalDecimals); + get isGreaterThanMaxAmount(): boolean { + return this.isGreaterThanOutgoingMaxAmount(this.amountSend, this.asset, this.isSoraToEvm, this.isRegisteredAsset); + } - return FPNumber.gt(fpAmount, fpLocked); + get isLowerThanMinAmount(): boolean { + return this.isLowerThanIncomingMinAmount(this.amountSend, this.asset, this.isSoraToEvm, this.isRegisteredAsset); } get isInsufficientXorForFee(): boolean { @@ -509,28 +522,32 @@ export default class Bridge extends Mixins( return this.getStringFromCodec(this.externalNetworkFee, this.nativeTokenDecimals); } + get formattedExternalTransferFee(): string { + return this.getStringFromCodec(this.externalTransferFee, this.asset?.externalDecimals); + } + get isConfirmTxDisabled(): boolean { return ( !this.isAssetSelected || !this.isRegisteredAsset || - !this.areNetworksConnected || + !this.areAccountsConnected || !this.isValidNetwork || this.isZeroAmountSend || this.isZeroAmountReceived || this.isInsufficientXorForFee || this.isInsufficientNativeTokenForFee || this.isInsufficientBalance || - this.isInsufficientLiquidity + this.isGreaterThanMaxAmount || + this.isLowerThanMinAmount ); } get isConfirmTxLoading(): boolean { return ( this.isSelectAssetLoading || - this.externalNetworkFeeFetching || - this.externalBalancesFetching || - this.registeredAssetsFetching || - this.assetLockedBalanceFetching + this.balancesFetching || + this.feesAndLockedFundsFetching || + this.registeredAssetsFetching ); } @@ -564,8 +581,11 @@ export default class Bridge extends Mixins( return FPNumber.gte(fpAfterTransfer, fpFee); } - getDecimals(isSora = true): number | undefined { - return isSora ? this.asset?.decimals : this.asset?.externalDecimals; + get amountDecimals(): number { + const internal = this.asset?.decimals ?? FPNumber.DEFAULT_PRECISION; + const external = this.asset?.externalDecimals ?? FPNumber.DEFAULT_PRECISION; + + return Math.min(internal, external); } private getBalance(isSora = true): Nullable { @@ -576,7 +596,7 @@ export default class Bridge extends Mixins( if (!balance) { return null; } - const decimals = this.getDecimals(isSora); + const decimals = isSora ? this.asset?.decimals : this.asset?.externalDecimals; return this.getFPNumberFromCodec(balance, decimals); } @@ -585,14 +605,16 @@ export default class Bridge extends Mixins( } async created(): Promise { - const { address, amount, isIncoming } = this.$route.params; - if (address) { - this.setAssetAddress(address); - } - if (isIncoming) { - this.setSoraToEvm(false); - } - this.setSendedAmount(amount); + await this.withParentLoading(async () => { + const { address, amount, isIncoming } = this.$route.params; + this.setSendedAmount(amount); + if (isIncoming) { + this.setSoraToEvm(false); + } + if (address) { + this.updateAssetAddress(address); + } + }); } getBridgeItemTitle(isSoraNetwork = false): string { @@ -634,10 +656,6 @@ export default class Bridge extends Mixins( this.showConfirmTransactionDialog = true; } - handleViewTransactionsHistory(): void { - router.push({ name: PageNames.BridgeTransactionsHistory }); - } - handleChangeNetwork(): void { this.setSelectNetworkDialogVisibility(true); } @@ -649,8 +667,12 @@ export default class Bridge extends Mixins( async selectAsset(selectedAsset?: RegisteredAccountAsset): Promise { if (!selectedAsset) return; + await this.updateAssetAddress(selectedAsset.address); + } + + private async updateAssetAddress(address: string): Promise { await this.withSelectAssetLoading(async () => { - await this.setAssetAddress(selectedAsset.address); + await this.setAssetAddress(address); }); } @@ -773,5 +795,9 @@ $bridge-input-color: var(--s-color-base-content-tertiary); line-height: var(--s-line-height-big); color: var(--s-color-base-content-secondary); } + + &-limit-card { + margin-top: $inner-spacing-medium; + } } diff --git a/src/views/BridgeContainer.vue b/src/views/BridgeContainer.vue index 65065713f..6b86e12ec 100644 --- a/src/views/BridgeContainer.vue +++ b/src/views/BridgeContainer.vue @@ -1,7 +1,7 @@