@@ -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+}