1import { Just, Nothing } from 'folktale/maybe';
2import React, { useCallback, useState, useEffect } from 'react';
3import * as azimuth from 'azimuth-js';
4import * as ob from 'urbit-ob';
5import * as kg from 'urbit-key-generation/dist/index';
6import { Input, Grid, CheckboxInput } from 'indigo-react';
8import { useNetwork } from 'store/network';
9import { useWallet } from 'store/wallet';
10import { usePointCursor } from 'store/pointCursor';
17} from 'lib/useInputs';
18import * as need from 'lib/need';
19import { WALLET_TYPES, urbitWalletFromTicket } from 'lib/wallet';
20import useImpliedPoint from 'lib/useImpliedPoint';
21import useLoginView from 'lib/useLoginView';
23export default function Ticket({ className }) {
24 useLoginView(WALLET_TYPES.TICKET);
26 const { contracts } = useNetwork();
27 const { setUrbitWallet } = useWallet();
28 const { setPointCursor } = usePointCursor();
29 const impliedPoint = useImpliedPoint();
32 const [pointInput, { data: pointName }] = usePointInput({
34 initialValue: impliedPoint || '',
39 const [passphraseInput, { data: passphrase }] = usePassphraseInput({
41 label: 'Wallet Passphrase',
44 const [hasPassphraseInput, { data: hasPassphrase }] = useCheckboxInput({
45 name: 'has-passphrase',
51 const [error, setError] = useState();
52 const [deriving, setDeriving] = useState(false);
53 const [ticketInput, { data: ticket, pass: validTicket }] = useTicketInput({
55 label: 'Master Ticket',
61 const [shardsInput, { data: isUsingShards }] = useCheckboxInput({
67 const [shard1Input, { data: shard1, pass: shard1Pass }] = useTicketInput({
72 const [shard2Input, { data: shard2, pass: shard2Pass }] = useTicketInput({
77 const [shard3Input, { data: shard3, pass: shard3Pass }] = useTicketInput({
82 const shardsReady = shard1Pass && shard2Pass && shard3Pass;
84 // TODO: maybe want to do this only on-go, because wallet derivation is slow...
85 const deriveWalletFromTicket = useCallback(async () => {
89 setUrbitWallet(Nothing());
91 if (!ob.isValidPatq(ticket) || !ob.isValidPatp(pointName)) {
96 const _contracts = need.contracts(contracts);
97 const point = ob.patp2dec(pointName);
98 const urbitWallet = await urbitWalletFromTicket(ticket, point, passphrase);
99 const [isOwner, isTransferProxy] = await Promise.all([
100 azimuth.azimuth.isOwner(
103 urbitWallet.ownership.keys.address
105 azimuth.azimuth.isTransferProxy(
108 urbitWallet.ownership.keys.address
112 if (!isOwner && !isTransferProxy) {
113 // notify the user, but allow login regardless
115 'This ticket is not the owner of or transfer proxy for this point.'
119 setUrbitWallet(Just(urbitWallet));
120 setPointCursor(Just(ob.patp2dec(pointName)));
132 const deriveWalletFromShards = useCallback(async () => {
133 const s1 = shard1 || undefined;
134 const s2 = shard2 || undefined;
135 const s3 = shard3 || undefined;
138 const ticket = kg.combine([s1, s2, s3]);
139 const point = ob.patp2dec(pointName);
140 const uhdw = await urbitWalletFromTicket(ticket, point, passphrase);
141 setUrbitWallet(Just(uhdw));
145 }, [passphrase, pointName, setUrbitWallet, shard1, shard2, shard3]);
147 // derive wallet on change
149 if (isUsingShards && shardsReady) {
150 deriveWalletFromShards();
151 } else if (validTicket) {
152 deriveWalletFromTicket();
158 deriveWalletFromShards,
159 deriveWalletFromTicket,
163 <Grid className={className}>
164 <Grid.Item full as={Input} {...pointInput} />
166 {!isUsingShards && <Grid.Item full as={Input} {...ticketInput} />}
169 <Grid.Item full as={Input} {...shard1Input} />
170 <Grid.Item full as={Input} {...shard2Input} />
171 <Grid.Item full as={Input} {...shard3Input} />
174 {hasPassphrase && <Grid.Item full as={Input} {...passphraseInput} />}
176 <Grid.Item full as={CheckboxInput} {...hasPassphraseInput} />
177 <Grid.Item full as={CheckboxInput} {...shardsInput} />
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