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';
16} from '../components/old/Base';
18import StatelessTransaction from '../components/old/StatelessTransaction';
20import { NETWORK_TYPES } from '../lib/network';
21import { getSpawnCandidate } from '../lib/child';
22import { canDecodePatp } from '../lib/txn';
24import { isValidAddress } from '../lib/wallet';
25import { withNetwork } from '../store/network';
26import { compose } from '../lib/lib';
27import { withPointCursor } from '../store/pointCursor';
28import View from 'components/View';
30const setFind = (set, pred) => {
31 for (const e of set) {
39class IssueChild extends React.Component {
43 const issuingPoint = need.point(props.pointCursor);
45 const getCandidate = () => ob.patp(getSpawnCandidate(issuingPoint));
56 issuingPoint: issuingPoint,
58 isAvailable: Nothing(), // use Nothing to allow attempt when offline
59 suggestions: suggestions,
60 validChildren: new Set(),
64 this.handlePointInput = this.handlePointInput.bind(this);
65 this.handleAddressInput = this.handleAddressInput.bind(this);
66 this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
67 this.statelessRef = React.createRef();
70 handleAddressInput = receivingAddress => {
71 this.setState({ receivingAddress });
72 this.statelessRef.current.clearTxn();
75 componentWillMount() {
76 const { issuingPoint } = this.state;
78 const validContracts = need.contracts(this.props.contracts);
81 .getUnspawnedChildren(validContracts, issuingPoint)
82 .then(ps => this.setState({ validChildren: new Set(ps.map(ob.patp)) }));
85 handlePointInput(desiredPoint) {
86 if (desiredPoint.length < 15) {
87 const suggestedPoint =
88 setFind(this.state.validChildren, e => e.startsWith(desiredPoint)) ||
91 ' '.repeat(desiredPoint.length) +
92 suggestedPoint.substring(desiredPoint.length);
94 const available = Just(this.state.validChildren.has(desiredPoint));
98 isAvailable: available,
99 autoComplete: rendered,
101 this.statelessRef.current.clearTxn();
105 createUnsignedTxn() {
106 const { state, props } = this;
108 if (isValidAddress(state.receivingAddress) === false) return Nothing();
109 if (state.isAvailable === false) return Nothing();
110 if (canDecodePatp(state.desiredPoint) === false) return Nothing();
112 const validContracts = need.contracts(props.contracts);
114 const pointDec = ob.patp2dec(state.desiredPoint);
116 const txn = ecliptic.spawn(
119 state.receivingAddress
125 validatePoint = patp => {
126 const point = this.point;
130 vpatp = ob.isValidPatp(patp);
135 vchild = ob.sein(patp) === ob.patp(point);
138 return vpatp && vchild;
142 const { props, state } = this;
144 const validAddress = isValidAddress(state.receivingAddress);
146 const canGenerate = props.web3.matchWith({
148 return validAddress === true;
151 return validAddress === true && state.isAvailable.value === true;
156 props.networkType === NETWORK_TYPES.ROPSTEN ||
157 props.networkType === NETWORK_TYPES.MAINNET;
160 props.networkType === NETWORK_TYPES.ROPSTEN
161 ? 'ropsten.etherscan.io'
167 {'Issue a Child From '}{' '}
168 <code>{`${ob.patp(state.issuingPoint)}`}</code>
172 {`Please enter the point you would like to issue, and specify the
173 receiving Ethereum address. If you need to create an address, you
174 can also use Wallet Generator.`}
178 {`Your point can only issue children with particular names. Some
179 valid suggestions for `}
180 {<code>{ob.patp(state.issuingPoint)}</code>}
182 <code>{state.suggestions[0]}</code>
184 <code>{state.suggestions[1]}</code>
186 <code>{state.suggestions[2]}</code>
192 prop-format="innerLabel"
193 className={'mono mt-8'}
194 placeholder={`e.g. ${state.suggestions[3]}`}
195 value={state.desiredPoint}
196 onChange={this.handlePointInput}>
197 <InnerLabel>{'Point to Issue'}</InnerLabel>
201 marginLeft: '4.6rem',
204 whiteSpace: 'pre-wrap',
206 className="abs tl-0 mono">
210 className={'tr-0 mt-05 mr-0 abs'}
211 patp={state.desiredPoint}
214 validator={() => this.validatePoint(state.desiredPoint)}
219 className="text-mono mt-8"
221 prop-format="innerLabel"
222 placeholder={`e.g. 0x84295d5e054d8cff5a22428b195f5a1615bd644f`}
223 value={state.receivingAddress}
225 Nothing.hasInstance(state.isAvailable) || !state.isAvailable.value
227 onChange={v => this.handleAddressInput(v)}>
228 <InnerLabel>{'Receiving Address'}</InnerLabel>
229 <ShowBlockie className={'mt-1'} address={state.receivingAddress} />
235 prop-disabled={!isValidAddress(state.receivingAddress) || !esvisible}
237 href={`https://${esdomain}/address/${state.receivingAddress}`}>
238 {'View on Etherscan ↗'}
241 <StatelessTransaction
242 canGenerate={canGenerate}
243 createUnsignedTxn={this.createUnsignedTxn}
244 ref={this.statelessRef}
251export 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