@@ -0,0 +1,181 @@
1+import { Nothing, Just } from 'folktale/maybe';
2+import React from 'react';
3+import * as azimuth from 'azimuth-js';
4+import * as ob from 'urbit-ob';
14+} from '../components/Base';
16+import * as need from '../lib/need';
17+import { compose } from '../lib/lib';
18+import { urbitWalletFromTicket } from '../lib/wallet';
19+import { withHistory } from '../store/history';
20+import { withNetwork } from '../store/network';
22+//TODO should be part of InputWithStatus component
23+const INPUT_STATUS = {
24+ SPIN: Symbol('SPIN'),
25+ GOOD: Symbol('GOOD'),
26+ FAIL: Symbol('FAIL'),
29+//TODO support "advances" login methods. design under discussion...
30+class Login extends React.Component {
37+ ticketStatus: Nothing(),
41+ this.handlePointNameInput = this.handlePointNameInput.bind(this);
42+ this.handleTicketInput = this.handleTicketInput.bind(this);
43+ this.verifyTicket = this.verifyTicket.bind(this);
44+ this.continue = this.continue.bind(this);
47+ componentDidMount() {
48+ //TODO deduce point name from URL if we can, prefill input if we found it
50+ // const { networkType, setNetworkType } = useNetwork();
51+ console.log(this.props);
52+ // setNetworkType(this.props.initialNetworkType);
55+ handlePointNameInput(pointName) {
56+ if (pointName.length < 15) {
57+ this.setState({ pointName });
58+ this.verifyTicket(pointName, this.state.ticket);
62+ handleTicketInput(ticket) {
63+ this.setState({ ticket });
64+ this.verifyTicket(this.state.pointName, ticket);
67+ //TODO maybe want to do this only on-go, because wallet derivation is slow...
68+ async verifyTicket(pointName, ticket) {
69+ if (!ob.isValidPatq(ticket) || !ob.isValidPatp(pointName)) {
70+ this.setState({ ticketStatus: Nothing(), wallet: Nothing() });
73+ this.setState({ ticketStatus: Just(INPUT_STATUS.SPIN) });
74+ const contracts = need.contracts(this.props);
75+ const pointNumber = ob.patp2dec(pointName);
76+ const uhdw = await urbitWalletFromTicket(ticket, pointName);
77+ const isOwner = azimuth.azimuth.isOwner(
80+ uhdw.ownership.keys.address
82+ const isTransferProxy = azimuth.azimuth.isTransferProxy(
85+ uhdw.ownership.keys.address
87+ let newState = { wallet: Just(uhdw) };
88+ newState.ticketStatus =
89+ (await isOwner) || (await isTransferProxy)
90+ ? Just(INPUT_STATUS.GOOD)
91+ : Just(INPUT_STATUS.FAIL);
92+ this.setState(newState);
96+ // this is our only requirement, since we still want people with
97+ // non-standard wallet setups to be able to log in
98+ return Just.hasInstance(this.state.wallet);
102+ //TODO slightly different for other login methods
103+ this.props.setUrbitWallet(this.state.wallet);
104+ //TODO history.popAndPush(ROUTE_NAMES.POINT_HOME);
108+ const pointInput = (
110+ className="mono mt-8"
112+ prop-format="innerLabel"
115+ value={this.state.pointName}
116+ onChange={this.handlePointNameInput}>
117+ <InnerLabel>{'Point'}</InnerLabel>
119+ className={'tr-0 mt-05 mr-0 abs'}
120+ patp={this.state.pointName}
127+ const ticketStatus = this.state.ticketStatus.matchWith({
128+ Nothing: () => <span />,
130+ switch (status.value) {
131+ case INPUT_STATUS.SPIN:
132+ return <span>⋯</span>;
133+ case INPUT_STATUS.GOOD:
134+ return <span>✓</span>;
135+ case INPUT_STATUS.FAIL:
136+ return <span>𐄂</span>;
138+ throw new Error('weird input status ' + status.value);
143+ const ticketInput = (
144+ //TODO NewTicketInput component, that does dashes etc
146+ className="mono mt-8"
148+ prop-format="innerLabel"
151+ value={this.state.ticket}
152+ onChange={this.handleTicketInput}>
153+ <InnerLabel>{'Code'}</InnerLabel>
168+ disabled={!this.canContinue()}
169+ onClick={this.continue}>
178+export default compose(