From 8656660829c8323fa5535872925e1fe2fdd24850 Mon Sep 17 00:00:00 2001 From: ahsan-javaiid Date: Thu, 18 Aug 2022 11:45:43 +0500 Subject: [PATCH] feat: rsk integration --- assets/img/currencies/png/RBTC.png | Bin 0 -> 30549 bytes assets/img/currencies/png/xusd.png | Bin 0 -> 12475 bytes assets/img/currencies/rbtc.svg | 1 + assets/img/currencies/xusd.svg | 1 + src/constants/SupportedCurrencyOptions.tsx | 20 +++ src/constants/config.card.ts | 13 ++ src/constants/currencies.ts | 118 +++++++++++++++++- src/constants/defaultDerivationPath.ts | 1 + src/constants/tokens.ts | 12 ++ .../assets/currency-shapes/RBTC-shape.svg | 1 + .../wallet/screens/CurrencySelection.tsx | 3 +- .../wallet/screens/WalletDetails.tsx | 6 + src/navigation/wallet/screens/send/SendTo.tsx | 2 + src/store/card/card.types.ts | 1 + src/store/scan/scan.effects.ts | 41 ++++++ src/store/wallet/effects/create/create.ts | 7 +- .../effects/transactions/transactions.ts | 5 +- src/store/wallet/utils/currency.ts | 19 ++- src/store/wallet/utils/validations.ts | 26 ++++ src/store/wallet/utils/wallet.ts | 8 +- src/utils/helper-methods.ts | 6 + 21 files changed, 281 insertions(+), 10 deletions(-) create mode 100644 assets/img/currencies/png/RBTC.png create mode 100644 assets/img/currencies/png/xusd.png create mode 100644 assets/img/currencies/rbtc.svg create mode 100644 assets/img/currencies/xusd.svg create mode 100644 src/navigation/card/assets/currency-shapes/RBTC-shape.svg diff --git a/assets/img/currencies/png/RBTC.png b/assets/img/currencies/png/RBTC.png new file mode 100644 index 0000000000000000000000000000000000000000..8b592cb0f3fa6e57af2ef4a8e650377214439258 GIT binary patch literal 30549 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�LBP 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 YTZji_dr$F!pVvfEkX4bXk}?YVKY0~)Jpcdz literal 0 HcmV?d00001 diff --git a/assets/img/currencies/png/xusd.png b/assets/img/currencies/png/xusd.png new file mode 100644 index 0000000000000000000000000000000000000000..5ec67bcf324fba4fa25c93b3688909922d6101b8 GIT binary patch literal 12475 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⋙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 literal 0 HcmV?d00001 diff --git a/assets/img/currencies/rbtc.svg b/assets/img/currencies/rbtc.svg new file mode 100644 index 000000000..72d40c535 --- /dev/null +++ b/assets/img/currencies/rbtc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/img/currencies/xusd.svg b/assets/img/currencies/xusd.svg new file mode 100644 index 000000000..d86a30137 --- /dev/null +++ b/assets/img/currencies/xusd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/constants/SupportedCurrencyOptions.tsx b/src/constants/SupportedCurrencyOptions.tsx index 42126d0fb..15a82c548 100644 --- a/src/constants/SupportedCurrencyOptions.tsx +++ b/src/constants/SupportedCurrencyOptions.tsx @@ -2,6 +2,8 @@ import React, {ReactElement} from 'react'; import BtcIcon from '../../assets/img/currencies/btc.svg'; import BchIcon from '../../assets/img/currencies/bch.svg'; import EthIcon from '../../assets/img/currencies/eth.svg'; +import RbtcIcon from '../../assets/img/currencies/rbtc.svg'; +import XUSDIcon from '../../assets/img/currencies/xusd.svg'; import DogeIcon from '../../assets/img/currencies/doge.svg'; import LtcIcon from '../../assets/img/currencies/ltc.svg'; import XrpIcon from '../../assets/img/currencies/xrp.svg'; @@ -32,6 +34,8 @@ export const CurrencyListIcons: { btc: props => , bch: props => , eth: props => , + rbtc: props => , + xusd: props => , doge: props => , ltc: props => , xrp: props => , @@ -71,6 +75,14 @@ export const SupportedCurrencyOptions: Array = [ hasMultisig: false, // TODO imgSrc: require('../../assets/img/currencies/png/ETH.png'), }, + { + id: 'rbtc', + img: CurrencyListIcons.rbtc, + currencyName: 'RSK', + currencyAbbreviation: 'RBTC', + hasMultisig: false, // TODO + imgSrc: require('../../assets/img/currencies/png/RBTC.png'), + }, { id: 'doge', img: CurrencyListIcons.doge, @@ -142,6 +154,14 @@ export const SupportedCurrencyOptions: Array = [ isToken: true, imgSrc: require('../../assets/img/currencies/png/BUSD.png'), }, + { + id: 'xusd', + img: CurrencyListIcons.xusd, + currencyName: 'Sovryn XUSD', + currencyAbbreviation: 'XUSD', + isToken: true, + imgSrc: require('../../assets/img/currencies/png/xusd.png'), + }, { id: 'dai', img: CurrencyListIcons.dai, diff --git a/src/constants/config.card.ts b/src/constants/config.card.ts index 378df47c7..93fb82412 100644 --- a/src/constants/config.card.ts +++ b/src/constants/config.card.ts @@ -8,6 +8,7 @@ import BUSDShape from '../navigation/card/assets/currency-shapes/BUSD-shape.svg' import DAIShape from '../navigation/card/assets/currency-shapes/DAI-shape.svg'; import DOGEShape from '../navigation/card/assets/currency-shapes/DOGE-shape.svg'; import ETHShape from '../navigation/card/assets/currency-shapes/ETH-shape.svg'; +import RBTCShape from '../navigation/card/assets/currency-shapes/RBTC-shape.svg'; import GUSDShape from '../navigation/card/assets/currency-shapes/GUSD-shape.svg'; import USDPShape from '../navigation/card/assets/currency-shapes/USDP-shape.svg'; import USDCShape from '../navigation/card/assets/currency-shapes/USDC-shape.svg'; @@ -192,6 +193,18 @@ export const SUPPORTED_DESIGN_CURRENCIES: SupportedDesignCurrenciesConfig = { pillCircleBackground: '#FFF', }, }, + RBTC: { + currency: 'RBTC', + enabled: true, + palette: { + BackgroundShape: RBTCShape, + stopColor1: '#9A9FF1', + stopColor2: '#575DC2', + pillColor: '#FFF', + pillBackground: '#595FC6', + pillCircleBackground: '#FFF', + }, + }, GUSD: { currency: 'GUSD', enabled: true, diff --git a/src/constants/currencies.ts b/src/constants/currencies.ts index 2165480ec..034f22204 100644 --- a/src/constants/currencies.ts +++ b/src/constants/currencies.ts @@ -1,4 +1,4 @@ -export type SupportedCoins = 'btc' | 'bch' | 'ltc' | 'doge' | 'eth'; +export type SupportedCoins = 'btc' | 'bch' | 'ltc' | 'doge' | 'eth' | 'rbtc'; export type SupportedTokens = | 'usdc' | 'gusd' @@ -8,7 +8,8 @@ export type SupportedTokens = | 'wbtc' | 'shib' | 'ape' - | 'euroc'; + | 'euroc' + | 'xusd'; export type SupportedCurrencies = SupportedCoins | SupportedTokens; export interface CurrencyOpts { @@ -168,6 +169,117 @@ export const Currencies: {[key in string]: CurrencyOpts} = { gradientBackgroundColor: '#6b71d6', }, }, + rbtc: { + name: 'Smart Bitcoin', + chain: 'RSK', + coin: 'rbtc', + unitInfo: { + unitName: 'RBTC', + unitToSatoshi: 1e18, + unitDecimals: 18, + unitCode: 'rbtc' + }, + properties: { + hasMultiSig: false, + hasMultiSend: false, + isUtxo: false, + isERCToken: false, + isStableCoin: false, + singleAddress: true + }, + paymentInfo: { + paymentCode: 'EIP681', + protocolPrefix: { livenet: 'rsk', testnet: 'rsk' }, + ratesApi: 'https://bws.bitpay.com/bws/api/v3/fiatrates/rbtc', + blockExplorerUrls: 'explorer.rsk.co/', + blockExplorerUrlsTestnet: 'explorer.testet.rsk.co/' + }, + feeInfo: { + feeUnit: 'Gwei', + feeUnitAmount: 1e9, + blockTime: 0.53, + maxMerchantFee: 'urgent' + }, + theme: { + coinColor: '#41d434', + backgroundColor: '#1e90ff', + gradientBackgroundColor: '#1e90ff' + } + }, + rsk: { // This entry is because exchange-rates assumes that chain and coin are the same and asks for theme to 'rsk' + name: 'Smart Bitcoin', + chain: 'RSK', + coin: 'rbtc', + unitInfo: { + unitName: 'RBTC', + unitToSatoshi: 1e18, + unitDecimals: 18, + unitCode: 'rbtc' + }, + properties: { + hasMultiSig: false, + hasMultiSend: false, + isUtxo: false, + isERCToken: false, + isStableCoin: false, + singleAddress: true + }, + paymentInfo: { + paymentCode: 'EIP681', + protocolPrefix: { livenet: 'rsk', testnet: 'rsk' }, + ratesApi: 'https://bws.bitpay.com/bws/api/v3/fiatrates/btc', + blockExplorerUrls: 'explorer.rsk.co/', + blockExplorerUrlsTestnet: 'explorer.testet.rsk.co/' + }, + feeInfo: { + feeUnit: 'Gwei', + feeUnitAmount: 1e9, + blockTime: 0.53, + maxMerchantFee: 'urgent' + }, + theme: { + coinColor: '#41d434', + backgroundColor: '#1e90ff', + gradientBackgroundColor: '#1e90ff' + }, + }, + xusd: { + name: 'Sovryn XUSD', + chain: 'RSK', + coin: 'xusd', + unitInfo: { + unitName: 'XUSD', + unitToSatoshi: 1e18, + unitDecimals: 18, + unitCode: 'xusd', + }, + properties: { + hasMultiSig: false, + hasMultiSend: false, + isUtxo: false, + isERCToken: true, + isStableCoin: true, + singleAddress: true, + }, + paymentInfo: { + paymentCode: 'EIP681', + protocolPrefix: { livenet: 'rsk', testnet: 'rsk' }, + ratesApi: 'https://bws.bitpay.com/bws/api/v3/fiatrates/xusd', + blockExplorerUrls: 'explorer.rsk.co/', + blockExplorerUrlsTestnet: 'explorer.testet.rsk.co/' + }, + feeInfo: { + feeUnit: 'Gwei', + feeUnitAmount: 1e9, + blockTime: 0.2, + maxMerchantFee: 'urgent', + }, + theme: { + coinColor: '#f3ba2d', + backgroundColor: 'rgba(135,206,250,1)', + gradientBackgroundColor: 'rgba(30,144,255, 0.2)', + }, + }, xrp: { name: 'XRP', chain: 'XRP', @@ -628,7 +740,7 @@ export const SUPPORTED_TOKENS = [ 'ape', 'euroc', ]; -export const SUPPORTED_COINS = ['btc', 'bch', 'eth', 'doge', 'ltc', 'xrp']; +export const SUPPORTED_COINS = ['btc', 'bch', 'eth', 'rbtc', 'doge', 'ltc', 'xrp']; export const SUPPORTED_CURRENCIES = [...SUPPORTED_COINS, ...SUPPORTED_TOKENS]; export const POPULAR_TOKENS = [ 'UNI', diff --git a/src/constants/defaultDerivationPath.ts b/src/constants/defaultDerivationPath.ts index bbb95d40d..523ad93a4 100644 --- a/src/constants/defaultDerivationPath.ts +++ b/src/constants/defaultDerivationPath.ts @@ -2,6 +2,7 @@ export enum DefaultDerivationPath { defaultBTC = "m/44'/0'/0'", defaultBCH = "m/44'/145'/0'", defaultETH = "m/44'/60'/0'", + defaultRBTC = "m/44'/137'/0'", defaultXRP = "m/44'/144'/0'", defaultDOGE = "m/44'/3'/0'", defaultLTC = "m/44'/2'/0'", diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index 7bd02e7c9..959e77e2f 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -32,6 +32,12 @@ export const BitpaySupportedTokenOpts: TokenOptsType = { decimals: 18, address: '0x4fabb145d64652a948d72533023f6e7a623c7c53', }, + xusd: { + name: 'Sovryn XUSD', + symbol: 'XUSD', + decimals: 18, + address: '0xb5999795BE0EbB5bAb23144AA5FD6A02D080299F', + }, dai: { name: 'Dai', symbol: 'DAI', @@ -89,6 +95,12 @@ export const BitpaySupportedTokenOptsByAddress: TokenOptsType = { decimals: 18, address: '0x4fabb145d64652a948d72533023f6e7a623c7c53', }, + '0xb5999795BE0EbB5bAb23144AA5FD6A02D080299F': { + name: 'Sovryn XUSD', + symbol: 'XUSD', + decimals: 18, + address: '0xb5999795BE0EbB5bAb23144AA5FD6A02D080299F', + }, '0x6b175474e89094c44da98b954eedeac495271d0f': { name: 'Dai', symbol: 'DAI', diff --git a/src/navigation/card/assets/currency-shapes/RBTC-shape.svg b/src/navigation/card/assets/currency-shapes/RBTC-shape.svg new file mode 100644 index 000000000..72d40c535 --- /dev/null +++ b/src/navigation/card/assets/currency-shapes/RBTC-shape.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/navigation/wallet/screens/CurrencySelection.tsx b/src/navigation/wallet/screens/CurrencySelection.tsx index 306fabfd9..8b739b166 100644 --- a/src/navigation/wallet/screens/CurrencySelection.tsx +++ b/src/navigation/wallet/screens/CurrencySelection.tsx @@ -129,6 +129,7 @@ const DESCRIPTIONS: Record = { const POPULAR_TOKENS: Record = { eth: ['usdc', 'busd', 'ape'], + rsk: ['xusd'], matic: ['usdc', 'busd', 'gusd'], }; @@ -256,7 +257,7 @@ const CurrencySelection: React.VFC = ({ const tokenData = Currencies[k] || appTokenData[k] || appCustomTokenData[k]; - const chainData = chainMap[tokenData.chain.toLowerCase()]; + const chainData = chainMap[tokenData.chain.toLowerCase() === 'rsk' ? 'rbtc' : tokenData.chain.toLowerCase()]; const imgSrc = SupportedCurrencyOptions.find(c => c.id === k)?.imgSrc; const isReqSrc = ( src: ImageSourcePropType | undefined, diff --git a/src/navigation/wallet/screens/WalletDetails.tsx b/src/navigation/wallet/screens/WalletDetails.tsx index 28adcdcb4..8d6150a77 100644 --- a/src/navigation/wallet/screens/WalletDetails.tsx +++ b/src/navigation/wallet/screens/WalletDetails.tsx @@ -714,6 +714,12 @@ const WalletDetails: React.FC = ({route}) => { ? `https://${Currencies.eth.paymentInfo.blockExplorerUrls}address/${address}` : `https://${Currencies.eth.paymentInfo.blockExplorerUrlsTestnet}address/${address}`; } + if (coin === 'rbtc') { + url = + fullWalletObj.network === 'livenet' + ? `https://${Currencies.rbtc.paymentInfo.blockExplorerUrls}address/${address}` + : `https://${Currencies.rbtc.paymentInfo.blockExplorerUrlsTestnet}address/${address}`; + } if (dispatch(IsERCToken(coin))) { url = fullWalletObj.network === 'livenet' diff --git a/src/navigation/wallet/screens/send/SendTo.tsx b/src/navigation/wallet/screens/send/SendTo.tsx index 1ed014f4f..c3e8e1520 100644 --- a/src/navigation/wallet/screens/send/SendTo.tsx +++ b/src/navigation/wallet/screens/send/SendTo.tsx @@ -87,6 +87,7 @@ const ValidDataTypes: string[] = [ 'BitcoinAddress', 'BitcoinCashAddress', 'EthereumAddress', + 'RSKAddress', 'RippleAddress', 'DogecoinAddress', 'LitecoinAddress', @@ -94,6 +95,7 @@ const ValidDataTypes: string[] = [ 'BitcoinUri', 'BitcoinCashUri', 'EthereumUri', + 'RSKUri', 'DogecoinUri', 'LitecoinUri', 'BitPayUri', diff --git a/src/store/card/card.types.ts b/src/store/card/card.types.ts index 6e4985420..33113a81d 100644 --- a/src/store/card/card.types.ts +++ b/src/store/card/card.types.ts @@ -28,6 +28,7 @@ export type SupportedCurrencies = | 'BTC' | 'BCH' | 'ETH' + | 'RBTC' | 'GUSD' | 'USDP' | 'BUSD' diff --git a/src/store/scan/scan.effects.ts b/src/store/scan/scan.effects.ts index 42b3fae80..2fdf50ebd 100644 --- a/src/store/scan/scan.effects.ts +++ b/src/store/scan/scan.effects.ts @@ -19,6 +19,8 @@ import { IsValidDogecoinUri, IsValidEthereumAddress, IsValidEthereumUri, + IsValidRSKAddress, + IsValidRSKUri, IsValidImportPrivateKey, IsValidJoinCode, IsValidLitecoinAddress, @@ -98,6 +100,9 @@ export const incomingData = // Ethereum URI } else if (IsValidEthereumUri(data)) { dispatch(handleEthereumUri(data, opts?.wallet)); + // RSK URI + } else if (IsValidRSKUri(data)) { + dispatch(handleRSKUri(data, opts?.wallet)); // Ripple URI } else if (IsValidRippleUri(data)) { dispatch(handleRippleUri(data, opts?.wallet)); @@ -128,6 +133,9 @@ export const incomingData = // Address (Ethereum) } else if (IsValidEthereumAddress(data)) { dispatch(handlePlainAddress(data, coin || 'eth', opts)); + // Address RSK + } else if (IsValidRSKAddress(data)) { + dispatch(handlePlainAddress(data, coin || 'rsk' || 'rbtc', opts)); // Address (Ripple) } else if (IsValidRippleAddress(data)) { dispatch(handlePlainAddress(data, coin || 'xrp', opts)); @@ -721,6 +729,39 @@ const handleEthereumUri = } }; +const handleRSKUri = + (data: string, wallet?: Wallet): Effect => + dispatch => { + dispatch(LogActions.info('[scan] Incoming-data: RSK URI')); + const coin = 'rbtc'; + const value = /[\?\&]value=(\d+([\,\.]\d+)?)/i; + const gasPrice = /[\?\&]gasPrice=(\d+([\,\.]\d+)?)/i; + let feePerKb; + if (gasPrice.exec(data)) { + feePerKb = Number(gasPrice.exec(data)![1]); + } + const address = ExtractBitPayUriAddress(data); + const recipient = { + type: 'address', + currency: coin, + address, + }; + if (!value.exec(data)) { + dispatch(goToAmount({coin, recipient, wallet, opts: {feePerKb}})); + } else { + const parsedAmount = value.exec(data)![1]; + const amount = Number(dispatch(FormatAmount(coin, Number(parsedAmount)))); + dispatch( + goToConfirm({ + recipient, + amount, + wallet, + opts: {feePerKb}, + }), + ); + } + }; + const handleRippleUri = (data: string, wallet?: Wallet): Effect => dispatch => { diff --git a/src/store/wallet/effects/create/create.ts b/src/store/wallet/effects/create/create.ts index a0dc275fd..126eb85a2 100644 --- a/src/store/wallet/effects/create/create.ts +++ b/src/store/wallet/effects/create/create.ts @@ -15,6 +15,7 @@ import { buildWalletObj, checkEncryptPassword, } from '../../utils/wallet'; +import { getRSKChainAbbrevation } from '../../utils/currency'; import { failedAddWallet, successAddWallet, @@ -244,7 +245,7 @@ const createMultipleWallets = })) as Wallet; wallets.push(wallet); - if (coin === 'eth') { + if (coin === 'eth' || coin === 'rbtc') { wallet.preferences = wallet.preferences || { tokenAddresses: [], }; @@ -307,7 +308,7 @@ const createWallet = (params: { bwcClient.fromString( key.createCredentials(password, { - coin, + coin: getRSKChainAbbrevation(coin), network, account, n: 1, @@ -323,7 +324,7 @@ const createWallet = (params: { { network, singleAddress, - coin, + coin: getRSKChainAbbrevation(coin), useNativeSegwit, }, (err: any) => { diff --git a/src/store/wallet/effects/transactions/transactions.ts b/src/store/wallet/effects/transactions/transactions.ts index b86afc6a9..865cbebe3 100644 --- a/src/store/wallet/effects/transactions/transactions.ts +++ b/src/store/wallet/effects/transactions/transactions.ts @@ -12,6 +12,7 @@ import { IsCustomERCToken, IsERCToken, IsUtxoCoin, + getRSKCurrencyAbbrevation, } from '../../utils/currency'; import {ToAddress, ToLtcAddress} from '../address/address'; import { @@ -125,6 +126,7 @@ const ProcessTx = tx: TransactionProposal, ): Effect => dispatch => { + currencyAbbreviation = getRSKCurrencyAbbrevation(currencyAbbreviation); if (!tx || tx.action === 'invalid') { return tx; } @@ -823,7 +825,8 @@ export const buildTransactionDetails = time, hasMultiplesOutputs, } = transaction; - const {coin: currency} = wallet.credentials; + let {coin: currency} = wallet.credentials; + currency = getRSKCurrencyAbbrevation(currency); const chain = dispatch(GetChain(currency)).toLowerCase(); const _fee = fees || fee; diff --git a/src/store/wallet/utils/currency.ts b/src/store/wallet/utils/currency.ts index 12209cbf1..d4f76f52d 100644 --- a/src/store/wallet/utils/currency.ts +++ b/src/store/wallet/utils/currency.ts @@ -34,7 +34,7 @@ export const GetPrecision = WALLET: {tokenData, customTokenData}, } = getState(); const tokens = {...tokenData, ...customTokenData}; - const currency = currencyAbbreviation.toLowerCase(); + const currency = getRSKCurrencyAbbrevation(currencyAbbreviation.toLowerCase()); return Currencies[currency]?.unitInfo || tokens[currency]?.unitInfo; }; @@ -76,6 +76,7 @@ export const IsERCToken = export const GetBlockExplorerUrl = (currencyAbbreviation: string, network: string = 'livenet'): Effect => (dispatch, getState) => { + currencyAbbreviation = getRSKCurrencyAbbrevation(currencyAbbreviation); const { WALLET: {tokenData, customTokenData}, } = getState(); @@ -147,3 +148,19 @@ export const isSingleAddressCoin = tokens[currency]?.properties.singleAddress ); }; + + /** + * In case of rsk chain and currency having different names. + * This function will return the currency name for rsk. + */ + export const getRSKCurrencyAbbrevation = (name: string) => { + return name === 'rsk' ? 'rbtc': name; + } + + /** + * In case of rsk chain and currency having different names. + * This function will return the chain name for rsk. + */ + export const getRSKChainAbbrevation = (name: string) => { + return name === 'rbtc' ? 'rsk': name; + } diff --git a/src/store/wallet/utils/validations.ts b/src/store/wallet/utils/validations.ts index f1cd8ac5b..5c114dac8 100644 --- a/src/store/wallet/utils/validations.ts +++ b/src/store/wallet/utils/validations.ts @@ -62,6 +62,11 @@ export const IsValidEthereumUri = (data: string): boolean => { return !!BWC.getCore().Validation.validateUri('ETH', data); }; +export const IsValidRSKUri = (data: string): boolean => { + data = SanitizeUri(data); + return !!BWC.getCore().Validation.validateUri('RSK', data); +}; + export const IsValidRippleUri = (data: string): boolean => { data = SanitizeUri(data); return !!BWC.getCore().Validation.validateUri('XRP', data); @@ -104,6 +109,10 @@ export const IsValidEthereumAddress = (data: string): boolean => { return !!BWC.getCore().Validation.validateAddress('ETH', 'livenet', data); }; +export const IsValidRSKAddress = (data: string): boolean => { + return !!BWC.getCore().Validation.validateAddress('RSK', 'livenet', data); +}; + export const IsValidRippleAddress = (data: string): boolean => { return !!BWC.getCore().Validation.validateAddress('XRP', 'livenet', data); }; @@ -219,6 +228,14 @@ export const ValidateURI = (data: string): any => { }; } + if (IsValidRSKUri(data)) { + return { + data, + type: 'RSKUri', + title: 'RSK URI', + }; + } + if (IsValidRippleUri(data)) { return { data, @@ -275,6 +292,14 @@ export const ValidateURI = (data: string): any => { }; } + if (IsValidRSKAddress(data)) { + return { + data, + type: 'RSKAddress', + title: 'RSK Address', + }; + } + if (IsValidRippleAddress(data)) { return { data, @@ -329,6 +354,7 @@ export const ValidateCoinAddress = ( const addressLtc = BWC.getBitcoreLtc().Address; return !!addressLtc.isValid(str, network); case 'eth': + case 'rsk': case 'xrp': const {Validation} = BWC.getCore(); return !!Validation.validateAddress(coin.toUpperCase(), network, str); diff --git a/src/store/wallet/utils/wallet.ts b/src/store/wallet/utils/wallet.ts index 9c36eb84e..b1f1ec4f9 100644 --- a/src/store/wallet/utils/wallet.ts +++ b/src/store/wallet/utils/wallet.ts @@ -11,7 +11,7 @@ import {Credentials} from 'bitcore-wallet-client/ts_build/lib/credentials'; import {SUPPORTED_CURRENCIES} from '../../../constants/currencies'; import {CurrencyListIcons} from '../../../constants/SupportedCurrencyOptions'; import {BwcProvider} from '../../../lib/bwc'; -import {GetName, GetPrecision, GetProtocolPrefix} from './currency'; +import {GetName, GetPrecision, GetProtocolPrefix, getRSKChainAbbrevation} from './currency'; import merge from 'lodash.merge'; import cloneDeep from 'lodash.clonedeep'; import {convertToFiat, formatFiatAmount} from '../../../utils/helper-methods'; @@ -45,6 +45,11 @@ const mapAbbreviationAndName = currencyAbbreviation: 'usdp', currencyName: dispatch(GetName(coin)), }; + case 'rsk': + return { + currencyAbbreviation: 'rbtc', + currencyName: dispatch(GetName('rbtc')), + }; default: return { currencyAbbreviation: coin, @@ -207,6 +212,7 @@ export const toFiat = customRate?: number, ): Effect => dispatch => { + currencyAbbreviation = getRSKChainAbbrevation(currencyAbbreviation); const ratesPerCurrency = rates[currencyAbbreviation]; if (!ratesPerCurrency) { diff --git a/src/utils/helper-methods.ts b/src/utils/helper-methods.ts index f1063c0cd..2f8889c79 100644 --- a/src/utils/helper-methods.ts +++ b/src/utils/helper-methods.ts @@ -64,6 +64,9 @@ export const getNetworkName = (path: string): string => { case "60'": // for ETH networkName = 'livenet'; break; + case "137'": // for RSK + networkName = 'livenet'; + break; case "144'": // for XRP networkName = 'livenet'; break; @@ -114,6 +117,9 @@ export const isValidDerivationPathCoin = ( case 'eth': isValid = ["60'", "0'", "1'"].indexOf(coinCode) > -1; break; + case 'rbtc': + isValid = ["137'", "0'", "1'"].indexOf(coinCode) > -1; + break; case 'xrp': isValid = ["144'", "0'", "1'"].indexOf(coinCode) > -1; break;