on fe6ee13 help sign in
bridge/src/lib/starRelease.js
132 lines 3.9 kB history raw
1import { linearSR, conditionalSR } from 'azimuth-js';
3function mapRange(amount, cb) {
4 return [...Array(amount).keys()].map(cb);
5}
7// Preferentially withdraw from conditional contracts and use linear
8// to mop up the rest
9export function generateWithdrawTxs(contracts, batchLimits, amount, to) {
10 const [left, ...csrTxs] = generateConditionalWithdrawTxs(
11 contracts,
12 batchLimits,
13 amount,
14 to
15 );
16 const lsrTxs = generateLinearWithdrawTxs(contracts, left, to);
17 return [...csrTxs, ...lsrTxs];
20/**
21 * Recurse over batchLimits to generate a valid number of withdraw txs.
22 * amount may exceed the number of withdraw txs available in the consolidated SR contract.
23 *
24 * @param {object} contracts - The azimuth contracts object
25 * @param {array} batchLimits - An array of the maximum withdraw limit for each batch
26 * @param {amount} amount - The number of txs to be generated
27 * @param {string} to - The addresss to withdraw to
28 * @return {array} An array with the number of transactions missing as the head
29 * (i.e. requested amount exceeded available), and the generated transactions
30 * as the rest of the list
31 */
32function generateConditionalWithdrawTxs(
33 contracts,
34 batchLimits,
35 amount,
36 to,
37 offset = 0
38) {
39 // Successfully withdrawn all requested, none missing
40 if (amount <= 0) {
41 return [0];
42 }
43 // Return missing amount in head of list
44 if (batchLimits.length === 0) {
45 return [amount];
46 }
47 const [next, ...rest] = batchLimits;
48 const currentAmount = Math.min(amount, next);
49 return [
50 ...generateConditionalWithdrawTxs(
51 contracts,
52 rest,
53 amount - currentAmount,
54 to,
55 offset + 1
56 ),
57 ...mapRange(currentAmount, () =>
58 conditionalSR.withdrawTo(contracts, offset, to)
59 ),
60 ];
63function generateLinearWithdrawTxs(contracts, amount, to) {
64 return mapRange(amount, () => linearSR.withdrawTo(contracts, to));
67export async function getConditional(contracts, address) {
68 const [commitment, batches, remaining] = await Promise.all([
69 conditionalSR.getCommitment(contracts, address),
70 conditionalSR.getBatches(contracts, address),
71 conditionalSR.getRemainingStars(contracts, address),
72 ]);
74 if (commitment === null || batches === null) {
75 return { total: 0, available: 0, withdrawn: 0, batchLimits: [] };
76 }
78 const total = remaining.length;
79 let balance = total;
81 // does not account for forfeiting or withdrawl
82 const limits = await Promise.all(
83 batches.map((_, idx) =>
84 conditionalSR.getWithdrawLimit(contracts, address, idx)
85 )
86 );
88 const withdrawn = await conditionalSR.getWithdrawn(contracts, address);
90 const forfeited = await conditionalSR.getForfeited(contracts, address);
92 const batchLimits = [];
94 for (let i = 0; i < limits.length; i++) {
95 // skip batch if forfeited or no stars left
96 if (forfeited[i] || balance === 0) {
97 batchLimits.push(0);
98 continue;
99 }
100 const availableInBatch = limits[i] - withdrawn[i];
101 if (balance < availableInBatch) {
102 batchLimits.push(balance);
103 balance = 0;
104 continue;
105 }
106 batchLimits.push(availableInBatch);
107 balance = balance - availableInBatch;
108 }
110 const withdrawnTotal = withdrawn.reduce((acc, val) => acc + val, 0);
111 const available =
112 batchLimits.reduce((acc, val) => acc + val, 0) + withdrawnTotal;
114 return { total, available, withdrawn: withdrawnTotal, batchLimits };
117export async function getLinear(contracts, address) {
118 const remaining = (await linearSR.getRemainingStars(contracts, address))
119 .length;
120 const batch = await linearSR.getBatch(contracts, address);
121 const { amount, withdrawn } = batch;
123 // Contract errors on withdrawing from a user that does not have any
124 const available =
125 amount > 0
126 ? Math.min(await linearSR.getWithdrawLimit(contracts, address), remaining)
127 : 0;
129 const total = Math.min(amount, remaining);
131 return { available, withdrawn, total };