on master help sign in
Add storage logic for star release contracts
commitfeb5b56dc619d9210123ad6b630bc7446c41f2b9 authorLiam Fitzgerald <liam@urizen.co> dateThu 7 Nov 2019, 12:37 (7 years ago) parentf47923e
5 files changed+173
src/lib/contracts.js+2 src/lib/starRelease.js+86 src/store/Provider.js+2 src/store/lib/useStarReleaseStore.js+63 src/store/starRelease.js+20
src/lib/contracts.js+2
@@ -4,6 +4,8 @@ const CONTRACT_ADDRESSES = {
44 azimuth: '0x863d9c2e5c4c133596cfac29d55255f0d0f86381',
55 polls: '0x935452c45eda2958976a429c9733c40302995efd',
66 delegatedSending: '0xb71c0b6cee1bcae56dfe95cd9d3e41ddd7eafc43',
7+ linearSR: '0xa32c3019b256880A8c5458379188eea6F3934e2F',
8+ conditionalSR: '0x35EB3B102d9C1B69Ac1469C1B1FE1799850CD3EB',
79 },
810 ROPSTEN: {
911 ecliptic: '0x8b9f86a28921d9c705b3113a755fb979e1bd1bce',
src/lib/starRelease.jsnew file+86
@@ -0,0 +1,86 @@
1+import { linearSR, conditionalSR } from 'azimuth-js';
2+import { Just, Nothing } from 'folktale/maybe';
3+
4+function mapRange(amount, cb) {
5+ return [...Array(amount).keys()].map(cb);
6+}
7+
8+// Preferentially withdraw from conditional contracts and use linear
9+// to mop up the rest
10+export function generateWithdrawTxs(contracts, batchLimits, amount, to) {
11+ const [left, ...csrTxs] = generateConditionalWithdrawTxs(
12+ contracts,
13+ batchLimits,
14+ amount,
15+ to
16+ );
17+ const lsrTxs = generateLinearWithdrawTxs(contracts, left, to);
18+ return [...csrTxs, ...lsrTxs];
19+}
20+
21+function generateConditionalWithdrawTxs(
22+ contracts,
23+ batchLimits,
24+ amount,
25+ to,
26+ offset = 0
27+) {
28+ // Successfully withdraw all requesed
29+ if (amount <= 0) {
30+ return [0];
31+ }
32+ // Return missing amount in car
33+ if (batchLimits.length === 0) {
34+ return [amount];
35+ }
36+ const [next, ...rest] = batchLimits;
37+ const currentAmount = Math.min(amount, next);
38+ return [
39+ ...generateConditionalWithdrawTxs(
40+ contracts,
41+ rest,
42+ amount - currentAmount,
43+ to,
44+ offset + 1
45+ ),
46+ ...mapRange(currentAmount, () =>
47+ conditionalSR.withdrawTo(contracts, offset, to)
48+ ),
49+ ];
50+}
51+
52+function generateLinearWithdrawTxs(contracts, amount, to) {
53+ return mapRange(amount, () => linearSR.withdrawTo(contracts, to));
54+}
55+
56+export async function getConditional(contracts, address) {
57+ const [commitment, batches] = await Promise.all([
58+ conditionalSR.getCommitment(contracts, address),
59+ conditionalSR.getBatches(contracts, address),
60+ ]);
61+
62+ const { total } = commitment;
63+ const withdrawLimits = await Promise.all(
64+ batches.map((_, idx) =>
65+ conditionalSR.getWithdrawLimit(contracts, address, idx)
66+ )
67+ );
68+ const available = withdrawLimits.reduce((acc, val) => acc + val, 0);
69+
70+ const withdrawnAmounts = await conditionalSR.getWithdrawn(contracts, address);
71+
72+ const withdrawn = withdrawnAmounts.reduce((acc, val) => acc + val, 0);
73+ const batchLimits = withdrawLimits.map(
74+ (limit, idx) => limit - withdrawnAmounts[idx]
75+ );
76+
77+ return { total, available, withdrawn, batchLimits };
78+}
79+
80+export async function getLinear(contracts, address) {
81+ const { amount, withdrawn } = await linearSR.getBatch(contracts, address);
82+
83+ const available = // Contract errors on withdrawing from a user that does not have any
84+ amount > 0 ? await linearSR.getWithdrawLimit(contracts, address) : 0;
85+ return { available, withdrawn, total: amount };
86+}
src/store/Provider.js+2
@@ -5,6 +5,7 @@ import { OnlineProvider } from './online';
55import { NetworkProvider } from './network';
66import { WalletProvider } from './wallet';
77import { PointCursorProvider } from './pointCursor';
8+import { StarReleaseCacheProvider } from './starRelease';
89import { PointCacheProvider } from './pointCache';
910import { TxnCursorProvider } from './txnCursor';
1011import { MediaQueryProvider } from 'lib/MediaQuery';
@@ -19,4 +20,5 @@ export default nest([
1920 PointCacheProvider,
2021 TxnCursorProvider,
2122 MediaQueryProvider,
23+ StarReleaseCacheProvider,
2224]);
src/store/lib/useStarReleaseStore.jsnew file+63
@@ -0,0 +1,63 @@
1+import { useState, useCallback } from 'react';
2+import { Nothing, Just } from 'folktale/maybe';
3+
4+import { useNetwork } from 'store/network';
5+import { useWallet } from 'store/wallet';
6+import {
7+ generateWithdrawTxs,
8+ getLinear,
9+ getConditional,
10+} from 'lib/starRelease';
11+
12+export default function useStarRelease() {
13+ const { contracts } = useNetwork();
14+ const { wallet } = useWallet();
15+
16+ const [starReleaseDetails, _setDetails] = useState(Nothing());
17+
18+ const [batchLimits, setBatchLimits] = useState([]);
19+
20+ const syncStarReleaseDetails = useCallback(async () => {
21+ const _wallet = wallet.getOrElse(null);
22+ const _contracts = contracts.getOrElse(null);
23+ if (!(_contracts && _wallet)) {
24+ return;
25+ }
26+ _setDetails(Nothing());
27+
28+ const address = _wallet.address;
29+
30+ try {
31+ const [linear, conditional] = await Promise.all([
32+ getLinear(_contracts, address),
33+ getConditional(_contracts, address),
34+ ]);
35+
36+ const keys = Object.keys(linear);
37+ const result = keys.reduce(
38+ (acc, key) => ({ ...acc, [key]: linear[key] + conditional[key] }),
39+ {}
40+ );
41+ setBatchLimits(conditional.batchLimits);
42+
43+ _setDetails(Just(result));
44+ } catch (e) {
45+ _setDetails(Nothing());
46+ console.error(e);
47+ }
48+ }, [contracts, wallet]);
49+
50+ const withdraw = useCallback(
51+ (amount, to) => {
52+ const _wallet = wallet.getOrElse(null);
53+ const _contracts = contracts.getOrElse(null);
54+ if (!(_contracts && _wallet)) {
55+ return [];
56+ }
57+ return generateWithdrawTxs(contracts, batchLimits, amount, to);
58+ },
59+ [batchLimits, contracts, wallet]
60+ );
61+
62+ return { starReleaseDetails, syncStarReleaseDetails, withdraw };
63+}
src/store/starRelease.jsnew file+20
@@ -0,0 +1,20 @@
1+import React, { createContext, useContext } from 'react';
2+
3+import useStarReleaseStore from './lib/useStarReleaseStore';
4+
5+export const StarReleaseCacheContext = createContext(null);
6+
7+export function StarReleaseCacheProvider({ children }) {
8+ const cache = useStarReleaseStore();
9+
10+ return (
11+ <StarReleaseCacheContext.Provider value={cache}>
12+ {children}
13+ </StarReleaseCacheContext.Provider>
14+ );
15+}
16+
17+// Hook version
18+export function useStarReleaseCache() {
19+ return useContext(StarReleaseCacheContext);
20+}