Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 68 additions & 11 deletions packages/mask/src/plugins/Savings/SNSAdaptor/SavingsForm.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
import BigNumber from 'bignumber.js'
import { Typography } from '@mui/material'
import { useState, useMemo, useCallback } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useAsync, useAsyncFn } from 'react-use'
import { unreachable } from '@dimensiondev/kit'
import { isLessThan, rightShift } from '@masknet/web3-shared-base'
import {
createContract,
createERC20Token,
EthereumTokenType,
useFungibleTokenBalance,
useWeb3,
useAccount,
formatCurrency,
formatBalance,
formatCurrency,
getAaveConstants,
isSameAddress,
TransactionState,
TransactionStateType,
useAccount,
useFungibleTokenBalance,
useTokenConstants,
createERC20Token,
getAaveConstants,
useWeb3,
ZERO_ADDRESS,
createContract,
} from '@masknet/web3-shared-evm'
import { TokenAmountPanel, FormattedCurrency, LoadingAnimation, TokenIcon } from '@masknet/shared'
import { FormattedCurrency, LoadingAnimation, TokenAmountPanel, TokenIcon } from '@masknet/shared'
import { useRemoteControlledDialog } from '@masknet/shared-base-ui'
import { useTokenPrice } from '../../Wallet/hooks/useTokenPrice'
import { useI18N } from '../../../utils'
import { useStyles } from './SavingsFormStyles'
import { TabType, ProtocolType, SavingsProtocol } from '../types'
import { ProtocolType, SavingsProtocol, TabType } from '../types'
import { EthereumWalletConnectedBoundary } from '../../../web3/UI/EthereumWalletConnectedBoundary'
import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary'
import { ActionButtonPromise } from '../../../extension/options-page/DashboardComponents/ActionButton'
Expand All @@ -33,6 +35,10 @@ import { EthereumERC20TokenApprovedBoundary } from '../../../web3/UI/EthereumERC
import type { AaveLendingPoolAddressProvider } from '@masknet/web3-contracts/types/AaveLendingPoolAddressProvider'
import AaveLendingPoolAddressProviderABI from '@masknet/web3-contracts/abis/AaveLendingPoolAddressProvider.json'
import type { AbiItem } from 'web3-utils'
import { WalletMessages } from '../../Wallet/messages'
import { isTwitter } from '../../../social-network-adaptor/twitter.com/base'
import { activatedSocialNetworkUI } from '../../../social-network'
import { isFacebook } from '../../../social-network-adaptor/facebook.com/base'

export interface SavingsFormProps {
chainId: number
Expand All @@ -41,6 +47,11 @@ export interface SavingsFormProps {
onClose?: () => void
}

const ProtocolName = {
[ProtocolType.Lido]: 'lido',
[ProtocolType.AAVE]: 'aave',
Comment on lines +51 to +52

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[ProtocolType.Lido]: 'lido',
[ProtocolType.AAVE]: 'aave',
[ProtocolType.Lido]: 'Lido',
[ProtocolType.AAVE]: 'AAVE',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend to use createLookupTableResolver, you will never lost new ProtocolTypes.

}

export function SavingsForm({ chainId, protocol, tab, onClose }: SavingsFormProps) {
const { t } = useI18N()
const { classes } = useStyles()
Expand All @@ -50,6 +61,10 @@ export function SavingsForm({ chainId, protocol, tab, onClose }: SavingsFormProp
const { NATIVE_TOKEN_ADDRESS } = useTokenConstants()
const [inputAmount, setInputAmount] = useState('')
const [estimatedGas, setEstimatedGas] = useState<BigNumber.Value>(new BigNumber('0'))
const [tradeState, setTradeState] = useState<TransactionState>({
type: TransactionStateType.UNKNOWN,
})
const [isOpen, setIsOpen] = useState(false)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const [isOpen, setIsOpen] = useState(false)
const [open, setOpen] = useState(false)


const { value: nativeTokenBalance } = useFungibleTokenBalance(EthereumTokenType.Native, '', chainId)

Expand Down Expand Up @@ -151,10 +166,34 @@ export function SavingsForm({ chainId, protocol, tab, onClose }: SavingsFormProp
}
}, [protocol.bareToken, inputAmount, chainId])

const { setDialog: setTransactionDialog } = useRemoteControlledDialog(
WalletMessages.events.transactionDialogUpdated,
(ev) => {
if (ev.open) return
setTradeState({
type: TransactionStateType.UNKNOWN,
})
},
)

const [, executor] = useAsyncFn(async () => {
switch (tab) {
case TabType.Deposit:
if (!(await protocol.deposit(account, chainId, web3, tokenAmount))) {
setTradeState({
type: TransactionStateType.WAIT_FOR_CONFIRMING,
})
if (
!(await protocol.deposit(account, chainId, web3, tokenAmount, (state) => {
setTradeState((prev) => {
if (
prev.type === TransactionStateType.UNKNOWN &&
state.type === TransactionStateType.CONFIRMED
)
return prev
return state
})
}))
) {
throw new Error('Failed to deposit token.')
} else {
await protocol.updateBalance(chainId, web3, account)
Expand All @@ -179,6 +218,24 @@ export function SavingsForm({ chainId, protocol, tab, onClose }: SavingsFormProp
}
}, [tab, protocol, account, chainId, web3, tokenAmount])

useEffect(() => {
if (tradeState.type === TransactionStateType.UNKNOWN) return
setTransactionDialog({
open: true,
state: tradeState,
shareText: [
`I just deposit ${inputAmount} ${protocol.bareToken.symbol} with ${ProtocolName[protocol.type]}. ${
isTwitter(activatedSocialNetworkUI) || isFacebook(activatedSocialNetworkUI)
? `Follow @${
isTwitter(activatedSocialNetworkUI) ? t('twitter_account') : t('facebook_account')
} (mask.io) to deposit.`
: ''
}`,
'#mask_io',
].join('\n'),
})
}, [tradeState])

const needsSwap = protocol.type === ProtocolType.Lido && tab === TabType.Withdraw

const buttonDom = useMemo(() => {
Expand Down
44 changes: 38 additions & 6 deletions packages/mask/src/plugins/Savings/protocols/AAVEProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import BigNumber from 'bignumber.js'
import { pow10, ZERO } from '@masknet/web3-shared-base'
import {
ChainId,
getAaveConstants,
createContract,
FungibleTokenDetailed,
getAaveConstants,
TransactionEventType,
TransactionState,
TransactionStateType,
ZERO_ADDRESS,
} from '@masknet/web3-shared-evm'
import type { AaveLendingPool } from '@masknet/web3-contracts/types/AaveLendingPool'
Expand Down Expand Up @@ -179,19 +182,48 @@ export class AAVEProtocol implements SavingsProtocol {
return contract?.methods.deposit(this.bareToken.address, new BigNumber(value).toFixed(), account, '0')
}

public async deposit(account: string, chainId: ChainId, web3: Web3, value: BigNumber.Value) {
public async deposit(
account: string,
chainId: ChainId,
web3: Web3,
value: BigNumber.Value,
onChange: (state: TransactionState) => void,
) {
try {
const gasEstimate = await this.depositEstimate(account, chainId, web3, value)
const operation = await this.createDepositTokenOperation(account, chainId, web3, value)
if (operation) {
await operation.send({
from: account,
gas: gasEstimate.toNumber(),
})
await operation
.send({
from: account,
gas: gasEstimate.toNumber(),
})
.on(TransactionEventType.ERROR, (error) => {
onChange({
type: TransactionStateType.FAILED,
error: error,
})
})
.on(TransactionEventType.CONFIRMATION, (no, receipt) => {
onChange({
type: TransactionStateType.CONFIRMED,
no,
receipt,
})
})

return true
}
onChange({
type: TransactionStateType.FAILED,
error: new Error("Can't create deposit operation"),
})
return false
} catch (error) {
onChange({
type: TransactionStateType.FAILED,
error: new Error('deposit failed'),
})
return false
}
}
Expand Down
45 changes: 36 additions & 9 deletions packages/mask/src/plugins/Savings/protocols/LDOProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ import type { AbiItem } from 'web3-utils'
import BigNumber from 'bignumber.js'
import {
ChainId,
getLidoConstants,
createContract,
FungibleTokenDetailed,
getLidoConstants,
TransactionEventType,
TransactionState,
TransactionStateType,
ZERO_ADDRESS,
} from '@masknet/web3-shared-evm'
import { ZERO } from '@masknet/web3-shared-base'
import type { Lido } from '@masknet/web3-contracts/types/Lido'
import LidoABI from '@masknet/web3-contracts/abis/Lido.json'
import { SavingsProtocol, ProtocolType } from '../types'
import { ProtocolType, SavingsProtocol } from '../types'

export class LidoProtocol implements SavingsProtocol {
private _apr = '0.00'
Expand Down Expand Up @@ -80,21 +83,45 @@ export class LidoProtocol implements SavingsProtocol {
}
}

public async deposit(account: string, chainId: ChainId, web3: Web3, value: BigNumber.Value) {
public async deposit(
account: string,
chainId: ChainId,
web3: Web3,
value: BigNumber.Value,
onChange: (state: TransactionState) => void,
) {
try {
const contract = createContract<Lido>(
web3,
getLidoConstants(chainId).LIDO_stETH_ADDRESS || ZERO_ADDRESS,
LidoABI as AbiItem[],
)
await contract?.methods.submit(getLidoConstants(chainId).LIDO_REFERRAL_ADDRESS || ZERO_ADDRESS).send({
from: account,
value: value.toString(),
gas: 300000,
})

await contract?.methods
.submit(getLidoConstants(chainId).LIDO_REFERRAL_ADDRESS || ZERO_ADDRESS)
.send({
from: account,
value: value.toString(),
gas: 300000,
})
.on(TransactionEventType.ERROR, (error) => {
onChange({
type: TransactionStateType.FAILED,
error,
})
})
.on(TransactionEventType.CONFIRMATION, (no, receipt) => {
onChange({
type: TransactionStateType.CONFIRMED,
no,
receipt,
})
})
return true
} catch (error) {
onChange({
type: TransactionStateType.FAILED,
error: new Error('deposit failed'),
})
console.error('LDO `deposit()` Error', error)
return false
}
Expand Down
10 changes: 8 additions & 2 deletions packages/mask/src/plugins/Savings/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type Web3 from 'web3'
import type BigNumber from 'bignumber.js'
import type { ChainId, FungibleTokenDetailed } from '@masknet/web3-shared-evm'
import type { ChainId, FungibleTokenDetailed, TransactionState } from '@masknet/web3-shared-evm'

export enum TabType {
Deposit = 'deposit',
Expand Down Expand Up @@ -36,7 +36,13 @@ export interface SavingsProtocol {
updateBalance(chainId: ChainId, web3: Web3, account: string): Promise<void>

depositEstimate(account: string, chainId: ChainId, web3: Web3, value: BigNumber.Value): Promise<BigNumber.Value>
deposit(account: string, chainId: ChainId, web3: Web3, value: BigNumber.Value): Promise<boolean>
deposit(
account: string,
chainId: ChainId,
web3: Web3,
value: BigNumber.Value,
onChange: (state: TransactionState) => void,
): Promise<boolean>
withdrawEstimate(account: string, chainId: ChainId, web3: Web3, value: BigNumber.Value): Promise<BigNumber.Value>
withdraw(account: string, chainId: ChainId, web3: Web3, value: BigNumber.Value): Promise<boolean>
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function SearchableList<T extends {}>({
shouldSort: true,
threshold: 0.45,
minMatchCharLength: 1,
keys: searchKey ?? data.length > 0 ? Object.keys(data[0]) : [],
keys: searchKey ?? Object.keys(data.length > 0 ? data[0] : []),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, they are different, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they will cause #6073

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, it's about the operator precedence.

}),
[data, searchKey],
)
Expand Down