on 685bb75 help sign in
bridge/src/lib/utils/roller.ts
221 lines 5.6 kB history raw
1import { Just, Nothing } from 'folktale/maybe';
2import { Invite } from 'lib/types/Invite';
3import { signTransactionHash } from 'lib/authToken';
4import { randomHex } from 'web3-utils';
6import RollerRPCAPI, {
7 Proxy,
8 Signature,
9 From,
10 EthAddress,
11 AddressParams,
12 Ship,
13 SpawnParams,
14 L2Data,
15 PendingTransaction,
16} from '@urbit/roller-api';
18import { deriveNetworkKeys, CRYPTO_SUITE_VERSION } from 'lib/keys';
19import { addHexPrefix } from 'lib/utils/address';
20import { makeDeterministicTicket, generateWallet } from 'lib/walletgen';
22export const SECOND = 1000;
23export const MINUTE = SECOND * 60;
24export const HOUR = MINUTE * 60;
26export const padZero = (amount: number) =>
27 `${amount < 10 && amount > 0 ? '0' : ''}${amount}`;
29export const hasPoint = (point: number) => (invite: Invite) =>
30 invite.planet === point;
32export const getTimeToNextBatch = (nextBatch: number, now: number) => {
33 const toNext = Math.max(nextBatch - now, 0);
34 const hours = Math.floor(toNext / HOUR);
35 const minutes = Math.floor((toNext - hours * HOUR) / MINUTE);
36 const seconds = Math.floor(
37 (toNext - hours * HOUR - minutes * MINUTE) / SECOND
38 );
40 return `${padZero(hours)}h ${padZero(minutes)}m ${padZero(seconds)}s`;
41};
43export const isL2 = (dom?: string) => dom === 'l2' || dom === 'spawn';
45export const isL2Spawn = (dom?: string) => dom === 'spawn';
47export const generateInviteWallet = async (point: number, seed: string) => {
48 const ticket = makeDeterministicTicket(point, seed);
49 const inviteWallet = await generateWallet(point, ticket, true);
51 return { ticket, inviteWallet };
52};
54export const spawn = async (
55 api: RollerRPCAPI,
56 _wallet: any,
57 _point: number,
58 proxy: string,
59 nonce: number,
60 planet: number
61) => {
62 const from = {
63 ship: _point, //ship that is spawning the planet
64 proxy,
65 };
67 const data = {
68 address: _wallet.address,
69 ship: planet, // ship to spawn
70 };
72 const hash = await api.hashTransaction(nonce, from, 'spawn', data);
73 const sSig = signTransactionHash(hash, _wallet.privateKey);
74 return api.spawn(sSig, from, _wallet.address, data);
75};
77export const configureKeys = async (
78 api: RollerRPCAPI,
79 wallet: any,
80 point: Ship,
81 proxy: string,
82 nonce: number,
83 networkSeed: any,
84 breach?: boolean
85) => {
86 const from = {
87 ship: point, //ship to configure keys
88 proxy,
89 };
91 // TODO: do something here?
92 if (Nothing.hasInstance(networkSeed)) {
93 console.log("Network key Error: couldn't derive network keys");
94 // throw new Error("Network key Error: couldn't derive network keys");
95 }
97 const seed = Just.hasInstance(networkSeed)
98 ? networkSeed.value
99 : randomHex(32);
101 const pair = deriveNetworkKeys(seed);
103 const data = {
104 encrypt: addHexPrefix(pair.crypt.public),
105 auth: addHexPrefix(pair.auth.public),
106 cryptoSuite: String(CRYPTO_SUITE_VERSION),
107 breach: breach || false,
108 };
110 const hash = await api.hashTransaction(nonce, from, 'configureKeys', data);
111 const sig = signTransactionHash(hash, wallet.privateKey);
112 return api.configureKeys(sig, from, wallet.address, data);
113};
115export const transferPointRequest = async (
116 api: RollerRPCAPI,
117 _wallet: any,
118 pointToTransfer: Ship,
119 proxy: string,
120 nonce: number,
121 address: string,
122 reset?: boolean
123) => {
124 const from = {
125 ship: pointToTransfer,
126 proxy,
127 };
129 const data = {
130 address,
131 reset: reset || false,
132 };
133 const hash = await api.hashTransaction(nonce, from, 'transferPoint', data);
134 const sig = signTransactionHash(hash, _wallet.privateKey);
135 return api.transferPoint(sig, from, _wallet.address, data);
136};
138const proxyType = (proxy: Proxy) => {
139 switch (proxy) {
140 case 'manage':
141 return 'setManagementProxy';
142 case 'spawn':
143 return 'setSpawnProxy';
144 case 'transfer':
145 return 'setTransferProxy';
146 default:
147 throw new Error(`Unknown proxyType ${proxy}`);
148 }
149};
151const setProxy = async (
152 api: RollerRPCAPI,
153 proxyAddressType: string,
154 sig: Signature,
155 from: From,
156 address: EthAddress,
157 data: AddressParams
158) => {
159 switch (proxyAddressType) {
160 case 'manage':
161 return await api.setManagementProxy(sig, from, address, data);
162 case 'spawn':
163 return await api.setSpawnProxy(sig, from, address, data);
164 case 'transfer':
165 return await api.setTransferProxy(sig, from, address, data);
166 default:
167 throw new Error(`Unknown proxyType ${proxyAddressType}`);
168 }
169};
171export const registerProxyAddress = async (
172 api: RollerRPCAPI,
173 _wallet: any,
174 _point: Ship,
175 proxy: string,
176 proxyAddressType: string,
177 nonce: number,
178 address: string
179) => {
180 const from = {
181 ship: _point,
182 proxy,
183 };
184 const proxyData = { address };
185 const proxyHash = await api.hashTransaction(
186 nonce,
187 from,
188 proxyType(proxyAddressType),
189 proxyData
190 );
192 return setProxy(
193 api,
194 proxyAddressType,
195 signTransactionHash(proxyHash, _wallet.privateKey),
196 from,
197 _wallet.address,
198 proxyData
199 );
200};
202export const reticketL2Point = async () => {};
204export const hasInvite = (point: number) => (invite: Invite) =>
205 invite.planet === point && invite.ticket.length > 0;
207function isSpawn(tx: L2Data | undefined): tx is SpawnParams {
208 return (tx as SpawnParams) !== undefined;
211function isShipNumber(ship: number | string | undefined): ship is number {
212 return (ship as number) !== undefined;
215export const getPendingSpawns = (pendingTxs: PendingTransaction[]) =>
216 pendingTxs.reduce((acc, pending) => {
217 return isSpawn(pending.rawTx?.tx) &&
218 isShipNumber(pending.rawTx?.tx.data.ship)
219 ? acc.add(pending.rawTx?.tx.data.ship!)
220 : acc;
221 }, new Set<number>());