on master help sign in
invite-flow: wip invite creation and acceptance
7f18d02yosoyubik
src/lib/useRoller.ts+9−11
@@ -10,7 +10,7 @@ import { ensureHexPrefix } from 'form/formatters';
10import { getOutgoingPoints } from 'views/Points';
10import { getOutgoingPoints } from 'views/Points';
11import { isDevelopment, isRopsten } from './flags';
11import { isDevelopment, isRopsten } from './flags';
12import { isPlanet } from './utils/point';
12import { isPlanet } from './utils/point';
13−import { hasPoint } from './utils/roller';
13+import { hasPoint, generateInviteWallet } from './utils/roller';
14import { ROLLER_HOSTS } from './constants';
14import { ROLLER_HOSTS } from './constants';
15import { signTransactionHash } from './authToken';
15import { signTransactionHash } from './authToken';
16import { useNetwork } from 'store/network';
16import { useNetwork } from 'store/network';
@@ -164,7 +164,7 @@ export default function useRoller() {
164 const planet = planets[i];
164 const planet = planets[i];
165 const nonceInc = i + nonce;
165 const nonceInc = i + nonce;
166
166
167− const { ticket, owner } = await wg.generateTemporaryDeterministicWallet(
167+ const { ticket, owner } = await generateInviteWallet(
168 planet,
168 planet,
169 _authToken
169 _authToken
170 );
170 );
@@ -224,8 +224,6 @@ export default function useRoller() {
224 contracts,
224 contracts,
225 pointCursor,
225 pointCursor,
226 wallet,
226 wallet,
227− // walletHdPath,
228− // walletType,
229 web3,
227 web3,
230 getDetails,
228 getDetails,
231 authMnemonic,
229 authMnemonic,
@@ -331,15 +329,16 @@ export default function useRoller() {
331 if (isDevelopment) {
329 if (isDevelopment) {
332 console.log('POSSIBLE MISSING', possibleMissingInvites);
330 console.log('POSSIBLE MISSING', possibleMissingInvites);
333 }
331 }
334−
332+ // TODO: this can be verym slow, so best to allow the user to manually
333+ // reveal the ticket, after checking if the invite is still "active"
334+ // (i.e. if the address inferred from the derived inviteWallet corresponds to
335+ // to the address the point has as owner)
336+ //
335 for (let i = 0; i < possibleMissingInvites.length; i++) {
337 for (let i = 0; i < possibleMissingInvites.length; i++) {
336 const planet = possibleMissingInvites[i];
338 const planet = possibleMissingInvites[i];
337 if (!availableInvites.find(hasPoint(planet))) {
339 if (!availableInvites.find(hasPoint(planet))) {
338 console.log('MISSING IN AVAILABLE', planet);
340 console.log('MISSING IN AVAILABLE', planet);
339− const {
341+ const { ticket, owner } = await generateInviteWallet(
340− ticket,
341− owner,
342− } = await wg.generateTemporaryDeterministicWallet(
343 planet,
342 planet,
344 _authToken
343 _authToken
345 );
344 );
@@ -401,7 +400,6 @@ export default function useRoller() {
401 toWallet,
400 toWallet,
402 }: AcceptInviteParams) => {
401 }: AcceptInviteParams) => {
403 const azimuthPoint = await api.getPoint(point);
402 const azimuthPoint = await api.getPoint(point);
404− const spawnerPatp = ob.patp(azimuthPoint?.network?.sponsor?.who);
405 console.log('azimuthPoint', azimuthPoint);
403 console.log('azimuthPoint', azimuthPoint);
406 const ownerAddress = azimuthPoint?.ownership?.owner?.address!;
404 const ownerAddress = azimuthPoint?.ownership?.owner?.address!;
407
405
@@ -415,7 +413,7 @@ export default function useRoller() {
415 const networkRevision = convertToInt(azimuthPoint.network.keys.life, 10);
413 const networkRevision = convertToInt(azimuthPoint.network.keys.life, 10);
416 const nextRevision = networkRevision + 1;
414 const nextRevision = networkRevision + 1;
417 const fromOwnerProxy: From = {
415 const fromOwnerProxy: From = {
418− ship: spawnerPatp,
416+ ship: point,
419 proxy: 'own',
417 proxy: 'own',
420 };
418 };
421
419
src/lib/utils/roller.ts+11
@@ -8,6 +8,10 @@ import {
8 CRYPTO_SUITE_VERSION,
8 CRYPTO_SUITE_VERSION,
9} from 'lib/keys';
9} from 'lib/keys';
10import { addHexPrefix } from 'lib/utils/address';
10import { addHexPrefix } from 'lib/utils/address';
11+import {
12+ makeDeterministicTicket,
13+ generateOwnershipWallet,
14+} from 'lib/walletgen';
11
15
12export const SECOND = 1000;
16export const SECOND = 1000;
13export const MINUTE = SECOND * 60;
17export const MINUTE = SECOND * 60;
@@ -29,6 +33,13 @@ export const getTimeToNextBatch = (nextBatch: number, now: number) => {
29
33
30export const isL2 = (dom?: string) => dom === 'l2' || dom === 'spawn';
34export const isL2 = (dom?: string) => dom === 'l2' || dom === 'spawn';
31
35
36+export const generateInviteWallet = async (point: number, seed: string) => {
37+ const ticket = makeDeterministicTicket(point, seed);
38+ const owner = await generateOwnershipWallet(point, ticket);
39+
40+ return { ticket, owner };
41+};
42+
32export const spawn = async (
43export const spawn = async (
33 api: any,
44 api: any,
34 _wallet: any,
45 _wallet: any,
src/react-app-env.d.ts+1
@@ -1 +1,2 @@
1/// <reference types="react-scripts" />
1/// <reference types="react-scripts" />
2+declare module 'folktale/maybe';
src/views/Activate/ActivateCodeForm.tsx+31−40
@@ -1,4 +1,3 @@
1−import * as azimuth from 'azimuth-js';
2import * as need from 'lib/need';
1import * as need from 'lib/need';
3import * as ob from 'urbit-ob';
2import * as ob from 'urbit-ob';
4import { WARNING } from 'form/helpers';
3import { WARNING } from 'form/helpers';
@@ -19,13 +18,10 @@ import { useActivateFlow } from './ActivateFlow';
19import WarningBox from 'components/WarningBox';
18import WarningBox from 'components/WarningBox';
20import useRoller from 'lib/useRoller';
19import useRoller from 'lib/useRoller';
21import useImpliedTicket from 'lib/useImpliedTicket';
20import useImpliedTicket from 'lib/useImpliedTicket';
22−import {
23− generateTemporaryOwnershipWallet,
24− generateWallet,
25−} from 'lib/walletgen';
21+import { generateOwnershipWallet } from 'lib/walletgen';
22+import { generateWallet } from 'lib/invite';
26import { walletFromMnemonic } from 'lib/wallet';
23import { walletFromMnemonic } from 'lib/wallet';
27−import { useNetwork } from 'store/network';
28−import { DEFAULT_HD_PATH, POINT_DOMINIONS, POINT_PROXIES } from 'lib/constants';
24+import { DEFAULT_HD_PATH, POINT_PROXIES } from 'lib/constants';
29import useBreakpoints from 'lib/useBreakpoints';
25import useBreakpoints from 'lib/useBreakpoints';
30import { Ship } from '@urbit/roller-api';
26import { Ship } from '@urbit/roller-api';
31import { convertToInt } from 'lib/convertToInt';
27import { convertToInt } from 'lib/convertToInt';
@@ -39,9 +35,13 @@ interface ActivateCodeFormProps {
39}
35}
40
36
41const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
37const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
42− const { contracts } = useNetwork();
43 const { api, getPoints } = useRoller();
38 const { api, getPoints } = useRoller();
39+ const {
44− const { impliedAzimuthPoint, impliedTicket } = useImpliedTicket();
40+ impliedAzimuthPoint,
41+ impliedTicket,
42+ impliedPatp,
43+ } = useImpliedTicket();
44+ console.log(impliedAzimuthPoint, impliedTicket);
45 const didWarn = useRef<boolean>(false);
45 const didWarn = useRef<boolean>(false);
46
46
47 const {
47 const {
@@ -80,27 +80,23 @@ const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
80 [validateForm]
80 [validateForm]
81 );
81 );
82
82
83− const loadL1Points = useCallback(
83+ const getTicketAndPoint = (invite: string) => {
84− async (address: string): Promise<number[]> => {
84+ const segments = invite.split('-');
85− const _contracts = need.contracts(contracts);
85+ console.log(segments);
86− const owned = await azimuth.azimuth.getOwnedPoints(_contracts, address);
87− const transferring = await azimuth.azimuth.getTransferringFor(
88− _contracts,
89− address
90− );
91− const incoming = [...owned, ...transferring];
92− console.log('incoming L1 points', incoming);
93− return incoming;
86+ return {
94− },
87+ ticket: segments.slice(0, 4).join('-'),
95− [contracts]
88+ point: impliedPatp
89+ ? ob.patp2dec(impliedPatp)
90+ : ob.patp2dec(`~${segments.slice(4, segments.length).join('-')}`),
91+ };
96− );
92+ };
97−
93+
98− const loadl2points = useCallback(
94+ const loadPoints = useCallback(
99 async (address: string): Promise<Ship[]> => {
95 async (address: string): Promise<Ship[]> => {
100 const owned = await getPoints(POINT_PROXIES.OWN, address);
96 const owned = await getPoints(POINT_PROXIES.OWN, address);
101 const transferring = await getPoints(POINT_PROXIES.TRANSFER, address);
97 const transferring = await getPoints(POINT_PROXIES.TRANSFER, address);
102 const incoming = [...owned, ...transferring];
98 const incoming = [...owned, ...transferring];
103− console.log('incoming L2 points', incoming);
99+ console.log('incoming points', incoming);
104 return incoming;
100 return incoming;
105 },
101 },
106 [getPoints]
102 [getPoints]
@@ -113,21 +109,16 @@ const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
113 await timeout(42);
109 await timeout(42);
114
110
115 // Derive wallet
111 // Derive wallet
112+ const { ticket, point } = getTicketAndPoint(
116− const ticket = impliedTicket || values.ticket;
113+ impliedTicket || values.ticket
114+ );
117− const { seed } = await generateTemporaryOwnershipWallet(ticket);
115+ const { seed } = await generateOwnershipWallet(point, ticket);
118 const inviteWallet = walletFromMnemonic(seed, DEFAULT_HD_PATH);
116 const inviteWallet = walletFromMnemonic(seed, DEFAULT_HD_PATH);
119 setInviteWallet(inviteWallet);
117 setInviteWallet(inviteWallet);
120 const _inviteWallet = need.wallet(inviteWallet);
118 const _inviteWallet = need.wallet(inviteWallet);
121 const inviteAddress = _inviteWallet.address;
119 const inviteAddress = _inviteWallet.address;
122
120
123− // Query for points depending on point's dominion
124− const rollerPoint = await api.getPoint(impliedAzimuthPoint!);
125− let incoming: number[] | Ship[];
121+ let incoming: number[] | Ship[] = await loadPoints(inviteAddress);
126− if (rollerPoint.dominion === POINT_DOMINIONS.L2) {
127− incoming = await loadl2points(inviteAddress);
128− } else {
129− incoming = await loadL1Points(inviteAddress);
130− }
131
122
132 // Set derived
123 // Set derived
133 if (incoming.length > 0) {
124 if (incoming.length > 0) {
@@ -143,11 +134,12 @@ const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
143 }
134 }
144
135
145 const point = convertToInt(incoming[0], 10);
136 const point = convertToInt(incoming[0], 10);
137+ const rollerPoint = await api.getPoint(point!);
146
138
147 setDerivedPatp(Just(ob.patp(point)));
139 setDerivedPatp(Just(ob.patp(point)));
148 setDerivedPoint(Just(point));
140 setDerivedPoint(Just(point));
149 setDerivedPointDominion(Just(rollerPoint.dominion));
141 setDerivedPointDominion(Just(rollerPoint.dominion));
150− setDerivedWallet(Just(await generateWallet(point, ticket, true)));
142+ setDerivedWallet(Just(await generateWallet(point, true)));
151 setIsIn(false);
143 setIsIn(false);
152 await timeout(100);
144 await timeout(100);
153 } else {
145 } else {
@@ -160,10 +152,9 @@ const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
160 },
152 },
161 [
153 [
162 api,
154 api,
163− impliedAzimuthPoint,
164 impliedTicket,
155 impliedTicket,
165− loadL1Points,
156+ getTicketAndPoint,
166− loadl2points,
157+ loadPoints,
167 setDerivedPatp,
158 setDerivedPatp,
168 setDerivedPoint,
159 setDerivedPoint,
169 setDerivedPointDominion,
160 setDerivedPointDominion,
src/views/Activate/MasterKeyTransfer.tsx+1−1
@@ -29,7 +29,7 @@ const MasterKeyTransfer = () => {
29 try {
29 try {
30 await acceptInvite({
30 await acceptInvite({
31 point: derivedPoint.value,
31 point: derivedPoint.value,
32− to: derivedWallet.value.ownership.address,
32+ to: derivedWallet.value.ownership.keys.address,
33 toWallet: derivedWallet.value,
33 toWallet: derivedWallet.value,
34 fromWallet: inviteWallet.value,
34 fromWallet: inviteWallet.value,
35 });
35 });