1import React, { useCallback, useMemo, useRef } from 'react';
2import { Just } from 'folktale/maybe';
3import cn from 'classnames';
4import * as azimuth from 'azimuth-js';
5import * as kg from 'urbit-key-generation';
13import { FORM_ERROR } from 'final-form';
15import { useNetwork } from 'store/network';
16import { useWallet } from 'store/wallet';
17import { usePointCursor } from 'store/pointCursor';
19import * as need from 'lib/need';
20import { WALLET_TYPES, urbitWalletFromTicket } from 'lib/wallet';
21import useImpliedPoint from 'lib/useImpliedPoint';
22import useLoginView from 'lib/useLoginView';
23import patp2dec from 'lib/patp2dec';
24import timeout from 'lib/timeout';
26import BridgeForm from 'form/BridgeForm';
27import Condition from 'form/Condition';
28import { TicketInput, PassphraseInput, PointInput } from 'form/Inputs';
31 buildCheckboxValidator,
34 buildPassphraseValidator,
36} from 'form/validators';
37import FormError from 'form/FormError';
38import SubmitButton from 'form/SubmitButton';
39import { WARNING } from 'form/helpers';
41import { ReactComponent as SecretShowIcon } from 'assets/secret-show.svg';
42import { ReactComponent as SecretHideIcon } from 'assets/secret-hidden.svg';
44function AdvancedOptions() {
47 <Condition when="useAdvanced" is={true}>
55 style={{ boxSizing: 'border-box' }}
64 style={{ boxSizing: 'border-box' }}
78function TicketInputAccessory({ name }) {
84 inverseLabel={<SecretShowIcon />}
85 label={<SecretHideIcon />}
91export default function Ticket({ className, goHome }) {
92 useLoginView(WALLET_TYPES.TICKET);
94 const { contracts } = useNetwork();
95 const { setUrbitWallet } = useWallet();
96 const { setPointCursor } = usePointCursor();
97 const impliedPoint = useImpliedPoint();
98 const didWarn = useRef(false);
100 const validateForm = useCallback((values, errors) => {
101 didWarn.current = false;
107 if (values.useShards) {
108 if (errors.shard1 || errors.shard2 || errors.shard3) {
111 const empty = ['shard1', 'shard2', 'shard3'].filter(s => !values[s]);
112 if (empty.length > 1) {
115 errors[s] = 'Please provide at least two out of three shards.';
126 const onSubmit = useCallback(
128 const ticket = values.useShards
130 [values.shard1, values.shard2, values.shard3].map(v =>
131 v === '' ? undefined : v
137 const _contracts = need.contracts(contracts);
138 const point = patp2dec(values.point);
140 await timeout(16); // allow ui events to flush
141 const urbitWallet = await urbitWalletFromTicket(
147 const [isOwner, isTransferProxy] = await Promise.all([
148 azimuth.azimuth.isOwner(
151 urbitWallet.ownership.keys.address
153 azimuth.azimuth.isTransferProxy(
156 urbitWallet.ownership.keys.address
160 const noPermissions = !isOwner && !isTransferProxy;
162 if (noPermissions && !didWarn.current) {
163 didWarn.current = true;
166 'This wallet is not the owner or transfer proxy for this point.',
170 setUrbitWallet(Just(urbitWallet));
171 setPointCursor(Just(patp2dec(values.point)));
173 console.error(error);
175 [FORM_ERROR]: `Unable to derive wallet from ${
176 values.useShards ? 'shards' : 'ticket'
181 [contracts, setPointCursor, setUrbitWallet]
184 const validate = useMemo(
188 useAdvanced: buildCheckboxValidator(),
189 usePassphrase: buildCheckboxValidator(),
190 useShards: buildCheckboxValidator(),
191 point: buildPointValidator(4),
192 ticket: buildPatqValidator(),
193 shard1: buildShardValidator(),
194 shard2: buildShardValidator(),
195 shard3: buildShardValidator(),
196 ticketHidden: buildCheckboxValidator(),
197 passphrase: buildPassphraseValidator(),
204 const initialValues = useMemo(
206 point: impliedPoint || '',
216 <Grid className={className}>
221 initialValues={initialValues}>
222 {({ handleSubmit, values, submitting }) => (
224 <Grid.Item full as={PointInput} name="point" />
226 <Condition when="useShards" is={false}>
230 hidden={values.ticketHidden}
231 labelAccessory={<AdvancedOptions />}
232 accessory={<TicketInputAccessory name="ticketHidden" />}
235 label="Master Ticket"
239 <Condition when="useShards" is={true}>
243 accessory={<TicketInputAccessory name="ticketHidden" />}
244 hidden={values.ticketHidden}
245 labelAccessory={<AdvancedOptions />}
253 accessory={<TicketInputAccessory name="ticketHidden" />}
254 hidden={values.ticketHidden}
263 accessory={<TicketInputAccessory name="ticketHidden" />}
264 hidden={values.ticketHidden}
270 <Condition when="usePassphrase" is={true}>
276 label="Wallet Passphrase"
280 <Grid.Item full as={FormError} />
286 handleSubmit={handleSubmit}>
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