on master help sign in
chore: nuke old files ๐ŸŽ‰
bc37544Matt Condon (shrugs)
src/components/old/StatelessTransaction.jsdeletedโˆ’598
@@ -1,598 +0,0 @@
1โˆ’import { Nothing, Just } from 'folktale/maybe';
2โˆ’import { Ok } from 'folktale/result';
3โˆ’import React from 'react';
4โˆ’import * as need from '../../lib/need';
5โˆ’
6โˆ’import { Code, H3 } from './Base';
7โˆ’import { Button } from './Base';
8โˆ’import { CheckboxButton, Input, InnerLabel, InnerLabelDropdown } from './Base';
9โˆ’import { Warning } from './Base';
10โˆ’
11โˆ’import { GAS_LIMITS } from '../../lib/constants';
12โˆ’import { BRIDGE_ERROR } from '../../lib/error';
13โˆ’import { ROUTE_NAMES } from '../../lib/routeNames';
14โˆ’import { compose } from '../../lib/lib';
15โˆ’import * as tank from '../../lib/tank';
16โˆ’import {
17โˆ’ sendSignedTransaction,
18โˆ’ hexify,
19โˆ’ renderSignedTx,
20โˆ’ signTransaction,
21โˆ’} from '../../lib/txn';
22โˆ’
23โˆ’import { withNetwork } from '../../store/network';
24โˆ’import { withHistory } from '../../store/history';
25โˆ’import { withWallet } from '../../store/wallet';
26โˆ’import { withTxnCursor } from '../../store/txnCursor';
27โˆ’import { fromWei, toWei } from 'web3-utils';
28โˆ’
29โˆ’const SUBMISSION_STATES = {
30โˆ’ PROMPT: 'Send transaction',
31โˆ’ PREPARING: 'Preparing...',
32โˆ’ FUNDING: 'Finding transaction funding...',
33โˆ’ SENDING: 'Sending transaction...',
34โˆ’};
35โˆ’
36โˆ’class StatelessTransaction extends React.Component {
37โˆ’ constructor(props) {
38โˆ’ super(props);
39โˆ’
40โˆ’ this.state = {
41โˆ’ gasPrice: '5',
42โˆ’ gasLimit: GAS_LIMITS.DEFAULT.toString(),
43โˆ’ showGasDetails: false,
44โˆ’ userApproval: false,
45โˆ’ chainId: '1',
46โˆ’ customChain: false,
47โˆ’ nonce: '0',
48โˆ’ stx: Nothing(),
49โˆ’ txn: Nothing(),
50โˆ’ txStatus: SUBMISSION_STATES.PROMPT,
51โˆ’ txError: Nothing(),
52โˆ’ };
53โˆ’
54โˆ’ this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
55โˆ’ this.setUserApproval = this.setUserApproval.bind(this);
56โˆ’ this.setTxn = this.setTxn.bind(this);
57โˆ’ this.setStx = this.setStx.bind(this);
58โˆ’ this.sendTxn = this.sendTxn.bind(this);
59โˆ’ this.setNonce = this.setNonce.bind(this);
60โˆ’ this.setChainId = this.setChainId.bind(this);
61โˆ’ this.setGasPrice = this.setGasPrice.bind(this);
62โˆ’ this.setGasLimit = this.setGasLimit.bind(this);
63โˆ’ this.rangeChange = this.rangeChange.bind(this);
64โˆ’ this.toggleGasDetails = this.toggleGasDetails.bind(this);
65โˆ’ this.handleChainUpdate = this.handleChainUpdate.bind(this);
66โˆ’ }
67โˆ’
68โˆ’ componentDidMount() {
69โˆ’ const { props } = this;
70โˆ’
71โˆ’ const addr = need.addressFromWallet(props.wallet);
72โˆ’
73โˆ’ props.web3.matchWith({
74โˆ’ Nothing: () => {},
75โˆ’ Just: w3 => {
76โˆ’ const validWeb3 = w3.value;
77โˆ’
78โˆ’ const getTxMetadata = [
79โˆ’ validWeb3.eth.getTransactionCount(addr),
80โˆ’ validWeb3.eth.net.getId(),
81โˆ’ validWeb3.eth.getGasPrice(),
82โˆ’ ];
83โˆ’
84โˆ’ Promise.all(getTxMetadata).then(r => {
85โˆ’ const txMetadata = {
86โˆ’ nonce: r[0],
87โˆ’ chainId: r[1],
88โˆ’ gasPrice: fromWei(r[2], 'gwei'),
89โˆ’ };
90โˆ’
91โˆ’ this.setState({ ...txMetadata });
92โˆ’ });
93โˆ’ },
94โˆ’ });
95โˆ’ }
96โˆ’
97โˆ’ handleChainUpdate(chainId) {
98โˆ’ if (chainId === 'custom') {
99โˆ’ this.setState({
100โˆ’ customChain: true,
101โˆ’ });
102โˆ’ } else {
103โˆ’ this.setState({
104โˆ’ customChain: false,
105โˆ’ chainId,
106โˆ’ });
107โˆ’ }
108โˆ’
109โˆ’ this.clearStx();
110โˆ’ }
111โˆ’
112โˆ’ setUserApproval() {
113โˆ’ const { state } = this;
114โˆ’ this.setState({ userApproval: !state.userApproval });
115โˆ’ }
116โˆ’
117โˆ’ toggleGasDetails() {
118โˆ’ this.setState({
119โˆ’ showGasDetails: !this.state.showGasDetails,
120โˆ’ });
121โˆ’ }
122โˆ’
123โˆ’ setStx(stx) {
124โˆ’ this.setState({
125โˆ’ stx,
126โˆ’ userApproval: false,
127โˆ’ });
128โˆ’ }
129โˆ’
130โˆ’ setTxn(txn) {
131โˆ’ this.setState({ txn });
132โˆ’ }
133โˆ’
134โˆ’ createUnsignedTxn() {
135โˆ’ const txn = this.props.createUnsignedTxn();
136โˆ’
137โˆ’ this.setState({ txn });
138โˆ’ }
139โˆ’
140โˆ’ clearTxn() {
141โˆ’ this.setState({
142โˆ’ userApproval: false,
143โˆ’ txn: Nothing(),
144โˆ’ stx: Nothing(),
145โˆ’ });
146โˆ’ }
147โˆ’
148โˆ’ setNonce(nonce) {
149โˆ’ this.setState({ nonce });
150โˆ’ this.clearStx();
151โˆ’ }
152โˆ’
153โˆ’ setChainId(chainId) {
154โˆ’ this.setState({ chainId });
155โˆ’ this.clearStx();
156โˆ’ }
157โˆ’
158โˆ’ setGasPrice(gasPrice) {
159โˆ’ this.setState({ gasPrice });
160โˆ’ this.clearStx();
161โˆ’ }
162โˆ’
163โˆ’ rangeChange(e) {
164โˆ’ this.setGasPrice(e.target.value);
165โˆ’ }
166โˆ’
167โˆ’ setGasLimit(gasLimit) {
168โˆ’ this.setState({ gasLimit });
169โˆ’ this.clearStx();
170โˆ’ }
171โˆ’
172โˆ’ clearStx() {
173โˆ’ this.setState({
174โˆ’ userApproval: false,
175โˆ’ stx: Nothing(),
176โˆ’ });
177โˆ’ }
178โˆ’
179โˆ’ async sendTxn() {
180โˆ’ const { props, state } = this;
181โˆ’ const web3 = props.web3.value;
182โˆ’
183โˆ’ const stx = state.stx.matchWith({
184โˆ’ Just: tx => tx.value,
185โˆ’ Nothing: () => {
186โˆ’ throw new Error(BRIDGE_ERROR.MISSING_TXN);
187โˆ’ },
188โˆ’ });
189โˆ’
190โˆ’ if (props.beforeSend) {
191โˆ’ try {
192โˆ’ this.setState({ txStatus: SUBMISSION_STATES.PREPARING });
193โˆ’ const res = await props.beforeSend(stx);
194โˆ’ if (res === false) throw new Error('beforeSend disallowed sending');
195โˆ’ } catch (e) {
196โˆ’ console.log('beforeSend error', e);
197โˆ’ this.setState({
198โˆ’ txStatus: SUBMISSION_STATES.PROMPT,
199โˆ’ txError: Just('Something went wrong!'),
200โˆ’ });
201โˆ’ return;
202โˆ’ }
203โˆ’ }
204โˆ’
205โˆ’ this.setState({ txStatus: SUBMISSION_STATES.FUNDING });
206โˆ’
207โˆ’ const rawTx = hexify(stx.serialize());
208โˆ’ const cost = state.gasLimit * toWei(state.gasPrice, 'gwei');
209โˆ’
210โˆ’ const address = need.addressFromWallet(props.wallet);
211โˆ’ let balance = await web3.eth.getBalance(address);
212โˆ’ let hasBalance = balance >= cost;
213โˆ’
214โˆ’ let usedTank = false;
215โˆ’ // if we need to, try and fund the transaction
216โˆ’ if (!hasBalance) {
217โˆ’ usedTank = await this.ensureFundsFor(web3, address, cost, [rawTx]);
218โˆ’ hasBalance = usedTank;
219โˆ’ }
220โˆ’
221โˆ’ // if we still don't have sufficient balance, fail and tell the user
222โˆ’ if (!hasBalance) {
223โˆ’ this.setState({
224โˆ’ txStatus: SUBMISSION_STATES.PROMPT,
225โˆ’ txError: Just(`Insufficient funds.
226โˆ’ Address ${address} needs at least ${fromWei(cost.toString())} ETH,
227โˆ’ currently has ${fromWei(balance.toString())} ETH.`),
228โˆ’ });
229โˆ’
230โˆ’ // if we have the balance, proceed with submission
231โˆ’ } else {
232โˆ’ this.setState({ txStatus: SUBMISSION_STATES.SENDING });
233โˆ’
234โˆ’ sendSignedTransaction(web3, stx, usedTank)
235โˆ’ .then(txHash => {
236โˆ’ props.setTxnCursor(Just(Ok(txHash)));
237โˆ’
238โˆ’ let routeData = {};
239โˆ’ if (props.newNetworkSeed) {
240โˆ’ props.setNetworkSeed(Just(props.newNetworkSeed));
241โˆ’ routeData.promptKeyfile = true;
242โˆ’ }
243โˆ’
244โˆ’ if (props.newRevision) {
245โˆ’ props.setNetworkRevision(Just(props.newRevision));
246โˆ’ }
247โˆ’
248โˆ’ props.history.popAndPush(ROUTE_NAMES.SENT_TRANSACTION, routeData);
249โˆ’ })
250โˆ’ .catch(err => {
251โˆ’ this.setState({
252โˆ’ txStatus: SUBMISSION_STATES.PROMPT,
253โˆ’ txError: Just(err),
254โˆ’ });
255โˆ’ });
256โˆ’ }
257โˆ’ }
258โˆ’
259โˆ’ // uses the gas tank to ensure funds, but if we have to ask the user
260โˆ’ // for funding, just resolve instead of waiting
261โˆ’ // returns true if the gas tank was used, false otherwise
262โˆ’ ensureFundsFor(web3, address, cost, signedTxs) {
263โˆ’ return new Promise((resolve, reject) => {
264โˆ’ tank
265โˆ’ .ensureFundsFor(web3, null, address, cost, signedTxs, () => {
266โˆ’ resolve(false);
267โˆ’ })
268โˆ’ .then(res => {
269โˆ’ resolve(res);
270โˆ’ });
271โˆ’ });
272โˆ’ }
273โˆ’
274โˆ’ getChainTitle(chainId) {
275โˆ’ let map = {
276โˆ’ '1': 'Mainnet - 1',
277โˆ’ '2': 'Morden - 2',
278โˆ’ '3': 'Ropsten - 3',
279โˆ’ '4': 'Goerli - 4',
280โˆ’ '42': 'Kovan - 42',
281โˆ’ '1337': 'Geth private chains - 1337',
282โˆ’ custom: 'Custom',
283โˆ’ };
284โˆ’
285โˆ’ return map[chainId];
286โˆ’ }
287โˆ’
288โˆ’ getChainOptions() {
289โˆ’ return [
290โˆ’ {
291โˆ’ title: this.getChainTitle('1'),
292โˆ’ value: '1',
293โˆ’ },
294โˆ’ {
295โˆ’ title: this.getChainTitle('2'),
296โˆ’ value: '2',
297โˆ’ },
298โˆ’ {
299โˆ’ title: this.getChainTitle('3'),
300โˆ’ value: '3',
301โˆ’ },
302โˆ’ {
303โˆ’ title: this.getChainTitle('4'),
304โˆ’ value: '4',
305โˆ’ },
306โˆ’ {
307โˆ’ title: this.getChainTitle('42'),
308โˆ’ value: '42',
309โˆ’ },
310โˆ’ {
311โˆ’ title: this.getChainTitle('1337'),
312โˆ’ value: '1337',
313โˆ’ },
314โˆ’ {
315โˆ’ title: this.getChainTitle('custom'),
316โˆ’ value: 'custom',
317โˆ’ },
318โˆ’ ];
319โˆ’ }
320โˆ’
321โˆ’ render() {
322โˆ’ const { web3, canGenerate } = this.props;
323โˆ’ const {
324โˆ’ gasPrice,
325โˆ’ gasLimit,
326โˆ’ nonce,
327โˆ’ chainId,
328โˆ’ txn,
329โˆ’ stx,
330โˆ’ userApproval,
331โˆ’ showGasDetails,
332โˆ’ customChain,
333โˆ’ txStatus,
334โˆ’ } = this.state;
335โˆ’
336โˆ’ const {
337โˆ’ setNonce,
338โˆ’ setChainId,
339โˆ’ setGasLimit,
340โˆ’ setGasPrice,
341โˆ’ toggleGasDetails,
342โˆ’ setUserApproval,
343โˆ’ sendTxn,
344โˆ’ createUnsignedTxn,
345โˆ’ handleChainUpdate,
346โˆ’ } = this;
347โˆ’
348โˆ’ const { state } = this;
349โˆ’
350โˆ’ const canSign = Just.hasInstance(txn);
351โˆ’ const canApprove = Just.hasInstance(stx);
352โˆ’ const canSend = Just.hasInstance(stx) && userApproval === true;
353โˆ’
354โˆ’ const chainOptions = this.getChainOptions();
355โˆ’
356โˆ’ const generateButtonColor = Nothing.hasInstance(txn) ? 'blue' : 'green';
357โˆ’
358โˆ’ const signerButtonColor = Nothing.hasInstance(stx) ? 'blue' : 'green';
359โˆ’
360โˆ’ const generateTxnButton = (
361โˆ’ <Button
362โˆ’ className={'mt-8'}
363โˆ’ disabled={!canGenerate}
364โˆ’ prop-color={generateButtonColor}
365โˆ’ prop-size={'lg wide'}
366โˆ’ onClick={createUnsignedTxn}>
367โˆ’ {'Generate Transaction'}
368โˆ’ </Button>
369โˆ’ );
370โˆ’
371โˆ’ const unsignedTxnDisplay = txn.matchWith({
372โˆ’ Nothing: _ => '',
373โˆ’ Just: tx => (
374โˆ’ <React.Fragment>
375โˆ’ <H3 className={'mt-8'}>{'Unsigned Transaction'}</H3>
376โˆ’ <Code>{JSON.stringify(tx.value, null, 2)}</Code>
377โˆ’ </React.Fragment>
378โˆ’ ),
379โˆ’ });
380โˆ’
381โˆ’ const gasPriceRangeDialogue = (
382โˆ’ <React.Fragment>
383โˆ’ <div className="mt-12 flex space-between align-baseline">
384โˆ’ <div>
385โˆ’ <span>Gas Price:</span>
386โˆ’ <span className="ml-4 text-700 text-sm">{gasPrice} gwei</span>
387โˆ’ </div>
388โˆ’ <div className="text-sm">
389โˆ’ <span>Max transaction fee: </span>
390โˆ’ <span className="text-700">
391โˆ’ {(gasPrice * gasLimit) / 1000000000} eth
392โˆ’ </span>
393โˆ’ </div>
394โˆ’ </div>
395โˆ’
396โˆ’ <input
397โˆ’ className="mt-4"
398โˆ’ type="range"
399โˆ’ min="2"
400โˆ’ max="20"
401โˆ’ list="gweiVals"
402โˆ’ value={gasPrice}
403โˆ’ onChange={this.rangeChange}
404โˆ’ />
405โˆ’
406โˆ’ <div className="flex space-between text-sm mb-8">
407โˆ’ <div>Cheap</div>
408โˆ’ <div>Fast</div>
409โˆ’ </div>
410โˆ’ </React.Fragment>
411โˆ’ );
412โˆ’
413โˆ’ const toggleGasDetailsDialogue = (
414โˆ’ <span className="text-link" onClick={toggleGasDetails}>
415โˆ’ Gas Details
416โˆ’ </span>
417โˆ’ );
418โˆ’
419โˆ’ const gasPriceDialogue = (
420โˆ’ <Input
421โˆ’ className={'mono mt-4'}
422โˆ’ prop-size={'md'}
423โˆ’ prop-format={'innerLabel'}
424โˆ’ value={gasPrice}
425โˆ’ onChange={setGasPrice}>
426โˆ’ <InnerLabel>{'Gas Price (gwei)'}</InnerLabel>
427โˆ’ </Input>
428โˆ’ );
429โˆ’
430โˆ’ const gasLimitDialogue = (
431โˆ’ <Input
432โˆ’ className={'mono mt-4'}
433โˆ’ prop-size={'md'}
434โˆ’ prop-format={'innerLabel'}
435โˆ’ value={gasLimit}
436โˆ’ onChange={setGasLimit}>
437โˆ’ <InnerLabel>{'Gas Limit'}</InnerLabel>
438โˆ’ </Input>
439โˆ’ );
440โˆ’
441โˆ’ const nonceDialogue = (
442โˆ’ <Input
443โˆ’ className={'mono mt-4 mb-4'}
444โˆ’ prop-size={'md'}
445โˆ’ prop-format={'innerLabel'}
446โˆ’ value={nonce}
447โˆ’ onChange={setNonce}>
448โˆ’ <InnerLabel>{'Nonce'}</InnerLabel>
449โˆ’ </Input>
450โˆ’ );
451โˆ’
452โˆ’ const chainDialogueTitle = customChain
453โˆ’ ? 'Custom'
454โˆ’ : this.getChainTitle(chainId);
455โˆ’ const chainDialogue = (
456โˆ’ <InnerLabelDropdown
457โˆ’ className={'mt-6'}
458โˆ’ fullWidth={true}
459โˆ’ title={'Chain ID'}
460โˆ’ options={chainOptions}
461โˆ’ handleUpdate={handleChainUpdate}
462โˆ’ currentSelectionTitle={chainDialogueTitle}
463โˆ’ />
464โˆ’ );
465โˆ’
466โˆ’ const customChainDialogue = !customChain ? null : (
467โˆ’ <Input
468โˆ’ className={'mono mt-4 mb-8'}
469โˆ’ prop-size={'md'}
470โˆ’ prop-format={'innerLabel'}
471โˆ’ value={chainId}
472โˆ’ onChange={setChainId}>
473โˆ’ <InnerLabel>{'Chain ID'}</InnerLabel>
474โˆ’ </Input>
475โˆ’ );
476โˆ’
477โˆ’ const onlineParamsDialogue = web3.matchWith({
478โˆ’ Just: _ => <div />,
479โˆ’ Nothing: _ => (
480โˆ’ <React.Fragment>
481โˆ’ {nonceDialogue}
482โˆ’ {chainDialogue}
483โˆ’ {customChainDialogue}
484โˆ’ </React.Fragment>
485โˆ’ ),
486โˆ’ });
487โˆ’
488โˆ’ const signTxnButton = (
489โˆ’ <Button
490โˆ’ disabled={!canSign}
491โˆ’ className={'mt-8'}
492โˆ’ prop-size={'lg wide'}
493โˆ’ prop-color={signerButtonColor}
494โˆ’ onClick={async () =>
495โˆ’ this.setStx(
496โˆ’ Just(
497โˆ’ await signTransaction({
498โˆ’ ...this.props,
499โˆ’ ...this.state,
500โˆ’ wallet: this.props.wallet.value,
501โˆ’ txn: txn.value,
502โˆ’ })
503โˆ’ )
504โˆ’ )
505โˆ’ }>
506โˆ’ {'Sign Transaction'}
507โˆ’ </Button>
508โˆ’ );
509โˆ’
510โˆ’ const signedTxnDisplay = stx.matchWith({
511โˆ’ Nothing: _ => '',
512โˆ’ Just: tx => (
513โˆ’ <React.Fragment>
514โˆ’ <H3 className={'mt-8'}>{'Signed Transaction'}</H3>
515โˆ’ <Code>{JSON.stringify(renderSignedTx(tx.value), null, 2)}</Code>
516โˆ’ </React.Fragment>
517โˆ’ ),
518โˆ’ });
519โˆ’
520โˆ’ const confirmButton = (
521โˆ’ <CheckboxButton
522โˆ’ className={'mt-8'}
523โˆ’ disabled={!canApprove}
524โˆ’ onToggle={setUserApproval}
525โˆ’ state={userApproval}
526โˆ’ label="I approve this transaction and wish to send."
527โˆ’ />
528โˆ’ );
529โˆ’
530โˆ’ const sending = txStatus !== SUBMISSION_STATES.PROMPT;
531โˆ’ const sendTxnSpinner = sending ? '' : 'hide';
532โˆ’ const sendTxnButton = (
533โˆ’ <Button
534โˆ’ prop-size={'xl wide'}
535โˆ’ className={'mt-8'}
536โˆ’ disabled={!canSend || sending}
537โˆ’ onClick={sendTxn}>
538โˆ’ <span className="relative">
539โˆ’ <span className={`btn-spinner ${sendTxnSpinner}`} />
540โˆ’ {txStatus}
541โˆ’ </span>
542โˆ’ </Button>
543โˆ’ );
544โˆ’
545โˆ’ const sendDialogue = web3.matchWith({
546โˆ’ Nothing: _ => '',
547โˆ’ Just: _ => (
548โˆ’ <React.Fragment>
549โˆ’ {confirmButton}
550โˆ’ {sendTxnButton}
551โˆ’ </React.Fragment>
552โˆ’ ),
553โˆ’ });
554โˆ’
555โˆ’ const txnErrorDialogue = Nothing.hasInstance(state.txError) ? (
556โˆ’ ''
557โˆ’ ) : (
558โˆ’ <Warning className={'mt-8'}>
559โˆ’ <H3 style={{ marginTop: 0, paddingTop: 0 }}>
560โˆ’ {'There was an error sending your transaction.'}
561โˆ’ </H3>
562โˆ’ {state.txError.value}
563โˆ’ </Warning>
564โˆ’ );
565โˆ’
566โˆ’ return (
567โˆ’ <React.Fragment>
568โˆ’ {generateTxnButton}
569โˆ’ {unsignedTxnDisplay}
570โˆ’
571โˆ’ {gasPriceRangeDialogue}
572โˆ’ {toggleGasDetailsDialogue}
573โˆ’
574โˆ’ {showGasDetails && (
575โˆ’ <div>
576โˆ’ {gasPriceDialogue}
577โˆ’ {gasLimitDialogue}
578โˆ’ </div>
579โˆ’ )}
580โˆ’ {onlineParamsDialogue}
581โˆ’
582โˆ’ {signTxnButton}
583โˆ’
584โˆ’ {signedTxnDisplay}
585โˆ’ {sendDialogue}
586โˆ’
587โˆ’ {txnErrorDialogue}
588โˆ’ </React.Fragment>
589โˆ’ );
590โˆ’ }
591โˆ’}
592โˆ’
593โˆ’export default compose(
594โˆ’ withNetwork,
595โˆ’ withHistory,
596โˆ’ withWallet,
597โˆ’ withTxnCursor
598โˆ’)(StatelessTransaction);
src/lib/routeNames.jsโˆ’1
@@ -26,7 +26,6 @@ export const ROUTE_NAMES = {
26 ISSUE_CHILD: Symbol('ISSUE_CHILD'),
26 ISSUE_CHILD: Symbol('ISSUE_CHILD'),
27 SET_KEYS: Symbol('SET_KEYS'),
27 SET_KEYS: Symbol('SET_KEYS'),
28 TRANSFER: Symbol('TRANSFER'),
28 TRANSFER: Symbol('TRANSFER'),
29โˆ’ SENT_TRANSACTION: Symbol('SENT_TRANSACTION'),
30 GEN_KEYFILE: Symbol('GEN_KEYFILE'),
29 GEN_KEYFILE: Symbol('GEN_KEYFILE'),
31 PARTY_SET_POOL_SIZE: Symbol('PARTY_SET_POOL_SIZE'),
30 PARTY_SET_POOL_SIZE: Symbol('PARTY_SET_POOL_SIZE'),
32};
31};
src/lib/router.js+15โˆ’33
@@ -1,50 +1,32 @@
1โˆ’import Landing from '../views/Landing';
1+import Landing from 'views/Landing';
2โˆ’import Disclaimer from '../views/Disclaimer';
2+import Disclaimer from 'views/Disclaimer';
3โˆ’import Login from '../views/Login.js';
3+import Login from 'views/Login.js';
4โˆ’import InvitesManage from '../views/InvitesManage.js';
5โˆ’import Admin from '../views/Admin';
4+import Admin from 'views/Admin';
6โˆ’import AcceptTransfer from '../views/AcceptTransfer';
7โˆ’import CancelTransfer from '../views/CancelTransfer';
8โˆ’import CreateGalaxy from '../views/CreateGalaxy';
5+import CreateGalaxy from 'views/CreateGalaxy';
9โˆ’import IssueChild from '../views/IssueChild';
6+import IssueChild from 'views/IssueChild';
10โˆ’import ViewPoint from '../views/ViewPoint';
7+import ViewPoint from 'views/ViewPoint';
11โˆ’import SentTransaction from '../views/SentTransaction';
8+
12โˆ’import SetKeys from '../views/SetKeys';
13โˆ’import {
14โˆ’ SetManagementProxy,
15โˆ’ SetSpawnProxy,
16โˆ’ SetTransferProxy,
17โˆ’} from '../views/SetProxy';
18โˆ’import Point from '../views/Point';
9+import Point from 'views/Point';
19โˆ’import Points from '../views/Points';
10+import Points from 'views/Points';
20โˆ’import Transfer from '../views/Transfer';
21import Invite from 'views/Invite';
11import Invite from 'views/Invite';
22import Activate from 'views/Activate';
12import Activate from 'views/Activate';
23
13
24โˆ’import { ROUTE_NAMES } from './routeNames';
25import PartySetPoolSize from 'views/Party/PartySetPoolSize';
14import PartySetPoolSize from 'views/Party/PartySetPoolSize';
26
15
16+import { ROUTE_NAMES } from './routeNames';
17+
27export const ROUTES = {
18export const ROUTES = {
28 [ROUTE_NAMES.LANDING]: Landing,
19 [ROUTE_NAMES.LANDING]: Landing,
29 [ROUTE_NAMES.DISCLAIMER]: Disclaimer,
20 [ROUTE_NAMES.DISCLAIMER]: Disclaimer,
30 [ROUTE_NAMES.ACTIVATE]: Activate,
21 [ROUTE_NAMES.ACTIVATE]: Activate,
31โˆ’ [ROUTE_NAMES.INVITE]: Invite,
32โˆ’ [ROUTE_NAMES.INVITES_MANAGE]: InvitesManage,
33โˆ’ [ROUTE_NAMES.LOGIN]: Login,
34โˆ’ [ROUTE_NAMES.ADMIN]: Admin,
35โˆ’ [ROUTE_NAMES.ACCEPT_TRANSFER]: AcceptTransfer,
36โˆ’ [ROUTE_NAMES.CANCEL_TRANSFER]: CancelTransfer,
37 [ROUTE_NAMES.VIEW_POINT]: ViewPoint,
22 [ROUTE_NAMES.VIEW_POINT]: ViewPoint,
23+ [ROUTE_NAMES.LOGIN]: Login,
38 [ROUTE_NAMES.POINTS]: Points,
24 [ROUTE_NAMES.POINTS]: Points,
39 [ROUTE_NAMES.POINT]: Point,
25 [ROUTE_NAMES.POINT]: Point,
40โˆ’ [ROUTE_NAMES.SET_MANAGEMENT_PROXY]: SetManagementProxy,
41โˆ’ [ROUTE_NAMES.SET_SPAWN_PROXY]: SetSpawnProxy,
42โˆ’ [ROUTE_NAMES.SET_TRANSFER_PROXY]: SetTransferProxy,
43 [ROUTE_NAMES.CREATE_GALAXY]: CreateGalaxy,
26 [ROUTE_NAMES.CREATE_GALAXY]: CreateGalaxy,
44 [ROUTE_NAMES.ISSUE_CHILD]: IssueChild,
27 [ROUTE_NAMES.ISSUE_CHILD]: IssueChild,
45โˆ’ [ROUTE_NAMES.SET_KEYS]: SetKeys,
46โˆ’ [ROUTE_NAMES.TRANSFER]: Transfer,
47โˆ’ [ROUTE_NAMES.SENT_TRANSACTION]: SentTransaction,
48 [ROUTE_NAMES.PARTY_SET_POOL_SIZE]: PartySetPoolSize,
28 [ROUTE_NAMES.PARTY_SET_POOL_SIZE]: PartySetPoolSize,
29+ [ROUTE_NAMES.INVITE]: Invite,
30+ [ROUTE_NAMES.ADMIN]: Admin,
49 // TODO: nest this route under the Party.js router
31 // TODO: nest this route under the Party.js router
50};
32};
src/views/AcceptTransfer.jsdeletedโˆ’121
@@ -1,121 +0,0 @@
1โˆ’import { Just } from 'folktale/maybe';
2โˆ’import React from 'react';
3โˆ’import { H1, P } from '../components/old/Base';
4โˆ’import {
5โˆ’ InnerLabel,
6โˆ’ AddressInput,
7โˆ’ ShowBlockie,
8โˆ’ Anchor,
9โˆ’} from '../components/old/Base';
10โˆ’import * as azimuth from 'azimuth-js';
11โˆ’import * as ob from 'urbit-ob';
12โˆ’import * as need from '../lib/need';
13โˆ’
14โˆ’import StatelessTransaction from '../components/old/StatelessTransaction';
15โˆ’import { NETWORK_TYPES } from '../lib/network';
16โˆ’import { isValidAddress } from '../lib/wallet';
17โˆ’import { withNetwork } from '../store/network';
18โˆ’import { compose } from '../lib/lib';
19โˆ’import { withWallet } from '../store/wallet';
20โˆ’import { withPointCursor } from '../store/pointCursor';
21โˆ’import View from 'components/View';
22โˆ’
23โˆ’class AcceptTransfer extends React.Component {
24โˆ’ constructor(props) {
25โˆ’ super(props);
26โˆ’
27โˆ’ const receivingAddress = need.addressFromWallet(props.wallet);
28โˆ’ const incomingPoint = need.point(props.pointCursor);
29โˆ’
30โˆ’ this.state = {
31โˆ’ receivingAddress: receivingAddress,
32โˆ’ incomingPoint: incomingPoint,
33โˆ’ };
34โˆ’
35โˆ’ this.handleAddressInput = this.handleAddressInput.bind(this);
36โˆ’ this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
37โˆ’ this.statelessRef = React.createRef();
38โˆ’ }
39โˆ’
40โˆ’ handleAddressInput(proxyAddress) {
41โˆ’ this.setState({ proxyAddress });
42โˆ’ this.statelessRef.current.clearTxn();
43โˆ’ }
44โˆ’
45โˆ’ createUnsignedTxn() {
46โˆ’ const { state, props } = this;
47โˆ’
48โˆ’ const validContracts = need.contracts(props.contracts);
49โˆ’ const validPoint = need.point(props.pointCursor);
50โˆ’ //TODO state.incomingPoint ?
51โˆ’
52โˆ’ return Just(
53โˆ’ azimuth.ecliptic.transferPoint(
54โˆ’ validContracts,
55โˆ’ validPoint,
56โˆ’ state.receivingAddress,
57โˆ’ true
58โˆ’ )
59โˆ’ );
60โˆ’ }
61โˆ’
62โˆ’ render() {
63โˆ’ const { state, props } = this;
64โˆ’ const validAddress = isValidAddress(state.receivingAddress);
65โˆ’ const canGenerate = validAddress === true;
66โˆ’
67โˆ’ const esvisible =
68โˆ’ props.networkType === NETWORK_TYPES.ROPSTEN ||
69โˆ’ props.networkType === NETWORK_TYPES.MAINNET;
70โˆ’
71โˆ’ const esdomain =
72โˆ’ props.networkType === NETWORK_TYPES.ROPSTEN
73โˆ’ ? 'ropsten.etherscan.io'
74โˆ’ : 'etherscan.io';
75โˆ’
76โˆ’ return (
77โˆ’ <View>
78โˆ’ <H1>
79โˆ’ {'Accept Transfer of '}{' '}
80โˆ’ <code>{` ${ob.patp(state.incomingPoint)} `}</code>
81โˆ’ </H1>
82โˆ’
83โˆ’ <P>
84โˆ’ {"By default, the recipient is the address you're logged in " +
85โˆ’ 'as. But you can transfer to any address you like.'}
86โˆ’ </P>
87โˆ’
88โˆ’ <AddressInput
89โˆ’ className="mono mt-8"
90โˆ’ prop-size="lg"
91โˆ’ prop-format="innerLabel"
92โˆ’ value={state.receivingAddress}
93โˆ’ onChange={v => this.handleAddressInput(v)}>
94โˆ’ <InnerLabel>{'Receiving Address'}</InnerLabel>
95โˆ’ <ShowBlockie className={'mt-1'} address={state.receivingAddress} />
96โˆ’ </AddressInput>
97โˆ’
98โˆ’ <Anchor
99โˆ’ className={'mt-1 sm'}
100โˆ’ prop-size="sm"
101โˆ’ prop-disabled={!isValidAddress(state.receivingAddress) || !esvisible}
102โˆ’ target={'_blank'}
103โˆ’ href={`https://${esdomain}/address/${state.receivingAddress}`}>
104โˆ’ {'View on Etherscan โ†—'}
105โˆ’ </Anchor>
106โˆ’
107โˆ’ <StatelessTransaction
108โˆ’ canGenerate={canGenerate}
109โˆ’ createUnsignedTxn={this.createUnsignedTxn}
110โˆ’ ref={this.statelessRef}
111โˆ’ />
112โˆ’ </View>
113โˆ’ );
114โˆ’ }
115โˆ’}
116โˆ’
117โˆ’export default compose(
118โˆ’ withNetwork,
119โˆ’ withWallet,
120โˆ’ withPointCursor
121โˆ’)(AcceptTransfer);
src/views/CancelTransfer.jsdeletedโˆ’81
@@ -1,81 +0,0 @@
1โˆ’import React from 'react';
2โˆ’import { Just } from 'folktale/maybe';
3โˆ’import * as azimuth from 'azimuth-js';
4โˆ’import * as ob from 'urbit-ob';
5โˆ’
6โˆ’import { H1, P } from '../components/old/Base';
7โˆ’import * as need from '../lib/need';
8โˆ’
9โˆ’import StatelessTransaction from '../components/old/StatelessTransaction';
10โˆ’import { ETH_ZERO_ADDR } from '../lib/wallet';
11โˆ’import { withNetwork } from '../store/network';
12โˆ’import { compose } from '../lib/lib';
13โˆ’import { withPointCursor } from '../store/pointCursor';
14โˆ’import { withPointCache } from '../store/pointCache';
15โˆ’import View from 'components/View';
16โˆ’
17โˆ’class CancelTransfer extends React.Component {
18โˆ’ constructor(props) {
19โˆ’ super(props);
20โˆ’
21โˆ’ const pointInTransfer = need.point(props.pointCursor);
22โˆ’
23โˆ’ this.state = {
24โˆ’ proxyAddress: '',
25โˆ’ pointInTransfer: pointInTransfer,
26โˆ’ };
27โˆ’
28โˆ’ this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
29โˆ’ }
30โˆ’
31โˆ’ createUnsignedTxn() {
32โˆ’ const { props } = this;
33โˆ’
34โˆ’ const validContracts = need.contracts(props.contracts);
35โˆ’ const validPoint = need.point(props.pointCursor);
36โˆ’ //TODO this.state.pointInTransfer ?
37โˆ’
38โˆ’ const txn = azimuth.ecliptic.setTransferProxy(
39โˆ’ validContracts,
40โˆ’ validPoint,
41โˆ’ ETH_ZERO_ADDR
42โˆ’ );
43โˆ’
44โˆ’ return Just(txn);
45โˆ’ }
46โˆ’
47โˆ’ render() {
48โˆ’ const { props, state } = this;
49โˆ’
50โˆ’ const online = Just.hasInstance(props.web3);
51โˆ’
52โˆ’ const proxy = online
53โˆ’ ? props.pointCache[state.pointInTransfer].transferProxy
54โˆ’ : 'any outgoing addresses';
55โˆ’
56โˆ’ // const canGenerate = validAddress === true
57โˆ’
58โˆ’ const canGenerate = true;
59โˆ’
60โˆ’ return (
61โˆ’ <View>
62โˆ’ <H1>
63โˆ’ {'Cancel Transfer of '}{' '}
64โˆ’ <code>{` ${ob.patp(state.pointInTransfer)} `}</code>
65โˆ’ </H1>
66โˆ’
67โˆ’ <P>{`This action will cancel the transfer to ${proxy}.`}</P>
68โˆ’ <StatelessTransaction
69โˆ’ canGenerate={canGenerate}
70โˆ’ createUnsignedTxn={this.createUnsignedTxn}
71โˆ’ />
72โˆ’ </View>
73โˆ’ );
74โˆ’ }
75โˆ’}
76โˆ’
77โˆ’export default compose(
78โˆ’ withNetwork,
79โˆ’ withPointCursor,
80โˆ’ withPointCache
81โˆ’)(CancelTransfer);
src/views/InvitesManage.jsdeletedโˆ’185
@@ -1,185 +0,0 @@
1โˆ’import { Just, Nothing } from 'folktale/maybe';
2โˆ’import React from 'react';
3โˆ’import * as ob from 'urbit-ob';
4โˆ’import * as azimuth from 'azimuth-js';
5โˆ’import * as need from '../lib/need';
6โˆ’
7โˆ’import {
8โˆ’ Warning,
9โˆ’ Input,
10โˆ’ PointInput,
11โˆ’ InnerLabel,
12โˆ’ ValidatedSigil,
13โˆ’} from '../components/old/Base';
14โˆ’import StatelessTransaction from '../components/old/StatelessTransaction';
15โˆ’import { withNetwork } from '../store/network';
16โˆ’import { compose } from '../lib/lib';
17โˆ’import { withPointCursor } from '../store/pointCursor';
18โˆ’import View from 'components/View';
19โˆ’
20โˆ’class InvitesManage extends React.Component {
21โˆ’ constructor(props) {
22โˆ’ super(props);
23โˆ’
24โˆ’ this.state = {
25โˆ’ invitesWillWork: Nothing(),
26โˆ’ planetInput: '',
27โˆ’ targetPlanet: Nothing(),
28โˆ’ currentPoolSize: Nothing(),
29โˆ’ cachedPoolSizes: {},
30โˆ’ targetPoolSize: 5,
31โˆ’ };
32โˆ’
33โˆ’ this.checkCurrentInvites = this.checkCurrentInvites.bind(this);
34โˆ’ this.handlePointInput = this.handlePointInput.bind(this);
35โˆ’ this.updatePoolSize = this.updatePoolSize.bind(this);
36โˆ’ this.handlePoolSizeInput = this.handlePoolSizeInput.bind(this);
37โˆ’ this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
38โˆ’ this.statelessRef = React.createRef();
39โˆ’ }
40โˆ’
41โˆ’ componentDidMount() {
42โˆ’ this.point = need.point(this.props.pointCursor);
43โˆ’ this.contracts = need.contracts(this.props.contracts);
44โˆ’
45โˆ’ azimuth.azimuth
46โˆ’ .isSpawnProxy(
47โˆ’ this.contracts,
48โˆ’ this.point,
49โˆ’ this.contracts.delegatedSending.address
50โˆ’ )
51โˆ’ .then(isSpawnProxy => {
52โˆ’ this.setState({ invitesWillWork: Just(isSpawnProxy) });
53โˆ’ });
54โˆ’ }
55โˆ’
56โˆ’ componentDidUpdate(prevProps) {
57โˆ’ //
58โˆ’ }
59โˆ’
60โˆ’ handlePointInput(targetPlanet) {
61โˆ’ let newState = {
62โˆ’ targetPlanet: Nothing(),
63โˆ’ planetInput: targetPlanet,
64โˆ’ canGenerate: false,
65โˆ’ currentPoolSize: Nothing(),
66โˆ’ };
67โˆ’ if (targetPlanet.length === 14 && ob.isValidPatp(targetPlanet)) {
68โˆ’ const target = ob.patp2dec(targetPlanet);
69โˆ’ //TODO there must be a simpler way to do this check
70โˆ’ const isChild = ob.sein(targetPlanet) === ob.patp(this.point);
71โˆ’ if (isChild) {
72โˆ’ newState.targetPlanet = Just(target);
73โˆ’ newState.currentPoolSize = this.checkCurrentInvites(target);
74โˆ’ newState.canGenerate = true;
75โˆ’ }
76โˆ’ }
77โˆ’ this.setState(newState);
78โˆ’ }
79โˆ’
80โˆ’ checkCurrentInvites(who) {
81โˆ’ const cachedPoolSizes = this.state.cachedPoolSizes;
82โˆ’ if (typeof cachedPoolSizes[who] !== 'undefined') {
83โˆ’ return Just(cachedPoolSizes[who]);
84โˆ’ } else {
85โˆ’ azimuth.delegatedSending.getPool(this.contracts, who).then(pool => {
86โˆ’ azimuth.delegatedSending
87โˆ’ .invitesInPool(this.contracts, pool, this.point)
88โˆ’ .then(size => {
89โˆ’ this.updatePoolSize(who, size);
90โˆ’ });
91โˆ’ });
92โˆ’ return Nothing();
93โˆ’ }
94โˆ’ }
95โˆ’
96โˆ’ updatePoolSize(who, size) {
97โˆ’ const cache = this.state.cachedPoolSizes;
98โˆ’ cache[who] = size;
99โˆ’ this.setState({ cachedPoolSizes: cache });
100โˆ’ const target = this.state.targetPlanet;
101โˆ’ const match = Just.hasInstance(target) ? who === target.value : false;
102โˆ’ if (match) {
103โˆ’ this.setState({ currentPoolSize: Just(size) });
104โˆ’ }
105โˆ’ }
106โˆ’
107โˆ’ handlePoolSizeInput(targetSize) {
108โˆ’ this.setState({ targetPoolSize: targetSize });
109โˆ’ }
110โˆ’
111โˆ’ createUnsignedTxn() {
112โˆ’ return Just(
113โˆ’ azimuth.delegatedSending.setPoolSize(
114โˆ’ this.contracts,
115โˆ’ this.point,
116โˆ’ this.state.targetPlanet.value,
117โˆ’ this.state.targetPoolSize
118โˆ’ )
119โˆ’ );
120โˆ’ }
121โˆ’
122โˆ’ render() {
123โˆ’ let spawnProxyWarning = null;
124โˆ’ if (this.state.invitesWillWork.value === false) {
125โˆ’ spawnProxyWarning = (
126โˆ’ <Warning>
127โˆ’ <h3 className={'mb-2'}>{'Warning'}</h3>
128โˆ’ {'Planets under this star will not be able to send invites ' +
129โˆ’ 'until the invite contract ('}
130โˆ’ <code>{this.contracts.delegatedSending.address}</code>
131โˆ’ {') is made spawn proxy for this star.'}
132โˆ’ </Warning>
133โˆ’ );
134โˆ’ }
135โˆ’
136โˆ’ let poolSizeText = this.state.currentPoolSize.matchWith({
137โˆ’ Just: ps => `(currently ${ps.value})`,
138โˆ’ Nothing: _ => '',
139โˆ’ });
140โˆ’
141โˆ’ return (
142โˆ’ <View>
143โˆ’ <p>
144โˆ’ {
145โˆ’ 'manage invites here, for stars. can only give invites to child planets'
146โˆ’ }
147โˆ’ </p>
148โˆ’
149โˆ’ {spawnProxyWarning}
150โˆ’
151โˆ’ <PointInput
152โˆ’ prop-format="innerlabel"
153โˆ’ prop-size="lg"
154โˆ’ placeholder={'~sampel-sipnem'}
155โˆ’ value={this.state.planetInput}
156โˆ’ onChange={this.handlePointInput}>
157โˆ’ <InnerLabel>{'Planet to set invites for'}</InnerLabel>
158โˆ’ <ValidatedSigil
159โˆ’ patp={this.state.targetPlanet}
160โˆ’ validator={() => this.validatePoint}
161โˆ’ />
162โˆ’ </PointInput>
163โˆ’
164โˆ’ <Input
165โˆ’ prop-format="innerlabel"
166โˆ’ prop-size="lg"
167โˆ’ value={this.state.targetPoolSize}
168โˆ’ onChange={this.handlePoolSizeInput}>
169โˆ’ <InnerLabel>{`Available invites ${poolSizeText}`}</InnerLabel>
170โˆ’ </Input>
171โˆ’
172โˆ’ <StatelessTransaction
173โˆ’ canGenerate={this.state.canGenerate}
174โˆ’ createUnsignedTxn={this.createUnsignedTxn}
175โˆ’ ref={this.statelessRef}
176โˆ’ />
177โˆ’ </View>
178โˆ’ );
179โˆ’ }
180โˆ’}
181โˆ’
182โˆ’export default compose(
183โˆ’ withNetwork,
184โˆ’ withPointCursor
185โˆ’)(InvitesManage);
src/views/SentTransaction.jsdeletedโˆ’172
@@ -1,172 +0,0 @@
1โˆ’import React from 'react';
2โˆ’import * as need from '../lib/need';
3โˆ’import { H1, H3, P, Warning, Anchor } from '../components/old/Base';
4โˆ’import { Button } from '../components/old/Base';
5โˆ’
6โˆ’import { ROUTE_NAMES } from '../lib/routeNames';
7โˆ’import { useHistory } from '../store/history';
8โˆ’import { BRIDGE_ERROR, renderTxnError } from '../lib/error';
9โˆ’import { NETWORK_TYPES } from '../lib/network';
10โˆ’import { useNetwork } from '../store/network';
11โˆ’import { useTxnCursor } from '../store/txnCursor';
12โˆ’import View from 'components/View';
13โˆ’import { Grid } from 'indigo-react';
14โˆ’
15โˆ’class Success extends React.Component {
16โˆ’ constructor(props) {
17โˆ’ super(props);
18โˆ’
19โˆ’ this.state = {
20โˆ’ pending: '.',
21โˆ’ interval: null,
22โˆ’ };
23โˆ’ }
24โˆ’
25โˆ’ componentDidMount() {
26โˆ’ const nextDot = { '.': '..', '..': '...', '...': '.' };
27โˆ’
28โˆ’ const interval = setInterval(() => {
29โˆ’ this.setState(({ pending }) => ({ pending: nextDot[pending] }));
30โˆ’ }, 1000);
31โˆ’ this.setState({ interval: interval });
32โˆ’ }
33โˆ’
34โˆ’ componentWillUnmount() {
35โˆ’ clearInterval(this.state.interval);
36โˆ’ }
37โˆ’
38โˆ’ render() {
39โˆ’ const { props, state } = this;
40โˆ’ const { networkType, hash } = props;
41โˆ’ const { pending } = state;
42โˆ’
43โˆ’ const esvisible =
44โˆ’ networkType === NETWORK_TYPES.ROPSTEN ||
45โˆ’ networkType === NETWORK_TYPES.MAINNET;
46โˆ’
47โˆ’ const esdomain =
48โˆ’ networkType === NETWORK_TYPES.ROPSTEN
49โˆ’ ? 'ropsten.etherscan.io'
50โˆ’ : 'etherscan.io';
51โˆ’
52โˆ’ const esmessage =
53โˆ’ esvisible === true
54โˆ’ ? 'If youโ€™d like to keep track of it, click the Etherscan link below.'
55โˆ’ : '';
56โˆ’
57โˆ’ const esanchor =
58โˆ’ esvisible === false ? null : (
59โˆ’ <Anchor
60โˆ’ className={'mb-4 mt-1'}
61โˆ’ prop-size={'sm'}
62โˆ’ target={'_blank'}
63โˆ’ href={`https://${esdomain}/tx/${hash}`}>
64โˆ’ {'View on Etherscan โ†—'}
65โˆ’ </Anchor>
66โˆ’ );
67โˆ’
68โˆ’ const confirmations = 1;
69โˆ’
70โˆ’ const requiredConfirmations = 1;
71โˆ’
72โˆ’ const status =
73โˆ’ confirmations < requiredConfirmations
74โˆ’ ? `Pending${pending}`
75โˆ’ : `Confirmed! (x${confirmations} confirmations)!`;
76โˆ’
77โˆ’ return (
78โˆ’ <Grid>
79โˆ’ <Grid.Item full>
80โˆ’ <H1>{'Your Transaction was Sent'}</H1>
81โˆ’
82โˆ’ <P>
83โˆ’ {`We sent your transaction to the chain. It can take some time to
84โˆ’ execute, especially if the network is busy. ${esmessage}`}
85โˆ’ </P>
86โˆ’
87โˆ’ <H3>{'Transaction Hash'}</H3>
88โˆ’ <P>{hash}</P>
89โˆ’
90โˆ’ <H3>{'Transaction Status'}</H3>
91โˆ’ <P>{status}</P>
92โˆ’ <P>{esanchor}</P>
93โˆ’ </Grid.Item>
94โˆ’ </Grid>
95โˆ’ );
96โˆ’ }
97โˆ’}
98โˆ’
99โˆ’const Failure = props => (
100โˆ’ <Grid>
101โˆ’ <Grid.Item full>
102โˆ’ <H1>{'Error!'}</H1>
103โˆ’
104โˆ’ <Warning>
105โˆ’ <H3>{'There was an error sending your transaction.'}</H3>
106โˆ’ {renderTxnError(props.web3, props.message)}
107โˆ’ </Warning>
108โˆ’ </Grid.Item>
109โˆ’ </Grid>
110โˆ’);
111โˆ’
112โˆ’function SentTransaction(props) {
113โˆ’ const history = useHistory();
114โˆ’ const { web3, networkType } = useNetwork();
115โˆ’ const { txnCursor } = useTxnCursor();
116โˆ’
117โˆ’ const promptKeyfile = history.data && history.data.promptKeyfile;
118โˆ’
119โˆ’ const w3 = need.web3(web3);
120โˆ’
121โˆ’ const result = txnCursor.matchWith({
122โˆ’ Nothing: _ => {
123โˆ’ throw new Error(BRIDGE_ERROR.MISSING_TXN);
124โˆ’ },
125โˆ’ Just: res => res.value,
126โˆ’ });
127โˆ’
128โˆ’ const body = result.matchWith({
129โˆ’ Error: message => <Failure web3={w3} message={message.value} />,
130โˆ’ Ok: hash => <Success hash={hash.value} networkType={networkType} />,
131โˆ’ });
132โˆ’
133โˆ’ const ok = (
134โˆ’ <Grid>
135โˆ’ <Grid.Item full>
136โˆ’ <Button
137โˆ’ prop-type={'link'}
138โˆ’ onClick={() => {
139โˆ’ history.pop();
140โˆ’ }}>
141โˆ’ {'Ok โ†’'}
142โˆ’ </Button>
143โˆ’ </Grid.Item>
144โˆ’ </Grid>
145โˆ’ );
146โˆ’
147โˆ’ let keyfile;
148โˆ’
149โˆ’ if (promptKeyfile) {
150โˆ’ keyfile = (
151โˆ’ <Grid>
152โˆ’ <Grid.Item full>
153โˆ’ <Button
154โˆ’ prop-type={'link'}
155โˆ’ onClick={() => history.popAndPush(ROUTE_NAMES.GEN_KEYFILE)}>
156โˆ’ {'Download Keyfile โ†’'}
157โˆ’ </Button>
158โˆ’ </Grid.Item>
159โˆ’ </Grid>
160โˆ’ );
161โˆ’ }
162โˆ’
163โˆ’ return (
164โˆ’ <View>
165โˆ’ {body}
166โˆ’ {ok}
167โˆ’ {keyfile}
168โˆ’ </View>
169โˆ’ );
170โˆ’}
171โˆ’
172โˆ’export default SentTransaction;
src/views/SetKeys.jsdeletedโˆ’210
@@ -1,210 +0,0 @@
1โˆ’import React from 'react';
2โˆ’import { Just, Nothing } from 'folktale/maybe';
3โˆ’import * as azimuth from 'azimuth-js';
4โˆ’import * as ob from 'urbit-ob';
5โˆ’import * as need from '../lib/need';
6โˆ’import * as kg from 'urbit-key-generation/dist';
7โˆ’import { H1, P, Warning, CheckboxButton } from '../components/old/Base';
8โˆ’
9โˆ’import StatelessTransaction from '../components/old/StatelessTransaction';
10โˆ’import { attemptNetworkSeedDerivation } from '../lib/keys';
11โˆ’
12โˆ’import { addHexPrefix } from '../lib/wallet';
13โˆ’import { compose } from '../lib/lib';
14โˆ’
15โˆ’import { withNetwork } from '../store/network';
16โˆ’import { withWallet } from '../store/wallet';
17โˆ’import { withPointCursor } from '../store/pointCursor';
18โˆ’import { withPointCache } from '../store/pointCache';
19โˆ’import View from 'components/View';
20โˆ’
21โˆ’class SetKeys extends React.Component {
22โˆ’ constructor(props) {
23โˆ’ super(props);
24โˆ’
25โˆ’ const point = need.point(props.pointCursor);
26โˆ’
27โˆ’ this.state = {
28โˆ’ auth: '',
29โˆ’ encr: '',
30โˆ’ newNetworkSeed: '',
31โˆ’ nondeterministicSeed: false,
32โˆ’ point: point,
33โˆ’ cryptoSuiteVersion: 1,
34โˆ’ discontinuity: false,
35โˆ’ isManagementSeed: false,
36โˆ’ };
37โˆ’
38โˆ’ this.toggleDiscontinuity = this.toggleDiscontinuity.bind(this);
39โˆ’ // Transaction
40โˆ’ this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
41โˆ’ }
42โˆ’
43โˆ’ toggleDiscontinuity() {
44โˆ’ this.setState({ discontinuity: !this.state.discontinuity });
45โˆ’ }
46โˆ’
47โˆ’ componentDidMount() {
48โˆ’ const { props } = this;
49โˆ’
50โˆ’ this.deriveSeed();
51โˆ’
52โˆ’ const addr = need.addressFromWallet(props.wallet);
53โˆ’
54โˆ’ this.determineManagementSeed(props.contracts.value, addr);
55โˆ’ }
56โˆ’
57โˆ’ async determineManagementSeed(ctrcs, addr) {
58โˆ’ const managing = await azimuth.azimuth.getManagerFor(ctrcs, addr);
59โˆ’
60โˆ’ this.setState({
61โˆ’ isManagementSeed: managing.length !== 0,
62โˆ’ });
63โˆ’ }
64โˆ’
65โˆ’ //TODO use web3.utils.randomHex when it gets fixed, see web3.js#1490
66โˆ’ randomHex(len) {
67โˆ’ let hex = '';
68โˆ’
69โˆ’ for (var i = 0; i < len; i++) {
70โˆ’ hex =
71โˆ’ hex +
72โˆ’ [
73โˆ’ '0',
74โˆ’ '1',
75โˆ’ '2',
76โˆ’ '3',
77โˆ’ '4',
78โˆ’ '5',
79โˆ’ '6',
80โˆ’ '7',
81โˆ’ '8',
82โˆ’ '9',
83โˆ’ 'A',
84โˆ’ 'B',
85โˆ’ 'C',
86โˆ’ 'D',
87โˆ’ 'E',
88โˆ’ 'F',
89โˆ’ ][Math.floor(Math.random() * 16)];
90โˆ’ }
91โˆ’
92โˆ’ return hex;
93โˆ’ }
94โˆ’
95โˆ’ async deriveSeed() {
96โˆ’ const next = true;
97โˆ’ let nondeterministicSeed = false;
98โˆ’
99โˆ’ const seed = await attemptNetworkSeedDerivation(next, this.props);
100โˆ’ const newNetworkSeed = seed.matchWith({
101โˆ’ Nothing: () => {
102โˆ’ nondeterministicSeed = true;
103โˆ’ return this.randomHex(64);
104โˆ’ },
105โˆ’ Just: p => p.value,
106โˆ’ });
107โˆ’
108โˆ’ this.setState({
109โˆ’ newNetworkSeed,
110โˆ’ nondeterministicSeed,
111โˆ’ });
112โˆ’ }
113โˆ’
114โˆ’ createUnsignedTxn() {
115โˆ’ const { state, props } = this;
116โˆ’
117โˆ’ const validContracts = need.contracts(props.contracts);
118โˆ’ const validPoint = need.point(props.pointCursor);
119โˆ’
120โˆ’ // TODO: move this to a lib for validating things
121โˆ’ const hexRegExp = /[0-9A-Fa-f]{64}/g;
122โˆ’
123โˆ’ if (hexRegExp.test(state.newNetworkSeed)) {
124โˆ’ // derive network keys
125โˆ’ const pair = kg.deriveNetworkKeys(state.newNetworkSeed);
126โˆ’
127โˆ’ const pencr = addHexPrefix(pair.crypt.public);
128โˆ’ const pauth = addHexPrefix(pair.auth.public);
129โˆ’
130โˆ’ const txn = azimuth.ecliptic.configureKeys(
131โˆ’ validContracts,
132โˆ’ validPoint,
133โˆ’ pencr,
134โˆ’ pauth,
135โˆ’ 1,
136โˆ’ state.discontinuity
137โˆ’ );
138โˆ’
139โˆ’ return Just(txn);
140โˆ’ }
141โˆ’
142โˆ’ return Nothing();
143โˆ’ }
144โˆ’
145โˆ’ render() {
146โˆ’ const { props, state } = this;
147โˆ’
148โˆ’ const canGenerate =
149โˆ’ state.newNetworkSeed.length === 64 && state.newNetworkSeed.length === 64;
150โˆ’
151โˆ’ const pointDetails = need.fromPointCache(props.pointCache, state.point);
152โˆ’
153โˆ’ return (
154โˆ’ <View>
155โˆ’ <H1>
156โˆ’ {'Set Network Keys For '} <code>{`${ob.patp(state.point)}`}</code>
157โˆ’ </H1>
158โˆ’
159โˆ’ <P className="mt-10">
160โˆ’ {`Set new authentication and encryption keys for your Arvo ship.`}
161โˆ’ </P>
162โˆ’
163โˆ’ {state.nondeterministicSeed && (
164โˆ’ <Warning>
165โˆ’ <h3 className={'mb-2'}>{'Warning'}</h3>
166โˆ’ {`Your network seed could not be derived automatically. We've
167โˆ’ generated a random one for you, so you must download your Arvo
168โˆ’ keyfile during this session after setting your keys.`}
169โˆ’ </Warning>
170โˆ’ )}
171โˆ’
172โˆ’ {pointDetails.keyRevisionNumber === 0 ? (
173โˆ’ <Warning>
174โˆ’ <h3 className={'mb-2'}>{'Warning'}</h3>
175โˆ’ {'Once these keys have been set, your point is considered ' +
176โˆ’ "'linked'. This operation cannot be undone."}
177โˆ’ </Warning>
178โˆ’ ) : (
179โˆ’ <div />
180โˆ’ )}
181โˆ’
182โˆ’ <CheckboxButton
183โˆ’ className="mt-8"
184โˆ’ onToggle={this.toggleDiscontinuity}
185โˆ’ state={state.discontinuity}
186โˆ’ label={`I have lost important off-chain data relating to this point
187โˆ’ and need to do a hard reset.
188โˆ’ (For example, rebooting an Arvo ship.)`}
189โˆ’ />
190โˆ’
191โˆ’ <StatelessTransaction
192โˆ’ // Upper scope
193โˆ’ {...props}
194โˆ’ // Tx
195โˆ’ canGenerate={canGenerate}
196โˆ’ createUnsignedTxn={this.createUnsignedTxn}
197โˆ’ newNetworkSeed={state.newNetworkSeed}
198โˆ’ newRevision={parseInt(pointDetails.keyRevisionNumber) + 1}
199โˆ’ />
200โˆ’ </View>
201โˆ’ );
202โˆ’ }
203โˆ’}
204โˆ’
205โˆ’export default compose(
206โˆ’ withNetwork,
207โˆ’ withWallet,
208โˆ’ withPointCursor,
209โˆ’ withPointCache
210โˆ’)(SetKeys);
src/views/SetProxy.jsdeletedโˆ’181
@@ -1,181 +0,0 @@
1โˆ’import React from 'react';
2โˆ’import { Just, Nothing } from 'folktale/maybe';
3โˆ’import * as need from '../lib/need';
4โˆ’import * as azimuth from 'azimuth-js';
5โˆ’import {
6โˆ’ H1,
7โˆ’ P,
8โˆ’ InnerLabel,
9โˆ’ ShowBlockie,
10โˆ’ Anchor,
11โˆ’ HorizontalSelector,
12โˆ’} from '../components/old/Base';
13โˆ’import { AddressInput } from '../components/old/Base';
14โˆ’import * as ob from 'urbit-ob';
15โˆ’
16โˆ’import { PROXY_TYPE } from '../lib/proxy';
17โˆ’
18โˆ’import { NETWORK_TYPES } from '../lib/network';
19โˆ’
20โˆ’import StatelessTransaction from '../components/old/StatelessTransaction';
21โˆ’
22โˆ’import { isValidAddress } from '../lib/wallet';
23โˆ’import { withNetwork } from '../store/network';
24โˆ’import { compose } from '../lib/lib';
25โˆ’import { withPointCursor } from '../store/pointCursor';
26โˆ’import View from 'components/View';
27โˆ’
28โˆ’class _SetProxy extends React.Component {
29โˆ’ constructor(props) {
30โˆ’ super(props);
31โˆ’
32โˆ’ const issuingPoint = need.point(props.pointCursor);
33โˆ’
34โˆ’ this.state = {
35โˆ’ proxyAddress: '',
36โˆ’ issuingPoint: issuingPoint,
37โˆ’ setProxy: true,
38โˆ’ };
39โˆ’
40โˆ’ this.statelessRef = React.createRef();
41โˆ’ this.handleSetUnset = this.handleSetUnset.bind(this);
42โˆ’ this.handleAddressInput = this.handleAddressInput.bind(this);
43โˆ’ this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
44โˆ’ }
45โˆ’
46โˆ’ handleSetUnset(selected) {
47โˆ’ const set = selected === 'set';
48โˆ’ this.setState({
49โˆ’ setProxy: set,
50โˆ’ proxyAddress: set ? '' : '0x0000000000000000000000000000000000000000',
51โˆ’ });
52โˆ’ }
53โˆ’
54โˆ’ handleAddressInput(proxyAddress) {
55โˆ’ this.setState({ proxyAddress });
56โˆ’
57โˆ’ this.statelessRef.current.clearTxn();
58โˆ’ }
59โˆ’
60โˆ’ createUnsignedTxn(proxyAddress) {
61โˆ’ const { state, props } = this;
62โˆ’
63โˆ’ const validContracts = need.contracts(props.contracts);
64โˆ’ const validPoint = need.point(props.pointCursor);
65โˆ’
66โˆ’ const txArgs = [validContracts, validPoint, state.proxyAddress];
67โˆ’
68โˆ’ if (props.proxyType === PROXY_TYPE.TRANSFER_PROXY) {
69โˆ’ return Just(azimuth.ecliptic.setTransferProxy(...txArgs));
70โˆ’ }
71โˆ’
72โˆ’ if (props.proxyType === PROXY_TYPE.SPAWN_PROXY) {
73โˆ’ return Just(azimuth.ecliptic.setSpawnProxy(...txArgs));
74โˆ’ }
75โˆ’
76โˆ’ if (props.proxyType === PROXY_TYPE.MANAGEMENT_PROXY) {
77โˆ’ return Just(azimuth.ecliptic.setManagementProxy(...txArgs));
78โˆ’ }
79โˆ’
80โˆ’ return Nothing();
81โˆ’ }
82โˆ’
83โˆ’ render() {
84โˆ’ const { props, state } = this;
85โˆ’
86โˆ’ const renderedProxyType = props.proxyType.toString();
87โˆ’ const validAddress = isValidAddress(state.proxyAddress);
88โˆ’ const canGenerate = validAddress === true;
89โˆ’
90โˆ’ const esvisible =
91โˆ’ props.networkType === NETWORK_TYPES.ROPSTEN ||
92โˆ’ props.networkType === NETWORK_TYPES.MAINNET;
93โˆ’
94โˆ’ const esdomain =
95โˆ’ props.networkType === NETWORK_TYPES.ROPSTEN
96โˆ’ ? 'ropsten.etherscan.io'
97โˆ’ : 'etherscan.io';
98โˆ’
99โˆ’ const ucFirst = w => w.charAt(0).toUpperCase() + w.slice(1);
100โˆ’
101โˆ’ const setUnset = [
102โˆ’ { title: 'Set', value: 'set' },
103โˆ’ { title: 'Unset', value: 'unset' },
104โˆ’ ];
105โˆ’
106โˆ’ const titleVerb = this.state.setProxy ? 'Set' : 'Unset';
107โˆ’
108โˆ’ let addressInput = null;
109โˆ’ if (this.state.setProxy) {
110โˆ’ addressInput = (
111โˆ’ <>
112โˆ’ <P className="mt-8">
113โˆ’ {'Please provide an Ethereum address to act as the ' +
114โˆ’ `${renderedProxyType} proxy. You can also use Wallet ` +
115โˆ’ 'Generator to generate a keypair.'}
116โˆ’ </P>
117โˆ’
118โˆ’ <AddressInput
119โˆ’ className="mono mt-8"
120โˆ’ prop-size="lg"
121โˆ’ prop-format="innerLabel"
122โˆ’ placeholder={`e.g. 0x84295d5e054d8cff5a22428b195f5a1615bd644f`}
123โˆ’ value={state.proxyAddress}
124โˆ’ onChange={v => this.handleAddressInput(v)}>
125โˆ’ <InnerLabel>{'Proxy Address'}</InnerLabel>
126โˆ’ <ShowBlockie className={'mt-1'} address={state.proxyAddress} />
127โˆ’ </AddressInput>
128โˆ’
129โˆ’ <Anchor
130โˆ’ className={'mt-1'}
131โˆ’ prop-size={'sm'}
132โˆ’ prop-disabled={!isValidAddress(state.proxyAddress) || !esvisible}
133โˆ’ target={'_blank'}
134โˆ’ href={`https://${esdomain}/address/${state.proxyAddress}`}>
135โˆ’ {'View on Etherscan โ†—'}
136โˆ’ </Anchor>
137โˆ’ </>
138โˆ’ );
139โˆ’ }
140โˆ’
141โˆ’ return (
142โˆ’ <View>
143โˆ’ <H1>
144โˆ’ {`${titleVerb} ${ucFirst(renderedProxyType)} Proxy For `}
145โˆ’ <code>{`${ob.patp(state.issuingPoint)}`}</code>
146โˆ’ </H1>
147โˆ’
148โˆ’ <HorizontalSelector
149โˆ’ options={setUnset}
150โˆ’ onChange={this.handleSetUnset}
151โˆ’ className="mt-8"
152โˆ’ />
153โˆ’
154โˆ’ {addressInput}
155โˆ’
156โˆ’ <StatelessTransaction
157โˆ’ ref={this.statelessRef}
158โˆ’ createUnsignedTxn={this.createUnsignedTxn}
159โˆ’ canGenerate={canGenerate}
160โˆ’ />
161โˆ’ </View>
162โˆ’ );
163โˆ’ }
164โˆ’}
165โˆ’
166โˆ’const SetProxy = compose(
167โˆ’ withNetwork,
168โˆ’ withPointCursor
169โˆ’)(_SetProxy);
170โˆ’
171โˆ’export const SetManagementProxy = props => (
172โˆ’ <SetProxy {...props} proxyType={PROXY_TYPE.MANAGEMENT_PROXY} />
173โˆ’);
174โˆ’
175โˆ’export const SetSpawnProxy = props => (
176โˆ’ <SetProxy {...props} proxyType={PROXY_TYPE.SPAWN_PROXY} />
177โˆ’);
178โˆ’
179โˆ’export const SetTransferProxy = props => (
180โˆ’ <SetProxy {...props} proxyType={PROXY_TYPE.TRANSFER_PROXY} />
181โˆ’);
src/views/Transfer.jsdeletedโˆ’127
@@ -1,127 +0,0 @@
1โˆ’import React from 'react';
2โˆ’import { Just } from 'folktale/maybe';
3โˆ’import * as azimuth from 'azimuth-js';
4โˆ’import * as ob from 'urbit-ob';
5โˆ’import * as need from '../lib/need';
6โˆ’
7โˆ’import { H1, InnerLabel, ShowBlockie, P, Anchor } from '../components/old/Base';
8โˆ’import { AddressInput } from '../components/old/Base';
9โˆ’import StatelessTransaction from '../components/old/StatelessTransaction';
10โˆ’
11โˆ’import { NETWORK_TYPES } from '../lib/network';
12โˆ’
13โˆ’import { isValidAddress } from '../lib/wallet';
14โˆ’import { withNetwork } from '../store/network';
15โˆ’import { compose } from '../lib/lib';
16โˆ’import { withPointCursor } from '../store/pointCursor';
17โˆ’import View from 'components/View';
18โˆ’
19โˆ’class Transfer extends React.Component {
20โˆ’ constructor(props) {
21โˆ’ super(props);
22โˆ’
23โˆ’ const issuingPoint = need.point(props.pointCursor);
24โˆ’
25โˆ’ this.state = {
26โˆ’ receivingAddress: '',
27โˆ’ issuingPoint: issuingPoint,
28โˆ’ };
29โˆ’
30โˆ’ this.handleAddressInput = this.handleAddressInput.bind(this);
31โˆ’ this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
32โˆ’ this.statelessRef = React.createRef();
33โˆ’ }
34โˆ’
35โˆ’ handleAddressInput(receivingAddress) {
36โˆ’ this.setState({ receivingAddress });
37โˆ’ this.statelessRef.current.clearTxn();
38โˆ’ }
39โˆ’
40โˆ’ handleConfirmAvailability() {
41โˆ’ this.confirmPointAvailability().then(r => {
42โˆ’ this.setState({ isAvailable: r });
43โˆ’ });
44โˆ’ }
45โˆ’
46โˆ’ createUnsignedTxn() {
47โˆ’ const { state, props } = this;
48โˆ’
49โˆ’ const validContracts = need.contracts(props.contracts);
50โˆ’ const validPoint = need.point(props.pointCursor);
51โˆ’
52โˆ’ const txn = azimuth.ecliptic.setTransferProxy(
53โˆ’ validContracts,
54โˆ’ validPoint,
55โˆ’ state.receivingAddress
56โˆ’ );
57โˆ’
58โˆ’ return Just(txn);
59โˆ’ }
60โˆ’
61โˆ’ render() {
62โˆ’ const { props, state } = this;
63โˆ’
64โˆ’ const validAddress = isValidAddress(state.receivingAddress);
65โˆ’ const canGenerate = validAddress === true;
66โˆ’
67โˆ’ const esvisible =
68โˆ’ props.networkType === NETWORK_TYPES.ROPSTEN ||
69โˆ’ props.networkType === NETWORK_TYPES.MAINNET;
70โˆ’
71โˆ’ const esdomain =
72โˆ’ props.networkType === NETWORK_TYPES.ROPSTEN
73โˆ’ ? 'ropsten.etherscan.io'
74โˆ’ : 'etherscan.io';
75โˆ’
76โˆ’ return (
77โˆ’ <View>
78โˆ’ <H1>
79โˆ’ {'Transfer'} <code>{` ${ob.patp(state.issuingPoint)} `}</code>
80โˆ’ {'To a New Owner'}
81โˆ’ </H1>
82โˆ’
83โˆ’ <P>
84โˆ’ {`Please provide the Ethereum address of the new owner. You own these
85โˆ’ points until the recipient accepts the incoming transfer.
86โˆ’ You may cancel the transfer until the transfer is accepted.`}
87โˆ’ </P>
88โˆ’
89โˆ’ <AddressInput
90โˆ’ className={'mono mt-8'}
91โˆ’ prop-size="lg"
92โˆ’ prop-format="innerLabel"
93โˆ’ value={state.receivingAddress}
94โˆ’ placeholder={`e.g. 0x84295d5e054d8cff5a22428b195f5a1615bd644f`}
95โˆ’ onChange={v => this.handleAddressInput(v)}>
96โˆ’ <InnerLabel>{'New ownership address'}</InnerLabel>
97โˆ’ <ShowBlockie className={'mt-1'} address={state.receivingAddress} />
98โˆ’ </AddressInput>
99โˆ’
100โˆ’ <Anchor
101โˆ’ className={'mt-1'}
102โˆ’ prop-size={'s'}
103โˆ’ prop-disabled={!isValidAddress(state.receivingAddress) || !esvisible}
104โˆ’ target={'_blank'}
105โˆ’ href={`https://${esdomain}/address/${state.receivingAddress}`}>
106โˆ’ {'View on Etherscan โ†—'}
107โˆ’ </Anchor>
108โˆ’
109โˆ’ <StatelessTransaction
110โˆ’ // Upper scope
111โˆ’ {...props}
112โˆ’ // Checks
113โˆ’ userApproval={state.userApproval}
114โˆ’ canGenerate={canGenerate}
115โˆ’ // Methods
116โˆ’ createUnsignedTxn={this.createUnsignedTxn}
117โˆ’ ref={this.statelessRef}
118โˆ’ />
119โˆ’ </View>
120โˆ’ );
121โˆ’ }
122โˆ’}
123โˆ’
124โˆ’export default compose(
125โˆ’ withNetwork,
126โˆ’ withPointCursor
127โˆ’)(Transfer);