on master help sign in
urbit-id: L2 support for edit management proxy
commit67d9ca6211ee96eb4fd119036b1c31f149a7283f authoryosoyubik <yosoyubik@gmail.com> dateMon 27 Sep 2021, 13:37 (5 years ago) parent2b07680
6 files changed+260−39
migrations/1_migration.js+6 src/lib/useRoller.ts+52−15 src/lib/utils/roller.ts+50−5 src/views/Point/Point.tsx+31−10 src/views/UrbitID/SetProxy.js+64−9 src/views/UrbitID/SetProxy.scss+57
migrations/1_migration.js+6
@@ -153,6 +153,12 @@ module.exports = async function(deployer) {
153153 // ~marzod -> L1
154154 await ecliptic.spawn(256, own);
155155 await ecliptic.configureKeys(256, '0xffff', '0xffff', 1, false);
156+ // ~marzod -> L2
157+ await ecliptic.transferPoint(
158+ 256,
159+ '0x1111111111111111111111111111111111111111',
160+ false
161+ );
156162 // ~wanzod -> L1
157163 await ecliptic.spawn(768, own);
158164 await ecliptic.configureKeys(768, '0xffff', '0xffff', 1, false);
src/lib/useRoller.ts+52−15
@@ -24,7 +24,11 @@ import {
2424} from 'store/storage/roller';
2525import { usePointCache } from 'store/pointCache';
2626import { getOutgoingPoints } from 'views/Points';
27−import { getSpawnNonce, getOwnerNonce } from './utils/nonce';
27+import {
28+ getSpawnNonce,
29+ getOwnerNonce,
30+ getManagementNonce,
31+} from './utils/nonce';
2832import { isPlanet } from './utils/point';
2933
3034import {
@@ -52,7 +56,7 @@ import {
5256 getTimeToNextBatch,
5357 spawn,
5458 transferPoint,
55− setSpawnProxy,
59+ registerProxyAddress,
5660} from './utils/roller';
5761
5862function isSpawn(tx: L2Data | undefined): tx is SpawnParams {
@@ -205,11 +209,12 @@ export default function useRoller() {
205209 inviteWallet
206210 );
207211
208− const setManagementProxyRequest = await setSpawnProxy(
212+ const setManagementProxyRequest = await registerProxyAddress(
209213 api,
210214 _wallet,
211215 planet,
212216 operator.proxy!,
217+ 'manage',
213218 1,
214219 inviteWallet.management.keys.address
215220 );
@@ -481,19 +486,14 @@ export default function useRoller() {
481486 // increaseNonce(point, operator.proxy!);
482487
483488 // 2. Set Management Proxy
484− const managementData = { address: manager };
485− const managementHash: Hash = await api.hashTransaction(
489+ await registerProxyAddress(
490+ api,
491+ fromWallet,
492+ point,
493+ operator.proxy!,
494+ 'manage',
486495 nonce + 1,
487− fromOwnerProxy,
488− 'setManagementProxy',
489− managementData
490− );
491−
492− await api.setManagementProxy(
493− signTransactionHash(managementHash, Buffer.from(keysSigningKey, 'hex')),
494− fromOwnerProxy,
495− ownerAddress,
496− managementData
496+ manager
497497 );
498498
499499 // 3. Transfer point
@@ -515,6 +515,42 @@ export default function useRoller() {
515515 return transferTxHash;
516516 };
517517
518+ const setProxyAddress = useCallback(
519+ async (proxyType: Proxy, address: EthAddress) => {
520+ console.log(proxyType, address);
521+ const _point = need.point(pointCursor);
522+ const _wallet = wallet.getOrElse(null);
523+
524+ if (!_wallet) {
525+ // not using need because we want a custom error
526+ throw new Error('Internal Error: Missing Wallet');
527+ }
528+
529+ const pointDetails = nonces[_point];
530+ const operator =
531+ getManagementNonce(pointDetails, _wallet.address) ||
532+ getOwnerNonce(pointDetails, _wallet.address);
533+
534+ if (operator === undefined)
535+ throw new Error("Error: Address doesn't match proxy");
536+
537+ const txHash = await registerProxyAddress(
538+ api,
539+ _wallet,
540+ _point,
541+ operator.proxy!,
542+ proxyType,
543+ operator.nonce!,
544+ address
545+ );
546+
547+ const pendingTx = await api.getPendingTx(txHash);
548+
549+ return pendingTx;
550+ },
551+ [api, pointCursor, wallet, nonces]
552+ );
553+
518554 // On load, get initial config
519555 useEffect(() => {
520556 if (config) {
@@ -550,5 +586,6 @@ export default function useRoller() {
550586 getPendingTransactions,
551587 generateInviteCodes,
552588 transferPoint,
589+ setProxyAddress,
553590 };
554591}
src/lib/utils/roller.ts+50−5
@@ -2,6 +2,16 @@ import { signTransactionHash } from 'lib/authToken';
22import { Invite } from 'lib/types/Invite';
33import { Just, Nothing } from 'folktale/maybe';
44import { randomHex } from 'web3-utils';
5+
6+import {
7+ Proxy,
8+ Signature,
9+ From,
10+ EthAddress,
11+ AddressParams,
12+ Ship,
13+} from '@urbit/roller-api';
14+
515import {
616 deriveNetworkSeedFromUrbitWallet,
717 deriveNetworkKeys,
@@ -121,11 +131,25 @@ export const transferPoint = async (
121131 return api.transferPoint(sig, from, _wallet.address, data);
122132};
123133
124−export const setSpawnProxy = async (
134+const proxyType = (proxy: Proxy) => {
135+ switch (proxy) {
136+ case 'manage':
137+ return 'setManagementProxy';
138+ case 'spawn':
139+ return 'setSpawnProxy';
140+ case 'transfer':
141+ return 'setTransferProxy';
142+ default:
143+ throw new Error(`Unknown proxyType ${proxy}`);
144+ }
145+};
146+
147+export const registerProxyAddress = async (
125148 api: any,
126149 _wallet: any,
127− _point: number,
150+ _point: Ship,
128151 proxy: string,
152+ proxyAddressType: string,
129153 nonce: number,
130154 address: string
131155) => {
@@ -137,11 +161,12 @@ export const setSpawnProxy = async (
137161 const managementHash = await api.hashTransaction(
138162 nonce,
139163 from,
140− 'setManagementProxy',
164+ proxyType(proxyAddressType),
141165 managementData
142166 );
143−
144− return api.setManagementProxy(
167+ return setProxy(
168+ api,
169+ proxyAddressType,
145170 signTransactionHash(managementHash, _wallet.privateKey),
146171 from,
147172 _wallet.address,
@@ -149,5 +174,25 @@ export const setSpawnProxy = async (
149174 );
150175};
151176
177+const setProxy = async (
178+ api: any,
179+ proxyAddressType: string,
180+ sig: Signature,
181+ from: From,
182+ address: EthAddress,
183+ data: AddressParams
184+) => {
185+ switch (proxyAddressType) {
186+ case 'manage':
187+ return await api.setManagementProxy(sig, from, address, data);
188+ case 'spawn':
189+ return await api.setSpawnProxy(sig, from, address, data);
190+ case 'transfer':
191+ return await api.setTrasferProxy(sig, from, address, data);
192+ default:
193+ throw new Error(`Unknown proxyType ${proxyAddressType}`);
194+ }
195+};
196+
152197export const hasPoint = (point: number) => (invite: Invite) =>
153198 invite.planet === point;
src/views/Point/Point.tsx+31−10
@@ -150,12 +150,12 @@ export default function Point() {
150150 })();
151151
152152 const address = need.addressFromWallet(wallet);
153−
154− const numPending = useMemo(() => {
155− return pendingTransactions.filter(
156− ({ rawTx }) => rawTx?.tx?.type === 'spawn'
157− ).length;
158− }, [pendingTransactions]);
153+ const spawnedPending = pendingTransactions.filter(
154+ ({ rawTx }) => rawTx?.tx?.type === 'spawn'
155+ ).length;
156+ const otherPending = pendingTransactions.filter(
157+ ({ rawTx }) => rawTx?.tx?.type !== 'spawn'
158+ );
159159
160160 return (
161161 <View
@@ -165,18 +165,17 @@ export default function Point() {
165165 hideBack
166166 header={
167167 <L2PointHeader
168− hideTimer={!!numPending}
168+ hideTimer={!!spawnedPending}
169169 numInvites={invites.length}
170170 hideInvites={!networkKeysSet}
171171 />
172172 }>
173173 <Greeting point={point} />
174− {!!numPending && (
174+ {!!spawnedPending && (
175175 <div className="transaction">
176176 <Row className="title-row">
177177 <div className="title">
178− {numPending} Planet
179− {numPending > 1 ? 's' : ''} Spawned
178+ {spawnedPending} Planet{spawnedPending > 1 ? 's' : ''} Spawned
180179 </div>
181180 <div className="rollup-timer">
182181 <Icon icon="Clock" />
@@ -189,6 +188,28 @@ export default function Point() {
189188 </Row>
190189 </div>
191190 )}
191+ {!!otherPending.length &&
192+ otherPending.map(pendingTx => (
193+ <div className="transaction">
194+ <Row className="title-row">
195+ <div className="title">
196+ {pendingTx.rawTx?.tx?.type === 'set-management-proxy'
197+ ? 'Management Address Changed'
198+ : pendingTx.rawTx?.tx?.type === 'configure-keys'
199+ ? 'Network Keys Configured'
200+ : ''}
201+ </div>
202+ <div className="rollup-timer">
203+ <Icon icon="Clock" />
204+ {nextRoll}
205+ </div>
206+ </Row>
207+ <Row className="info-row">
208+ <LayerIndicator layer={2} size="sm" />
209+ <div className="date"></div>
210+ </Row>
211+ </div>
212+ ))}
192213 <Passport
193214 point={Just(point)}
194215 address={Just(address)}
src/views/UrbitID/SetProxy.js+64−9
@@ -1,11 +1,14 @@
1−import React, { useCallback, useMemo } from 'react';
1+import React, { useCallback, useMemo, useState } from 'react';
22import cn from 'classnames';
3−import { Grid, Text, Flex } from 'indigo-react';
3+import { Grid, Text, Flex, Button } from 'indigo-react';
44import * as azimuth from 'azimuth-js';
55
6+import './SetProxy.scss';
7+
68import { useNetwork } from 'store/network';
79import { usePointCache } from 'store/pointCache';
810import { usePointCursor } from 'store/pointCursor';
11+import { useRollerStore } from 'store/roller';
912
1013import {
1114 PROXY_TYPE,
@@ -17,6 +20,7 @@ import { useLocalRouter } from 'lib/LocalRouter';
1720import { eqAddr, isZeroAddress } from 'lib/utils/address';
1821import { capitalize } from 'lib/capitalize';
1922import useEthereumTransaction from 'lib/useEthereumTransaction';
23+import useRoller from 'lib/useRoller';
2024
2125import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
2226import { ETH_ZERO_ADDR, GAS_LIMITS } from 'lib/constants';
@@ -29,6 +33,15 @@ import {
2933import BridgeForm from 'form/BridgeForm';
3034import FormError from 'form/FormError';
3135
36+const getL2ProxyName = proxy =>
37+ proxy === PROXY_TYPE.MANAGEMENT
38+ ? 'manage'
39+ : proxy === PROXY_TYPE.SPAWN
40+ ? 'spawn'
41+ : proxy === PROXY_TYPE.TRANSFER
42+ ? 'transfer'
43+ : '';
44+
3245const proxyFromDetails = (details, contracts, proxyType) => {
3346 switch (proxyType) {
3447 case PROXY_TYPE.MANAGEMENT:
@@ -97,6 +110,9 @@ export default function SetProxy() {
97110 const { getDetails } = usePointCache();
98111 const { pointCursor } = usePointCursor();
99112 const { contracts } = useNetwork();
113+ const { currentL2 } = useRollerStore();
114+ const { setProxyAddress, getPendingTransactions } = useRoller();
115+ const [newAddress, setNewAddress] = useState('');
100116
101117 const _point = need.point(pointCursor);
102118 const _details = need.details(getDetails(_point));
@@ -113,7 +129,30 @@ export default function SetProxy() {
113129 bind,
114130 } = useSetProxy(data.proxyType);
115131
132+ const setProxy = useCallback(async () => {
133+ // setLoading(true);
134+ console.log(newAddress);
135+ if (newAddress === '') return;
136+ try {
137+ await setProxyAddress(getL2ProxyName(data.proxyType), newAddress);
138+ getPendingTransactions(_point);
139+ pop();
140+ } catch (error) {
141+ // setError(error);
142+ } finally {
143+ // setLoading(false);
144+ }
145+ }, [
146+ newAddress,
147+ getPendingTransactions,
148+ _point,
149+ pop,
150+ data.proxyType,
151+ setProxyAddress,
152+ ]);
153+
116154 const validateForm = useCallback((values, errors) => {
155+ console.log('hola');
117156 if (!values.unset && errors.address) {
118157 return errors;
119158 }
@@ -133,18 +172,21 @@ export default function SetProxy() {
133172
134173 const onValues = useCallback(
135174 ({ valid, values, form }) => {
175+ console.log('currentL2', currentL2);
136176 if (valid) {
137177 if (values.unset) {
138178 unset();
139179 form.change('address', '');
180+ setNewAddress('');
140181 } else {
141182 construct(values.address);
183+ setNewAddress(values.address);
142184 }
143185 } else {
144186 unconstruct();
145187 }
146188 },
147− [construct, unconstruct, unset]
189+ [construct, unconstruct, unset, setNewAddress, currentL2]
148190 );
149191
150192 const initialValues = useMemo(() => ({ unset: false }), []);
@@ -213,12 +255,25 @@ export default function SetProxy() {
213255
214256 <Grid.Item full as={FormError} />
215257
216− <Grid.Item
217− full
218− as={InlineEthereumTransaction}
219− {...bind}
220− onReturn={() => pop()}
221− />
258+ {currentL2 ? (
259+ <Grid.Item
260+ as={Button}
261+ full
262+ className="set-proxy"
263+ center
264+ solid
265+ disabled={values.unset}
266+ onClick={setProxy}>
267+ {'Sign Transaction'}
268+ </Grid.Item>
269+ ) : (
270+ <Grid.Item
271+ full
272+ as={InlineEthereumTransaction}
273+ {...bind}
274+ onReturn={() => pop()}
275+ />
276+ )}
222277 </>
223278 )}
224279 </BridgeForm>
src/views/UrbitID/SetProxy.scssnew file+57
@@ -0,0 +1,57 @@
1+@import 'style/shared/variables.scss';
2+
3+.cohort {
4+ font-size: 14px;
5+
6+ .number-emphasis {
7+ background-color: $light-gray;
8+ border-radius: $small-border-radius;
9+ margin: 0 4px;
10+ }
11+
12+ .body-pane {
13+ min-height: 212px;
14+ justify-content: space-between;
15+ font-size: 14px;
16+
17+ &.center {
18+ justify-content: center;
19+ }
20+
21+ .content {
22+ width: 100%;
23+ font-size: 14px;
24+ line-height: 24px;
25+
26+ &.center {
27+ text-align: center;
28+ margin-top: 20px;
29+ width: 320px;
30+ margin: auto;
31+ }
32+
33+ }
34+
35+
36+ }
37+
38+.set-proxy {
39+ border-radius: $medium-border-radius;
40+ width: 100%;
41+ height: 32px;
42+ font-size: 14px;
43+ background-color: black;
44+ color: white;
45+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, Roboto, Helvetica,
46+ Arial, sans-serif, 'Apple Color Emoji';
47+ border: none;
48+ margin-top: 8px;
49+ padding: 8px;
50+
51+ &.loading {
52+ background-color: $mid-gray;
53+ }
54+}
55+
56+
57+}