@@ -4,36 +4,39 @@ import * as need from 'lib/need';
44import SecureLS from 'secure-ls';
55
66import { Invite } from 'lib/types/Invite';
7−import { convertToInt } from './convertToInt';
8−import { isDevelopment, isRopsten } from './flags';
97import {
10− adopt,
11− detach,
12− generateInviteWallet,
13− getPendingSpawns,
14− reject,
15−} from './utils/roller';
16−import { ROLLER_HOSTS } from './constants';
8+ deriveNetworkSeedFromUrbitWallet,
9+ attemptNetworkSeedDerivation,
10+} from 'lib/keys';
1711
1812import { useNetwork } from 'store/network';
1913import { usePointCursor } from 'store/pointCursor';
20−import { useRollerStore } from 'store/roller';
14+import { EMPTY_POINT, useRollerStore } from 'store/rollerStore';
2115import { useWallet } from 'store/wallet';
2216import { getStoredInvites, setStoredInvites } from 'store/storage/roller';
2317import { usePointCache } from 'store/pointCache';
2418import { getOutgoingPoints } from 'views/Points';
19+
2520import {
2621 getSpawnProxy,
2722 getManagerProxy,
2823 getAddressProxy,
2924 getTransferProxy,
3025} from './utils/proxy';
31−import { isPlanet } from './utils/point';
32−
26+import { isPlanet, toL1Details } from './utils/point';
27+import { convertToInt } from './convertToInt';
28+import { isDevelopment, isRopsten } from './flags';
3329import {
34− deriveNetworkSeedFromUrbitWallet,
35− attemptNetworkSeedDerivation,
36−} from 'lib/keys';
30+ generateInviteWallet,
31+ getPendingSpawns,
32+ submitL2Transaction,
33+ getTimeToNextBatch,
34+ registerProxyAddress,
35+ adopt,
36+ detach,
37+ reject,
38+} from './utils/roller';
39+import { ROLLER_HOSTS } from './constants';
3740
3841import {
3942 Config,
@@ -45,13 +48,9 @@ import {
4548 UnspawnedPoints,
4649} from '@urbit/roller-api';
4750
48−import {
49− configureKeys,
50− getTimeToNextBatch,
51− spawn,
52− transferPointRequest,
53− registerProxyAddress,
54−} from './utils/roller';
51+import Point, { Points, Relationship } from './types/Point';
52+import { useTimerStore } from 'store/timerStore';
53+import { ReticketParams, SendL2Params } from './types/L2Transaction';
5554
5655const ONE_SECOND = 1000;
5756
@@ -81,17 +80,19 @@ export default function useRoller() {
8180 const controlledPoints = allPoints?.controlledPoints;
8281 const getDetails = allPoints?.getDetails;
8382
83+ const { setNextRoll } = useTimerStore();
84+
8485 const {
8586 nextBatchTime,
86− currentL2,
87+ point,
8788 invitePoints,
8889 invites,
8990 setNextBatchTime,
90− setNextRoll,
9191 setPendingTransactions,
9292 setInvites,
9393 setInvitePoints,
9494 setInviteGeneratingNum,
95+ setPoints,
9596 } = useRollerStore();
9697 const [config, setConfig] = useState<Config | null>(null);
9798
@@ -158,6 +159,7 @@ export default function useRoller() {
158159 throw new Error('Internal Error: Missing Contracts/Web3/Wallet');
159160 }
160161
162+ // TODO: remove when UI disables management proxy from spawning invites
161163 // if (Just.hasInstance(authMnemonic)) {
162164 // throw new Error(
163165 // "Auth key Error: A management mnemonic can't create invite codes"
@@ -173,7 +175,6 @@ export default function useRoller() {
173175
174176 const starInfo = await api.getPoint(_point);
175177 const invites: Invite[] = [];
176− const requests: Promise<string>[] = [];
177178
178179 const proxy = getSpawnProxy(starInfo.ownership!, _wallet.address);
179180
@@ -195,33 +196,36 @@ export default function useRoller() {
195196 _authToken
196197 );
197198
198− const spawnRequest = spawn(
199+ await submitL2Transaction({
199200 api,
200− _wallet,
201− _point,
201+ address: _wallet.address,
202+ wallet: _wallet,
203+ ship: _point,
202204 proxy,
203− nonceInc,
204− planet,
205+ nonce: nonceInc,
206+ pointToSpawn: planet,
207+ type: 'spawn',
205208 walletType,
206− _web3
207− );
209+ web3: _web3,
210+ });
208211
209212 const networkSeed = await deriveNetworkSeedFromUrbitWallet(
210213 inviteWallet,
211214 1
212215 );
213− const configureKeysRequest = configureKeys(
216+ await submitL2Transaction({
214217 api,
215− _wallet,
216− planet,
217− 'own',
218− 0,
218+ wallet: _wallet,
219+ ship: planet,
220+ proxy: 'own',
221+ nonce: 0,
219222 networkSeed,
223+ type: 'configureKeys',
220224 walletType,
221− _web3
222− );
225+ web3: _web3,
226+ });
223227
224− const setManagementProxyRequest = registerProxyAddress(
228+ await registerProxyAddress(
225229 api,
226230 _wallet,
227231 planet,
@@ -233,24 +237,17 @@ export default function useRoller() {
233237 _web3
234238 );
235239
236− const transferRequest = transferPointRequest(
240+ await submitL2Transaction({
237241 api,
238− _wallet,
239− planet,
240− 'own',
241− 2,
242− inviteWallet.ownership.keys.address,
242+ wallet: _wallet,
243+ ship: planet,
244+ proxy: 'own',
245+ type: 'transferPoint',
246+ nonce: 2,
247+ address: inviteWallet.ownership.keys.address,
243248 walletType,
244− _web3
245− );
246−
247− requests.push(
248− spawnRequest,
249− configureKeysRequest,
250− setManagementProxyRequest,
251− transferRequest
252− );
253− await Promise.all(requests);
249+ web3: _web3,
250+ });
254251
255252 invites.push({
256253 hash: '',
@@ -497,30 +494,23 @@ export default function useRoller() {
497494 authToken,
498495 revision: nextRevision,
499496 });
500− const txHash = await configureKeys(
497+ const txHash = await submitL2Transaction({
501498 api,
502− _wallet,
503− _point,
504− proxy!,
499+ wallet: _wallet,
500+ ship: _point,
501+ proxy: proxy!,
505502 nonce,
506503 networkSeed,
504+ type: 'configureKeys',
507505 walletType,
508− _web3,
509− breach
510− );
506+ web3: _web3,
507+ breach,
508+ });
511509 const pendingTx = await api.getPendingTx(txHash);
512510
513511 return pendingTx;
514512 };
515513
516− interface ReticketParams {
517− point: Ship;
518− to: EthAddress;
519− manager: EthAddress;
520− fromWallet: any; // TODO: wallet type
521− toWallet: any; // TODO: wallet type
522− }
523−
524514 const performL2Reticket = async ({
525515 point,
526516 to,
@@ -542,16 +532,17 @@ export default function useRoller() {
542532 toWallet,
543533 nextRevision
544534 );
545− const configureKeysRequest = await configureKeys(
535+ const configureKeysRequest = await submitL2Transaction({
546536 api,
547− fromWallet,
548− point,
537+ wallet: fromWallet,
538+ ship: point,
549539 proxy,
550540 nonce,
551541 networkSeed,
552542 walletType,
553− _web3
554− );
543+ type: 'configureKeys',
544+ web3: _web3,
545+ });
555546 nonce = nonce + 1;
556547 requests.push(configureKeysRequest);
557548
@@ -587,16 +578,17 @@ export default function useRoller() {
587578 requests.push(registerSpawnRequest);
588579 }
589580 // 4. Transfer point
590− const transferTxRequest = await transferPointRequest(
581+ const transferTxRequest = await submitL2Transaction({
591582 api,
592− fromWallet,
593− point,
594− proxy,
583+ wallet: fromWallet,
584+ ship: point,
585+ proxy: 'own',
586+ type: 'transferPoint',
595587 nonce,
596− to,
588+ address: to,
597589 walletType,
598− _web3
599− );
590+ web3: _web3,
591+ });
600592 requests.push(transferTxRequest);
601593
602594 const hashes = await Promise.all(requests);
@@ -724,17 +716,19 @@ export default function useRoller() {
724716
725717 const nonce = await api.getNonce({ ship: _point, proxy });
726718
727− const txHash = await transferPointRequest(
719+ const txHash = await submitL2Transaction({
728720 api,
729− _wallet,
730− _point,
721+ wallet: _wallet,
722+ ship: _point,
731723 proxy,
732724 nonce,
733725 address,
726+ type: 'transferPoint',
734727 walletType,
735− _web3,
736− reset || false
737− );
728+ web3: _web3,
729+ reset,
730+ });
731+
738732 const pendingTx = await api.getPendingTx(txHash);
739733
740734 return pendingTx;
@@ -742,6 +736,114 @@ export default function useRoller() {
742736 [api, pointCursor, wallet, web3, walletType]
743737 );
744738
739+ const sendL2Transaction = useCallback(
740+ async (params: SendL2Params) => {
741+ const _point = need.point(pointCursor);
742+ const _wallet = wallet.getOrElse(null);
743+ const _web3 = web3.getOrElse(null);
744+
745+ if (!_wallet) {
746+ // not using need because we want a custom error
747+ throw new Error('Internal Error: Missing Wallet');
748+ }
749+
750+ return submitL2Transaction({
751+ ...params,
752+ api,
753+ wallet: _wallet,
754+ walletType,
755+ web3: _web3,
756+ ship: _point,
757+ });
758+ },
759+ [api, pointCursor, wallet, web3, walletType]
760+ );
761+
762+ const changeSponsor = useCallback(
763+ async (newSponsor: number) => {
764+ const _wallet = wallet.getOrElse(null);
765+ const _point = need.point(pointCursor);
766+
767+ if (!_wallet) {
768+ // not using need because we want a custom error
769+ throw new Error('Internal Error: Missing Wallet');
770+ }
771+
772+ const pointDetails = await api.getPoint(_point);
773+ const proxy = getManagerProxy(pointDetails.ownership!, _wallet.address);
774+
775+ if (proxy === undefined)
776+ throw new Error("Error: Address doesn't match proxy");
777+
778+ const nonce = await api.getNonce({ ship: _point, proxy });
779+
780+ sendL2Transaction({
781+ newSponsor,
782+ nonce,
783+ proxy,
784+ type: 'escape',
785+ ship: _point,
786+ });
787+ },
788+ [api, sendL2Transaction, wallet, pointCursor]
789+ );
790+
791+ const initPoint = useCallback(
792+ (relationship: Relationship) => async (point: string | number) => {
793+ const _wallet = wallet.getOrElse(null);
794+
795+ if (!_wallet) {
796+ return EMPTY_POINT;
797+ }
798+ try {
799+ const pointNum = Number(point);
800+ const rawDetails = await api.getPoint(pointNum);
801+ const details = toL1Details(rawDetails);
802+
803+ return new Point(pointNum, relationship, details, _wallet.address);
804+ } catch (e) {
805+ console.warn(e);
806+ }
807+ },
808+ [api, wallet]
809+ );
810+
811+ const getPointDetails = useCallback(
812+ async (
813+ ownedPoints: number[],
814+ incomingPoints: number[],
815+ managingPoints: number[],
816+ votingPoints: number[],
817+ spawningPoints: number[]
818+ ) => {
819+ try {
820+ const allPoints = [
821+ await Promise.all(ownedPoints.map(initPoint(Relationship.own))),
822+ await Promise.all(
823+ incomingPoints.map(initPoint(Relationship.transfer))
824+ ),
825+ await Promise.all(managingPoints.map(initPoint(Relationship.manage))),
826+ await Promise.all(votingPoints.map(initPoint(Relationship.vote))),
827+ await Promise.all(spawningPoints.map(initPoint(Relationship.spawn))),
828+ ];
829+
830+ setPoints(
831+ allPoints.reduce((acc: Points, cur: (Point | undefined)[]) => {
832+ cur.forEach(p => {
833+ if (p) {
834+ acc[p.value] = p;
835+ }
836+ });
837+ return acc;
838+ }, {})
839+ );
840+ } catch (e) {
841+ console.warn(e);
842+ }
843+ },
844+ [setPoints, initPoint]
845+ );
846+
745847 // On load, get initial config
746848 useEffect(() => {
747849 if (config) {
@@ -759,30 +861,32 @@ export default function useRoller() {
759861 if (nextBatchTime - ONE_SECOND <= new Date().getTime()) {
760862 api.getRollerConfig().then(response => {
761863 setNextBatchTime(response.nextBatch);
762− getNumInvites(currentL2);
864+ getNumInvites(!!point?.isL2);
763865 });
764866 }
765867 }, 10000000);
766868
767869 return () => clearInterval(interval);
768− }, [nextBatchTime, getPendingTransactions, currentL2]); // eslint-disable-line react-hooks/exhaustive-deps
870+ }, [nextBatchTime, getPendingTransactions, point]); // eslint-disable-line react-hooks/exhaustive-deps
769871
770872 return {
771873 adoptPoint,
772874 api,
773− performL2Reticket,
875+ changeSponsor,
774876 config,
775− getPoints,
877+ configureNetworkingKeys,
776878 getInvites,
879+ getNumInvites,
880+ getPoints,
881+ getPointDetails,
777882 getPendingTransactions,
778883 generateInviteCodes,
779884 kickPoint,
780885 rejectPoint,
781886 transferPoint,
887+ ls,
888+ performL2Reticket,
782889 setProxyAddress,
783− configureNetworkingKeys,
784− getNumInvites,
785890 showInvite,
786− ls,
787891 };
788892}