From 9d4769342f98c08131352da712d74a854f18b9ac Mon Sep 17 00:00:00 2001 From: Alejandro Cavallero Date: Mon, 2 Jul 2018 18:37:19 -0300 Subject: [PATCH 1/5] RSK Mainnet configuration (#1994) * RSK mainnet configuration * Changes to fix errors on push * Reverts unnecessary props --- common/config/contracts/rsk_testnet.json | 8 +++++ common/config/dpaths.ts | 6 ++++ common/config/tokens/rsk.json | 2 +- common/config/tokens/rsk_testnet.json | 1 + .../config/networks/static/reducer.ts | 31 +++++++++++++++++-- common/libs/nodes/configs.ts | 9 ++++++ shared/types/network.d.ts | 1 + spec/libs/validators.spec.ts | 7 +++++ 8 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 common/config/contracts/rsk_testnet.json create mode 100644 common/config/tokens/rsk_testnet.json diff --git a/common/config/contracts/rsk_testnet.json b/common/config/contracts/rsk_testnet.json new file mode 100644 index 00000000..cf8d3c9f --- /dev/null +++ b/common/config/contracts/rsk_testnet.json @@ -0,0 +1,8 @@ +[ + { + "name": "Bridge", + "address": "0x0000000000000000000000000000000001000006", + "abi": + "[{ \"name\": \"getFederationAddress\", \"type\": \"function\", \"constant\": true, \"inputs\": [], \"outputs\": [{ \"name\": \"\", \"type\": \"string\" }] }]" + } +] diff --git a/common/config/dpaths.ts b/common/config/dpaths.ts index 1449c582..5af627f2 100644 --- a/common/config/dpaths.ts +++ b/common/config/dpaths.ts @@ -83,6 +83,11 @@ export const RSK_TESTNET: DPath = { value: "m/44'/37310'/0'/0" }; +export const RSK_MAINNET: DPath = { + label: 'Mainnet (RSK)', + value: "m/44'/137'/0'/0" +}; + export const GO_DEFAULT: DPath = { label: 'Default (GO)', value: "m/44'/6060'/0'/0" @@ -114,6 +119,7 @@ export const DPaths: DPath[] = [ ETSC_DEFAULT, EGEM_DEFAULT, CLO_DEFAULT, + RSK_MAINNET, RSK_TESTNET, GO_DEFAULT, EOSC_DEFAULT, diff --git a/common/config/tokens/rsk.json b/common/config/tokens/rsk.json index fe51488c..0637a088 100644 --- a/common/config/tokens/rsk.json +++ b/common/config/tokens/rsk.json @@ -1 +1 @@ -[] +[] \ No newline at end of file diff --git a/common/config/tokens/rsk_testnet.json b/common/config/tokens/rsk_testnet.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/common/config/tokens/rsk_testnet.json @@ -0,0 +1 @@ +[] diff --git a/common/features/config/networks/static/reducer.ts b/common/features/config/networks/static/reducer.ts index cab27ae8..3f1f2846 100644 --- a/common/features/config/networks/static/reducer.ts +++ b/common/features/config/networks/static/reducer.ts @@ -21,6 +21,7 @@ import { ETSC_DEFAULT, EGEM_DEFAULT, CLO_DEFAULT, + RSK_MAINNET, RSK_TESTNET, GO_DEFAULT, EOSC_DEFAULT, @@ -369,6 +370,32 @@ export const STATIC_NETWORKS_INITIAL_STATE: StaticNetworksState = { } }, + RSK: { + id: 'RSK', + name: 'RSK', + unit: 'SBTC', + chainId: 30, + color: '#58A052', + isCustom: false, + blockExplorer: makeExplorer({ + name: 'RSK Explorer', + origin: 'https://explorer.rsk.co' + }), + tokens: require('config/tokens/rsk.json'), + contracts: require('config/contracts/rsk.json'), + isTestnet: false, + dPathFormats: { + [SecureWalletName.TREZOR]: RSK_MAINNET, + [SecureWalletName.LEDGER_NANO_S]: RSK_MAINNET, + [InsecureWalletName.MNEMONIC_PHRASE]: RSK_MAINNET + }, + gasPriceSettings: { + min: 0.183, + max: 1.5, + initial: 0.183 + } + }, + RSK_TESTNET: { id: 'RSK_TESTNET', name: 'RSK', @@ -380,8 +407,8 @@ export const STATIC_NETWORKS_INITIAL_STATE: StaticNetworksState = { name: 'RSK Testnet Explorer', origin: 'https://explorer.testnet.rsk.co' }), - tokens: require('config/tokens/rsk.json'), - contracts: require('config/contracts/rsk.json'), + tokens: require('config/tokens/rsk_testnet.json'), + contracts: require('config/contracts/rsk_testnet.json'), isTestnet: true, dPathFormats: { [SecureWalletName.TREZOR]: RSK_TESTNET, diff --git a/common/libs/nodes/configs.ts b/common/libs/nodes/configs.ts index a660f08c..951a5483 100644 --- a/common/libs/nodes/configs.ts +++ b/common/libs/nodes/configs.ts @@ -168,6 +168,15 @@ export const NODE_CONFIGS: { [key in StaticNetworkIds]: RawNodeConfig[] } = { } ], + RSK: [ + { + name: makeNodeName('RSK', 'rsk_mainnet'), + type: 'rpc', + service: 'mycrypto.rsk.co', + url: 'https://mycrypto.rsk.co/' + } + ], + RSK_TESTNET: [ { name: makeNodeName('RSK_TESTNET', 'rsk_testnet'), diff --git a/shared/types/network.d.ts b/shared/types/network.d.ts index 5913b900..8a7a8554 100644 --- a/shared/types/network.d.ts +++ b/shared/types/network.d.ts @@ -13,6 +13,7 @@ type StaticNetworkIds = | 'ETSC' | 'EGEM' | 'CLO' + | 'RSK' | 'RSK_TESTNET' | 'GO' | 'EOSC' diff --git a/spec/libs/validators.spec.ts b/spec/libs/validators.spec.ts index 342f6ed9..8dc74a3f 100644 --- a/spec/libs/validators.spec.ts +++ b/spec/libs/validators.spec.ts @@ -16,6 +16,7 @@ configuredStore.getState(); const VALID_BTC_ADDRESS = '1MEWT2SGbqtz6mPCgFcnea8XmWV5Z4Wc6'; const VALID_ETH_ADDRESS = '0x7cB57B5A97eAbe94205C07890BE4c1aD31E486A8'; const VALID_RSK_TESTNET_ADDRESS = '0x5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd'; +const VALID_RSK_MAINNET_ADDRESS = '0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD'; const VALID_ETH_PRIVATE_KEY = '3f4fd89ea4970cc77bfd2d07a95786575ea62e183857afe6301578e1a3c5c782'; const INVALID_ETH_PRIVATE_KEY = '3f4fd89ea4970cc77bfd2d07a95786575ea62e183857afe6301578e1a3c5ZZZZ'; const VALID_ETH_PRIVATE_BUFFER = Buffer.from(VALID_ETH_PRIVATE_KEY, 'hex'); @@ -50,6 +51,12 @@ describe('Validator', () => { it('should validate correct RSK address in RSK mainnet network as false', () => { expect(isValidAddress(VALID_RSK_TESTNET_ADDRESS, RSK_MAINNET_CHAIN_ID)).toBeFalsy(); }); + it('should validate correct RSK address in RSK mainnet network as true', () => { + expect(isValidAddress(VALID_RSK_MAINNET_ADDRESS, RSK_MAINNET_CHAIN_ID)).toBeTruthy(); + }); + it('should validate correct RSK mainnet address in RSK testnet network as false', () => { + expect(isValidAddress(VALID_RSK_MAINNET_ADDRESS, RSK_TESTNET_CHAIN_ID)).toBeFalsy(); + }); it('should validate an incorrect DPath as false', () => { expect(isValidPath('m/44/60/0/0')).toBeFalsy(); }); From 6718e7ef65459928465cf9fd216d6b1a8367408d Mon Sep 17 00:00:00 2001 From: Danny Skubak Date: Mon, 2 Jul 2018 17:39:25 -0400 Subject: [PATCH 2/5] Refactor Bad Browser Check (#1996) * move bad browser check into standalone files * refactor dup var * remove console logs * have warning support all browser versions * Revert "have warning support all browser versions". Webpack conventions still cause IE8 to break. This reverts commit a8531038622d2419a3da342ddfe0c356a90e4eee. * correct typo --- common/badBrowserCheckA.js | 9 +++++++++ common/badBrowserCheckB.js | 33 +++++++++++++++++++++++++++++++++ common/index.html | 34 ---------------------------------- webpack_config/makeConfig.js | 2 ++ 4 files changed, 44 insertions(+), 34 deletions(-) create mode 100644 common/badBrowserCheckA.js create mode 100644 common/badBrowserCheckB.js diff --git a/common/badBrowserCheckA.js b/common/badBrowserCheckA.js new file mode 100644 index 00000000..ec2a1658 --- /dev/null +++ b/common/badBrowserCheckA.js @@ -0,0 +1,9 @@ + +// use dates as vars so they're not stripped out by minification +let letCheck = new Date(); +const constCheck = new Date(); +const arrowCheck = (() => new Date())(); + +if (letCheck && constCheck && arrowCheck) { + window.localStorage.setItem('goodBrowser', 'true'); +} diff --git a/common/badBrowserCheckB.js b/common/badBrowserCheckB.js new file mode 100644 index 00000000..51a82334 --- /dev/null +++ b/common/badBrowserCheckB.js @@ -0,0 +1,33 @@ +var badBrowser = false; + +try { + // Local storage + window.localStorage.setItem('test', 'test'); + window.localStorage.removeItem('test'); + + // Flexbox + var elTest = document.createElement('div'); + elTest.style.display = 'flex'; + if (elTest.style.display !== 'flex') { + badBrowser = true; + } + + // const and let check from badBrowserCheckA.js + if (window.localStorage.goodBrowser !== 'true') { + badBrowser = true; + } + window.localStorage.removeItem('goodBrowser'); + +} catch (err) { + badBrowser = true; +} + +if (badBrowser) { + var el = document.getElementsByClassName('BadBrowser')[0]; + el.className += ' is-open'; + // Dumb check for known mobile OS's. Not important to catch all, just + // displays more appropriate information. + if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) { + el.className += ' is-mobile'; + } +} diff --git a/common/index.html b/common/index.html index 0b00eab7..cac71d94 100644 --- a/common/index.html +++ b/common/index.html @@ -71,40 +71,6 @@ - diff --git a/webpack_config/makeConfig.js b/webpack_config/makeConfig.js index 365c2b09..d9304990 100644 --- a/webpack_config/makeConfig.js +++ b/webpack_config/makeConfig.js @@ -32,6 +32,8 @@ module.exports = function(opts = {}) { // ====== Entry ======= // ==================== const entry = { + badBrowserCheckA: './common/badBrowserCheckA.js', + badBrowserCheckB: './common/badBrowserCheckB.js', client: './common/index.tsx' }; From 54b479f04ec7a82728b2b2ba793ca41cb055b37b Mon Sep 17 00:00:00 2001 From: Connor Bryan Date: Mon, 2 Jul 2018 16:44:44 -0500 Subject: [PATCH 3/5] Disable buttons on confirmation modal when transaction is broadcasting (#1987) * Fix an issue where the disableButtons property was not being passed to the modal body. * Add a hideButtons property for modals and hide the buttons for a broadcasting confirmation modal * Don't show fade when there are no buttons --- .../ConfirmationModalTemplate.tsx | 1 + common/components/ui/Modal/ModalBody.tsx | 9 ++++---- common/components/ui/Modal/index.tsx | 23 +++++++++++++++++-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/common/components/ConfirmationModalTemplate/ConfirmationModalTemplate.tsx b/common/components/ConfirmationModalTemplate/ConfirmationModalTemplate.tsx index f0c87969..d07912cf 100644 --- a/common/components/ConfirmationModalTemplate/ConfirmationModalTemplate.tsx +++ b/common/components/ConfirmationModalTemplate/ConfirmationModalTemplate.tsx @@ -100,6 +100,7 @@ class ConfirmationModalTemplateClass extends React.Component { buttons={buttons} handleClose={onClose} disableButtons={transactionBroadcasting} + hideButtons={transactionBroadcasting} isOpen={isOpen} > {transactionBroadcasting ? ( diff --git a/common/components/ui/Modal/ModalBody.tsx b/common/components/ui/Modal/ModalBody.tsx index d82cba9f..8c74e41c 100644 --- a/common/components/ui/Modal/ModalBody.tsx +++ b/common/components/ui/Modal/ModalBody.tsx @@ -9,7 +9,8 @@ interface Props { modalStyle?: CSSProperties; hasButtons?: number; buttons?: IButton[]; - disableButtons?: any; + disableButtons?: boolean; + hideButtons?: boolean; handleClose(): void; } @@ -45,7 +46,7 @@ export default class ModalBody extends React.Component { }; public render() { - const { title, children, modalStyle, hasButtons, handleClose } = this.props; + const { title, children, modalStyle, hasButtons, hideButtons, handleClose } = this.props; return (
{
(this.modalContent = div as HTMLElement)}> {children} -
+
- {hasButtons &&
{this.renderButtons()}
} + {hasButtons && !hideButtons &&
{this.renderButtons()}
}
); } diff --git a/common/components/ui/Modal/index.tsx b/common/components/ui/Modal/index.tsx index 181d22f1..26c70547 100644 --- a/common/components/ui/Modal/index.tsx +++ b/common/components/ui/Modal/index.tsx @@ -15,6 +15,7 @@ interface Props { isOpen?: boolean; title?: React.ReactNode; disableButtons?: boolean; + hideButtons?: boolean; children: React.ReactNode; buttons?: IButton[]; maxWidth?: number; @@ -56,7 +57,16 @@ export default class Modal extends PureComponent { } public render() { - const { isOpen, title, children, buttons, handleClose, maxWidth } = this.props; + const { + isOpen, + title, + children, + buttons, + disableButtons, + hideButtons, + handleClose, + maxWidth + } = this.props; const hasButtons = buttons && buttons.length; const modalStyle: ModalStyle = {}; @@ -65,7 +75,16 @@ export default class Modal extends PureComponent { modalStyle.maxWidth = `${maxWidth}px`; } - const modalBodyProps = { title, children, modalStyle, hasButtons, buttons, handleClose }; + const modalBodyProps = { + title, + children, + modalStyle, + hasButtons, + buttons, + disableButtons, + hideButtons, + handleClose + }; const modal = ( From a3a92504d29e5f33b76899c68ae3c274482db465 Mon Sep 17 00:00:00 2001 From: Roman Storm Date: Mon, 2 Jul 2018 14:48:32 -0700 Subject: [PATCH 4/5] Update POA Node URL (#1986) * Closes #1984. Change POA.network RPC endpoint to Poa.Infura.io * change type to infura --- common/features/config/networks/static/reducer.ts | 2 +- common/libs/nodes/configs.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/features/config/networks/static/reducer.ts b/common/features/config/networks/static/reducer.ts index 3f1f2846..b3a07312 100644 --- a/common/features/config/networks/static/reducer.ts +++ b/common/features/config/networks/static/reducer.ts @@ -206,7 +206,7 @@ export const STATIC_NETWORKS_INITIAL_STATE: StaticNetworksState = { isCustom: false, color: '#6d2eae', blockExplorer: makeExplorer({ - name: 'Etherchain Light', + name: 'POA Explorer', origin: 'https://poaexplorer.com', addressPath: 'address/search', blockPath: 'blocks/block' diff --git a/common/libs/nodes/configs.ts b/common/libs/nodes/configs.ts index 951a5483..18505415 100644 --- a/common/libs/nodes/configs.ts +++ b/common/libs/nodes/configs.ts @@ -108,9 +108,9 @@ export const NODE_CONFIGS: { [key in StaticNetworkIds]: RawNodeConfig[] } = { POA: [ { name: makeNodeName('POA', 'core'), - type: 'rpc', - service: 'poa.network', - url: 'https://core.poa.network' + type: 'infura', + service: 'poa.infura.io', + url: 'https://poa.infura.io' } ], From 0d13dc93c5a342dbfe6b8e251b3a1ca66f262a98 Mon Sep 17 00:00:00 2001 From: Connor Bryan Date: Mon, 2 Jul 2018 16:51:51 -0500 Subject: [PATCH 5/5] Add additional validation to Amount input field (#1982) * Adjust the validator and update validity class logic on AmountField * Improve readability and add a condition to invalidity for Input * Undo changes to Input and pass down showInvalidWithoutValue * Fix prop ordering issue * Add removed validator * Adjust logic for NoneField --- common/components/AmountField.tsx | 5 ++++- common/components/NonceField.tsx | 10 +++++++++- .../TXMetaDataPanel/components/AdvancedGas.tsx | 2 +- common/components/ui/Input.tsx | 2 +- .../Tabs/SendTransaction/components/Fields/Fields.tsx | 6 +++++- .../Tabs/SendTransaction/components/RequestPayment.tsx | 1 + common/libs/validators.ts | 9 +++++++++ 7 files changed, 30 insertions(+), 5 deletions(-) diff --git a/common/components/AmountField.tsx b/common/components/AmountField.tsx index d104f183..2248b615 100644 --- a/common/components/AmountField.tsx +++ b/common/components/AmountField.tsx @@ -9,6 +9,7 @@ interface Props { hasUnitDropdown?: boolean; hasSendEverything?: boolean; showAllTokens?: boolean; + showInvalidWithoutValue?: boolean; customValidator?(rawAmount: string): boolean; } @@ -16,7 +17,8 @@ export const AmountField: React.SFC = ({ hasUnitDropdown, hasSendEverything, showAllTokens, - customValidator + customValidator, + showInvalidWithoutValue }) => ( ( @@ -30,6 +32,7 @@ export const AmountField: React.SFC = ({ value={raw} readOnly={!!readOnly} onChange={onChange} + showInvalidWithoutValue={showInvalidWithoutValue} /> {hasSendEverything && } {hasUnitDropdown && } diff --git a/common/components/NonceField.tsx b/common/components/NonceField.tsx index 32b889f5..c9831642 100644 --- a/common/components/NonceField.tsx +++ b/common/components/NonceField.tsx @@ -12,6 +12,7 @@ import './NonceField.scss'; interface OwnProps { alwaysDisplay: boolean; + showInvalidBeforeBlur?: boolean; } interface StateProps { @@ -27,7 +28,13 @@ type Props = OwnProps & DispatchProps & StateProps; class NonceField extends React.Component { public render() { - const { alwaysDisplay, requestNonce, noncePending, isOffline } = this.props; + const { + alwaysDisplay, + showInvalidBeforeBlur, + requestNonce, + noncePending, + isOffline + } = this.props; return ( { @@ -51,6 +58,7 @@ class NonceField extends React.Component { onChange={onChange} disabled={noncePending} showInvalidWithoutValue={true} + showInvalidBeforeBlur={showInvalidBeforeBlur} /> {noncePending ? (
diff --git a/common/components/TXMetaDataPanel/components/AdvancedGas.tsx b/common/components/TXMetaDataPanel/components/AdvancedGas.tsx index 92ac3359..98452d58 100644 --- a/common/components/TXMetaDataPanel/components/AdvancedGas.tsx +++ b/common/components/TXMetaDataPanel/components/AdvancedGas.tsx @@ -106,7 +106,7 @@ class AdvancedGas extends React.Component { )} {nonceField && (
- +
)}
diff --git a/common/components/ui/Input.tsx b/common/components/ui/Input.tsx index 34e31c0d..21dbaadc 100644 --- a/common/components/ui/Input.tsx +++ b/common/components/ui/Input.tsx @@ -49,7 +49,7 @@ class Input extends React.Component { } else if (!hasBlurred && !showInvalidBeforeBlur) { validClass = ''; } - if (!hasValue && showInvalidWithoutValue) { + if ((!isStateless || showInvalidBeforeBlur) && !hasValue && showInvalidWithoutValue) { validClass = 'invalid'; } diff --git a/common/containers/Tabs/SendTransaction/components/Fields/Fields.tsx b/common/containers/Tabs/SendTransaction/components/Fields/Fields.tsx index 7cf85fa5..e55f26fc 100644 --- a/common/containers/Tabs/SendTransaction/components/Fields/Fields.tsx +++ b/common/containers/Tabs/SendTransaction/components/Fields/Fields.tsx @@ -54,7 +54,11 @@ class FieldsClass extends Component {
- +
{schedulingAvailable && (
diff --git a/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx b/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx index 3f7cfbbc..6a027e71 100644 --- a/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx +++ b/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx @@ -102,6 +102,7 @@ class RequestPayment extends React.Component { hasUnitDropdown={true} showAllTokens={true} customValidator={isValidAmount(decimal)} + showInvalidWithoutValue={true} />
diff --git a/common/libs/validators.ts b/common/libs/validators.ts index 358804f9..41981e4f 100644 --- a/common/libs/validators.ts +++ b/common/libs/validators.ts @@ -133,11 +133,20 @@ export const validPositiveNumber = (num: number) => validNumber(num) && num !== export const validDecimal = (input: string, decimal: number) => { const arr = input.split('.'); + + // Only a single decimal can exist. + if (arr.length > 2) { + return false; + } + const fractionPortion = arr[1]; + if (!fractionPortion || fractionPortion.length === 0) { return true; } + const decimalLength = fractionPortion.length; + return decimalLength <= decimal; };