Skip to content

Commit

Permalink
US-1856 Added security measure for bitcoin where return remainder bal… (
Browse files Browse the repository at this point in the history
#712)

* US-1856 Added security measure for bitcoin where return remainder balance will go to a new address of the user.
Increased bitcoin decimals to 6

* Modified fetchAddressToReturnFundsTo

* Increased package.json version

* Fixed back button for bitcoin
  • Loading branch information
Freshenext authored Aug 29, 2023
1 parent ac8102f commit b0c31f7
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 17 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
"@rsksmart/rif-relay-light-sdk": "^1.0.3",
"@rsksmart/rif-wallet-abi-enhancer": "^1.0.4",
"@rsksmart/rif-wallet-adapters": "^1.0.0",
"@rsksmart/rif-wallet-bitcoin": "^1.1.0",
"@rsksmart/rif-wallet-bitcoin": "^1.2.0",
"@rsksmart/rif-wallet-core": "^1.0.2",
"@rsksmart/rif-wallet-eip681": "1.0.1",
"@rsksmart/rif-wallet-services": "^1.0.4",
"@rsksmart/rif-wallet-services": "^1.0.5",
"@rsksmart/rif-wallet-token": "^1.0.1",
"@rsksmart/rlogin-dpath": "^1.0.1",
"@rsksmart/rns-resolver.js": "^1.0.1",
Expand Down
2 changes: 1 addition & 1 deletion src/redux/rootReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const migrations = {

const settingsPersistConfig: PersistConfig<SettingsSlice> = {
key: 'settings',
whitelist: ['pin', 'chainId', 'isFirstLaunch'],
whitelist: ['pin', 'chainId', 'isFirstLaunch', 'usedBitcoinAddresses'],
storage: reduxStorage,
}

Expand Down
8 changes: 8 additions & 0 deletions src/redux/slices/settingsSlice/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ const initialState: SettingsSlice = {
pin: null,
bitcoin: null,
chainId: 31,
usedBitcoinAddresses: {},
}

const settingsSlice = createSlice({
Expand Down Expand Up @@ -428,6 +429,12 @@ const settingsSlice = createSlice({
setBitcoinState: (state, { payload }: PayloadAction<Bitcoin>) => {
state.bitcoin = payload
},
addAddressToUsedBitcoinAddresses: (
state,
{ payload }: PayloadAction<string>,
) => {
state.usedBitcoinAddresses[payload] = payload
},
},
extraReducers(builder) {
builder.addCase(createWallet.pending, state => {
Expand Down Expand Up @@ -480,6 +487,7 @@ export const {
setFullscreen,
setHideBalance,
setBitcoinState,
addAddressToUsedBitcoinAddresses,
} = settingsSlice.actions

export const settingsSliceReducer = settingsSlice.reducer
Expand Down
1 change: 1 addition & 0 deletions src/redux/slices/settingsSlice/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,5 @@ export interface SettingsSlice {
hideBalance: boolean
pin: string | null
bitcoin: Bitcoin | null
usedBitcoinAddresses: { [key: string]: string }
}
2 changes: 0 additions & 2 deletions src/screens/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import { selectTransactions } from 'store/slices/transactionsSlice'
import { sharedColors } from 'shared/constants'
import { castStyle } from 'shared/utils'
import { ActivityBasicRow } from 'screens/activity/ActivityRow'
import { rootTabsRouteNames } from 'navigation/rootNavigator'

import { HomeInformationBar } from './HomeInformationBar'
import { getTokenColor } from './tokenColor'
Expand Down Expand Up @@ -124,7 +123,6 @@ export const HomeScreen = ({
})
case 'SEND':
return navigation.navigate(homeStackRouteNames.Send, {
backScreen: rootTabsRouteNames.Home,
token: _selected?.symbol,
contractAddress: _selected?.contractAddress,
})
Expand Down
21 changes: 21 additions & 0 deletions src/screens/send/bitcoinUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ interface FetchUtxoFunction {
onSetBalance?: (balance: BigNumber) => void
}

interface FetchAddressToReturnFundsToFunction {
token: BitcoinTokenBalanceObject
usedBitcoinAddresses: { [key: string]: string }
onSetAddress?: (address: string) => void
}

export const calculateBalanceFromUtxos = (
utxos: UnspentTransactionType[],
): BigNumber =>
Expand All @@ -35,3 +41,18 @@ export const fetchUtxo = ({
})
}
}

export const fetchAddressToReturnFundsTo = ({
token,
onSetAddress,
usedBitcoinAddresses,
}: FetchAddressToReturnFundsToFunction) => {
token.bips[0].fetchExternalAvailableAddresses({}).then(addresses => {
for (const address of addresses) {
if (!usedBitcoinAddresses[address]) {
onSetAddress?.(address)
break
}
}
})
}
10 changes: 9 additions & 1 deletion src/screens/send/transferBitcoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ interface ITransferBitcoin {
btcToPay: number
to: string
utxos: Array<UnspentTransactionType>
balance: number
addressToReturnRemainingAmount: string
onBitcoinTransactionSuccess?: (options: { addressUsed: string }) => void
onSetError?: OnSetErrorFunction
onSetCurrentTransaction?: OnSetCurrentTransactionFunction
balance: number
}

const MINIMUM_FEE = 141 // should be removed when estimate fee is up...
Expand All @@ -28,6 +30,8 @@ export const transferBitcoin = ({
to,
utxos,
balance,
addressToReturnRemainingAmount,
onBitcoinTransactionSuccess,
}: ITransferBitcoin) => {
if (onSetError) {
onSetError(null)
Expand All @@ -44,11 +48,15 @@ export const transferBitcoin = ({
unspentTransactions: utxos,
miningFee: Number(MINIMUM_FEE),
balance,
addressToReturnRemainingAmount,
})
.then(async txIdJson => {
if (txIdJson.result) {
// success
if (onSetCurrentTransaction) {
onBitcoinTransactionSuccess?.({
addressUsed: addressToReturnRemainingAmount,
})
//@TODO: make the status a constant value
onSetCurrentTransaction({
status: 'PENDING',
Expand Down
32 changes: 29 additions & 3 deletions src/screens/send/usePaymentExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,23 @@ import { RIFWallet } from '@rsksmart/rif-wallet-core'
import { ITokenWithBalance } from '@rsksmart/rif-wallet-services'
import { useTranslation } from 'react-i18next'

import { useAppDispatch } from 'store/storeUtils'
import { useAppDispatch, useAppSelector } from 'store/storeUtils'
import {
addPendingTransaction,
modifyTransaction,
ApiTransactionWithExtras,
ModifyTransaction,
} from 'store/slices/transactionsSlice'
import { fetchUtxo } from 'screens/send/bitcoinUtils'
import {
fetchAddressToReturnFundsTo,
fetchUtxo,
} from 'screens/send/bitcoinUtils'
import { AppDispatch } from 'store/index'
import { TokenBalanceObject } from 'store/slices/balancesSlice/types'
import {
addAddressToUsedBitcoinAddresses,
selectWholeSettingsState,
} from 'store/slices/settingsSlice'

import { transferBitcoin } from './transferBitcoin'
import { transfer } from './transferTokens'
Expand Down Expand Up @@ -119,9 +126,20 @@ export const usePaymentExecutor = (
useState<TransactionInformation | null>(null)
const [error, setError] = useState<string | null | { message: string }>()
const [utxos, setUtxos] = useState<UnspentTransactionType[]>([])
const [addressToReturnRemainingAmount, setAddressToReturnRemainingAmount] =
useState<string>('')
const [bitcoinBalance, setBalanceAvailable] = useState<number>(0)
const { t } = useTranslation()
const dispatch = useAppDispatch()
const { usedBitcoinAddresses } = useAppSelector(selectWholeSettingsState)

const onBitcoinTransactionSuccess = ({
addressUsed,
}: {
addressUsed: string
}) => {
dispatch(addAddressToUsedBitcoinAddresses(addressUsed))
}

const executePayment = ({
token,
Expand Down Expand Up @@ -150,6 +168,8 @@ export const usePaymentExecutor = (
to,
utxos,
balance: bitcoinBalance,
addressToReturnRemainingAmount,
onBitcoinTransactionSuccess,
})
} else {
transfer({
Expand All @@ -166,15 +186,21 @@ export const usePaymentExecutor = (
}
}
// When bitcoin network changes - fetch utxos
// and also set the return address
useEffect(() => {
if (bitcoinNetwork && 'satoshis' in bitcoinNetwork) {
fetchUtxo({
token: bitcoinNetwork,
onSetUtxos: setUtxos,
onSetBalance: balance => setBalanceAvailable(balance.toNumber()),
})
fetchAddressToReturnFundsTo({
token: bitcoinNetwork,
onSetAddress: setAddressToReturnRemainingAmount,
usedBitcoinAddresses,
})
}
}, [bitcoinNetwork])
}, [bitcoinNetwork, usedBitcoinAddresses])

return {
currentTransaction,
Expand Down
16 changes: 8 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2085,10 +2085,10 @@
bitcoin-address-validation "^2.2.1"
bitcoinjs-lib "^6.0.2"

"@rsksmart/rif-wallet-bitcoin@^1.1.0":
version "1.1.0"
resolved "https://npm.pkg.github.com/download/@rsksmart/rif-wallet-bitcoin/1.1.0/42a8730086f472152406d32ff9dd5518857448ca#42a8730086f472152406d32ff9dd5518857448ca"
integrity sha512-mGtZNHin6SY5T5PQrXao/2Vu3qb5uugU6tk2+zTOvdnX9D/cPuj95nBIBw+utxqzYoRqIv2/hBVf2QfjMtRkZg==
"@rsksmart/rif-wallet-bitcoin@^1.2.0":
version "1.2.0"
resolved "https://npm.pkg.github.com/download/@rsksmart/rif-wallet-bitcoin/1.2.0/b40502c4511daf596e6b98add0152602257a4cfc#b40502c4511daf596e6b98add0152602257a4cfc"
integrity sha512-x9NgO+CCIx6ZPVByH7bFsSKWahGjzEhJyr49fSi9qU+d0jvvqfd2JpNygAKV6mP1VHAQfLvN4FgBacwp/w9HEw==
dependencies:
"@ethersproject/bignumber" "^5.7.0"
"@ethersproject/units" "^5.7.0"
Expand All @@ -2115,10 +2115,10 @@
dependencies:
"@rsksmart/rsk-utils" "^1.1.0"

"@rsksmart/rif-wallet-services@^1.0.4":
version "1.0.4"
resolved "https://npm.pkg.github.com/download/@rsksmart/rif-wallet-services/1.0.4/511c4cd4a3751e494cb4f3a6395cbc5b3c03cd56#511c4cd4a3751e494cb4f3a6395cbc5b3c03cd56"
integrity sha512-i5DR1wXd3YDIWG2BkvAxkVolKdyB0HoIyW4/G2R61TNVBOs1Sq5J7tyY9LV7qD3yehcu0anym25UvS9TaP6uHg==
"@rsksmart/rif-wallet-services@^1.0.5":
version "1.0.5"
resolved "https://npm.pkg.github.com/download/@rsksmart/rif-wallet-services/1.0.5/dd97e829db5229df0b7c632e9b9e37c4c0118d96#dd97e829db5229df0b7c632e9b9e37c4c0118d96"
integrity sha512-RjCbqU4aj3Q2Hn5XhhxBqcQnKNgJY/dgGLton4d8k5B5xPDqCxOCvH6W3zyGRQXhqQz+Ax2pPl16L8GqsZwjUA==
dependencies:
"@ethersproject/contracts" "^5.7.0"
"@rsksmart/rif-wallet-abi-enhancer" "*"
Expand Down

0 comments on commit b0c31f7

Please sign in to comment.