diff --git a/package-lock.json b/package-lock.json index f9d546531b..fe79dfbcde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "@web3-react/abstract-connector": "^6.0.7", "@web3-react/types": "^6.0.7", "adex-protocol-eth": "git+https://git@github.com/AmbireTech/adex-protocol-eth.git#4ddebac4109e9709c4cc862ee0708f208dac9ee2", - "ambire-common": "github:AmbireTech/ambire-common#v1.0.2", + "ambire-common": "github:AmbireTech/ambire-common#v1.0.3", "bip44-constants": "^128.0.0", "blockies-ts": "^1.0.0", "chart.js": "^3.9.1", @@ -13480,8 +13480,8 @@ "integrity": "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==" }, "node_modules/ambire-common": { - "version": "1.0.2", - "resolved": "git+ssh://git@github.com/AmbireTech/ambire-common.git#dc45a6b3d0a2a32a00e3d37c201a200db2205577", + "version": "1.0.3", + "resolved": "git+ssh://git@github.com/AmbireTech/ambire-common.git#0221924f075d33a879f1cd6d52a982a0693c42f9", "peerDependencies": { "@ambire/signature-validator": "^1.0.3", "@ensdomains/eth-ens-namehash": "^2.0.15", @@ -67667,8 +67667,8 @@ "integrity": "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==" }, "ambire-common": { - "version": "git+ssh://git@github.com/AmbireTech/ambire-common.git#dc45a6b3d0a2a32a00e3d37c201a200db2205577", - "from": "ambire-common@github:AmbireTech/ambire-common#v1.0.2", + "version": "git+ssh://git@github.com/AmbireTech/ambire-common.git#0221924f075d33a879f1cd6d52a982a0693c42f9", + "from": "ambire-common@github:AmbireTech/ambire-common#v1.0.3", "requires": {} }, "amdefine": { diff --git a/package.json b/package.json index b86659604b..173c824ccf 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@web3-react/abstract-connector": "^6.0.7", "@web3-react/types": "^6.0.7", "adex-protocol-eth": "git+https://git@github.com/AmbireTech/adex-protocol-eth.git#4ddebac4109e9709c4cc862ee0708f208dac9ee2", - "ambire-common": "github:AmbireTech/ambire-common#v1.0.2", + "ambire-common": "github:AmbireTech/ambire-common#v1.0.3", "bip44-constants": "^128.0.0", "blockies-ts": "^1.0.0", "chart.js": "^3.9.1", diff --git a/src/components/common/TxnPreview/ExtendedSummaryItem/ExtendedSummaryItem.js b/src/components/common/TxnPreview/ExtendedSummaryItem/ExtendedSummaryItem.js index d9db30f1c0..1a3dc69183 100644 --- a/src/components/common/TxnPreview/ExtendedSummaryItem/ExtendedSummaryItem.js +++ b/src/components/common/TxnPreview/ExtendedSummaryItem/ExtendedSummaryItem.js @@ -102,6 +102,14 @@ const ExtendedSummaryItem = ({ item, i, networkDetails, feeAssets }) => { ) } + if (item.type === 'link') + return ( +
+ + {item.text} + +
+ ) return null } diff --git a/src/lib/humanizers/Bungee.js b/src/lib/humanizers/Bungee.js new file mode 100644 index 0000000000..f6cfadb3fb --- /dev/null +++ b/src/lib/humanizers/Bungee.js @@ -0,0 +1,82 @@ +import { Interface } from 'ethers/lib/utils' +import networks from 'consts/networks' +import { nativeToken, getName } from 'lib/humanReadableTransactions' + +const getNetwork = (chainId, extended = false) => { + const network = networks.find((n) => n.chainId === Number(chainId)) + return !extended ? network.name : { ...network, type: 'network' } +} + +// bungee runs some of its calls through falllback that serves as router to unverified contracts, +// thats why we can't fetch data from block explorers in ambire constants +const Bungee = (humanizerInfo) => { + const iface = new Interface(humanizerInfo.abis.StargateImplL2V2) + return { + // some bungee bridge txn start with 4 bytes number and the next 4 bytes are a sigHash + // bungee uses fallback and later redirects to address based on the first 4 bytes + '0x00000005:0x3a23F943181408EAC424116Af7b7790c94Cb97a5': ( + txn, + network, + { extended = false } + ) => { + const parsedCallData = `0x${txn.data.slice(10)}` + const [_number, recipient, chainId, _bytes, _moreData] = iface.decodeFunctionData( + 'swapAndBridge(uint32,address,uint256,bytes32,bytes)', + parsedCallData + ) + return !extended + ? [`Bridge tokens on Bungee to ${getNetwork(chainId)}`] + : [['Bridge', 'tokens on Bungee to', getNetwork(chainId, true)]] + }, + '0x00000016:0x3a23F943181408EAC424116Af7b7790c94Cb97a5': ( + txn, + network, + { extended = false } + ) => { + const parsedCallData = `0x${txn.data.slice(10)}` + const [_number, _data, [address1, address2, destinationNetwork]] = iface.decodeFunctionData( + 'swapAndBridge(uint32,bytes,(address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes32))', + parsedCallData + ) + return !extended + ? [`Bridge tokens on Bungee to ${getNetwork(destinationNetwork)}`] + : [['Bridge', 'tokens on Bungee to', getNetwork(destinationNetwork, true)]] + }, + '0x00000003:0x3a23F943181408EAC424116Af7b7790c94Cb97a5': ( + txn, + network, + { extended = false } + ) => { + const parsedCallData = `0x${txn.data.slice(10)}` + const [amountnNative, bytes32, recipient, destinationNetwork] = iface.decodeFunctionData( + 'bridgeNativeTo(uint256,bytes32,address,uint256)', + parsedCallData + ) + + return !extended + ? [ + `Bridge ${nativeToken(network, amountnNative)} to ${getNetwork(destinationNetwork)} ${ + recipient !== txn.from ? `and send to ${getName(humanizerInfo, recipient)}` : '' + }` + ] + : [ + [ + 'Bridge', + { + type: 'token', + ...nativeToken(network, amountnNative, true) + }, + 'to', + getNetwork(destinationNetwork, true), + ...(recipient !== txn.from + ? [ + 'and send to', + { type: 'address', address: recipient, name: getName(humanizerInfo, recipient) } + ] + : []) + ] + ] + } + } +} +export default Bungee diff --git a/src/lib/humanizers/CowSwap.js b/src/lib/humanizers/CowSwap.js new file mode 100644 index 0000000000..3a5962b116 --- /dev/null +++ b/src/lib/humanizers/CowSwap.js @@ -0,0 +1,28 @@ +import { Interface } from 'ethers/lib/utils' +import { token } from 'lib/humanReadableTransactions' + +const onBehalfText = (onBehalf, txnFrom) => + onBehalf.toLowerCase() !== txnFrom.toLowerCase() ? ` on behalf of ${onBehalf}` : '' + +const CowSwap = (humanizerInfo) => { + const iface = new Interface(humanizerInfo.abis.CowSwapSettlement) + + return { + [iface.getSighash('setPreSignature')]: (txn, network, { extended }) => { + const [orderUid, _signed] = iface.parseTransaction(txn).args + if (extended) + return [ + [ + 'Execute CowSwap order', + { + type: 'link', + link: `https://explorer.cow.fi/orders/${orderUid}?tab=overview`, + text: 'more info here' + } + ] + ] + return [`CowSwap order ${orderUid}`] + } + } +} +export default CowSwap diff --git a/src/lib/humanizers/GMX.js b/src/lib/humanizers/GMX.js new file mode 100644 index 0000000000..355efe91f5 --- /dev/null +++ b/src/lib/humanizers/GMX.js @@ -0,0 +1,52 @@ +import { Interface } from 'ethers/lib/utils' +import { token, getName } from 'lib/humanReadableTransactions' + +const GMX = (humanizerInfo) => { + const orderHandler = new Interface(humanizerInfo.abis.GMXOrderHandler) + + return { + [orderHandler.getSighash('executeOrder')]: (txn, network, { extended }) => { + // oracleParams + /* + struct SetPricesParams { + uint256 signerInfo; + address[] tokens; + uint256[] compactedMinOracleBlockNumbers; + uint256[] compactedMaxOracleBlockNumbers; + uint256[] compactedOracleTimestamps; + uint256[] compactedDecimals; + uint256[] compactedMinPrices; + uint256[] compactedMinPricesIndexes; + uint256[] compactedMaxPrices; + uint256[] compactedMaxPricesIndexes; + bytes[] signatures; + address[] priceFeedTokens; + address[] realtimeFeedTokens; + bytes[] realtimeFeedData; + } + */ + const { key, oracleParams } = orderHandler.parseTransaction(txn).args + const tokens = oracleParams.realtimeFeedTokens + const data = oracleParams.realtimeFeedData + if (extended) + return [ + [ + 'Open GMX position', + 'from', + { type: 'token', ...token(humanizerInfo, tokens[tokens.length - 2], -1, true) }, + 'to', + { type: 'token', ...token(humanizerInfo, tokens[0], -1, true) } + ] + ] + return [ + `Open GMX position from ${token(humanizerInfo, tokens[tokens.length - 1], -1)} to ${token( + humanizerInfo, + tokens[0], + -1 + )}` + ] + } + } +} + +export default GMX diff --git a/src/lib/humanizers/Joe.js b/src/lib/humanizers/Joe.js new file mode 100644 index 0000000000..82f710368d --- /dev/null +++ b/src/lib/humanizers/Joe.js @@ -0,0 +1,94 @@ +import { Interface } from 'ethers/lib/utils' +import { token, getName, nativeToken } from 'lib/humanReadableTransactions' + +const Joe = (humanizerInfo) => { + const iface = new Interface(humanizerInfo.abis.JoeRouter) + + return { + [iface.getSighash('swapExactTokensForAVAX')]: (txn, network, { extended }) => { + const { amountIn, amountOutMin, path, to, deadline } = iface.parseTransaction(txn).args + if (extended) + return [ + [ + 'Swap', + { type: 'token', ...token(humanizerInfo, path[0], amountIn, true) }, + 'for at least', + { type: 'token', ...token(humanizerInfo, path[path.length - 1], amountOutMin, true) }, + ...(txn.from !== to + ? [ + 'and send swapped to', + { type: 'address', address: to, name: getName(humanizerInfo, to) } + ] + : []) + ] + ] + return [ + `Swap ${token(humanizerInfo, path[0], amountIn)} for at least ${token( + humanizerInfo, + path[path.length - 1], + amountOutMin + )} ${txn.from !== to ? `and send swapped to ${getName(humanizerInfo, to)}` : ''}` + ] + }, + [iface.getSighash('swapExactAVAXForTokens(uint256,address[],address,uint256)')]: ( + txn, + network, + { extended } + ) => { + const { to, amountOutMin, path, deadline } = iface.parseTransaction(txn).args + if (extended) + return [ + [ + 'Swap', + { type: 'token', ...nativeToken(network, txn.value, true) }, + 'for at least', + { type: 'token', ...token(humanizerInfo, path[path.length - 1], amountOutMin, true) }, + ...(txn.from !== to + ? [ + 'and send swapped to', + { type: 'address', address: to, name: getName(humanizerInfo, to) } + ] + : []) + ] + ] + return [ + `Swap ${nativeToken(network, txn.value)} for at least ${token( + humanizerInfo, + path[path.length - 1], + amountOutMin + )} ${txn.from !== to ? ` and send swapped to ${getName(humanizerInfo, to)}` : ''}` + ] + }, + [iface.getSighash('swapAVAXForExactTokens(uint256,address[],address,uint256)')]: ( + txn, + network, + { extended } + ) => { + const [amountOutMin, path, to, deadline] = iface.parseTransaction(txn).args + + if (extended) + return [ + [ + 'Swap', + { type: 'token', ...nativeToken(network, txn.value, true) }, + 'for at least', + { type: 'token', ...token(humanizerInfo, path[path.length - 1], amountOutMin, true) }, + ...(txn.from !== to + ? [ + 'and send swapped to', + { type: 'address', address: to, name: getName(humanizerInfo, to) } + ] + : []) + ] + ] + return [ + `Swap ${nativeToken(network, txn.value)} for at least ${token( + humanizerInfo, + path[path.length - 1], + amountOutMin + )} ${txn.from !== to ? ` and send swapped to ${getName(humanizerInfo, to)}` : ''}` + ] + } + } +} +export default Joe diff --git a/src/lib/humanizers/Lido.js b/src/lib/humanizers/Lido.js new file mode 100644 index 0000000000..f36ab8a45a --- /dev/null +++ b/src/lib/humanizers/Lido.js @@ -0,0 +1,48 @@ +import { Interface } from 'ethers/lib/utils' +import { token, getName, nativeToken } from 'lib/humanReadableTransactions' + +function getAddress(humanizerInfo, address) { + return { + type: 'address', + address, + name: getName(humanizerInfo, address) + } +} +const MATIC_ON_ETH_ADDRESS = '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0' +const Lido = (humanizerInfo) => { + const ifaceETH = new Interface(humanizerInfo.abis.LidoStETH) + const ifaceMATIC = new Interface(humanizerInfo.abis.LidoStMATIC) + return { + [ifaceETH.getSighash('submit')]: (txn, network, { extended }) => { + const { _positionId, _recipient } = ifaceETH.parseTransaction(txn).args + if (extended) + return [ + _recipient === txn.from + ? [`Stake ${nativeToken(network, txn.value)}`] + : [ + 'Stake', + { + type: 'token', + ...nativeToken(network, txn.value, true) + }, + 'to', + getAddress(humanizerInfo, txn.to) + ] + ] + return [ + _recipient === txn.from + ? [`Withdraw swapped tokens from position ${_positionId}`] + : [`Send swapped tokens from position ${_positionId} to ${_recipient}`] + ] + }, + [ifaceMATIC.getSighash('submit')]: (txn, network, { extended }) => { + const { _amount } = ifaceMATIC.parseTransaction(txn).args + if (extended) + return [ + ['Stake', { type: 'token', ...token(humanizerInfo, MATIC_ON_ETH_ADDRESS, _amount, true) }] + ] + return [[`Stake ${token(humanizerInfo, MATIC_ON_ETH_ADDRESS, _amount)}`]] + } + } +} +export default Lido diff --git a/src/lib/humanizers/MeanFinance.js b/src/lib/humanizers/MeanFinance.js new file mode 100644 index 0000000000..685f597330 --- /dev/null +++ b/src/lib/humanizers/MeanFinance.js @@ -0,0 +1,145 @@ +import { Interface } from 'ethers/lib/utils' +import { token, getName } from 'lib/humanReadableTransactions' + +export function getInterval(seconds) { + if (seconds <= 60) return `${seconds} seconds` + if (seconds <= 60 * 60) return `${seconds / 60} minutes` + if (seconds <= 60 * 60 * 24) return `${seconds / 60 / 60} hours` + if (seconds <= 60 * 60 * 24 * 7) return `${seconds / 60 / 60 / 24} days` + return `${seconds / 60 / 60 / 24 / 7} weeks` +} +function getAddress(humanizerInfo, address) { + return { + type: 'address', + address, + name: getName(humanizerInfo, address) + } +} + +const MeanFinance = (humanizerInfo) => { + const iface = new Interface(humanizerInfo.abis.MeanFinance) + + return { + [iface.getSighash( + 'deposit(address,address,uint256,uint32,uint32,address,(address,uint8[])[])' + )]: (txn, network, { extended }) => { + const { _from, _to, _amountOfSwaps, _swapInterval, _owner, _permissions, _amount } = + iface.parseTransaction(txn).args + if (extended) + return [ + [ + 'Swap', + { + type: 'token', + ...token(humanizerInfo, _from, _amount, true) + }, + 'for', + { + type: 'token', + ...token(humanizerInfo, _to, -1, true) + }, + `Split into ${_amountOfSwaps} swaps over ${getInterval( + _swapInterval * _amountOfSwaps + )}`, + 'via', + { + type: 'address', + address: txn.to, + name: getName(humanizerInfo, txn.to) + } + ] + ] + return [ + `Swap ${token(humanizerInfo, _from, _amount)} for ${getName( + humanizerInfo, + _to + )} Split into ${_amountOfSwaps} swaps over ${getInterval( + _swapInterval * _amountOfSwaps + )} via ${txn.to}` + ] + }, + [iface.getSighash( + 'deposit(address,address,uint256,uint32,uint32,address,(address,uint8[])[],bytes)' + )]: (txn, network, { extended }) => { + const { _from, _to, _amountOfSwaps, _swapInterval, _owner, _permissions, _amount } = + iface.parseTransaction(txn).args + if (extended) + return [ + [ + 'Swap', + { + type: 'token', + ...token(humanizerInfo, _from, _amount, true) + }, + 'for', + { + type: 'token', + ...token(humanizerInfo, _to, -1, true) + }, + `Split into ${_amountOfSwaps} swaps over ${getInterval( + _swapInterval * _amountOfSwaps + )}`, + 'via', + { + type: 'address', + address: txn.to, + name: getName(humanizerInfo, txn.to) + } + ] + ] + return [ + `Swap ${token(humanizerInfo, _from, _amount)} for ${getName( + humanizerInfo, + _to + )} Split into ${_amountOfSwaps} swaps over ${getInterval( + _swapInterval * _amountOfSwaps + )} via ${txn.to}` + ] + }, + [iface.getSighash('terminate')]: (txn, network, { extended }) => { + // used for the url, mean finance makes sense of the versions internaly + const ORDER_VERSION = 4 + const { _positionId, _recipientUnswapped, _recipientSwapped } = + iface.parseTransaction(txn).args + if (extended) + return [ + [ + `Terminate position ${_positionId}`, + { + type: 'link', + link: `https://mean.finance/${network.chainId}/positions/${ORDER_VERSION}/${_positionId}`, + text: 'more info here' + } + ], + txn.from !== _recipientUnswapped + ? ['Send', 'unswapped tokens to', getAddress(humanizerInfo, _recipientUnswapped)] + : ['Withdraw', 'unswapped tokens'], + txn.from !== _recipientSwapped + ? ['Send', 'swapped tokens to', getAddress(humanizerInfo, _recipientSwapped)] + : ['Withdraw', 'swapped tokens'] + ] + return [ + `Terminate position ${_positionId}, send unswapped tokens to ${_recipientUnswapped} and send swapped tokens to ${_recipientSwapped}` + ] + }, + [iface.getSighash('withdrawSwapped')]: (txn, network, { extended }) => { + const { _positionId, _recipient } = iface.parseTransaction(txn).args + if (extended) + return [ + _recipient === txn.from + ? ['Withdraw', `swapped tokens from position ${_positionId}`] + : [ + 'Send', + `swapped tokens from position ${_positionId} to`, + getAddress(humanizerInfo, _recipient) + ] + ] + return [ + _recipient === txn.from + ? [`Withdraw swapped tokens from position ${_positionId}`] + : [`Send swapped tokens from position ${_positionId} to ${_recipient}`] + ] + } + } +} +export default MeanFinance diff --git a/src/lib/humanizers/UniswapV3Pool.js b/src/lib/humanizers/UniswapV3Pool.js index 336967ce9d..003f8fa23c 100644 --- a/src/lib/humanizers/UniswapV3Pool.js +++ b/src/lib/humanizers/UniswapV3Pool.js @@ -1,5 +1,9 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/* eslint-disable no-nested-ternary */ +/* eslint-disable import/no-cycle */ import { Interface } from 'ethers/lib/utils' import { nativeToken, token, getName } from 'lib/humanReadableTransactions' +import { getInterval } from './MeanFinance' const recipientText = (humanizerInfo, recipient, txnFrom, extended = false) => recipient.toLowerCase() === txnFrom.toLowerCase() @@ -47,7 +51,9 @@ const toExtended = (action, word, fromToken, toToken, recipient = [], expires = const UniswapV3Pool = (humanizerInfo) => { const ifaceV3 = new Interface(humanizerInfo.abis.UniswapV3Pool) - + const exchangeRouter = new Interface(humanizerInfo.abis.ExchangeRouter) + // DCAhub comes from mean finance + const DCAHubCompanion = new Interface(humanizerInfo.abis.DCAHubCompanion) return { [ifaceV3.getSighash('multicall')]: (txn, network) => { const args = ifaceV3.parseTransaction(txn).args @@ -84,6 +90,189 @@ const UniswapV3Pool = (humanizerInfo) => { recipientText(humanizerInfo, params.recipient, txn.from, true) ) }, + [exchangeRouter.getSighash('sendWnt')]: (txn, network, opts = { extended: true }) => { + const args = exchangeRouter.parseTransaction(txn).args + return !opts.extended + ? [ + [ + `Wrap and send ${nativeToken(network, args.amount)} to ${getName( + humanizerInfo, + args.receiver + )}` + ] + ] + : [ + [ + 'Wrap and send', + { type: 'token', ...nativeToken(network, args.amount, true) }, + 'to', + { + type: 'address', + address: args.receiver, + name: getName(humanizerInfo, args.receiver) + } + ] + ] + }, + [exchangeRouter.getSighash('sendTokens')]: (txn, network, opts = { extended: true }) => { + const args = exchangeRouter.parseTransaction(txn).args + return !opts.extended + ? [ + [ + `Send ${token(humanizerInfo, args.token, args.amount)} to ${getName( + humanizerInfo, + args.receiver + )}` + ] + ] + : [ + [ + 'Send', + { type: 'token', ...token(humanizerInfo, args.token, args.amount, true) }, + 'to', + { + type: 'address', + address: args.receiver, + name: getName(humanizerInfo, args.receiver) + } + ] + ] + }, + [exchangeRouter.getSighash('createOrder')]: (txn, network, opts = { extended: true }) => { + const { params } = exchangeRouter.parseTransaction(txn).args + const [ + addresses, + numbers, + orderType, + decreasePositionSwapType, + isLong, + shouldUnwrapNativeToken, + referralCode + ] = params + return !opts.extended + ? [ + `Open ${isLong ? 'long' : 'short'} position with collateral ${token( + humanizerInfo, + addresses[4], + -1 + )} in ${getName(txn.to)}` + ] + : [ + [ + `Open ${isLong ? 'long' : 'short'} position`, + 'with collateral', + { type: 'token', ...token(humanizerInfo, addresses[4], -1, true) }, + 'in', + { type: 'address', address: txn.to, name: getName(humanizerInfo, txn.to) } + ] + ] + }, + // DCAHub companion can be moved to mean finance and exported to be applied also here + [DCAHubCompanion.getSighash('terminate')]: (txn, network, opts = { extended: true }) => { + const { _hub, _positionId, _recipientUnswapped, _recipientSwapped } = + DCAHubCompanion.parseTransaction(txn).args + return !opts.extended + ? [`Terminate position ${_positionId} on ${getName(humanizerInfo, _hub)}`] + : [ + [ + 'Terminate position', + `${_positionId}`, + 'on', + { type: 'address', address: _hub, name: getName(humanizerInfo, _hub) } + ] + ] + }, + [DCAHubCompanion.getSighash('runSwap')]: (txn, network, opts = { extended: true }) => { + const { _allowanceToken, _value, _swapData, _tokenOut, _minTokenOut } = + DCAHubCompanion.parseTransaction(txn).args + const tokenA = + Number(_allowanceToken) === 0 + ? nativeToken(network, _value, opts.extended) + : token(humanizerInfo, _allowanceToken, _value, opts.extended) + const tokenB = + Number(_tokenOut) === 0 + ? nativeToken(network, _minTokenOut, opts.extended) + : token(humanizerInfo, _tokenOut, _minTokenOut, opts.extended) + return !opts.extended + ? [`Swap ${tokenA}} for ${tokenB}`] + : [['Swap', { type: 'token', ...tokenA }, 'for', { type: 'token', ...tokenB }]] + }, + [DCAHubCompanion.getSighash('sendBalanceOnContractToRecipient')]: ( + txn, + network, + opts = { extended: true } + ) => { + const { _token, _recipient } = DCAHubCompanion.parseTransaction(txn).args + const displayableToken = + Number(_token) === 0 + ? nativeToken(network, txn.value, opts.extended) + : token(humanizerInfo, _token, 0, opts.extended) + if (_recipient !== txn.from) + return !opts.extended + ? [`Pull ${displayableToken} from ${getName(txn.to)}to ${getName(_recipient)}`] + : [ + [ + 'Pull all', + { type: 'token', ...displayableToken }, + 'from', + { type: 'address', address: txn.to, name: getName(humanizerInfo, txn.to) }, + 'to', + { type: 'address', address: _recipient, name: getName(humanizerInfo, _recipient) } + ] + ] + return !opts.extended + ? [`Withdraw all ${displayableToken} from ${getName(txn.to)}`] + : [ + [ + 'Withdraw all', + { type: 'token', ...displayableToken }, + 'from', + { type: 'address', address: txn.to, name: getName(humanizerInfo, txn.to) } + ] + ] + }, + [DCAHubCompanion.getSighash('depositWithBalanceOnContract')]: ( + txn, + network, + opts = { extended: true } + ) => { + const { + _hub, + _from, + _to, + _amountOfSwaps, + _swapInterval, + _owner, + _permissions, + _miscellaneous + } = DCAHubCompanion.parseTransaction(txn).args + return !opts.extended + ? ['watafak'] + : [ + [ + 'and swap', + 'the resulting amount of', + { + type: 'token', + ...token(humanizerInfo, _from, 0, true) + }, + 'for', + { + type: 'token', + ...token(humanizerInfo, _to, 0, true) + }, + `Split into ${_amountOfSwaps} swaps over ${getInterval( + _swapInterval * _amountOfSwaps + )}`, + 'via', + { + type: 'address', + address: txn.to, + name: getName(humanizerInfo, _hub) + } + ] + ] + }, [ifaceV3.getSighash('unwrapWETH9')]: (txn, network, opts = { extended: true }) => { const [amountMinimum, recipient] = ifaceV3.parseTransaction(txn).args diff --git a/src/lib/humanizers/index.js b/src/lib/humanizers/index.js index 7a06d79be0..52b58b5f78 100644 --- a/src/lib/humanizers/index.js +++ b/src/lib/humanizers/index.js @@ -1,3 +1,4 @@ +/* eslint-disable import/no-cycle */ import UniRouters from './UniRouters/UniRouters' import ERC20 from './ERC20' import AaveLendingPoolV2 from './AaveLendingPoolV2' @@ -14,6 +15,12 @@ import WALLETStakingPool from './WALLETStakingPool' import AaveWethGatewayV2 from './AaveWethGatewayV2' import OneInch from './OneInch' import UniswapV3Pool from './UniswapV3Pool' +import Bungee from './Bungee' +import CowSwap from './CowSwap' +import MeanFinance from './MeanFinance' +import GMX from './GMX' +import Lido from './Lido' +import Joe from './Joe' const all = ({ humanizerInfo, tokenList }) => ({ ...UniRouters(humanizerInfo), @@ -31,7 +38,13 @@ const all = ({ humanizerInfo, tokenList }) => ({ ...AmbireBatcher(humanizerInfo, tokenList), ...WALLETStakingPool(humanizerInfo), ...OneInch(humanizerInfo), - ...UniswapV3Pool(humanizerInfo) + ...UniswapV3Pool(humanizerInfo), + ...Bungee(humanizerInfo), + ...CowSwap(humanizerInfo), + ...MeanFinance(humanizerInfo), + ...GMX(humanizerInfo), + ...Lido(humanizerInfo), + ...Joe(humanizerInfo) }) export default all