1import { Just, Nothing } from 'folktale/maybe';
2import React from 'react';
3import { azimuth, ecliptic } from 'azimuth-js';
4import * as ob from 'urbit-ob';
5import * as need from '../lib/need';
18} from '../components/old/Base';
20import StatelessTransaction from '../components/old/StatelessTransaction';
22import { NETWORK_TYPES } from '../lib/network';
23import { getSpawnCandidate } from '../lib/child';
24import { canDecodePatp } from '../lib/txn';
26import { isValidAddress } from '../lib/wallet';
27import { withNetwork } from '../store/network';
28import { compose } from '../lib/lib';
29import { withPointCursor } from '../store/pointCursor';
31const setFind = (set, pred) => {
32 for (const e of set) {
40class IssueChild extends React.Component {
44 const issuingPoint = parseInt(need.pointCursor(props), 10);
46 const getCandidate = () => ob.patp(getSpawnCandidate(issuingPoint));
57 issuingPoint: issuingPoint,
59 isAvailable: Nothing(), // use Nothing to allow attempt when offline
60 suggestions: suggestions,
61 validChildren: new Set(),
65 this.handlePointInput = this.handlePointInput.bind(this);
66 this.handleAddressInput = this.handleAddressInput.bind(this);
67 this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
68 this.statelessRef = React.createRef();
71 handleAddressInput = receivingAddress => {
72 this.setState({ receivingAddress });
73 this.statelessRef.current.clearTxn();
76 componentWillMount() {
77 const { issuingPoint } = this.state;
79 const validContracts = need.contracts(this.props);
82 .getUnspawnedChildren(validContracts, issuingPoint)
83 .then(ps => this.setState({ validChildren: new Set(ps.map(ob.patp)) }));
86 handlePointInput(desiredPoint) {
87 if (desiredPoint.length < 15) {
88 const suggestedPoint =
89 setFind(this.state.validChildren, e => e.startsWith(desiredPoint)) ||
92 ' '.repeat(desiredPoint.length) +
93 suggestedPoint.substring(desiredPoint.length);
95 const available = Just(this.state.validChildren.has(desiredPoint));
99 isAvailable: available,
100 autoComplete: rendered,
102 this.statelessRef.current.clearTxn();
106 createUnsignedTxn() {
107 const { state, props } = this;
109 if (isValidAddress(state.receivingAddress) === false) return Nothing();
110 if (state.isAvailable === false) return Nothing();
111 if (canDecodePatp(state.desiredPoint) === false) return Nothing();
113 const validContracts = need.contracts(props);
115 const pointDec = ob.patp2dec(state.desiredPoint);
117 const txn = ecliptic.spawn(
120 state.receivingAddress
126 validatePoint = patp => {
127 const point = this.point;
131 vpatp = ob.isValidPatp(patp);
136 vchild = ob.sein(patp) === ob.patp(point);
139 return vpatp && vchild;
143 const { props, state } = this;
145 const validAddress = isValidAddress(state.receivingAddress);
147 const canGenerate = props.web3.matchWith({
149 return validAddress === true;
152 return validAddress === true && state.isAvailable.value === true;
157 props.networkType === NETWORK_TYPES.ROPSTEN ||
158 props.networkType === NETWORK_TYPES.MAINNET;
161 props.networkType === NETWORK_TYPES.ROPSTEN
162 ? 'ropsten.etherscan.io'
169 {'Issue a Child From '}{' '}
170 <code>{`${ob.patp(state.issuingPoint)}`}</code>
174 {`Please enter the point you would like to issue, and specify the
175 receiving Ethereum address. If you need to create an address, you
176 can also use Wallet Generator.`}
180 {`Your point can only issue children with particular names. Some
181 valid suggestions for `}
182 {<code>{ob.patp(state.issuingPoint)}</code>}
184 <code>{state.suggestions[0]}</code>
186 <code>{state.suggestions[1]}</code>
188 <code>{state.suggestions[2]}</code>
194 prop-format="innerLabel"
195 className={'mono mt-8'}
196 placeholder={`e.g. ${state.suggestions[3]}`}
197 value={state.desiredPoint}
198 onChange={this.handlePointInput}>
199 <InnerLabel>{'Point to Issue'}</InnerLabel>
203 marginLeft: '4.6rem',
206 whiteSpace: 'pre-wrap',
208 className="abs tl-0 mono">
212 className={'tr-0 mt-05 mr-0 abs'}
213 patp={state.desiredPoint}
216 validator={() => this.validatePoint(state.desiredPoint)}
221 className="text-mono mt-8"
223 prop-format="innerLabel"
224 placeholder={`e.g. 0x84295d5e054d8cff5a22428b195f5a1615bd644f`}
225 value={state.receivingAddress}
227 Nothing.hasInstance(state.isAvailable) || !state.isAvailable.value
229 onChange={v => this.handleAddressInput(v)}>
230 <InnerLabel>{'Receiving Address'}</InnerLabel>
231 <ShowBlockie className={'mt-1'} address={state.receivingAddress} />
238 !isValidAddress(state.receivingAddress) || !esvisible
241 href={`https://${esdomain}/address/${state.receivingAddress}`}>
242 {'View on Etherscan ↗'}
245 <StatelessTransaction
246 canGenerate={canGenerate}
247 createUnsignedTxn={this.createUnsignedTxn}
248 ref={this.statelessRef}
256export default compose(
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list