diff --git a/package.json b/package.json index 903b6d684..799525ae4 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "@rabby-wallet/gnosis-sdk": "1.3.9", "@rabby-wallet/page-provider": "0.4.2", "@rabby-wallet/rabby-action": "0.1.8", - "@rabby-wallet/rabby-api": "0.8.5", + "@rabby-wallet/rabby-api": "0.9.2", "@rabby-wallet/rabby-security-engine": "2.0.7", "@rabby-wallet/rabby-swap": "0.0.42", "@rabby-wallet/widgets": "1.0.9", diff --git a/src/background/controller/wallet.ts b/src/background/controller/wallet.ts index d38428ba3..0168c7a71 100644 --- a/src/background/controller/wallet.ts +++ b/src/background/controller/wallet.ts @@ -141,8 +141,6 @@ import { getEnsContentHash } from './ens'; const stashKeyrings: Record = {}; -const MAX_UNSIGNED_256_INT = new BigNumber(2).pow(256).minus(1).toString(10); - export class WalletController extends BaseController { openapi = openapiService; testnetOpenapi = testnetOpenapiService; @@ -5047,6 +5045,60 @@ export class WalletController extends BaseController { getEnsContentHash = getEnsContentHash; validateSafeConfirmation = validateConfirmation; + + gasMarketV2 = async ( + params: + | { + chain: Chain; + tx: Tx; + customGas?: number; + } + | { + chainId: string; + customGas?: number; + } + ) => { + let chainId: string; + let tx: Tx | undefined; + + if ('tx' in params) { + if (params.tx.nonce === undefined) { + params.tx.nonce = await this.getRecommendNonce({ + from: params.tx.from, + chainId: params.chain.id, + }); + } + + if (params.tx.gasPrice === undefined || params.tx.gasPrice === '') { + params.tx.gasPrice = '0x0'; + } + if (params.tx.gas === undefined || params.tx.gas === '') { + params.tx.gas = '0x0'; + } + if (params.tx.data === undefined || params.tx.data === '') { + params.tx.data = '0x'; + } + chainId = params.chain.serverId; + tx = { + chainId: params.tx.chainId, + data: params.tx.data, + from: params.tx.from, + gas: params.tx.gas, + nonce: params.tx.nonce, + to: params.tx.to, + value: params.tx.value, + gasPrice: params.tx.gasPrice, + }; + } else { + chainId = params.chainId; + } + + return openapiService.gasMarketV2({ + customGas: params.customGas, + chainId, + tx, + }); + }; } const wallet = new WalletController(); diff --git a/src/ui/utils/sendTransaction.ts b/src/ui/utils/sendTransaction.ts index 11c24cd38..3d0f26745 100644 --- a/src/ui/utils/sendTransaction.ts +++ b/src/ui/utils/sendTransaction.ts @@ -143,7 +143,10 @@ export const sendTransaction = async ({ // get gas let normalGas = gasLevel; if (!normalGas) { - const gasMarket = await wallet.openapi.gasMarket(chainServerId); + const gasMarket = await wallet.gasMarketV2({ + chain, + tx, + }); normalGas = gasMarket.find((item) => item.level === 'normal')!; } diff --git a/src/ui/views/Approval/components/MiniSignTx/index.tsx b/src/ui/views/Approval/components/MiniSignTx/index.tsx index 82180835e..811778fa2 100644 --- a/src/ui/views/Approval/components/MiniSignTx/index.tsx +++ b/src/ui/views/Approval/components/MiniSignTx/index.tsx @@ -462,10 +462,11 @@ export const MiniSignTx = ({ chain: Chain, custom?: number ): Promise => { - const list = await wallet.openapi.gasMarket( - chain.serverId, - custom && custom > 0 ? custom : undefined - ); + const list = await wallet.gasMarketV2({ + chain, + customGas: custom && custom > 0 ? custom : undefined, + tx: txs[0], + }); setGasList(list); return list; }; @@ -850,6 +851,7 @@ export const MiniSignTx = ({ className={clsx(task.status !== 'idle' && 'pointer-events-none')} > { { chain: Chain, custom?: number ): Promise => { - const list = await wallet.openapi.gasMarket( - chain.serverId, - custom && custom > 0 ? custom : undefined - ); + const list = await wallet.gasMarketV2({ + chain, + customGas: custom && custom > 0 ? custom : undefined, + tx, + }); setGasList(list); return list; }; @@ -2002,6 +2003,7 @@ const SignTx = ({ params, origin }: SignTxProps) => { { const wallet = useWallet(); const dispatch = useRabbyDispatch(); @@ -350,10 +352,11 @@ const GasSelectorHeader = ({ const loadCustomGasData = useCallback( async (custom?: number): Promise => { - const list = await wallet.openapi.gasMarket( - chain.serverId, - custom && custom > 0 ? custom : undefined - ); + const list = await wallet.gasMarketV2({ + chain, + customGas: custom && custom > 0 ? custom : undefined, + tx, + }); return list.find((item) => item.level === 'custom')!; }, [] diff --git a/src/ui/views/Dashboard/components/GasPriceBar/index.tsx b/src/ui/views/Dashboard/components/GasPriceBar/index.tsx index f2cde451f..f571afad7 100644 --- a/src/ui/views/Dashboard/components/GasPriceBar/index.tsx +++ b/src/ui/views/Dashboard/components/GasPriceBar/index.tsx @@ -40,7 +40,9 @@ export const GasPriceBar: React.FC = ({ currentConnectedSiteChain }) => { ? await wallet.getCustomTestnetGasMarket({ chainId: chain?.id, }) - : await wallet.openapi.gasMarket(currentConnectedSiteChainNativeToken); + : await wallet.gasMarketV2({ + chainId: currentConnectedSiteChainNativeToken, + }); const selectedGasPice = marketGas.find((item) => item.level === 'slow') ?.price; if (selectedGasPice) { diff --git a/src/ui/views/Ecology/dbk-chain/pages/Bridge/hooks/useDbkChainBridge.ts b/src/ui/views/Ecology/dbk-chain/pages/Bridge/hooks/useDbkChainBridge.ts index 25fbad134..1246eba5d 100644 --- a/src/ui/views/Ecology/dbk-chain/pages/Bridge/hooks/useDbkChainBridge.ts +++ b/src/ui/views/Ecology/dbk-chain/pages/Bridge/hooks/useDbkChainBridge.ts @@ -215,7 +215,7 @@ export const useDbkChainBridge = ({ ); const fetchGasPrice = useMemoizedFn(async (serverId: string) => { - const marketGas = await wallet.openapi.gasMarket(serverId); + const marketGas = await wallet.gasMarketV2({ chainId: serverId }); const selectedGasPice = marketGas.find((item) => item.level === 'normal'); return selectedGasPice; }); diff --git a/src/ui/views/SendToken/index.tsx b/src/ui/views/SendToken/index.tsx index ad2002b56..78f3b49b8 100644 --- a/src/ui/views/SendToken/index.tsx +++ b/src/ui/views/SendToken/index.tsx @@ -31,7 +31,7 @@ import { query2obj } from 'ui/utils/url'; import { formatTokenAmount, splitNumberByStep } from 'ui/utils/number'; import AccountCard from '../Approval/components/AccountCard'; import TokenAmountInput from 'ui/component/TokenAmountInput'; -import { GasLevel, TokenItem } from 'background/service/openapi'; +import { GasLevel, TokenItem, Tx } from 'background/service/openapi'; import { PageHeader, AddressViewer } from 'ui/component'; import ContactEditModal from 'ui/component/Contact/EditModal'; import ContactListModal from 'ui/component/Contact/ListModal'; @@ -461,21 +461,6 @@ const SendToken = () => { const isNativeToken = !!chainItem && currentToken?.id === chainItem.nativeTokenAddress; - const fetchGasList = useCallback(async () => { - const list: GasLevel[] = chainItem?.isTestnet - ? await wallet.getCustomTestnetGasMarket({ chainId: chainItem.id }) - : await wallet.openapi.gasMarket(chainItem?.serverId || ''); - return list; - }, [wallet, chainItem]); - - const [{ value: gasList }, loadGasList] = useAsyncFn(() => { - return fetchGasList(); - }, [fetchGasList]); - - useEffect(() => { - loadGasList(); - }, [loadGasList]); - useDebounce( async () => { const targetChain = findChainByEnum(chain)!; @@ -512,6 +497,118 @@ const SendToken = () => { }; }, [isNativeToken, addressType]); + const getParams = React.useCallback( + ({ + to, + amount, + messageDataForSendToEoa, + messageDataForContractCall, + }: FormSendToken) => { + const chain = findChain({ + serverId: currentToken.chain, + })!; + const sendValue = new BigNumber(amount || 0) + .multipliedBy(10 ** currentToken.decimals) + .decimalPlaces(0, BigNumber.ROUND_DOWN); + const dataInput = [ + { + name: 'transfer', + type: 'function', + inputs: [ + { + type: 'address', + name: 'to', + }, + { + type: 'uint256', + name: 'value', + }, + ] as any[], + } as const, + [ + to || '0x0000000000000000000000000000000000000000', + sendValue.toFixed(0), + ] as any[], + ] as const; + const params: Record = { + chainId: chain.id, + from: currentAccount!.address, + to: currentToken.id, + value: '0x0', + data: abiCoder.encodeFunctionCall(dataInput[0], dataInput[1]), + isSend: true, + }; + if (safeInfo?.nonce != null) { + params.nonce = safeInfo.nonce; + } + if (isNativeToken) { + params.to = to; + delete params.data; + + if (isShowMessageDataForToken && messageDataForSendToEoa) { + const encodedValue = formatTxInputDataOnERC20(messageDataForSendToEoa) + .hexData; + + params.data = encodedValue; + } else if (isShowMessageDataForContract && messageDataForContractCall) { + params.data = messageDataForContractCall; + } + + params.value = `0x${sendValue.toString(16)}`; + } + + return params; + }, + [ + currentAccount, + currentToken.chain, + currentToken.decimals, + currentToken.id, + isNativeToken, + isShowMessageDataForContract, + isShowMessageDataForToken, + safeInfo, + ] + ); + + const fetchGasList = useCallback(async () => { + const values = form.getFieldsValue(); + const params = getParams(values) as Tx; + + const list: GasLevel[] = chainItem?.isTestnet + ? await wallet.getCustomTestnetGasMarket({ chainId: chainItem.id }) + : await wallet.gasMarketV2({ + chain: chainItem!, + tx: params, + }); + return list; + }, [chainItem, form, getParams, wallet]); + + const [{ value: gasList }, loadGasList] = useAsyncFn(() => { + return fetchGasList(); + }, [fetchGasList]); + + useDebounce( + async () => { + const targetChain = findChainByEnum(chain)!; + let gasList: GasLevel[]; + if ( + gasPriceMap[targetChain.enum] && + gasPriceMap[targetChain.enum].expireAt > Date.now() + ) { + gasList = gasPriceMap[targetChain.enum].list; + } + }, + 500, + [chain] + ); + + useEffect(() => { + if (clickedMax) { + loadGasList(); + } + }, [clickedMax, loadGasList]); + const handleSubmit = async ({ to, amount, @@ -522,51 +619,14 @@ const SendToken = () => { const chain = findChain({ serverId: currentToken.chain, })!; - const sendValue = new BigNumber(amount) - .multipliedBy(10 ** currentToken.decimals) - .decimalPlaces(0, BigNumber.ROUND_DOWN); - const dataInput = [ - { - name: 'transfer', - type: 'function', - inputs: [ - { - type: 'address', - name: 'to', - }, - { - type: 'uint256', - name: 'value', - }, - ] as any[], - } as const, - [to, sendValue.toFixed(0)] as any[], - ] as const; - const params: Record = { - chainId: chain.id, - from: currentAccount!.address, - to: currentToken.id, - value: '0x0', - data: abiCoder.encodeFunctionCall(dataInput[0], dataInput[1]), - isSend: true, - }; - if (safeInfo?.nonce != null) { - params.nonce = safeInfo.nonce; - } - if (isNativeToken) { - params.to = to; - delete params.data; - - if (isShowMessageDataForToken && messageDataForSendToEoa) { - const encodedValue = formatTxInputDataOnERC20(messageDataForSendToEoa) - .hexData; - - params.data = encodedValue; - } else if (isShowMessageDataForContract && messageDataForContractCall) { - params.data = messageDataForContractCall; - } + const params = getParams({ + to, + amount, + messageDataForSendToEoa, + messageDataForContractCall, + }); - params.value = `0x${sendValue.toString(16)}`; + if (isNativeToken) { // L2 has extra validation fee so we can not set gasLimit as 21000 when send native token const couldSpecifyIntrinsicGas = !CAN_NOT_SPECIFY_INTRINSIC_GAS_CHAINS.includes( chain.enum diff --git a/src/ui/views/Swap/hooks/quote.tsx b/src/ui/views/Swap/hooks/quote.tsx index 8b9bf6de1..b9e96712e 100644 --- a/src/ui/views/Swap/hooks/quote.tsx +++ b/src/ui/views/Swap/hooks/quote.tsx @@ -164,7 +164,15 @@ export const useQuoteMethods = () => { const lastTimeGas: ChainGas | null = await walletController.getLastTimeGasSelection( CHAINS[chain].id ); - const gasMarket = await walletOpenapi.gasMarket(CHAINS[chain].serverId); + const gasMarket = await walletController.gasMarketV2({ + chain: CHAINS[chain], + tx: { + ...quote.tx, + nonce, + chainId: CHAINS[chain].id, + gas: '0x0', + }, + }); let gasPrice = 0; if (lastTimeGas?.lastTimeSelect === 'gasPrice' && lastTimeGas.gasPrice) { @@ -321,9 +329,9 @@ export const useQuoteMethods = () => { try { let gasPrice: number; if (isOpenOcean) { - const gasMarket = await walletOpenapi.gasMarket( - CHAINS[chain].serverId - ); + const gasMarket = await walletController.gasMarketV2({ + chainId: CHAINS[chain].serverId, + }); gasPrice = gasMarket?.[1]?.price; } stats.report('swapRequestQuote', { diff --git a/src/ui/views/Swap/hooks/token.tsx b/src/ui/views/Swap/hooks/token.tsx index fae6b8544..7f1ab2fbc 100644 --- a/src/ui/views/Swap/hooks/token.tsx +++ b/src/ui/views/Swap/hooks/token.tsx @@ -294,7 +294,7 @@ export const useTokenPair = (userAddress: string) => { const { value: gasList } = useAsync(() => { gasPriceRef.current = undefined; setGasLevel('normal'); - return wallet.openapi.gasMarket(CHAINS[chain].serverId); + return wallet.gasMarketV2({ chainId: CHAINS[chain].serverId }); }, [chain]); const [reserveGasOpen, setReserveGasOpen] = useState(false); diff --git a/src/ui/views/TransactionHistory/components/SkipNonceAlert.tsx b/src/ui/views/TransactionHistory/components/SkipNonceAlert.tsx index 7fccf5ad4..4ac7c28f0 100644 --- a/src/ui/views/TransactionHistory/components/SkipNonceAlert.tsx +++ b/src/ui/views/TransactionHistory/components/SkipNonceAlert.tsx @@ -167,7 +167,10 @@ export const SkipNonceAlert = ({ ? await wallet.getCustomTestnetGasMarket({ chainId: chain.id, }) - : await wallet.openapi.gasMarket(chain.serverId); + : await wallet.gasMarketV2({ + chain, + tx: maxGasTx.rawTx, + }); const maxGasMarketPrice = maxBy(gasLevels, (level) => level.price)!.price; await wallet.sendRequest({ method: 'eth_sendTransaction', diff --git a/src/ui/views/TransactionHistory/components/TransactionItem.tsx b/src/ui/views/TransactionHistory/components/TransactionItem.tsx index 011bc8c05..c96d8445d 100644 --- a/src/ui/views/TransactionHistory/components/TransactionItem.tsx +++ b/src/ui/views/TransactionHistory/components/TransactionItem.tsx @@ -153,7 +153,10 @@ export const TransactionItem = ({ ? await wallet.getCustomTestnetGasMarket({ chainId: chain.id, }) - : await wallet.openapi.gasMarket(chain.serverId); + : await wallet.gasMarketV2({ + chain, + tx: maxGasTx.rawTx, + }); const maxGasMarketPrice = maxBy(gasLevels, (level) => level.price)!.price; await wallet.sendRequest({ method: 'eth_sendTransaction', @@ -190,7 +193,10 @@ export const TransactionItem = ({ ? await wallet.getCustomTestnetGasMarket({ chainId: chain.id, }) - : await wallet.openapi.gasMarket(chain.serverId); + : await wallet.gasMarketV2({ + chain, + tx: originTx.rawTx, + }); const maxGasMarketPrice = maxBy(gasLevels, (level) => level.price)!.price; await wallet.sendRequest({ method: 'eth_sendTransaction', diff --git a/yarn.lock b/yarn.lock index f43faa728..bfc42bba4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4774,10 +4774,10 @@ resolved "https://registry.yarnpkg.com/@rabby-wallet/rabby-action/-/rabby-action-0.1.8.tgz#05b258b628a224d51dc471e93117d4106024a916" integrity sha512-K0euVX55tW2mbnudm3bHPAbbLYlnDQD5PgAvM1mwPPFHhF/Ve/U5MYdg1XERJPxkoXKqiVti46idFFB+s8sv7A== -"@rabby-wallet/rabby-api@0.8.5": - version "0.8.5" - resolved "https://registry.yarnpkg.com/@rabby-wallet/rabby-api/-/rabby-api-0.8.5.tgz#b2c7820c52ffe2aa8cb3226304593eaca1231b88" - integrity sha512-yykwK/pZA/5eCn/QCRwgP6uDQQhOdG3Zl1CAjFqK5AVNyc5DE1BCcZWkABWzXjt63KJHePVcAX7rP8rhzbmsTQ== +"@rabby-wallet/rabby-api@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@rabby-wallet/rabby-api/-/rabby-api-0.9.2.tgz#a01eae1033e21ab38a99ea37c336ade3204e7f4b" + integrity sha512-YAxCDSYvg0Qfq/m9FcfwVQ7iLUhVyr8CTj1kS+n+XYw2fHFGCXmqzurqlcaaO31HCZLLOCkHCvVfF/Vj9j3OLg== dependencies: "@rabby-wallet/rabby-sign" "0.4.0" axios "^0.27.2" @@ -19049,6 +19049,7 @@ string-length@^4.0.1: strip-ansi "^6.0.0" "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.2.3: + name string-width-cjs version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -19128,6 +19129,7 @@ string_decoder@~1.1.1: safe-buffer "~5.1.0" "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1: + name strip-ansi-cjs version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -21146,6 +21148,7 @@ wildcard@^2.0.0: integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + name wrap-ansi-cjs version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==