Skip to content

Commit

Permalink
Merge pull request #603 from floating/beta.7
Browse files Browse the repository at this point in the history
* Refactor Ledger signer, add tests (#581)

* Update Polygon block explorer URL (#572)

* Upgrade Electron to 15.1.1 (#584)

* Implement EIP-1559 support for Trezors, refactor Trezors to use adapter pattern (#549)

* Use correct v from Lattice signature (#587)

* Enforce max 24 characters Lattice suffix (#588)

* Batch multicall requests for balances (#586)

* Add unit tests for addNetwork action, update network ID parsing (#589)

* Remove relative dependencies from hot signer worker (#590)

* Update dialog API to allow finding keystore file (#591)

* Switch chains, standardize chain id as number (#592)

* Raise hard transaction fee cap for non-ETH chains (#585)

* Add @ethereumjs/common, patch to use node-fetch in ipfs-utils (#595)

* Support signTypedData_v4 for Lattice (#596)

* Allow hex prefix when creating hot signer from a private key (#597)

* Improve cleanup of scan worker process when exiting (#600)

* Allow up to 40 Lattice addresses to be loaded (#598)

* Hide account grabber for now

* Add Aragon ENS registry for polygon

* Split keystore and private key setup, clear setup after adding signer

* Don't overwrite local state endpoint in chain setup

* Move add chain to top

* Ledger testing (#605)

* Remove unused case from removeNetwork action

* Update deps (#594)

Co-authored-by: Matt Holtzman <matt.holtzman@gmail.com>
  • Loading branch information
floating and mholtzman committed Oct 15, 2021
2 parents 35c7786 + 20050c6 commit 7f8e12c
Show file tree
Hide file tree
Showing 72 changed files with 9,075 additions and 11,351 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -2,6 +2,7 @@ node_modules
.DS_Store
bundle
.cache
cache
hot.json
nohot.json
config.json
Expand All @@ -13,3 +14,4 @@ test/.userData
.parcel-cache
*.tsbuildinfo
scripts
*.code-workspace
10 changes: 8 additions & 2 deletions app/App/Panel/Local/index.js
Expand Up @@ -109,7 +109,11 @@ class Settings extends React.Component {
inputLatticeSuffix (e) {
e.preventDefault()
clearTimeout(this.inputLatticeSuffixTimeout)
const value = e.target.value.replace(/\s+/g, '')

// Lattice only supports a suffix of up to 24 characters, and we append "Frame-"
// to the front so limit it to 18 characters
const value = e.target.value.replace(/\s+/g, '').substring(0, 18)

this.setState({ latticeSuffix: value })
// TODO: Update to target specific Lattice device rather than global
this.inputLatticeSuffixTimeout = setTimeout(() => link.send('tray:action', 'setLatticeSuffix', this.state.latticeSuffix), 1000)
Expand Down Expand Up @@ -379,7 +383,9 @@ class Settings extends React.Component {
onChange={(value) => link.send('tray:action', 'setLatticeAccountLimit', value)}
options={[
{ text: '5', value: 5 },
{ text: '10', value: 10 }
{ text: '10', value: 10 },
{ text: '20', value: 20 },
{ text: '40', value: 40 },
]}
/>
</div>
Expand Down
69 changes: 49 additions & 20 deletions app/App/Panel/Main/Account/Requests/ChainRequest/index.js
Expand Up @@ -15,6 +15,7 @@ class ChainRequest extends React.Component {
render () {
const status = this.props.req.status
const notice = this.props.req.notice
const type = this.props.req.type
let requestClass = 'signerRequest'
if (status === 'success') requestClass += ' signerRequestSuccess'
if (status === 'declined') requestClass += ' signerRequestDeclined'
Expand Down Expand Up @@ -50,36 +51,64 @@ class ChainRequest extends React.Component {
</div>
) : (
<div className='approveTransactionPayload'>
<div className='approveRequestHeader approveTransactionHeader'>
<div className='approveRequestHeaderIcon'> {svg.octicon('shield', { height: 20 })}</div>
<div className='approveRequestHeaderLabel'> Add Chain</div>
</div>
{type === 'switchChain' ? (
<div className='approveRequestHeader approveTransactionHeader'>
<div className='approveRequestHeaderIcon'> {svg.octicon('shield', { height: 20 })}</div>
<div className='approveRequestHeaderLabel'> Switch Chain</div>
</div>
) : (
<div className='approveRequestHeader approveTransactionHeader'>
<div className='approveRequestHeaderIcon'> {svg.octicon('shield', { height: 20 })}</div>
<div className='approveRequestHeaderLabel'> Add Chain</div>
</div>
)}
<div className='requestChain scaleIn'>
<div className='requestChainInner'>
<div className={originClass}>{this.props.req.origin}</div>
<div className={'requestChainOriginSub'}>{'wants to add chain'}</div>
<div className='requestChainName'>{chain.name}</div>
<div className={'requestChainOriginSub'}>{type === 'switchChain' ? 'wants to switch to chain' : 'wants to add chain'}</div>
<div className='requestChainName'>{type === 'switchChain' ? (
this.store('main.networks', chain.type, parseInt(chain.id), 'name')
) : chain.name}</div>
</div>
</div>
</div>
)}
</div>
<div className='requestApprove'>
<div
className='requestDecline'
style={{ pointerEvents: this.state.allowInput && this.props.onTop ? 'auto' : 'none'}}
onClick={() => { if (this.state.allowInput && this.props.onTop) link.send('tray:addChain', false, this.props.req)
}}>
<div className='requestDeclineButton _txButton _txButtonBad'>Decline</div>
{type === 'switchChain' ? (
<div className='requestApprove'>
<div
className='requestDecline'
style={{ pointerEvents: this.state.allowInput && this.props.onTop ? 'auto' : 'none'}}
onClick={() => { if (this.state.allowInput && this.props.onTop) link.send('tray:switchChain', false, false, this.props.req)
}}>
<div className='requestDeclineButton _txButton _txButtonBad'>Decline</div>
</div>
<div
className='requestSign'
style={{ pointerEvents: this.state.allowInput && this.props.onTop ? 'auto' : 'none'}}
onClick={() => { if (this.state.allowInput && this.props.onTop) link.send('tray:switchChain', chain.type, parseInt(chain.id), this.props.req)
}}>
<div className='requestSignButton _txButton'>Switch</div>
</div>
</div>
<div
className='requestSign'
style={{ pointerEvents: this.state.allowInput && this.props.onTop ? 'auto' : 'none'}}
onClick={() => { if (this.state.allowInput && this.props.onTop) this.store.notify('addChain', this.props.req)
}}>
<div className='requestSignButton _txButton'>Review</div>
) : (
<div className='requestApprove'>
<div
className='requestDecline'
style={{ pointerEvents: this.state.allowInput && this.props.onTop ? 'auto' : 'none'}}
onClick={() => { if (this.state.allowInput && this.props.onTop) link.send('tray:addChain', false, this.props.req)
}}>
<div className='requestDeclineButton _txButton _txButtonBad'>Decline</div>
</div>
<div
className='requestSign'
style={{ pointerEvents: this.state.allowInput && this.props.onTop ? 'auto' : 'none'}}
onClick={() => { if (this.state.allowInput && this.props.onTop) this.store.notify('addChain', this.props.req)
}}>
<div className='requestSignButton _txButton'>Review</div>
</div>
</div>
</div>
)}
</div>
)
}
Expand Down
Expand Up @@ -11,7 +11,7 @@ class TxFee extends React.Component {
super(props, context)
this.chain = {
type: 'ethereum',
id: parseInt(props.req.data.chainId, 'hex').toString()
id: parseInt(props.req.data.chainId, 'hex')
}
}
toDisplayUSD (bn) {
Expand Down
Expand Up @@ -9,6 +9,22 @@ import { usesBaseFee } from '../../../../../../../../../main/transaction'

import BigNumber from 'bignumber.js'

function maxFee (tx = { chainId: '' }) {
const chainId = parseInt(tx.chainId)

// for ETH-based chains, the max fee should be 2 ETH
if ([1, 3, 4, 5, 6, 10, 42, 61, 62, 63, 69, 42161, 421611].includes(chainId)) {
return 2 * 1e18
}

// for Fantom, the max fee should be 250 FTM
if ([250, 4002].includes(chainId)) {
return 250 * 1e18
}

// for all other chains, default to 10 of the chain's currency
return 10 * 1e18
}

// <div className='txModuleTop'>
// <div className={'txModuleTopData txModuleTopDataExpanded'}>
Expand All @@ -20,8 +36,6 @@ import BigNumber from 'bignumber.js'
// </div>
// <div className='txModuleBody'>

const FEE_MAX_TOTAL_ETH_WEI = 2 * 1e18

class TxFeeOverlay extends React.Component {
constructor (props, context) {
super(props, context)
Expand Down Expand Up @@ -95,8 +109,10 @@ class TxFeeOverlay extends React.Component {
baseFee = this.limitRange(baseFee, 0, 9999)
const priorityFee = parseFloat(this.state.priorityFee)
const gasLimit = parseInt(this.state.gasLimit)
if (gweiToWei(baseFee + priorityFee) * gasLimit > FEE_MAX_TOTAL_ETH_WEI) {
baseFee = Math.floor(FEE_MAX_TOTAL_ETH_WEI / gasLimit / 1e9) - priorityFee
const maxTotalFee = maxFee(this.props.req.data)

if (gweiToWei(baseFee + priorityFee) * gasLimit > maxTotalFee) {
baseFee = Math.floor(maxTotalFee / gasLimit / 1e9) - priorityFee
}
link.rpc('setBaseFee', gweiToWeiHex(baseFee), this.props.req.handlerId, e => {
if (e) console.error(e)
Expand All @@ -114,8 +130,10 @@ class TxFeeOverlay extends React.Component {
priorityFee = this.limitRange(priorityFee, 0, 9999)
const baseFee = parseFloat(this.state.baseFee)
const gasLimit = parseInt(this.state.gasLimit)
if (gweiToWei(baseFee + priorityFee) * gasLimit > FEE_MAX_TOTAL_ETH_WEI) {
priorityFee = Math.floor(FEE_MAX_TOTAL_ETH_WEI / gasLimit / 1e9) - baseFee
const maxTotalFee = maxFee(this.props.req.data)

if (gweiToWei(baseFee + priorityFee) * gasLimit > maxTotalFee) {
priorityFee = Math.floor(maxTotalFee / gasLimit / 1e9) - baseFee
}
link.rpc('setPriorityFee', gweiToWeiHex(priorityFee), this.props.req.handlerId, e => {
if (e) console.error(e)
Expand All @@ -134,8 +152,10 @@ class TxFeeOverlay extends React.Component {
if (isNaN(gasPrice)) return
gasPrice = this.limitRange(gasPrice, 0, 9999)
const gasLimit = parseInt(this.state.gasLimit)
if (gweiToWei(gasPrice) * gasLimit > FEE_MAX_TOTAL_ETH_WEI) {
gasPrice = Math.floor(FEE_MAX_TOTAL_ETH_WEI / gasLimit / 1e9)
const maxTotalFee = maxFee(this.props.req.data)

if (gweiToWei(gasPrice) * gasLimit > maxTotalFee) {
gasPrice = Math.floor(maxTotalFee / gasLimit / 1e9)
}
link.rpc('setGasPrice', gweiToWeiHex(gasPrice), this.props.req.handlerId, e => {
if (e) console.error(e)
Expand All @@ -150,17 +170,21 @@ class TxFeeOverlay extends React.Component {
this.gasLimitSubmitTimeout = setTimeout(() => {
gasLimit = parseInt(gasLimit)
if (isNaN(gasLimit)) return
if (gasLimit > 12.5e6) gasLimit = 12.5e6
if (gasLimit > 12.5e6) gasLimit = 12.5e6

const maxTotalFee = maxFee(this.props.req.data)

if (usesBaseFee(this.props.req.data)) {
const baseFee = parseFloat(this.state.baseFee)
const priorityFee = parseFloat(this.state.priorityFee)
if (gweiToWei(baseFee + priorityFee) * gasLimit > FEE_MAX_TOTAL_ETH_WEI) {
gasLimit = Math.floor(FEE_MAX_TOTAL_ETH_WEI / gweiToWei(baseFee + priorityFee))

if (gweiToWei(baseFee + priorityFee) * gasLimit > maxTotalFee) {
gasLimit = Math.floor(maxTotalFee / gweiToWei(baseFee + priorityFee))
}
} else {
const gasPrice = parseFloat(this.state.gasPrice)
if (gweiToWei(gasPrice) * gasLimit > FEE_MAX_TOTAL_ETH_WEI) {
gasLimit = Math.floor(FEE_MAX_TOTAL_ETH_WEI / gweiToWei(gasPrice))
if (gweiToWei(gasPrice) * gasLimit > maxTotalFee) {
gasLimit = Math.floor(maxTotalFee / gweiToWei(gasPrice))
}
}
link.rpc('setGasLimit', '0x' + gasLimit.toString(16), this.props.req.handlerId, e => {
Expand Down
Expand Up @@ -71,7 +71,7 @@ class TransactionRequest extends React.Component {
super(props, context)
this.chain = {
type: 'ethereum',
id: parseInt(props.req.data.chainId, 'hex').toString()
id: parseInt(props.req.data.chainId, 'hex')
}
this.state = { allowInput: false, dataView: false }
setTimeout(() => {
Expand Down
2 changes: 1 addition & 1 deletion app/App/Panel/Main/Account/Requests/index.js
Expand Up @@ -146,7 +146,7 @@ class Requests extends React.Component {
if (req.type === 'access') return <ProviderRequest key={req.handlerId} req={req} pos={pos} z={z} onTop={i === normal.length - 1} />
if (req.type === 'sign') return <SignatureRequest key={req.handlerId} req={req} pos={pos} z={z} onTop={i === normal.length - 1} />
if (req.type === 'signTypedData') return <SignTypedDataRequest key={req.handlerId} req={req} pos={pos} z={z} onTop={i === normal.length - 1} />
if (req.type === 'addChain') return <ChainRequest key={req.handlerId} req={req} pos={pos} z={z} onTop={i === normal.length - 1} />
if (req.type === 'addChain' || req.type === 'switchChain') return <ChainRequest key={req.handlerId} req={req} pos={pos} z={z} onTop={i === normal.length - 1} />
return null
})}
</div>
Expand Down
24 changes: 0 additions & 24 deletions app/App/Panel/Main/Account/SignerStatus/index.js
Expand Up @@ -21,30 +21,6 @@ class SignerStatus extends React.Component {
this.inputRef = React.createRef()
}

// clickListener (event) {
// console.log('found a clikc')
// const statusRef = ReactDOM.findDOMNode(this.statusRef.current)
// if (statusRef && statusRef.contains(event.target)) {
// console.log('inside statu ref')
// this.setState({ hideStatus: false })
// } else {
// console.log('outside statu ref')
// this.setState({ hideStatus: true })
// }
// // if (!element.contains(event.target)) { // or use: event.target.closest(selector) === null
// // element.style.display = 'none'
// // removeClickListener()
// // }
// }

// componentDidMount () {
// document.addEventListener('mousedown', this.clickListener.bind(this))
// }

// componentWillUnmount () {
// document.removeEventListener('mousedown', this.clickListener.bind(this))
// }

shake () {
this.setState({ shake: true })
setTimeout(() => {
Expand Down
2 changes: 1 addition & 1 deletion app/App/Panel/Main/Account/Verify/index.js
Expand Up @@ -19,7 +19,7 @@ class Verify extends React.Component {
}

verifyAddress () {
link.rpc('verifyAddress', (err, res) => {
link.rpc('verifyAddress', err => {
if (err) {
this.setState({ verifyAddressSuccess: false, verifyAddressResponse: err })
} else {
Expand Down
4 changes: 2 additions & 2 deletions app/App/Panel/Main/Account/index.js
Expand Up @@ -289,7 +289,7 @@ class _AccountMain extends React.Component {
const chainId = this.store('main.currentNetwork.id')
let slideHeight = 0
const modules = accountModuleOrder.map((id, i) => {
if (chainId !== '1' && id === 'inventory') return undefined
if (chainId !== 1 && id === 'inventory') return undefined
const module = accountModules[id] || { height: 0 }
slideHeight += module.height + 5
return this.renderModule(id, module, slideHeight - module.height - 5, i, id => {
Expand Down Expand Up @@ -981,7 +981,7 @@ class Account extends React.Component {
{!this.state.addressHover ? this.renderSignerIndicator() : null}
{!this.state.addressHover ? (
<>
<div className='accountGrabber' style={open ? { opacity: 0, pointerEvents: 'none' } : {}}>
<div className='accountGrabber' style={open || true ? { opacity: 0, pointerEvents: 'none' } : {}}>
{svg.grab(35)}
</div>
<div className='signerSelect' onMouseDown={this.typeClick.bind(this)}>
Expand Down
2 changes: 1 addition & 1 deletion app/App/Panel/Main/Signer/index.js
Expand Up @@ -32,7 +32,7 @@ class _Balances extends React.Component {

setActive (active) {
const { type, id } = this.store('main.currentNetwork')
if (type !== 'ethereum' || id !== '1') return
if (type !== 'ethereum' || id !== 1) return
this.setState({ openActive: active })
this.openTimer = setTimeout(() => this.setState({ open: active }), 480)
if (active && !this.state.openActive) {
Expand Down
30 changes: 30 additions & 0 deletions app/App/Panel/Main/style/index.styl
Expand Up @@ -132,6 +132,36 @@
font-size 20px
padding 18px

.panelHeaderAddChain
position absolute
right 12px
top 16px
bottom 0
cursor pointer
height 32px
width 106px
border-radius 16px
background var(--ghostB)
display flex
justify-content center
align-items center
font-size 10px
font-weight 300
overflow hidden
background-position 0 100%
text-transform uppercase
letter-spacing 2px
font-weight 600
cursor pointer

.panelHeaderAddChainInner
pointer-events none
margin-left 4px
margin-top -1px

.panelHeaderAddChain:hover
color var(--good)

.panelHeaderUpdate
position absolute
right 12px
Expand Down

0 comments on commit 7f8e12c

Please sign in to comment.