on master help sign in
Merge pull request #127 from urbit/zero-address

Count 0x0 as valid address input

commit868ba2b6db611032b058aebc4d20860461864fb7 authorFang <Fang-@users.noreply.github.com> dateMon 6 May 2019, 20:04 (7 years ago) parenta0fc18f4678c3f
5 files changed+123−32
src/bridge/components/Base.js+5 src/bridge/components/HorizontalSelector.js+57 src/bridge/lib/wallet.js+1−1 src/bridge/views/Point/Actions.js+2−2 src/bridge/views/SetProxy.js+58−29
src/bridge/components/Base.js+5
@@ -37,6 +37,9 @@ import DropdownItem from './DropdownItem';
3737import DropdownDivider from './DropdownDivider';
3838import InnerLabelDropdown from './InnerLabelDropdown';
3939
40+// Option selectors
41+import HorizontalSelector from './HorizontalSelector';
42+
4043// Path Control
4144import Breadcrumb from './Breadcrumb';
4245import BreadcrumbItem from './BreadcrumbItem';
@@ -183,6 +186,8 @@ export {
183186 DropdownDivider,
184187 InnerLabelDropdown,
185188
189+ HorizontalSelector,
190+
186191 Breadcrumb,
187192 BreadcrumbItem,
188193
src/bridge/components/HorizontalSelector.jsnew file+57
@@ -0,0 +1,57 @@
1+import React from 'react'
2+import PropTypes from 'prop-types';
3+
4+class HorizontalSelector extends React.Component {
5+ constructor(props) {
6+ super(props);
7+
8+ this.state = {
9+ option: this.props.options[0].value
10+ };
11+
12+ this.selectOption = this.selectOption.bind(this);
13+ }
14+
15+ selectOption(opt) {
16+ this.props.onChange(opt);
17+ this.setState({option: opt});
18+ }
19+
20+ getOptionElems() {
21+ return this.props.options.map(opt => {
22+ let active = (opt.value === this.state.option)
23+ ? 'btn-primary active'
24+ : '';
25+ return (
26+ <button
27+ className={`btn ${active} h-10 ph-4 flex sans ${this.props.className}`}
28+ value={opt.value}
29+ onClick={() => this.selectOption(opt.value)}>
30+ { opt.title }
31+ </button>
32+ )
33+ })
34+ }
35+
36+ render() {
37+ const optionElems = this.getOptionElems();
38+
39+ return (
40+ <div className='btn-group'>
41+ { optionElems }
42+ </div>
43+ )
44+ }
45+}
46+
47+HorizontalSelector.propTypes = {
48+ className: PropTypes.string,
49+ options: PropTypes.array
50+};
51+
52+HorizontalSelector.defaultProps = {
53+ className: '',
54+ options: []
55+};
56+
57+export default HorizontalSelector
src/bridge/lib/wallet.js+1−1
@@ -70,7 +70,7 @@ const stripHexPrefix = hex =>
7070const keccak256 = str =>
7171 keccak('keccak256').update(str).digest()
7272
73−const isValidAddress = isAddress
73+const isValidAddress = a => (('0x0' === a) || isAddress(a))
7474
7575const toChecksumAddress = (address) => {
7676 const addr = stripHexPrefix(address).toLowerCase()
src/bridge/views/Point/Actions.js+2−2
@@ -177,7 +177,7 @@ const Actions = (props) => {
177177 pushRoute(ROUTE_NAMES.SET_SPAWN_PROXY)
178178 }}
179179 >
180− { 'Set spawn proxy' }
180+ { 'Change spawn proxy' }
181181 </Button>
182182
183183 <Button
@@ -188,7 +188,7 @@ const Actions = (props) => {
188188 pushRoute(ROUTE_NAMES.SET_MANAGEMENT_PROXY)
189189 }}
190190 >
191− { 'Set management proxy' }
191+ { 'Change management proxy' }
192192 </Button>
193193
194194 <Button
src/bridge/views/SetProxy.js+58−29
@@ -1,7 +1,7 @@
11import Maybe from 'folktale/maybe'
22import React from 'react'
33import * as azimuth from 'azimuth-js'
4−import { Row, Col, H1, P, InnerLabel, ShowBlockie, Anchor } from '../components/Base'
4+import { Row, Col, H1, P, InnerLabel, ShowBlockie, Anchor, HorizontalSelector } from '../components/Base'
55import { AddressInput } from '../components/Base'
66import * as ob from 'urbit-ob'
77
@@ -46,13 +46,23 @@ class SetProxy extends React.Component {
4646 this.state = {
4747 proxyAddress: '',
4848 issuingPoint: issuingPoint,
49+ setProxy: true
4950 }
5051
5152 this.statelessRef = React.createRef();
53+ this.handleSetUnset = this.handleSetUnset.bind(this);
5254 this.handleAddressInput = this.handleAddressInput.bind(this)
5355 this.createUnsignedTxn = this.createUnsignedTxn.bind(this)
5456 }
5557
58+ handleSetUnset(selected) {
59+ const set = (selected === 'set');
60+ this.setState({
61+ setProxy: set,
62+ proxyAddress: set ? '' : '0x0000000000000000000000000000000000000000'
63+ });
64+ }
65+
5666 handleAddressInput(proxyAddress) {
5767 this.setState({ proxyAddress })
5868
@@ -116,42 +126,61 @@ class SetProxy extends React.Component {
116126
117127 const ucFirst = w => w.charAt(0).toUpperCase() + w.slice(1);
118128
129+ const setUnset = [
130+ { title: 'Set', value: 'set' },
131+ { title: 'Unset', value: 'unset' }
132+ ];
133+
134+ const titleVerb = this.state.setProxy ? 'Set' : 'Unset';
135+
136+ let addressInput = null;
137+ if (this.state.setProxy) {
138+ addressInput = (<>
139+ <P className='mt-8'>
140+ {
141+ 'Please provide an Ethereum address to act as the ' +
142+ `${renderedProxyType} proxy. You can also use Wallet ` +
143+ 'Generator to generate a keypair.'
144+ }
145+ </P>
146+
147+ <AddressInput
148+ className='mono mt-8'
149+ prop-size='lg'
150+ prop-format='innerLabel'
151+ placeholder={ `e.g. 0x84295d5e054d8cff5a22428b195f5a1615bd644f` }
152+ value={ state.proxyAddress }
153+ onChange={ v => this.handleAddressInput(v) }>
154+ <InnerLabel>{ 'Proxy Address' }</InnerLabel>
155+ <ShowBlockie className={'mt-1'} address={state.proxyAddress} />
156+ </AddressInput>
157+
158+ <Anchor
159+ className={'mt-1'}
160+ prop-size={'sm'}
161+ prop-disabled={!isValidAddress(state.proxyAddress) || !esvisible}
162+ target={'_blank'}
163+ href={`https://${esdomain}/address/${state.proxyAddress}`}>
164+ {'View on Etherscan ↗'}
165+ </Anchor>
166+ </>)
167+ }
119168
120169 return (
121170 <Row>
122171 <Col>
123172 <H1>
124− { `Set ${ucFirst(renderedProxyType)} Proxy For ` }
173+ { `${titleVerb} ${ucFirst(renderedProxyType)} Proxy For ` }
125174 <code>{ `${ob.patp(state.issuingPoint)}` }</code>
126175 </H1>
127176
128− <P>
129− {
130− 'Please provide an Ethereum address to act as the ' +
131− `${renderedProxyType} proxy. You can also use Wallet ` +
132− 'Generator to generate a keypair.'
133− }
134− </P>
135−
136− <AddressInput
137− className='mono mt-8'
138− prop-size='lg'
139− prop-format='innerLabel'
140− placeholder={ `e.g. 0x84295d5e054d8cff5a22428b195f5a1615bd644f` }
141− value={ state.proxyAddress }
142− onChange={ v => this.handleAddressInput(v) }>
143− <InnerLabel>{ 'Proxy Address' }</InnerLabel>
144− <ShowBlockie className={'mt-1'} address={state.proxyAddress} />
145− </AddressInput>
146−
147− <Anchor
148− className={'mt-1'}
149− prop-size={'sm'}
150− prop-disabled={!isValidAddress(state.proxyAddress) || !esvisible}
151− target={'_blank'}
152− href={`https://${esdomain}/address/${state.proxyAddress}`}>
153− {'View on Etherscan ↗'}
154− </Anchor>
177+ <HorizontalSelector
178+ options={setUnset}
179+ onChange={this.handleSetUnset}
180+ className='mt-8'
181+ />
182+
183+ { addressInput }
155184
156185 <StatelessTransaction
157186 // Upper scope