From 7251968ce3e3fcdf7ee7959d11a0baf605e92576 Mon Sep 17 00:00:00 2001 From: poocart <7067483+poocart@users.noreply.github.com> Date: Mon, 23 Oct 2023 15:19:34 +0300 Subject: [PATCH 1/8] fixed staking v2 missing ethereum mainnet mappings (#229) * fixed staking v2 missing ethereum mainnet mappings --- .../PlrStakingV2TransactionBlock.tsx | 63 +++++++++++++------ src/constants/assetConstants.ts | 3 +- src/utils/asset.ts | 13 ---- src/utils/transaction.ts | 6 +- 4 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx b/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx index ba7dfd0e..adeaf79e 100644 --- a/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx +++ b/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx @@ -28,12 +28,13 @@ import { Chain, supportedChains, CHAIN_ID } from '../../utils/chain'; import { swapServiceIdToDetails } from '../../utils/swap'; import { Theme } from '../../utils/theme'; import { bridgeServiceIdToDetails } from '../../utils/bridge'; -import { getPlrAssetForChainId, plrStakedAssetEthereumMainnet } from '../../utils/asset'; +import { getPlrAssetForChainId } from '../../utils/asset'; // constants import { PLR_ADDRESS_PER_CHAIN, PLR_STAKING_ADDRESS_ETHEREUM_MAINNET, + STKPLR_ADDRESS_ETHEREUM_MAINNET, } from '../../constants/assetConstants'; interface ICrossChainSwap { @@ -174,6 +175,7 @@ const PlrStakingV2TransactionBlock = ({ addressPlrBalancePerChain, setAddressPlrBalancePerChain, ] = useState<{ [address: string]: IPlrBalancePerChain }>({}); + const [stkPlrBalance, setStkPlrBalance] = useState(undefined); const hasEnoughPlrToStake = useMemo(() => [providerAddress, accountAddress].some((address) => { if (!address || !addressPlrBalancePerChain?.[address]?.[CHAIN_ID.ETHEREUM_MAINNET]) return false; @@ -210,7 +212,7 @@ const PlrStakingV2TransactionBlock = ({ setSelectedFromNetwork(ethereumMainnetChain); setSelectedToNetwork(ethereumMainnetChain); setSelectedFromAsset(plrAsset); - setSelectedToAsset(plrStakedAssetEthereumMainnet); + setSelectedToAsset({ ...getPlrAssetForChainId(CHAIN_ID.ETHEREUM_MAINNET), symbol: 'stkPLR' }); } else { setSelectedToNetwork(ethereumMainnetChain); setSelectedToAsset(plrAsset); @@ -477,10 +479,14 @@ const PlrStakingV2TransactionBlock = ({ const plrAddressForChain = PLR_ADDRESS_PER_CHAIN[chain.chainId]; + const tokensForBalance = chain.chainId === CHAIN_ID.ETHEREUM_MAINNET + ? [plrAddressForChain, STKPLR_ADDRESS_ETHEREUM_MAINNET] // query for sktPLR balance on ethereum mainnet + : [plrAddressForChain]; + try { const { items: balances } = await sdk.getAccountBalances({ account: address, - tokens: [plrAddressForChain], + tokens: tokensForBalance, chainId: chain.chainId, }); @@ -497,8 +503,14 @@ const PlrStakingV2TransactionBlock = ({ [chain.chainId]: plrBalance, }, })); + + const stkPlrBalance = balances + .find((balance) => addressesEqual(STKPLR_ADDRESS_ETHEREUM_MAINNET, balance.token)) + ?.balance; + + setStkPlrBalance(stkPlrBalance ?? undefined); } catch (e) { - // + console.warn('Failed to get token balances', tokensForBalance, e); } })); })); @@ -571,12 +583,14 @@ const PlrStakingV2TransactionBlock = ({ return sum + walletSum; }, 0), [addressPlrBalancePerChain]); - const isStakingAssetSelected = selectedToAsset?.address === plrStakedAssetEthereumMainnet.address; + const isStakingAssetSelected = addressesEqual(selectedToAsset?.address, getPlrAssetForChainId(CHAIN_ID.ETHEREUM_MAINNET).address); const assetToSelectDisabled = !selectedFromNetwork || !selectedFromAsset || isStakingAssetSelected; + const hasStkPlrBalance = !!stkPlrBalance && stkPlrBalance.gt(0); + return ( <> {!hideTitle && Pillar Validator Staking} @@ -593,21 +607,34 @@ const PlrStakingV2TransactionBlock = ({ {hasEnoughPlrToStake && <>You can stake your PLR tokens.} + {hasStkPlrBalance && ( + + You have + +  {formatAmountDisplay(ethers.utils.formatUnits(stkPlrBalance, 18))} stkPLR + +  tokens: + + )} {plrTokensSum > 0 && ( <> - - You have - -  {formatAmountDisplay(plrTokensSum)} PLR - -  tokens: - + {!hasStkPlrBalance && ( + + You have + +  {formatAmountDisplay(plrTokensSum)} PLR + +  tokens: + + )} {supportedChains .filter((chain) => chainIdsWithPlrTokens.includes(chain.chainId)) .map((chain) => { diff --git a/src/constants/assetConstants.ts b/src/constants/assetConstants.ts index bfee3ee3..f9849a8c 100644 --- a/src/constants/assetConstants.ts +++ b/src/constants/assetConstants.ts @@ -22,5 +22,6 @@ export const PLR_DAO_CONTRACT_PER_CHAIN = { [TESTNET_CHAIN_ID.POLYGON]: '0x23690E5981996cDC5eFc1e126ce9377B9876C95e', }; -// TODO: to be added once available, contract said to be deployed once QA passes UI export const PLR_STAKING_ADDRESS_ETHEREUM_MAINNET = '0x4fa3d9Cf11Dc94e5E0f3BCCa980aA8FB3a0d27f3'; + +export const STKPLR_ADDRESS_ETHEREUM_MAINNET = '0xdfc4575b3cec99d756f45ed22289fa3f1fc530d7'; diff --git a/src/utils/asset.ts b/src/utils/asset.ts index ff5aacda..a7435169 100644 --- a/src/utils/asset.ts +++ b/src/utils/asset.ts @@ -51,16 +51,3 @@ export const getPlrAssetForChainId = (chainId: number, balance: BigNumber = BigN assetPriceUsd: null, balanceWorthUsd: null, }); - -// TODO: replace with actual values once deployed to mainnet, deployment said to happen after qa passes -export const plrStakedAssetEthereumMainnet: IAssetWithBalance = { - address: '0xa6b37fc85d870711c56fbcb8afe2f8db049ae774', - chainId: CHAIN_ID.ETHEREUM_MAINNET, - name: 'Staked Pillar', - symbol: 'stkPLR', - decimals: 18, - logoURI: 'https://assets.coingecko.com/coins/images/809/small/v2logo-1.png', - balance: BigNumber.from(0), - assetPriceUsd: null, - balanceWorthUsd: null, -}; diff --git a/src/utils/transaction.ts b/src/utils/transaction.ts index ce288dda..9aa84911 100644 --- a/src/utils/transaction.ts +++ b/src/utils/transaction.ts @@ -26,7 +26,7 @@ import { map as rxjsMap } from 'rxjs/operators'; import { TRANSACTION_BLOCK_TYPE } from '../constants/transactionBuilderConstants'; import { addressesEqual, isValidEthereumAddress, isZeroAddress } from './validation'; import { CHAIN_ID, changeToChain, nativeAssetPerChainId, plrDaoMemberNft, supportedChains } from './chain'; -import { plrDaoAsset, plrDaoAssetPerChainId, plrStakedAssetEthereumMainnet } from './asset'; +import { getPlrAssetForChainId, plrDaoAsset, plrDaoAssetPerChainId } from './asset'; import { parseEtherspotErrorMessageIfAvailable } from './etherspot'; import { getAssetPriceInUsd, getNativeAssetPriceInUsd } from '../services/coingecko'; import { bridgeServiceIdToDetails } from './bridge'; @@ -46,8 +46,6 @@ import { POLYGON_USDC_CONTRACT_ADDRESS, } from '../constants/assetConstants'; import { PlrV2StakingContract } from '../types/etherspotContracts'; -import { UNISWAP_ROUTER_ABI } from '../constants/uniswapRouterAbi'; -import { UniswapV2RouterContract } from '../contracts/UniswapV2Router'; import { MAX_PLR_TOKEN_LIMIT } from '../components/TransactionBlock/PlrDaoStakingTransactionBlock'; interface IPillarDao { @@ -1896,7 +1894,7 @@ export const buildCrossChainAction = async ( const fromAmountBN = ethers.utils.parseUnits(amount, fromAssetDecimals); - let toAssetAmount = addressesEqual(toAssetAddress, plrStakedAssetEthereumMainnet.address) ? fromAmountBN : '0'; + let toAssetAmount = addressesEqual(toAssetAddress, getPlrAssetForChainId(CHAIN_ID.ETHEREUM_MAINNET).address) ? fromAmountBN : '0'; let providerName; let providerIconUrl; From f28a526d8f2ff163207aaed11444898a2da7988e Mon Sep 17 00:00:00 2001 From: poocart <7067483+poocart@users.noreply.github.com> Date: Mon, 23 Oct 2023 17:22:43 +0300 Subject: [PATCH 2/8] PLR staking buidler block display offers if staking asset selected --- .../TransactionBlock/PlrStakingV2TransactionBlock.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx b/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx index adeaf79e..98bd7e41 100644 --- a/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx +++ b/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx @@ -782,8 +782,7 @@ const PlrStakingV2TransactionBlock = ({ hideKeyBased={smartWalletOnly || isEtherspotPrime(etherspotMode)} /> - {!isStakingAssetSelected && - !!selectedToAsset && + {!!selectedToAsset && !!selectedFromAsset && !!amount && (remainingSelectedFromAssetBalance ?? 0) >= 0 && ( From a245dfa91f456659cf2c3e5307c21db0df6e8fd4 Mon Sep 17 00:00:00 2001 From: poocart <7067483+poocart@users.noreply.github.com> Date: Mon, 23 Oct 2023 21:51:04 +0300 Subject: [PATCH 3/8] fixed stkplr staking action, fixed wallet block appearance --- .../PlrStakingV2TransactionBlock.tsx | 29 ++++++++++++------- .../TransactionBuilderContextProvider.tsx | 3 -- src/utils/asset.ts | 17 ++++++++++- src/utils/transaction.ts | 6 ++-- src/utils/validation.ts | 9 ++++-- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx b/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx index 98bd7e41..bb4a1a31 100644 --- a/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx +++ b/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx @@ -28,12 +28,11 @@ import { Chain, supportedChains, CHAIN_ID } from '../../utils/chain'; import { swapServiceIdToDetails } from '../../utils/swap'; import { Theme } from '../../utils/theme'; import { bridgeServiceIdToDetails } from '../../utils/bridge'; -import { getPlrAssetForChainId } from '../../utils/asset'; +import { getPlrAssetForChainId, stkPlrAsset } from '../../utils/asset'; // constants import { PLR_ADDRESS_PER_CHAIN, - PLR_STAKING_ADDRESS_ETHEREUM_MAINNET, STKPLR_ADDRESS_ETHEREUM_MAINNET, } from '../../constants/assetConstants'; @@ -139,7 +138,7 @@ const mapRouteToOption = (route: Route) => { interface IPlrBalancePerChain { [chainId: string]: BigNumber | undefined } -const MIN_PLR_STAKE_AMOUNT = '10000'; +const MIN_PLR_STAKE_AMOUNT = '50'; const chainIdsWithPlrTokens = [CHAIN_ID.ETHEREUM_MAINNET, CHAIN_ID.BINANCE, CHAIN_ID.XDAI, CHAIN_ID.POLYGON]; @@ -208,16 +207,23 @@ const PlrStakingV2TransactionBlock = ({ addressPlrBalancePerChain?.[balanceAddress]?.[CHAIN_ID.ETHEREUM_MAINNET] as BigNumber ); - if (isEnoughPlrBalanceToStake(addressPlrBalancePerChain?.[providerAddress]?.[CHAIN_ID.ETHEREUM_MAINNET])) { - setSelectedFromNetwork(ethereumMainnetChain); + if (isEnoughPlrBalanceToStake(addressPlrBalancePerChain?.[balanceAddress]?.[CHAIN_ID.ETHEREUM_MAINNET]) + && (!selectedFromAsset || addressesEqual(selectedFromAsset?.address, plrAsset.address))) { + if (!selectedFromNetwork) { + setSelectedFromNetwork(ethereumMainnetChain); + } + if (!selectedFromAsset) { + setSelectedFromAsset(plrAsset); + } setSelectedToNetwork(ethereumMainnetChain); - setSelectedFromAsset(plrAsset); - setSelectedToAsset({ ...getPlrAssetForChainId(CHAIN_ID.ETHEREUM_MAINNET), symbol: 'stkPLR' }); - } else { + setSelectedToAsset(stkPlrAsset); + } else if (!addressesEqual(selectedFromAsset?.address, plrAsset.address)) { setSelectedToNetwork(ethereumMainnetChain); setSelectedToAsset(plrAsset); } }, [ + selectedFromAsset, + selectedFromNetwork, addressPlrBalancePerChain, selectedAccountType, providerAddress, @@ -421,7 +427,7 @@ const PlrStakingV2TransactionBlock = ({ route, } } else if (selectedFromNetwork?.chainId === selectedToNetwork?.chainId - && !addressesEqual(selectedFromAsset?.address, PLR_STAKING_ADDRESS_ETHEREUM_MAINNET)) { + && !addressesEqual(selectedFromAsset?.address, stkPlrAsset.address)) { const offer = availableOffers?.find((availableOffer) => availableOffer.provider === selectedOffer?.value); swap = { type: 'SAME_CHAIN_SWAP', @@ -583,7 +589,7 @@ const PlrStakingV2TransactionBlock = ({ return sum + walletSum; }, 0), [addressPlrBalancePerChain]); - const isStakingAssetSelected = addressesEqual(selectedToAsset?.address, getPlrAssetForChainId(CHAIN_ID.ETHEREUM_MAINNET).address); + const isStakingAssetSelected = addressesEqual(selectedToAsset?.address, stkPlrAsset.address); const assetToSelectDisabled = !selectedFromNetwork || !selectedFromAsset @@ -782,7 +788,8 @@ const PlrStakingV2TransactionBlock = ({ hideKeyBased={smartWalletOnly || isEtherspotPrime(etherspotMode)} /> - {!!selectedToAsset && + {!isStakingAssetSelected && + !!selectedToAsset && !!selectedFromAsset && !!amount && (remainingSelectedFromAssetBalance ?? 0) >= 0 && ( diff --git a/src/providers/TransactionBuilderContextProvider.tsx b/src/providers/TransactionBuilderContextProvider.tsx index 238e0d86..e76577ea 100644 --- a/src/providers/TransactionBuilderContextProvider.tsx +++ b/src/providers/TransactionBuilderContextProvider.tsx @@ -1119,7 +1119,6 @@ const TransactionBuilderContextProvider = ({ !crossChainActionClick ) { if (transactionBlocks?.length === 0 && crossChainActions.length === 0) { - setShowWalletBlock(!mappedDefaultTransactionBlocks?.length && !hideWalletBlock); if (mappedDefaultTransactionBlocks?.length) setTransactionBlocks(mappedDefaultTransactionBlocks); } } @@ -1131,9 +1130,7 @@ const TransactionBuilderContextProvider = ({ crossChainActions, isSubmitting, crossChainActionClick, - hideWalletBlock, mappedDefaultTransactionBlocks, - showWalletBlock, ]); return ( diff --git a/src/utils/asset.ts b/src/utils/asset.ts index a7435169..8d10b41f 100644 --- a/src/utils/asset.ts +++ b/src/utils/asset.ts @@ -1,7 +1,10 @@ import { BigNumber } from 'ethers'; import { IAssetWithBalance } from '../providers/EtherspotContextProvider'; import { CHAIN_ID, MAINNET_CHAIN_ID, TESTNET_CHAIN_ID } from './chain'; -import { PLR_ADDRESS_PER_CHAIN } from '../constants/assetConstants'; +import { + PLR_ADDRESS_PER_CHAIN, + STKPLR_ADDRESS_ETHEREUM_MAINNET +} from '../constants/assetConstants'; export const plrDaoAsset: IAssetWithBalance = { address: '0xa6b37fc85d870711c56fbcb8afe2f8db049ae774', @@ -51,3 +54,15 @@ export const getPlrAssetForChainId = (chainId: number, balance: BigNumber = BigN assetPriceUsd: null, balanceWorthUsd: null, }); + +export const stkPlrAsset = { + address: STKPLR_ADDRESS_ETHEREUM_MAINNET, + chainId: CHAIN_ID.ETHEREUM_MAINNET, + name: 'Staked Pillar', + symbol: 'stkPLR', + decimals: 18, + logoURI: 'https://assets.coingecko.com/coins/images/809/small/v2logo-1.png', + balance: BigNumber.from(0), + assetPriceUsd: null, + balanceWorthUsd: null, +} diff --git a/src/utils/transaction.ts b/src/utils/transaction.ts index 9aa84911..d1b953d5 100644 --- a/src/utils/transaction.ts +++ b/src/utils/transaction.ts @@ -26,7 +26,7 @@ import { map as rxjsMap } from 'rxjs/operators'; import { TRANSACTION_BLOCK_TYPE } from '../constants/transactionBuilderConstants'; import { addressesEqual, isValidEthereumAddress, isZeroAddress } from './validation'; import { CHAIN_ID, changeToChain, nativeAssetPerChainId, plrDaoMemberNft, supportedChains } from './chain'; -import { getPlrAssetForChainId, plrDaoAsset, plrDaoAssetPerChainId } from './asset'; +import { plrDaoAsset, plrDaoAssetPerChainId, stkPlrAsset } from './asset'; import { parseEtherspotErrorMessageIfAvailable } from './etherspot'; import { getAssetPriceInUsd, getNativeAssetPriceInUsd } from '../services/coingecko'; import { bridgeServiceIdToDetails } from './bridge'; @@ -1894,7 +1894,7 @@ export const buildCrossChainAction = async ( const fromAmountBN = ethers.utils.parseUnits(amount, fromAssetDecimals); - let toAssetAmount = addressesEqual(toAssetAddress, getPlrAssetForChainId(CHAIN_ID.ETHEREUM_MAINNET).address) ? fromAmountBN : '0'; + let toAssetAmount = addressesEqual(toAssetAddress, stkPlrAsset.address) ? fromAmountBN : '0'; let providerName; let providerIconUrl; @@ -1935,7 +1935,7 @@ export const buildCrossChainAction = async ( } catch (e) { return { errorMessage: 'Failed to build cross chain swap transaction!' }; } - } else if (addressesEqual(toAssetAddress, PLR_STAKING_ADDRESS_ETHEREUM_MAINNET)) { + } else if (addressesEqual(toAssetAddress, stkPlrAsset.address)) { try { const plrV2StakingContract = sdk.registerContract( 'plrV2StakingContract', diff --git a/src/utils/validation.ts b/src/utils/validation.ts index 1016cfc3..2bc37984 100644 --- a/src/utils/validation.ts +++ b/src/utils/validation.ts @@ -11,6 +11,7 @@ import { IPlrDaoTransactionBlockValues } from '../components/TransactionBlock/Pl import { IPlrStakingV2BlockValues } from '../components/TransactionBlock/PlrStakingV2TransactionBlock'; import { IHoneySwapLPTransactionBlockValues } from '../components/TransactionBlock/HoneySwapLPTransactionBlock'; import { GNOSIS_USDC_CONTRACT_ADDRESS } from '../constants/assetConstants'; +import { stkPlrAsset } from './asset'; export const isValidEthereumAddress = (address: string | undefined): boolean => { if (!address) return false; @@ -110,10 +111,14 @@ export const validateTransactionBlockValues = (transactionBlock: ITransactionBlo if (!isValidAmount(transactionBlockValues?.amount)) errors.amount = 'Incorrect asset amount!'; if (!transactionBlockValues?.fromAsset) errors.fromAsset = 'Invalid source asset selected!'; if (!transactionBlockValues?.toAsset) errors.toAsset = 'Invalid destination asset selected!'; - if (transactionBlockValues?.swap?.type === 'CROSS_CHAIN_SWAP' && !transactionBlockValues?.swap?.route) { + if (transactionBlockValues?.swap?.type === 'CROSS_CHAIN_SWAP' + && !transactionBlockValues?.swap?.route + && !addressesEqual(transactionBlockValues?.toAsset?.address, stkPlrAsset.address)) { errors.route = 'No route selected!'; } - if (transactionBlockValues?.swap?.type === 'SAME_CHAIN_SWAP' && !transactionBlockValues?.swap?.offer) { + if (transactionBlockValues?.swap?.type === 'SAME_CHAIN_SWAP' + && !transactionBlockValues?.swap?.offer + && !addressesEqual(transactionBlockValues?.toAsset?.address, stkPlrAsset.address)) { errors.route = 'No offer selected!'; } if (transactionBlockValues?.receiverAddress && !isValidEthereumAddress(transactionBlockValues?.receiverAddress)) { From cb755c70af4ee5cb15933173c03ba73b398d81fc Mon Sep 17 00:00:00 2001 From: poocart <7067483+poocart@users.noreply.github.com> Date: Mon, 23 Oct 2023 21:52:17 +0300 Subject: [PATCH 4/8] fixed min plr stake amount --- .../TransactionBlock/PlrStakingV2TransactionBlock.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx b/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx index bb4a1a31..56d0f0d0 100644 --- a/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx +++ b/src/components/TransactionBlock/PlrStakingV2TransactionBlock.tsx @@ -138,7 +138,7 @@ const mapRouteToOption = (route: Route) => { interface IPlrBalancePerChain { [chainId: string]: BigNumber | undefined } -const MIN_PLR_STAKE_AMOUNT = '50'; +const MIN_PLR_STAKE_AMOUNT = '10000'; const chainIdsWithPlrTokens = [CHAIN_ID.ETHEREUM_MAINNET, CHAIN_ID.BINANCE, CHAIN_ID.XDAI, CHAIN_ID.POLYGON]; From cbff41740280e35978a9bbbeeb16e7c1c7d00302 Mon Sep 17 00:00:00 2001 From: poocart <7067483+poocart@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:51:49 +0300 Subject: [PATCH 5/8] fixed plr staking cross chain swap txs --- src/utils/transaction.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/utils/transaction.ts b/src/utils/transaction.ts index d1b953d5..5d3c20a2 100644 --- a/src/utils/transaction.ts +++ b/src/utils/transaction.ts @@ -1930,7 +1930,9 @@ export const buildCrossChainAction = async ( if (routeData.errorMessage) return { errorMessage: routeData.errorMessage }; if (!routeData.bestRoute) return { errorMessage: 'Failed build swap transaction!' }; - transactions = routeData.destinationTxns ?? []; + transactions = routeData.transactions ?? []; + if (!transactions.length) return { errorMessage: 'Failed build swap transactions!' }; + toAssetAmount = BigNumber.from(routeData.bestRoute.toAmount); } catch (e) { return { errorMessage: 'Failed to build cross chain swap transaction!' }; @@ -2003,10 +2005,15 @@ export const buildCrossChainAction = async ( } } - if (receiverAddress && isValidEthereumAddress(receiverAddress)) { + // cross chain swaps transfers to receiver already + if (receiverAddress + && isValidEthereumAddress(receiverAddress) + && !addressesEqual(toAssetAddress, nativeAssetPerChainId[toChainId].address) + && transactions.length > 0 + && swap?.type !== 'CROSS_CHAIN_SWAP') { try { const abi = getContractAbi(ContractNames.ERC20Token); - const erc20Contract = sdk.registerContract('erc20Contract', abi, fromAssetAddress); + const erc20Contract = sdk.registerContract('erc20Contract', abi, toAssetAddress); const transferTransactionRequest = erc20Contract?.encodeTransfer?.(receiverAddress, toAssetAmount); if (!transferTransactionRequest || !transferTransactionRequest.to) { return { errorMessage: 'Failed build transfer transaction!' }; From 89afbc9e4667b9eac9b23f06a341ed1ae948a051 Mon Sep 17 00:00:00 2001 From: poocart <7067483+poocart@users.noreply.github.com> Date: Tue, 24 Oct 2023 17:20:52 +0300 Subject: [PATCH 6/8] fixed plr staking cross chain route txs mapping --- src/utils/transaction.ts | 139 ++++++--------------------------------- 1 file changed, 19 insertions(+), 120 deletions(-) diff --git a/src/utils/transaction.ts b/src/utils/transaction.ts index 5d3c20a2..72d12635 100644 --- a/src/utils/transaction.ts +++ b/src/utils/transaction.ts @@ -1,7 +1,5 @@ import { AccountTypes, - BridgingQuote, - CrossChainServiceProvider, ExchangeOffer, GatewayTransactionStates, LiFiStatus, @@ -12,7 +10,7 @@ import { Web3WalletProvider, } from 'etherspot'; import { Route } from '@lifi/sdk'; -import { BigNumber, BigNumberish, ethers, utils } from 'ethers'; +import { BigNumber, BigNumberish, ethers } from 'ethers'; import { uniqueId } from 'lodash'; import { ERC20TokenContract } from 'etherspot/dist/sdk/contract/internal/erc20-token.contract'; @@ -26,7 +24,7 @@ import { map as rxjsMap } from 'rxjs/operators'; import { TRANSACTION_BLOCK_TYPE } from '../constants/transactionBuilderConstants'; import { addressesEqual, isValidEthereumAddress, isZeroAddress } from './validation'; import { CHAIN_ID, changeToChain, nativeAssetPerChainId, plrDaoMemberNft, supportedChains } from './chain'; -import { plrDaoAsset, plrDaoAssetPerChainId, stkPlrAsset } from './asset'; +import { plrDaoAssetPerChainId, stkPlrAsset } from './asset'; import { parseEtherspotErrorMessageIfAvailable } from './etherspot'; import { getAssetPriceInUsd, getNativeAssetPriceInUsd } from '../services/coingecko'; import { bridgeServiceIdToDetails } from './bridge'; @@ -68,97 +66,6 @@ interface IPlrTransaction { status: string; } -const fetchBestRoute = async ( - sdk: EtherspotSdk, - fromChainId: number, - toChainId: number, - fromAmount: BigNumber, - fromTokenAddress: string, - toTokenAddress: string, - toAddress?: string -) => { - try { - const createTimestamp = +new Date(); - const routes = await sdk.getAdvanceRoutesLiFi({ - fromChainId, - toChainId, //Polygon - fromAmount, - fromTokenAddress, - toTokenAddress, - toAddress, - }); - const bestRoute = routes.items.reduce((best: Route, route) => { - if (!best?.toAmount || BigNumber.from(best.toAmount).lt(route.toAmount)) return route; - return best; - }); - - if (!bestRoute) { - return { errorMessage: 'Failed to get bridge route' }; - } - const { items: advancedRouteSteps } = await sdk.getStepTransaction({ route: bestRoute }); - - let destinationTxns: ICrossChainActionTransaction[] = []; - let transactions: ICrossChainActionTransaction[] = []; - - if (bestRoute.containsSwitchChain) { - advancedRouteSteps.forEach((step) => { - if (step.chainId === plrDaoAsset.chainId) { - return destinationTxns.push({ - to: step.to as string, - value: step.value, - data: step.data, - createTimestamp, - status: CROSS_CHAIN_ACTION_STATUS.UNSENT, - }); - } - return transactions.push({ - to: step.to as string, - value: step.value, - data: step.data, - createTimestamp, - status: CROSS_CHAIN_ACTION_STATUS.UNSENT, - }); - }); - } else { - transactions = advancedRouteSteps.map(({ to, value, data, chainId }) => ({ - to: to as string, - value, - data, - chainId: chainId ?? fromChainId, - createTimestamp, - status: CROSS_CHAIN_ACTION_STATUS.UNSENT, - })); - } - - if ( - ethers.utils.isAddress(bestRoute.fromToken.address) && - !addressesEqual(bestRoute.fromToken.address, nativeAssetPerChainId[fromChainId].address) && - transactions.length === 1 && - bestRoute.fromAmount - ) { - const abi = getContractAbi(ContractNames.ERC20Token); - const erc20Contract = sdk.registerContract('erc20Contract', abi, bestRoute.fromToken.address); - const approvalTransactionRequest = erc20Contract?.encodeApprove?.(transactions[0].to, bestRoute.fromAmount); - if (!approvalTransactionRequest || !approvalTransactionRequest.to) { - return { errorMessage: 'Failed build bridge approval transaction!' }; - } - - const approvalTransaction = { - to: approvalTransactionRequest.to, - data: approvalTransactionRequest.data, - value: 0, - createTimestamp, - status: CROSS_CHAIN_ACTION_STATUS.UNSENT, - }; - - transactions = [approvalTransaction, ...transactions]; - } - return { bestRoute, transactions, destinationTxns }; - } catch (err) { - return { errorMessage: 'Failed to get bridge route' }; - } -}; - const fetchSwapAssetTransaction = async ( chainId: number, fromAmountBN: BigNumber, @@ -230,22 +137,27 @@ const fetchSwapAssetTransaction = async ( } }; -const buildBridgeAssetToPlrTransactions = async ( +const buildLiFiBridgeTransactions = async ( chainId: number, route: Route | null, sdk?: EtherspotSdk | null -): Promise<{ errorMessage?: string; result?: { transactions: ICrossChainActionTransaction[] } }> => { +): Promise<{ errorMessage?: string; transactions?: ICrossChainActionTransaction[] }> => { try { const createTimestamp = +new Date(); if (!sdk) return { errorMessage: 'No sdk found' }; if (!route) return { errorMessage: 'Failed to fetch routes' }; const { items: advancedRouteSteps } = await sdk.getStepTransaction({ route }); - let transactions: ICrossChainActionTransaction[] = advancedRouteSteps.map(({ to, value, data, chainId }) => ({ + let transactions: ICrossChainActionTransaction[] = advancedRouteSteps.map(({ + to, + value, + data, + chainId: routeChainId + }) => ({ to: to as string, value, data, - chainId: chainId, + chainId: routeChainId, createTimestamp, status: CROSS_CHAIN_ACTION_STATUS.UNSENT, })); @@ -273,7 +185,7 @@ const buildBridgeAssetToPlrTransactions = async ( transactions = [approvalTransaction, ...transactions]; } - return { result: { transactions } }; + return { transactions }; } catch (err) { return { errorMessage: 'Failed build transfer transaction!' }; } @@ -1020,7 +932,7 @@ export const buildCrossChainAction = async ( route, }; - const result = await buildBridgeAssetToPlrTransactions(fromChainId, route, sdk); + const result = await buildLiFiBridgeTransactions(fromChainId, route, sdk); if (result?.errorMessage) return { errorMessage: result.errorMessage }; const crossChainAction: ICrossChainAction = { @@ -1029,7 +941,7 @@ export const buildCrossChainAction = async ( chainId: fromChainId, type: TRANSACTION_BLOCK_TYPE.PLR_DAO_STAKE, preview, - transactions: result?.result?.transactions || [], + transactions: result?.transactions || [], destinationCrossChainAction: [], isEstimating: false, estimated: null, @@ -1916,27 +1828,14 @@ export const buildCrossChainAction = async ( return { errorMessage: 'Failed to build same chain swap transaction!' }; } } else if (swap?.type === 'CROSS_CHAIN_SWAP' && swap.route) { - try { - const routeData = await fetchBestRoute( - sdk, - fromChainId, - toChainId, - fromAmountBN, - fromAssetAddress, - toAssetAddress, - receiverAddress - ); + const result = await buildLiFiBridgeTransactions(fromChainId, swap.route, sdk); - if (routeData.errorMessage) return { errorMessage: routeData.errorMessage }; - if (!routeData.bestRoute) return { errorMessage: 'Failed build swap transaction!' }; + if (result?.errorMessage) return { errorMessage: result.errorMessage }; - transactions = routeData.transactions ?? []; - if (!transactions.length) return { errorMessage: 'Failed build swap transactions!' }; + if (!result?.transactions?.length) return { errorMessage: 'Failed build swap transactions!' }; - toAssetAmount = BigNumber.from(routeData.bestRoute.toAmount); - } catch (e) { - return { errorMessage: 'Failed to build cross chain swap transaction!' }; - } + transactions = result.transactions; + toAssetAmount = BigNumber.from(swap.route.toAmount); } else if (addressesEqual(toAssetAddress, stkPlrAsset.address)) { try { const plrV2StakingContract = sdk.registerContract( From 332352bfee0fc45bcddad776a292b570e4fc3ad7 Mon Sep 17 00:00:00 2001 From: poocart <7067483+poocart@users.noreply.github.com> Date: Thu, 26 Oct 2023 09:13:08 +0300 Subject: [PATCH 7/8] honeyswap block default account eoa --- package.json | 2 +- .../HoneySwapLPTransactionBlock.tsx | 25 ++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 34fdc82f..49de96b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@etherspot/react-transaction-buidler", - "version": "0.26.10", + "version": "0.26.11", "description": "Etherspot React component.", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", diff --git a/src/components/TransactionBlock/HoneySwapLPTransactionBlock.tsx b/src/components/TransactionBlock/HoneySwapLPTransactionBlock.tsx index ce39c2af..ca64725d 100644 --- a/src/components/TransactionBlock/HoneySwapLPTransactionBlock.tsx +++ b/src/components/TransactionBlock/HoneySwapLPTransactionBlock.tsx @@ -1,21 +1,20 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { debounce } from 'lodash'; import styled, { useTheme } from 'styled-components'; -import { AccountStates, AccountTypes, BridgingQuote, CrossChainServiceProvider, ExchangeOffer } from 'etherspot'; +import { AccountStates, AccountTypes, ExchangeOffer } from 'etherspot'; import { Route } from '@lifi/sdk'; -import { BigNumber, ethers, utils } from 'ethers'; +import { BigNumber, ethers } from 'ethers'; // Types -import { IHoneySwapLPBlock, IKlimaStakingTransactionBlock } from '../../types/transactionBlock'; +import { IHoneySwapLPBlock } from '../../types/transactionBlock'; // Components import { useEtherspot, useTransactionBuilder } from '../../hooks'; import AccountSwitchInput from '../AccountSwitchInput'; import NetworkAssetSelectInput from '../NetworkAssetSelectInput'; -import { CombinedRoundedImages, RoundedImage } from '../Image'; +import { CombinedRoundedImages } from '../Image'; import TextInput from '../TextInput'; import { Pill } from '../Text'; -import Text from '../Text/Text'; import SelectInput from '../SelectInput'; import { SelectOption } from '../SelectInput/SelectInput'; @@ -24,22 +23,20 @@ import { IAssetWithBalance } from '../../providers/EtherspotContextProvider'; // utils import { formatAmountDisplay, formatAssetAmountInput, formatMaxAmount, isEtherspotPrime } from '../../utils/common'; -import { addressesEqual, isValidAmount, isValidEthereumAddress } from '../../utils/validation'; +import { isValidAmount, isValidEthereumAddress } from '../../utils/validation'; import { Theme } from '../../utils/theme'; -import { Chain, CHAIN_ID, supportedChains, klimaAsset } from '../../utils/chain'; +import { Chain, CHAIN_ID, supportedChains } from '../../utils/chain'; // constants import { bridgeServiceIdToDetails } from '../../utils/bridge'; -import { DestinationWalletEnum } from '../../enums/wallet.enum'; +import { GNOSIS_USDC_CONTRACT_ADDRESS } from '../../constants/assetConstants'; // hooks -import useAssetPriceUsd from '../../hooks/useAssetPriceUsd'; -import { BiCheck } from 'react-icons/bi'; -import { getNativeAssetPriceInUsd } from '../../services/coingecko'; -import RouteOption from '../RouteOption/RouteOption'; -import { GNOSIS_USDC_CONTRACT_ADDRESS } from '../../constants/assetConstants'; import HoneySwapRoute from '../HoneySwapRoute/HoneySwapRoute'; +// services +import { getNativeAssetPriceInUsd } from '../../services/coingecko'; + export interface IHoneySwapLPTransactionBlockValues { fromChainId?: number; fromAssetAddress?: string; @@ -98,7 +95,7 @@ const HoneySwapLPTransactionBlock = ({ const { smartWalletOnly, providerAddress, accountAddress, sdk, getSdkForChainId, etherspotMode } = useEtherspot(); const [amount, setAmount] = useState(''); const [selectedFromAsset, setSelectedFromAsset] = useState(null); - const [selectedAccountType, setSelectedAccountType] = useState(AccountTypes.Contract); + const [selectedAccountType, setSelectedAccountType] = useState(AccountTypes.Key); const [selectedFromNetwork, setSelectedFromNetwork] = useState(null); const [receiveAmount, setReceiveAmount] = useState(''); const [routeToUSDC, setRouteToUSDC] = useState([]); From 1e58848f20a74749a6f50bdf8ef6af23d5d2a148 Mon Sep 17 00:00:00 2001 From: poocart <7067483+poocart@users.noreply.github.com> Date: Thu, 26 Oct 2023 09:42:42 +0300 Subject: [PATCH 8/8] eoa chain switch fix, eoa reject loop fix --- src/utils/transaction.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/utils/transaction.ts b/src/utils/transaction.ts index 72d12635..39c8a300 100644 --- a/src/utils/transaction.ts +++ b/src/utils/transaction.ts @@ -2148,9 +2148,16 @@ export const submitWeb3ProviderTransaction = async ( return { errorMessage: 'Unable to find connected Web3 provider!' }; } - // TODO: check against current + let currentChainId; + try { + // @ts-ignore + currentChainId = +ethers.BigNumber.from(web3Provider.web3.chainId).toString(); + } catch (e) { + console.warn('Unable to extract current chain ID'); + } + // @ts-ignore - if (chainId !== 1 && web3Provider?.type !== 'WalletConnect') { + if (chainId !== currentChainId && web3Provider?.type !== 'WalletConnect') { const changed = await changeToChain(chainId); if (!changed) return { errorMessage: 'Unable to change to selected network!' }; } @@ -2171,7 +2178,7 @@ export const submitWeb3ProviderTransaction = async ( } } - if (waitForCompleted) { + if (transactionHash && waitForCompleted) { let transactionStatus = null; while (transactionStatus === null) {