Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

US-2158 Make sure that we use the same strategy when working with fee #892

Merged
merged 9 commits into from
Mar 1, 2024
3 changes: 2 additions & 1 deletion src/core/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ChainID } from 'lib/eoaWallet'
import { chainTypesById } from 'shared/constants/chainConstants'
import { SETTINGS } from 'core/types'
import { TokenSymbol } from 'screens/home/TokenImage'
import { rbtcMap } from 'shared/utils'

/**
* This function will get the environment settings from the config.json
Expand Down Expand Up @@ -46,7 +47,7 @@ export const getTokenAddress = (symbol: TokenSymbol, chainId: ChainID) => {
)

if (!result) {
if (symbol === TokenSymbol.TRBTC || symbol === TokenSymbol.RBTC) {
if (rbtcMap.get(symbol)) {
return constants.AddressZero.toLowerCase()
}

Expand Down
37 changes: 0 additions & 37 deletions src/core/setup.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { AbiEnhancer } from '@rsksmart/rif-wallet-abi-enhancer'
import { AddrResolver } from '@rsksmart/rns-sdk'
import mainnetContracts from '@rsksmart/rsk-contract-metadata'
import testnetContracts from '@rsksmart/rsk-testnet-contract-metadata'
import axios from 'axios'

import { ChainID } from 'lib/eoaWallet'

import { SETTINGS } from 'core/types'
import { MAINNET, TESTNET } from 'screens/rnsManager/addresses.json'
import { ITokenWithoutLogo } from 'store/slices/balancesSlice/types'
import { Wallet } from 'shared/wallet'

import { getWalletSetting } from './config'
Expand All @@ -26,37 +23,3 @@ export const getRnsResolver = (chainId: ChainID, wallet: Wallet) => {

return new AddrResolver(rnsRegistryAddress, wallet)
}

const defaultMainnetTokens: ITokenWithoutLogo[] = Object.keys(mainnetContracts)
.filter(address =>
['RIF', 'USDRIF'].includes(mainnetContracts[address].symbol),
)
.map(address => {
const { decimals, name, symbol } = mainnetContracts[address]
return {
decimals,
name,
symbol,
contractAddress: address.toLowerCase(),
balance: '0x00',
usdBalance: 0,
}
})
const defaultTestnetTokens: ITokenWithoutLogo[] = Object.keys(testnetContracts)
.filter(address =>
['tRIF', 'USDRIF'].includes(testnetContracts[address].symbol),
)
.map(address => {
const { decimals, name, symbol } = testnetContracts[address]
return {
decimals,
name,
symbol,
contractAddress: address.toLowerCase(),
balance: '0x00',
usdBalance: 0,
}
})
export const getDefaultTokens = (chainId: ChainID) => {
return chainId === 30 ? defaultMainnetTokens : defaultTestnetTokens
}
37 changes: 20 additions & 17 deletions src/lib/eoaWallet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import {
} from '@ethersproject/abstract-provider'
import { TypedDataSigner } from '@ethersproject/abstract-signer'
import { fromSeed, mnemonicToSeedSync } from '@rsksmart/rif-id-mnemonic'
import { RelayPayment } from '@rsksmart/rif-relay-light-sdk'
import { getDPathByChainId } from '@rsksmart/rlogin-dpath'
import {
BigNumberish,
Bytes,
BytesLike,
TypedDataDomain,
Expand All @@ -33,38 +31,42 @@ const generatePrivateKey = (mnemonic: string, chainId: ChainID) => {
return privateKey
}

export enum RequestType {
SEND_TRANSACTION = 'sendTransaction',
SIGN_MESSAGE = 'signMessage',
SIGN_TYPED_DATA = 'signTypedData',
}

export type Request =
| SendTransactionRequest
| SignMessageRequest
| SignTypedDataRequest

export type OnRequest = (request: Request) => void

export interface IncomingRequest<Type, Payload, ConfirmArgs> {
type: Type
payload: Payload
confirm: (args?: ConfirmArgs) => Promise<void>
confirm: (args: ConfirmArgs) => Promise<void>
reject: (reason?: any) => void
}

export type SignMessageRequest = IncomingRequest<'signMessage', BytesLike, void>

export interface OverriddableTransactionOptions {
gasLimit: BigNumberish
gasPrice: BigNumberish
tokenPayment?: RelayPayment
pendingTxsCount?: number
}
export type SignMessageRequest = IncomingRequest<
RequestType.SIGN_MESSAGE,
BytesLike,
void
>

export type SendTransactionRequest = IncomingRequest<
'sendTransaction',
RequestType.SEND_TRANSACTION,
TransactionRequest,
Partial<OverriddableTransactionOptions>
unknown
>

export type SignTypedDataArgs = Parameters<TypedDataSigner['_signTypedData']>

export type SignTypedDataRequest = IncomingRequest<
'signTypedData',
RequestType.SIGN_TYPED_DATA,
SignTypedDataArgs,
void
>
Expand Down Expand Up @@ -124,11 +126,12 @@ export class EOAWallet extends Wallet {

return new Promise((resolve, reject) => {
const nextRequest = Object.freeze<SendTransactionRequest>({
type: 'sendTransaction',
type: RequestType.SEND_TRANSACTION,
payload: transactionRequest,
confirm: async () => {
try {
const obj = await super.sendTransaction(transactionRequest)

resolve(obj)
} catch (err) {
reject(err)
Expand All @@ -151,7 +154,7 @@ export class EOAWallet extends Wallet {
): Promise<string> {
return new Promise((resolve, reject) => {
const nextRequest = Object.freeze<SignTypedDataRequest>({
type: 'signTypedData',
type: RequestType.SIGN_TYPED_DATA,
payload: [domain, types, value],
confirm: async () => {
try {
Expand All @@ -174,7 +177,7 @@ export class EOAWallet extends Wallet {
signMessage(message: string | Bytes): Promise<string> {
return new Promise((resolve, reject) => {
const nextRequest = Object.freeze<SignMessageRequest>({
type: 'signMessage',
type: RequestType.SIGN_MESSAGE,
payload: message,
confirm: async () => {
try {
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ const resources = {
'Please, wait for previous transaction to succeed or fail before making the next one',
send_screen_sending_transaction: 'Sending transaction...',
send_screen_return_to_home: 'Return to Home Screen',
send_transaction_popup: 'Invalid "to" address, rejecting transaction',
security_info_header: 'Security Information',
security_info_user_agreement: 'User agreement',
security_info_disclaimer:
Expand Down
55 changes: 28 additions & 27 deletions src/lib/relayWallet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@ import {
TransactionRequest,
TransactionResponse,
} from '@ethersproject/abstract-provider'
import {
RIFRelaySDK,
RelayPayment,
RifRelayConfig,
} from '@rsksmart/rif-relay-light-sdk'
import { Wallet, providers } from 'ethers'
import { BigNumber, BigNumberish, Wallet, providers } from 'ethers'
import { BlockchainAuthenticatorConfig } from '@json-rpc-tools/utils'
import { defineReadOnly } from 'ethers/lib/utils'
import { RIFRelaySDK } from '@rsksmart/rif-relay-light-sdk'

import {
ChainID,
EOAWallet,
IncomingRequest,
OnRequest,
SendTransactionRequest,
RequestType,
WalletState,
} from '../eoaWallet'

Expand All @@ -31,6 +28,25 @@ const filterTxOptions = (transactionRequest: TransactionRequest) =>
return obj
}, {})

export interface RelayPayment {
tokenContract: string
tokenAmount: BigNumber
tokenGasIncrease?: number
}

export interface OverriddableTransactionOptions {
gasLimit: BigNumberish
gasPrice: BigNumberish
tokenPayment: RelayPayment
pendingTxsCount?: number
}

type SendRelayTransactionRequest = IncomingRequest<
RequestType.SEND_TRANSACTION,
TransactionRequest,
OverriddableTransactionOptions
>

export class RelayWallet extends EOAWallet {
public rifRelaySdk: RIFRelaySDK

Expand Down Expand Up @@ -104,12 +120,11 @@ export class RelayWallet extends EOAWallet {
transactionRequest: TransactionRequest,
): Promise<TransactionResponse> {
return new Promise((resolve, reject) => {
const nextRequest = Object.freeze<SendTransactionRequest>({
type: 'sendTransaction',
const nextRequest = Object.freeze<SendRelayTransactionRequest>({
type: RequestType.SEND_TRANSACTION,
payload: transactionRequest,
confirm: async overriddenOptions => {
// check if paying with tokens:
if (overriddenOptions && overriddenOptions.tokenPayment) {
try {
console.log('sendRelayTransaction', transactionRequest)
return resolve(
await this.rifRelaySdk.sendRelayTransaction(
Expand All @@ -121,23 +136,9 @@ export class RelayWallet extends EOAWallet {
overriddenOptions.tokenPayment,
),
)
} catch (err) {
reject(err)
}

// direct execute transaction paying gas with EOA wallet:
const txOptions = {
...filterTxOptions(transactionRequest),
...(overriddenOptions || {}),
}

console.log('txOptions', txOptions)

return resolve(
await this.rifRelaySdk.smartWallet.directExecute(
transactionRequest.to!,
transactionRequest.data ?? HashZero,
txOptions,
),
)
},
reject,
})
Expand Down
2 changes: 1 addition & 1 deletion src/redux/slices/settingsSlice/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
} from 'store/slices/persistentDataSlice'
import { Wallet } from 'shared/wallet'
import { addressToUse } from 'shared/hooks'
import { createAppWallet, loadAppWallet } from 'src/shared/utils'
import { createAppWallet, loadAppWallet } from 'shared/utils'
import { MMKVStorage } from 'storage/MMKVStorage'

import {
Expand Down
58 changes: 35 additions & 23 deletions src/screens/send/TransactionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@ import {
} from 'components/index'
import { CurrencyValue, TokenBalance } from 'components/token'
import { defaultIconSize, sharedColors, testIDs } from 'shared/constants'
import { castStyle } from 'shared/utils'
import {
bitcoinFeeMap,
castStyle,
getAllowedFees,
getDefaultFeeEOA,
getDefaultFeeRelay,
isRelayWallet,
} from 'shared/utils'
import { IPrice } from 'src/subscriptions/types'
import { TokenBalanceObject } from 'store/slices/balancesSlice/types'
import { Contact, ContactWithAddressRequired } from 'src/shared/types'
Expand Down Expand Up @@ -75,16 +82,6 @@ interface FormValues {

export type ProposedContact = Omit<Contact, 'name'>

const bitcoinFeeMap = new Map([
[TokenSymbol.BTC, true],
[TokenSymbol.BTCT, true],
])

const rifFeeMap = new Map([
[TokenSymbol.TRIF, true],
[TokenSymbol.RIF, true],
])

const transactionSchema = yup.object().shape({
amount: yup.number().min(0.000000001),
to: yup.object({
Expand All @@ -111,10 +108,6 @@ export const TransactionForm = ({
status,
contactList,
}: Props) => {
const rifToken = useMemo(
() => tokenList.filter(tk => rifFeeMap.get(tk.symbol as TokenSymbol))[0],
[tokenList],
)
const insets = useSafeAreaInsets()
const { recipient, asset, amount: initialAmount } = initialValues
const { t } = useTranslation()
Expand All @@ -123,21 +116,40 @@ export const TransactionForm = ({
const [selectedToken, setSelectedToken] = useState<TokenBalanceObject>(
asset || tokenList[0],
)

// when we're able to change fee token
// use selectedFeeToken instead of selectedToken
const feeToken = useMemo(() => {
if (bitcoinFeeMap.get(selectedToken.symbol as TokenSymbol)) {
return selectedToken
}

if (!isRelayWallet) {
return getDefaultFeeEOA()
}

const contractAddress = getAllowedFees(chainId).find(
af => af.contractAddress === selectedToken.contractAddress,
)?.contractAddress

if (!contractAddress) {
return getDefaultFeeRelay(chainId)
}

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return tokenList.find(
tok =>
tok.contractAddress.toLowerCase() === contractAddress.toLowerCase(),
)!
}, [chainId, selectedToken, tokenList])

const [selectedTokenAddress, setSelectedTokenAddress] = useState<
string | undefined
>(selectedToken.contractAddress)

// const [selectedFeeToken, setSelectedFeeToken] =
// useState<TokenBalanceObject>(selectedToken)

const feeToken = useMemo((): TokenBalanceObject => {
if (bitcoinFeeMap.get(selectedToken.symbol as TokenSymbol)) {
return selectedToken
} else {
return rifToken
}
}, [selectedToken, rifToken])

const tokenQuote = selectedToken.contractAddress.startsWith('BITCOIN')
? tokenPrices.BTC.price
: tokenPrices[selectedToken.contractAddress]?.price
Expand Down
Loading
Loading