diff --git a/common/actions/swap.js b/common/actions/swap.js index 15f2a4d0..79c37555 100644 --- a/common/actions/swap.js +++ b/common/actions/swap.js @@ -3,7 +3,9 @@ import { SWAP_DESTINATION_KIND, SWAP_ORIGIN_AMOUNT, SWAP_ORIGIN_KIND, - SWAP_UPDATE_BITY_RATES + SWAP_UPDATE_BITY_RATES, + SWAP_PART_ONE_COMPLETE, + SWAP_RECEIVING_ADDRESS } from './swapConstants'; export const originKindSwap = value => { @@ -40,3 +42,17 @@ export const updateBityRatesSwap = value => { value }; }; + +export const partOneCompleteSwap = (value: boolean) => { + return { + type: SWAP_PART_ONE_COMPLETE, + value + }; +}; + +export const receivingAddressSwap = value => { + return { + type: SWAP_RECEIVING_ADDRESS, + value + }; +}; diff --git a/common/actions/swapConstants.js b/common/actions/swapConstants.js index ca72fc2c..ecf0fb4a 100644 --- a/common/actions/swapConstants.js +++ b/common/actions/swapConstants.js @@ -3,3 +3,5 @@ export const SWAP_DESTINATION_KIND = 'SWAP_DESTINATION_KIND'; export const SWAP_ORIGIN_AMOUNT = 'SWAP_ORIGIN_AMOUNT'; export const SWAP_DESTINATION_AMOUNT = 'SWAP_DESTINATION_AMOUNT'; export const SWAP_UPDATE_BITY_RATES = 'SWAP_UPDATE_BITY_RATES'; +export const SWAP_PART_ONE_COMPLETE = 'SWAP_PART_ONE_COMPLETE'; +export const SWAP_RECEIVING_ADDRESS = 'SWAP_RECEIVING_ADDRESS'; diff --git a/common/components/Footer/index.jsx b/common/components/Footer/index.jsx index 1c7bdd82..39da157a 100644 --- a/common/components/Footer/index.jsx +++ b/common/components/Footer/index.jsx @@ -1,100 +1,202 @@ -import React, {Component} from 'react'; -import translate, {getTranslators} from 'translations'; - +import React, { Component } from 'react'; +import translate, { getTranslators } from 'translations'; +import { DONATION_ADDRESSES_MAP } from 'config/data'; export default class Footer extends Component { - render() { - const translators = getTranslators() - return ( - + ); + } } diff --git a/common/config/data.js b/common/config/data.js index 0094ba20..dac459b5 100644 --- a/common/config/data.js +++ b/common/config/data.js @@ -1,162 +1,168 @@ +export const DONATION_ADDRESSES_MAP = { + BTC: '1MEWT2SGbqtz6mPCgFcnea8XmWV5Z4Wc6', + ETH: '0x7cB57B5A97eAbe94205C07890BE4c1aD31E486A8', + REP: '0x7cB57B5A97eAbe94205C07890BE4c1aD31E486A8' +}; + export const languages = [ - { - sign: 'en', - name: 'English' - }, - { - sign: 'de', - name: 'Deutsch' - }, - { - sign: 'el', - name: 'Ελληνικά' - }, - { - sign: 'es', - name: 'Español' - }, - { - sign: 'fi', - name: 'Suomi' - }, - { - sign: 'fr', - name: 'Français' - }, - { - sign: 'hu', - name: 'Magyar' - }, - { - sign: 'id', - name: 'Indonesian' - }, - { - sign: 'it', - name: 'Italiano' - }, - { - sign: 'ja', - name: '日本語' - }, - { - sign: 'nl', - name: 'Nederlands' - }, - { - sign: 'no', - name: 'Norsk Bokmål' - }, - { - sign: 'pl', - name: 'Polski' - }, - { - sign: 'pt', - name: 'Português' - }, - { - sign: 'ru', - name: 'Русский' - }, - { - sign: 'ko', - name: 'Korean' - }, - // { - // 'sign': 'sk', - // 'name': 'Slovenčina' - // }, - // { - // 'sign': 'sl', - // 'name': 'Slovenščina' - // }, - // { - // 'sign': 'sv', - // 'name': 'Svenska' - // }, - { - sign: 'tr', - name: 'Türkçe' - }, - { - sign: 'vi', - name: 'Tiếng Việt' - }, - { - sign: 'zhcn', - name: '简体中文' - }, - { - sign: 'zhtw', - name: '繁體中文' - } + { + sign: 'en', + name: 'English' + }, + { + sign: 'de', + name: 'Deutsch' + }, + { + sign: 'el', + name: 'Ελληνικά' + }, + { + sign: 'es', + name: 'Español' + }, + { + sign: 'fi', + name: 'Suomi' + }, + { + sign: 'fr', + name: 'Français' + }, + { + sign: 'hu', + name: 'Magyar' + }, + { + sign: 'id', + name: 'Indonesian' + }, + { + sign: 'it', + name: 'Italiano' + }, + { + sign: 'ja', + name: '日本語' + }, + { + sign: 'nl', + name: 'Nederlands' + }, + { + sign: 'no', + name: 'Norsk Bokmål' + }, + { + sign: 'pl', + name: 'Polski' + }, + { + sign: 'pt', + name: 'Português' + }, + { + sign: 'ru', + name: 'Русский' + }, + { + sign: 'ko', + name: 'Korean' + }, + // { + // 'sign': 'sk', + // 'name': 'Slovenčina' + // }, + // { + // 'sign': 'sl', + // 'name': 'Slovenščina' + // }, + // { + // 'sign': 'sv', + // 'name': 'Svenska' + // }, + { + sign: 'tr', + name: 'Türkçe' + }, + { + sign: 'vi', + name: 'Tiếng Việt' + }, + { + sign: 'zhcn', + name: '简体中文' + }, + { + sign: 'zhtw', + name: '繁體中文' + } ]; export const nodeList = [ - { - name: 'ETH', - blockExplorerTX: 'https://etherscan.io/tx/[[txHash]]', - blockExplorerAddr: 'https://etherscan.io/address/[[address]]', - // 'type': nodes.nodeTypes.ETH, - eip155: true, - chainId: 1, - // 'tokenList': require('./tokens/ethTokens.json'), - // 'abiList': require('./abiDefinitions/ethAbi.json'), - estimateGas: true, - service: 'MyEtherWallet' - // 'lib': new nodes.customNode('https://api.myetherapi.com/eth', '') - }, - { - name: 'ETH', - blockExplorerTX: 'https://etherscan.io/tx/[[txHash]]', - blockExplorerAddr: 'https://etherscan.io/address/[[address]]', - // 'type': nodes.nodeTypes.ETH, - eip155: true, - chainId: 1, - // 'tokenList': require('./tokens/ethTokens.json'), - // 'abiList': require('./abiDefinitions/ethAbi.json'), - estimateGas: false, - service: 'Etherscan.io' - // 'lib': require('./nodeHelpers/etherscan') - }, - { - name: 'Ropsten', - // 'type': nodes.nodeTypes.Ropsten, - blockExplorerTX: 'https://ropsten.etherscan.io/tx/[[txHash]]', - blockExplorerAddr: 'https://ropsten.etherscan.io/address/[[address]]', - eip155: true, - chainId: 3, - // 'tokenList': require('./tokens/ropstenTokens.json'), - // 'abiList': require('./abiDefinitions/ropstenAbi.json'), - estimateGas: false, - service: 'MyEtherWallet' - // 'lib': new nodes.customNode('https://api.myetherapi.com/rop', '') - }, - { - name: 'Kovan', - // 'type': nodes.nodeTypes.Kovan, - blockExplorerTX: 'https://kovan.etherscan.io/tx/[[txHash]]', - blockExplorerAddr: 'https://kovan.etherscan.io/address/[[address]]', - eip155: true, - chainId: 42, - // 'tokenList': require('./tokens/kovanTokens.json'), - // 'abiList': require('./abiDefinitions/kovanAbi.json'), - estimateGas: false, - service: 'Etherscan.io' - // 'lib': require('./nodeHelpers/etherscanKov') - }, - { - name: 'ETC', - blockExplorerTX: 'https://gastracker.io/tx/[[txHash]]', - blockExplorerAddr: 'https://gastracker.io/addr/[[address]]', - // 'type': nodes.nodeTypes.ETC, - eip155: true, - chainId: 61, - // 'tokenList': require('./tokens/etcTokens.json'), - // 'abiList': require('./abiDefinitions/etcAbi.json'), - estimateGas: false, - service: 'Epool.io' - // 'lib': new nodes.customNode('https://mewapi.epool.io', '') - } + { + name: 'ETH', + blockExplorerTX: 'https://etherscan.io/tx/[[txHash]]', + blockExplorerAddr: 'https://etherscan.io/address/[[address]]', + // 'type': nodes.nodeTypes.ETH, + eip155: true, + chainId: 1, + // 'tokenList': require('./tokens/ethTokens.json'), + // 'abiList': require('./abiDefinitions/ethAbi.json'), + estimateGas: true, + service: 'MyEtherWallet' + // 'lib': new nodes.customNode('https://api.myetherapi.com/eth', '') + }, + { + name: 'ETH', + blockExplorerTX: 'https://etherscan.io/tx/[[txHash]]', + blockExplorerAddr: 'https://etherscan.io/address/[[address]]', + // 'type': nodes.nodeTypes.ETH, + eip155: true, + chainId: 1, + // 'tokenList': require('./tokens/ethTokens.json'), + // 'abiList': require('./abiDefinitions/ethAbi.json'), + estimateGas: false, + service: 'Etherscan.io' + // 'lib': require('./nodeHelpers/etherscan') + }, + { + name: 'Ropsten', + // 'type': nodes.nodeTypes.Ropsten, + blockExplorerTX: 'https://ropsten.etherscan.io/tx/[[txHash]]', + blockExplorerAddr: 'https://ropsten.etherscan.io/address/[[address]]', + eip155: true, + chainId: 3, + // 'tokenList': require('./tokens/ropstenTokens.json'), + // 'abiList': require('./abiDefinitions/ropstenAbi.json'), + estimateGas: false, + service: 'MyEtherWallet' + // 'lib': new nodes.customNode('https://api.myetherapi.com/rop', '') + }, + { + name: 'Kovan', + // 'type': nodes.nodeTypes.Kovan, + blockExplorerTX: 'https://kovan.etherscan.io/tx/[[txHash]]', + blockExplorerAddr: 'https://kovan.etherscan.io/address/[[address]]', + eip155: true, + chainId: 42, + // 'tokenList': require('./tokens/kovanTokens.json'), + // 'abiList': require('./abiDefinitions/kovanAbi.json'), + estimateGas: false, + service: 'Etherscan.io' + // 'lib': require('./nodeHelpers/etherscanKov') + }, + { + name: 'ETC', + blockExplorerTX: 'https://gastracker.io/tx/[[txHash]]', + blockExplorerAddr: 'https://gastracker.io/addr/[[address]]', + // 'type': nodes.nodeTypes.ETC, + eip155: true, + chainId: 61, + // 'tokenList': require('./tokens/etcTokens.json'), + // 'abiList': require('./abiDefinitions/etcAbi.json'), + estimateGas: false, + service: 'Epool.io' + // 'lib': new nodes.customNode('https://mewapi.epool.io', '') + } ]; diff --git a/common/containers/Tabs/Swap/components/wantToSwapMy.js b/common/containers/Tabs/Swap/components/currencySwap.js similarity index 94% rename from common/containers/Tabs/Swap/components/wantToSwapMy.js rename to common/containers/Tabs/Swap/components/currencySwap.js index f82da9f0..be58f129 100644 --- a/common/containers/Tabs/Swap/components/wantToSwapMy.js +++ b/common/containers/Tabs/Swap/components/currencySwap.js @@ -31,9 +31,9 @@ class CoinTypeDropDown extends Component { } } -export default class WantToSwapMy extends Component { - constructor(props, context) { - super(props, context); +export default class CurrencySwap extends Component { + constructor(props) { + super(props); } static propTypes = { @@ -47,10 +47,13 @@ export default class WantToSwapMy extends Component { originKindSwap: PropTypes.func, destinationKindSwap: PropTypes.func, originAmountSwap: PropTypes.func, - destinationAmountSwap: PropTypes.func + destinationAmountSwap: PropTypes.func, + partOneCompleteSwap: PropTypes.func }; - onClickStartSwap() {} + onClickStartSwap = () => { + this.props.partOneCompleteSwap(true); + }; onChangeOriginAmount = amount => { let originAmountAsNumber = parseFloat(amount); diff --git a/common/containers/Tabs/Swap/components/currentRates.js b/common/containers/Tabs/Swap/components/currentRates.js index 577df5a4..1016bec4 100644 --- a/common/containers/Tabs/Swap/components/currentRates.js +++ b/common/containers/Tabs/Swap/components/currentRates.js @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import translate from 'translations'; import PropTypes from 'prop-types'; +import { toFixedIfLarger } from 'utils/formatters'; export default class CurrentRates extends Component { constructor(props) { @@ -48,10 +49,10 @@ export default class CurrentRates extends Component { name="ETHBTCAmount" /> - ETH = {(this.state.ETHBTCAmount * this.props.ETHBTC).toFixed( + {` ETH = ${toFixedIfLarger( + this.state.ETHBTCAmount * this.props.ETHBTC, 6 - )}{' '} - BTC + )} BTC`}

@@ -62,10 +63,10 @@ export default class CurrentRates extends Component { name="ETHREPAmount" /> - ETH = {(this.state.ETHREPAmount * this.props.ETHREP).toFixed( + {` ETH = ${toFixedIfLarger( + this.state.ETHREPAmount * this.props.ETHREP, 6 - )}{' '} - REP + )} REP`}

@@ -78,10 +79,10 @@ export default class CurrentRates extends Component { name="BTCETHAmount" /> - BTC = {(this.state.BTCETHAmount * this.props.BTCETH).toFixed( + {` BTC = ${toFixedIfLarger( + this.state.BTCETHAmount * this.props.BTCETH, 6 - )}{' '} - ETH + )} ETH`}

@@ -92,10 +93,10 @@ export default class CurrentRates extends Component { name="BTCREPAmount" /> - BTC = {(this.state.BTCREPAmount * this.props.BTCREP).toFixed( + {` BTC = ${toFixedIfLarger( + this.state.BTCREPAmount * this.props.BTCREP, 6 - )}{' '} - REP + )} REP`}

diff --git a/common/containers/Tabs/Swap/components/receivingAddress.js b/common/containers/Tabs/Swap/components/receivingAddress.js new file mode 100644 index 00000000..c2bc37a8 --- /dev/null +++ b/common/containers/Tabs/Swap/components/receivingAddress.js @@ -0,0 +1,67 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { DONATION_ADDRESSES_MAP } from 'config/data'; +import Validator from 'libs/validator'; +import translate from 'translations'; + +export default class ReceivingAddress extends Component { + constructor(props) { + super(props); + this.validator = new Validator(); + this.state = { + validAddress: false + }; + } + + static propTypes = { + destinationKind: PropTypes.string.isRequired, + receivingAddressSwap: PropTypes.func.isRequired, + receivingAddress: PropTypes.string + }; + + onChangeReceivingAddress = event => { + const value = event.target.value; + this.props.receivingAddressSwap(value); + let validAddress; + // TODO - find better pattern here once currencies move beyond BTC, ETH, REP + if (this.props.destinationKind === 'BTC') { + validAddress = this.validator.isValidBTCAddress(value); + } else { + validAddress = this.validator.isValidETHAddress(value); + } + this.setState({ validAddress }); + }; + + render() { + const { destinationKind, receivingAddress } = this.props; + const { validAddress } = this.state; + return ( +
+
+
+
+ + +
+
+
+ +
+
+
+ ); + } +} diff --git a/common/containers/Tabs/Swap/components/swapInformation.js b/common/containers/Tabs/Swap/components/swapInformation.js new file mode 100644 index 00000000..def61d99 --- /dev/null +++ b/common/containers/Tabs/Swap/components/swapInformation.js @@ -0,0 +1,79 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { toFixedIfLarger } from 'utils/formatters'; +import translate from 'translations'; + +export default class SwapInformation extends Component { + constructor(props) { + super(props); + } + + static propTypes = { + originAmount: PropTypes.number.isRequired, + destinationAmount: PropTypes.number.isRequired, + originKind: PropTypes.string.isRequired, + destinationKind: PropTypes.string.isRequired + }; + + computedOriginDestinationRatio = () => { + return this.props.destinationAmount / this.props.originAmount; + }; + + render() { + const { + originAmount, + originKind, + destinationAmount, + destinationKind + } = this.props; + + return ( +
+
+
+ {translate('SWAP_information')} +
+
+ + {/* Todo - fix*/} + + +
+
+
+
+

+ {` ${toFixedIfLarger(originAmount, 6)} ${originKind}`} +

+

{translate('SEND_amount')}

+
+
+

+ {` ${toFixedIfLarger(destinationAmount, 6)} ${destinationKind}`} +

+

{translate('SWAP_rec_amt')}

+
+
+

+ {` ${toFixedIfLarger( + this.computedOriginDestinationRatio(), + 6 + )} ${originKind}/${destinationKind} `} +

+

{translate('SWAP_your_rate')}

+
+
+
+ ); + } +} diff --git a/common/containers/Tabs/Swap/index.js b/common/containers/Tabs/Swap/index.js index 62dc6158..e54bb613 100644 --- a/common/containers/Tabs/Swap/index.js +++ b/common/containers/Tabs/Swap/index.js @@ -1,6 +1,9 @@ import React, { Component } from 'react'; -import WantToSwapMy from './components/wantToSwapMy'; +import CurrencySwap from './components/currencySwap'; +import SwapInformation from './components/swapInformation'; import CurrentRates from './components/currentRates'; +import ReceivingAddress from './components/receivingAddress'; + import { connect } from 'react-redux'; import * as swapActions from 'actions/swap'; @@ -18,14 +21,18 @@ class Swap extends Component { originAmount: PropTypes.any, destinationAmount: PropTypes.any, originKind: PropTypes.string, + partOneComplete: PropTypes.bool, destinationKind: PropTypes.string, destinationKindOptions: PropTypes.array, originKindOptions: PropTypes.array, + receivingAddress: PropTypes.string, originKindSwap: PropTypes.func, destinationKindSwap: PropTypes.func, originAmountSwap: PropTypes.func, destinationAmountSwap: PropTypes.func, - updateBityRatesSwap: PropTypes.func + updateBityRatesSwap: PropTypes.func, + partOneCompleteSwap: PropTypes.func, + receivingAddressSwap: PropTypes.func }; componentDidMount() { @@ -55,7 +62,11 @@ class Swap extends Component { originKindSwap, destinationKindSwap, originAmountSwap, - destinationAmountSwap + destinationAmountSwap, + partOneComplete, + partOneCompleteSwap, + receivingAddressSwap, + receivingAddress } = this.props; let wantToSwapMyProps = { @@ -69,15 +80,37 @@ class Swap extends Component { originKindSwap, destinationKindSwap, originAmountSwap, - destinationAmountSwap + destinationAmountSwap, + partOneCompleteSwap + }; + + let yourInformationProps = { + originAmount, + destinationAmount, + originKind, + destinationKind + }; + + let yourReceivingProps = { + destinationKind, + receivingAddressSwap, + receivingAddress }; return (
- - + {!partOneComplete && +
+ + +
} + {partOneComplete && +
+ + +
}
@@ -87,6 +120,8 @@ class Swap extends Component { function mapStateToProps(state) { return { + receivingAddress: state.swap.receivingAddress, + partOneComplete: state.swap.partOneComplete, originAmount: state.swap.originAmount, destinationAmount: state.swap.destinationAmount, originKind: state.swap.originKind, diff --git a/common/libs/validator.js b/common/libs/validator.js new file mode 100644 index 00000000..c930f47a --- /dev/null +++ b/common/libs/validator.js @@ -0,0 +1,16 @@ +import WalletAddressValidator from 'wallet-address-validator'; +import ethUtil from 'ethereumjs-util'; + +export default class Validator { + isValidETHAddress = function(address) { + if (address && address === '0x0000000000000000000000000000000000000000') + return false; + if (address) { + return ethUtil.isValidAddress(address); + } + return false; + }; + isValidBTCAddress = function(address) { + return WalletAddressValidator.validate(address, 'BTC'); + }; +} diff --git a/common/reducers/swap.js b/common/reducers/swap.js index b827df05..3de1b101 100644 --- a/common/reducers/swap.js +++ b/common/reducers/swap.js @@ -3,15 +3,17 @@ import { SWAP_DESTINATION_KIND, SWAP_ORIGIN_AMOUNT, SWAP_ORIGIN_KIND, - SWAP_UPDATE_BITY_RATES + SWAP_UPDATE_BITY_RATES, + SWAP_PART_ONE_COMPLETE, + SWAP_RECEIVING_ADDRESS } from 'actions/swapConstants'; import { combineAndUpper } from 'api/bity'; export const ALL_CRYPTO_KIND_OPTIONS = ['BTC', 'ETH', 'REP']; const initialState = { - originAmount: 0, - destinationAmount: 0, + originAmount: '', + destinationAmount: '', originKind: 'BTC', destinationKind: 'ETH', destinationKindOptions: ALL_CRYPTO_KIND_OPTIONS.filter( @@ -20,7 +22,9 @@ const initialState = { originKindOptions: ALL_CRYPTO_KIND_OPTIONS.filter( element => element !== 'REP' ), - bityRates: {} + partOneComplete: false, + bityRates: {}, + receivingAddress: '' }; const buildDestinationAmount = ( @@ -94,6 +98,16 @@ export function swap(state = initialState, action) { ...action.value } }; + case SWAP_PART_ONE_COMPLETE: + return { + ...state, + partOneComplete: action.value + }; + case SWAP_RECEIVING_ADDRESS: + return { + ...state, + receivingAddress: action.value + }; default: return state; } diff --git a/common/utils/formatters.js b/common/utils/formatters.js new file mode 100644 index 00000000..8cc26eb2 --- /dev/null +++ b/common/utils/formatters.js @@ -0,0 +1,5 @@ +//flow + +export function toFixedIfLarger(number: number, fixedSize: number = 6): string { + return parseFloat(number.toFixed(fixedSize)).toString(); +} diff --git a/package.json b/package.json index 67af8b8c..69a85824 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "redux-logger": "^3.0.1", "redux-saga": "^0.15.3", "store2": "^2.5.0", + "wallet-address-validator": "^0.1.0", "whatwg-fetch": "^2.0.2" }, "devDependencies": { diff --git a/spec/libs/validator.spec.js b/spec/libs/validator.spec.js new file mode 100644 index 00000000..a29b0bc8 --- /dev/null +++ b/spec/libs/validator.spec.js @@ -0,0 +1,34 @@ +import Validator from '../../common/libs/validator'; +import { DONATION_ADDRESSES_MAP } from '../../common/config/data'; + +describe('Validator', () => { + it('should validate correct BTC address as true', () => { + const validator = new Validator(); + expect( + validator.isValidBTCAddress(DONATION_ADDRESSES_MAP.BTC) + ).toBeTruthy(); + }); + it('should validate incorrect BTC address as false', () => { + const validator = new Validator(); + expect( + validator.isValidBTCAddress( + 'nonsense' + DONATION_ADDRESSES_MAP.BTC + 'nonsense' + ) + ).toBeFalsy(); + }); + + it('should validate correct ETH address as true', () => { + const validator = new Validator(); + expect( + validator.isValidETHAddress(DONATION_ADDRESSES_MAP.ETH) + ).toBeTruthy(); + }); + it('should validate incorrect ETH address as false', () => { + const validator = new Validator(); + expect( + validator.isValidETHAddress( + 'nonsense' + DONATION_ADDRESSES_MAP.ETH + 'nonsense' + ) + ).toBeFalsy(); + }); +}); diff --git a/spec/utils/formatters.spec.js b/spec/utils/formatters.spec.js new file mode 100644 index 00000000..31b02d46 --- /dev/null +++ b/spec/utils/formatters.spec.js @@ -0,0 +1,17 @@ +import { toFixedIfLarger } from '../../common/utils/formatters'; + +describe('toFixedIfLarger', () => { + it('should return same value if decimal isnt longer than default', () => { + const numExample = 7.002; + expect(toFixedIfLarger(numExample)).toEqual(String(numExample)); + }); + + it('should return shortened value rounded up if decimal is longer than default', () => { + const numExample = 7.1234567; + expect(toFixedIfLarger(numExample)).toEqual(String(7.123457)); + }); + it('should return shortened value if decimal is longer than passed fixedSize', () => { + const numExample = 7.12345678; + expect(toFixedIfLarger(numExample, 2)).toEqual(String(7.12)); + }); +});