on master help sign in
urbit-id: add logic for L2 transferPoint
0bb5d7eyosoyubik
src/lib/useRoller.ts+52−20
@@ -28,6 +28,7 @@ import {
28 getSpawnNonce,
28 getSpawnNonce,
29 getOwnerNonce,
29 getOwnerNonce,
30 getManagementNonce,
30 getManagementNonce,
31+ getTransferNonce,
31} from './utils/nonce';
32} from './utils/nonce';
32import { isPlanet } from './utils/point';
33import { isPlanet } from './utils/point';
33
34
@@ -55,7 +56,7 @@ import {
55 configureKeys,
56 configureKeys,
56 getTimeToNextBatch,
57 getTimeToNextBatch,
57 spawn,
58 spawn,
58− transferPoint,
59+ transferPointRequest,
59 registerProxyAddress,
60 registerProxyAddress,
60} from './utils/roller';
61} from './utils/roller';
61
62
@@ -219,7 +220,7 @@ export default function useRoller() {
219 inviteWallet.management.keys.address
220 inviteWallet.management.keys.address
220 );
221 );
221
222
222− const transferPointRequest = await transferPoint(
223+ const transferRequest = await transferPointRequest(
223 api,
224 api,
224 _wallet,
225 _wallet,
225 planet,
226 planet,
@@ -232,7 +233,7 @@ export default function useRoller() {
232 spawnRequest,
233 spawnRequest,
233 configureKeysRequest,
234 configureKeysRequest,
234 setManagementProxyRequest,
235 setManagementProxyRequest,
235− transferPointRequest
236+ transferRequest
236 );
237 );
237 tickets.push({
238 tickets.push({
238 ticket,
239 ticket,
@@ -475,7 +476,7 @@ export default function useRoller() {
475 );
476 );
476
477
477 const keysSigningKey = fromWallet.privateKey;
478 const keysSigningKey = fromWallet.privateKey;
478− await api.configureKeys(
479+ const configureKeysRequest = await api.configureKeys(
479 signTransactionHash(keysHash, Buffer.from(keysSigningKey, 'hex')),
480 signTransactionHash(keysHash, Buffer.from(keysSigningKey, 'hex')),
480 fromOwnerProxy,
481 fromOwnerProxy,
481 ownerAddress,
482 ownerAddress,
@@ -486,7 +487,7 @@ export default function useRoller() {
486 // increaseNonce(point, operator.proxy!);
487 // increaseNonce(point, operator.proxy!);
487
488
488 // 2. Set Management Proxy
489 // 2. Set Management Proxy
489− await registerProxyAddress(
490+ const registerProxyAddressRequest = await registerProxyAddress(
490 api,
491 api,
491 fromWallet,
492 fromWallet,
492 point,
493 point,
@@ -497,27 +498,24 @@ export default function useRoller() {
497 );
498 );
498
499
499 // 3. Transfer point
500 // 3. Transfer point
500− const transferData = { address: to, reset: false };
501+ const transferTxRequest = await transferPointRequest(
501− const transferHash: Hash = await api.hashTransaction(
502+ api,
503+ fromWallet,
504+ point,
505+ operator.proxy!,
502 nonce + 2,
506 nonce + 2,
503− fromOwnerProxy,
507+ to
504− 'transferPoint',
505− transferData
506 );
508 );
507−
509+ const hashes = await Promise.all([
508− const transferTxHash = await api.transferPoint(
510+ configureKeysRequest,
509− signTransactionHash(transferHash, Buffer.from(keysSigningKey, 'hex')),
511+ registerProxyAddressRequest,
510− fromOwnerProxy,
512+ transferTxRequest,
511− ownerAddress,
512− transferData
513− );
513+ ]);
514−
514+ return hashes;
515− return transferTxHash;
516 };
515 };
517
516
518 const setProxyAddress = useCallback(
517 const setProxyAddress = useCallback(
519 async (proxyType: Proxy, address: EthAddress) => {
518 async (proxyType: Proxy, address: EthAddress) => {
520− console.log(proxyType, address);
521 const _point = need.point(pointCursor);
519 const _point = need.point(pointCursor);
522 const _wallet = wallet.getOrElse(null);
520 const _wallet = wallet.getOrElse(null);
523
521
@@ -551,6 +549,40 @@ export default function useRoller() {
551 [api, pointCursor, wallet, nonces]
549 [api, pointCursor, wallet, nonces]
552 );
550 );
553
551
552+ const transferPoint = useCallback(
553+ async (address: EthAddress, reset?: boolean) => {
554+ const _point = need.point(pointCursor);
555+ const _wallet = wallet.getOrElse(null);
556+
557+ if (!_wallet) {
558+ // not using need because we want a custom error
559+ throw new Error('Internal Error: Missing Wallet');
560+ }
561+
562+ const pointDetails = nonces[_point];
563+ const operator =
564+ getTransferNonce(pointDetails, _wallet.address) ||
565+ getOwnerNonce(pointDetails, _wallet.address);
566+
567+ if (operator === undefined)
568+ throw new Error("Error: Address doesn't match proxy");
569+
570+ const txHash = await transferPointRequest(
571+ api,
572+ _wallet,
573+ _point,
574+ operator.proxy!,
575+ operator.nonce!,
576+ address,
577+ reset || false
578+ );
579+ const pendingTx = await api.getPendingTx(txHash);
580+
581+ return pendingTx;
582+ },
583+ [api, pointCursor, wallet, nonces]
584+ );
585+
554 // On load, get initial config
586 // On load, get initial config
555 useEffect(() => {
587 useEffect(() => {
556 if (config) {
588 if (config) {
src/lib/utils/roller.ts+5−5
@@ -110,13 +110,14 @@ export const configureKeys = async (
110 return api.configureKeys(sig, from, _wallet.address, data);
110 return api.configureKeys(sig, from, _wallet.address, data);
111};
111};
112
112
113−export const transferPoint = async (
113+export const transferPointRequest = async (
114 api: any,
114 api: any,
115 _wallet: any,
115 _wallet: any,
116− _point: number,
116+ _point: Ship,
117 proxy: string,
117 proxy: string,
118 nonce: number,
118 nonce: number,
119− address: string
119+ address: string,
120+ reset?: boolean
120) => {
121) => {
121 const from = {
122 const from = {
122 ship: _point, // ship to transfer
123 ship: _point, // ship to transfer
@@ -125,9 +126,8 @@ export const transferPoint = async (
125
126
126 const data = {
127 const data = {
127 address,
128 address,
128− reset: false,
129+ reset: reset || false,
129 };
130 };
130−
131 const hash = await api.hashTransaction(nonce, from, 'transferPoint', data);
131 const hash = await api.hashTransaction(nonce, from, 'transferPoint', data);
132 const sig = signTransactionHash(hash, _wallet.privateKey);
132 const sig = signTransactionHash(hash, _wallet.privateKey);
133 return api.transferPoint(sig, from, _wallet.address, data);
133 return api.transferPoint(sig, from, _wallet.address, data);
src/views/UrbitID/Transfer.js+46−11
@@ -1,18 +1,20 @@
1−import React, { useCallback, useMemo } from 'react';
1+import React, { useCallback, useMemo, useState } from 'react';
2import cn from 'classnames';
2import cn from 'classnames';
3−import { Grid, Text } from 'indigo-react';
3+import { Grid, Text, Button } from 'indigo-react';
4import * as azimuth from 'azimuth-js';
4import * as azimuth from 'azimuth-js';
5
5
6import { useNetwork } from 'store/network';
6import { useNetwork } from 'store/network';
7import { usePointCursor } from 'store/pointCursor';
7import { usePointCursor } from 'store/pointCursor';
8import { usePointCache } from 'store/pointCache';
8import { usePointCache } from 'store/pointCache';
9import { useStarReleaseCache } from 'store/starRelease';
9import { useStarReleaseCache } from 'store/starRelease';
10+import { useRollerStore } from 'store/roller';
10
11
11import * as need from 'lib/need';
12import * as need from 'lib/need';
12import { useLocalRouter } from 'lib/LocalRouter';
13import { useLocalRouter } from 'lib/LocalRouter';
13import useCurrentPointName from 'lib/useCurrentPointName';
14import useCurrentPointName from 'lib/useCurrentPointName';
14import useEthereumTransaction from 'lib/useEthereumTransaction';
15import useEthereumTransaction from 'lib/useEthereumTransaction';
15import { GAS_LIMITS } from 'lib/constants';
16import { GAS_LIMITS } from 'lib/constants';
17+import useRoller from 'lib/useRoller';
16
18
17import ViewHeader from 'components/ViewHeader';
19import ViewHeader from 'components/ViewHeader';
18import NoticeBox from 'components/NoticeBox';
20import NoticeBox from 'components/NoticeBox';
@@ -45,6 +47,9 @@ export default function AdminTransfer() {
45 const name = useCurrentPointName();
47 const name = useCurrentPointName();
46 const { pointCursor } = usePointCursor();
48 const { pointCursor } = usePointCursor();
47 const { starReleaseDetails } = useStarReleaseCache();
49 const { starReleaseDetails } = useStarReleaseCache();
50+ const { currentL2 } = useRollerStore();
51+ const { transferPoint, getPendingTransactions } = useRoller();
52+ const [owner, setNewOwner] = useState('');
48
53
49 const {
54 const {
50 construct,
55 construct,
@@ -54,29 +59,46 @@ export default function AdminTransfer() {
54 bind,
59 bind,
55 } = useTransfer();
60 } = useTransfer();
56
61
62+ const point = need.point(pointCursor);
63+
57 const needLockupWarning = useMemo(() => {
64 const needLockupWarning = useMemo(() => {
58− const point = need.point(pointCursor);
59 const az = azimuth.azimuth;
65 const az = azimuth.azimuth;
60 return (
66 return (
61 az.getPointSize(point) === az.PointSize.Galaxy &&
67 az.getPointSize(point) === az.PointSize.Galaxy &&
62 starReleaseDetails.map(a => a.kind).getOrElse('none') !== 'none'
68 starReleaseDetails.map(a => a.kind).getOrElse('none') !== 'none'
63 );
69 );
64− }, [pointCursor, starReleaseDetails]);
70+ }, [starReleaseDetails, point]);
65
71
66 const validate = useMemo(
72 const validate = useMemo(
67 () => composeValidator({ address: buildAddressValidator() }),
73 () => composeValidator({ address: buildAddressValidator() }),
68 []
74 []
69 );
75 );
70
76
77+ const onSignTx = useCallback(async () => {
78+ // setLoading(true);
79+ if (owner === '') return;
80+ try {
81+ await transferPoint(owner);
82+ getPendingTransactions(point);
83+ pop();
84+ } catch (error) {
85+ // setError(error);
86+ } finally {
87+ // setLoading(false);
88+ }
89+ }, [owner, getPendingTransactions, point, pop, transferPoint]);
90+
71 const onValues = useCallback(
91 const onValues = useCallback(
72 ({ valid, values }) => {
92 ({ valid, values }) => {
73 if (valid) {
93 if (valid) {
74 construct(values.address);
94 construct(values.address);
95+ setNewOwner(values.address);
75 } else {
96 } else {
76 unconstruct();
97 unconstruct();
98+ setNewOwner('');
77 }
99 }
78 },
100 },
79− [construct, unconstruct]
101+ [construct, unconstruct, setNewOwner]
80 );
102 );
81
103
82 return (
104 return (
@@ -127,12 +149,25 @@ export default function AdminTransfer() {
127
149
128 <Grid.Item full as={FormError} />
150 <Grid.Item full as={FormError} />
129
151
152+ {currentL2 ? (
130− <Grid.Item
153+ <Grid.Item
154+ as={Button}
131− full
155+ full
156+ className="set-proxy"
157+ center
158+ solid
159+ disabled={values.unset}
160+ onClick={onSignTx}>
161+ {'Sign Transaction'}
162+ </Grid.Item>
163+ ) : (
164+ <Grid.Item
165+ full
132− as={InlineEthereumTransaction}
166+ as={InlineEthereumTransaction}
133− {...bind}
167+ {...bind}
134− onReturn={() => pop()}
168+ onReturn={() => pop()}
135− />
169+ />
170+ )}
136 </>
171 </>
137 )}
172 )}
138 </BridgeForm>
173 </BridgeForm>