@reserve-protocol/dtf-rebalance-lib 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { PriceRange, Rebalance, RebalanceLimits, WeightRange } from './types';
1
+ import { PriceRange, Rebalance, RebalanceLimits, WeightRange } from "./types";
2
2
  export declare enum AuctionRound {
3
3
  EJECT = 0,
4
4
  PROGRESS = 1,
@@ -59,4 +59,4 @@ export declare const getTargetBasket: (_initialWeights: WeightRange[], _prices:
59
59
  * @param _priceError {1} Price error to use for each token during auction pricing; should be smaller than price error during startRebalance
60
60
  * @param _finalStageAt {1} The % rebalanced from the initial Folio to determine when is the final stage of the rebalance
61
61
  */
62
- export declare const getOpenAuction: (rebalance: Rebalance, _supply: bigint, _initialFolio: bigint[] | undefined, _targetBasket: bigint[] | undefined, _folio: bigint[], _decimals: bigint[], _prices: number[], _priceError: number[], _finalStageAt: number, logging?: boolean) => [OpenAuctionArgs, AuctionMetrics];
62
+ export declare const getOpenAuction: (rebalance: Rebalance, _supply: bigint, _initialFolio: bigint[] | undefined, _targetBasket: bigint[] | undefined, _folio: bigint[], _decimals: bigint[], _prices: number[], _priceError: number[], _finalStageAt: number, debug?: boolean) => [OpenAuctionArgs, AuctionMetrics];
@@ -27,17 +27,13 @@ var AuctionRound;
27
27
  */
28
28
  const getTargetBasket = (_initialWeights, _prices, _decimals) => {
29
29
  if (_initialWeights.length != _prices.length) {
30
- throw new Error('length mismatch');
30
+ throw new Error("length mismatch");
31
31
  }
32
32
  const vals = _initialWeights.map((initialWeight, i) => {
33
33
  const price = new decimal_js_light_1.default(_prices[i]);
34
34
  const decimalScale = new decimal_js_light_1.default(`1e${_decimals[i]}`);
35
35
  // {USD/wholeBU} = D27{tok/BU} * {BU/wholeBU} / {tok/wholeTok} / D27 * {USD/wholeTok}
36
- return new decimal_js_light_1.default(initialWeight.spot.toString())
37
- .mul(numbers_1.D18d)
38
- .div(decimalScale)
39
- .div(numbers_1.D27d)
40
- .mul(price);
36
+ return new decimal_js_light_1.default(initialWeight.spot.toString()).mul(numbers_1.D18d).div(decimalScale).div(numbers_1.D27d).mul(price);
41
37
  });
42
38
  const totalValue = vals.reduce((a, b) => a.add(b));
43
39
  // D18{1} = {USD/wholeBU} / {USD/wholeBU} * D18
@@ -59,19 +55,19 @@ exports.getTargetBasket = getTargetBasket;
59
55
  * @param _priceError {1} Price error to use for each token during auction pricing; should be smaller than price error during startRebalance
60
56
  * @param _finalStageAt {1} The % rebalanced from the initial Folio to determine when is the final stage of the rebalance
61
57
  */
62
- const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket = [], _folio, _decimals, _prices, _priceError, _finalStageAt, logging) => {
63
- if (logging) {
64
- console.log('getOpenAuction', rebalance, _supply, _initialFolio, _targetBasket, _folio, _decimals, _prices, _priceError, _finalStageAt);
58
+ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket = [], _folio, _decimals, _prices, _priceError, _finalStageAt, debug) => {
59
+ if (debug) {
60
+ console.log("getOpenAuction", rebalance, _supply, _initialFolio, _targetBasket, _folio, _decimals, _prices, _priceError, _finalStageAt);
65
61
  }
66
62
  if (rebalance.tokens.length != _targetBasket.length ||
67
63
  _targetBasket.length != _folio.length ||
68
64
  _folio.length != _decimals.length ||
69
65
  _decimals.length != _prices.length ||
70
66
  _prices.length != _priceError.length) {
71
- throw new Error('length mismatch');
67
+ throw new Error("length mismatch");
72
68
  }
73
69
  if (_finalStageAt > 1) {
74
- throw new Error('finalStageAt must be less than 1');
70
+ throw new Error("finalStageAt must be less than 1");
75
71
  }
76
72
  // ================================================================
77
73
  // {wholeShare} = {share} / {share/wholeShare}
@@ -96,18 +92,9 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
96
92
  // {wholeTok/wholeBU} = D27{tok/BU} * {BU/wholeBU} / {tok/wholeTok} / D27
97
93
  let weightRanges = rebalance.weights.map((range, i) => {
98
94
  return {
99
- low: new decimal_js_light_1.default(range.low.toString())
100
- .mul(numbers_1.D18d)
101
- .div(decimalScale[i])
102
- .div(numbers_1.D27d),
103
- spot: new decimal_js_light_1.default(range.spot.toString())
104
- .mul(numbers_1.D18d)
105
- .div(decimalScale[i])
106
- .div(numbers_1.D27d),
107
- high: new decimal_js_light_1.default(range.high.toString())
108
- .mul(numbers_1.D18d)
109
- .div(decimalScale[i])
110
- .div(numbers_1.D27d),
95
+ low: new decimal_js_light_1.default(range.low.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
96
+ spot: new decimal_js_light_1.default(range.spot.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
97
+ high: new decimal_js_light_1.default(range.high.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
111
98
  };
112
99
  });
113
100
  const finalStageAt = new decimal_js_light_1.default(_finalStageAt.toString());
@@ -115,15 +102,18 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
115
102
  // calculate ideal spot limit, the actual BU<->share ratio
116
103
  // {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
117
104
  const shareValue = folio
118
- .map((f, i) => f.mul(prices[i]))
105
+ .map((f, i) => {
106
+ return rebalance.inRebalance[i] ? f.mul(prices[i]) : numbers_1.ZERO;
107
+ })
119
108
  .reduce((a, b) => a.add(b));
120
109
  // {USD/wholeBU} = {wholeTok/wholeBU} * {USD/wholeTok}
121
- const buValue = weightRanges
122
- .map((weightRange, i) => weightRange.spot.mul(prices[i]))
123
- .reduce((a, b) => a.add(b));
124
- if (logging) {
125
- console.log('shareValue', shareValue.toString());
126
- console.log('buValue', buValue.toString());
110
+ const buValue = weightRanges.map((weightRange, i) => weightRange.spot.mul(prices[i])).reduce((a, b) => a.add(b));
111
+ if (debug) {
112
+ console.log("shareValue", shareValue.toString());
113
+ console.log("buValue", buValue.toString());
114
+ }
115
+ if (buValue.div(shareValue).gt(10) || shareValue.div(buValue).gt(100)) {
116
+ throw new Error("buValue and shareValue are too different");
127
117
  }
128
118
  // ================================================================
129
119
  // calculate rebalanceTarget
@@ -135,7 +125,9 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
135
125
  }
136
126
  // {1} = {wholeTok/wholeShare} * {USD/wholeTok} / {USD/wholeShare}
137
127
  const portionBeingEjected = ejectionIndices
138
- .map((i) => folio[i].mul(prices[i]))
128
+ .map((i) => {
129
+ return rebalance.inRebalance[i] ? folio[i].mul(prices[i]) : numbers_1.ZERO;
130
+ })
139
131
  .reduce((a, b) => a.add(b), numbers_1.ZERO)
140
132
  .div(shareValue);
141
133
  // {1} = {USD/wholeShare} / {USD/wholeShare}
@@ -144,9 +136,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
144
136
  // {wholeTok/wholeShare} = {USD/wholeShare} * {1} / {USD/wholeTok}
145
137
  const balanceExpected = shareValue.mul(targetBasket[i]).div(prices[i]);
146
138
  // {wholeTok/wholeShare} = {wholeTok/wholeBU} * {wholeBU/wholeShare}
147
- const balanceInBU = balanceExpected.gt(actualBalance)
148
- ? actualBalance
149
- : balanceExpected;
139
+ const balanceInBU = balanceExpected.gt(actualBalance) ? actualBalance : balanceExpected;
150
140
  // {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
151
141
  return balanceInBU.mul(prices[i]);
152
142
  })
@@ -158,9 +148,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
158
148
  // {wholeTok/wholeShare} = {USD/wholeShare} * {1} / {USD/wholeTok}
159
149
  const balanceExpected = shareValue.mul(targetBasket[i]).div(prices[i]);
160
150
  // {wholeTok/wholeShare} = {wholeTok/wholeBU} * {wholeBU/wholeShare}
161
- const balanceInBU = balanceExpected.gt(initialBalance)
162
- ? initialBalance
163
- : balanceExpected;
151
+ const balanceInBU = balanceExpected.gt(initialBalance) ? initialBalance : balanceExpected;
164
152
  // {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
165
153
  return balanceInBU.mul(prices[i]);
166
154
  })
@@ -175,40 +163,45 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
175
163
  : progression.sub(initialProgression).div(numbers_1.ONE.sub(initialProgression));
176
164
  let rebalanceTarget = numbers_1.ONE;
177
165
  let round = AuctionRound.FINAL;
178
- if (logging) {
179
- console.log('initialProgression', initialProgression.toString());
180
- console.log('progression', progression.toString());
181
- console.log('relativeProgression', relativeProgression.toString());
182
- console.log('portionBeingEjected', portionBeingEjected.toString());
183
- console.log('finalStageAt', finalStageAt.toString());
166
+ if (debug) {
167
+ console.log("initialProgression", initialProgression.toString());
168
+ console.log("progression", progression.toString());
169
+ console.log("relativeProgression", relativeProgression.toString());
170
+ console.log("portionBeingEjected", portionBeingEjected.toString());
171
+ console.log("finalStageAt", finalStageAt.toString());
184
172
  }
185
- // make it an eject auction if there is 1 bps or more of value to eject
186
- if (portionBeingEjected.gte(1e-4)) {
187
- round = AuctionRound.EJECT;
188
- if (relativeProgression.lt(finalStageAt.sub(0.02))) {
189
- rebalanceTarget = progression.add(portionBeingEjected.mul(1.1)); // set rebalanceTarget to 10% more than needed to ensure ejection completes
190
- // do not finish trading yet
191
- if (rebalanceTarget.gte(numbers_1.ONE)) {
192
- rebalanceTarget = initialProgression.add(numbers_1.ONE.sub(initialProgression).mul(finalStageAt));
193
- }
194
- }
195
- }
196
- else if (relativeProgression.lt(finalStageAt.sub(0.02))) {
197
- // wiggle room to prevent having to re-run an auction at the same stage after price movement
173
+ // approach finalStageAt first
174
+ if (progression.lt(0.99) && relativeProgression.lt(finalStageAt.sub(0.02))) {
198
175
  round = AuctionRound.PROGRESS;
199
176
  rebalanceTarget = initialProgression.add(numbers_1.ONE.sub(initialProgression).mul(finalStageAt));
177
+ if (numbers_1.ONE.sub(rebalanceTarget).lt(0.99)) {
178
+ rebalanceTarget = numbers_1.ONE;
179
+ }
200
180
  if (rebalanceTarget.eq(numbers_1.ONE)) {
201
181
  round = AuctionRound.FINAL;
202
182
  }
203
183
  }
204
- if (rebalanceTarget.gt(numbers_1.ONE)) {
205
- throw new Error('something has gone very wrong');
184
+ // EJECT
185
+ if (portionBeingEjected.gt(0)) {
186
+ round = AuctionRound.EJECT;
187
+ // if the ejections are everything that's left, keep the finalStageAt targeting from above
188
+ if (progression.add(portionBeingEjected).lt(numbers_1.ONE)) {
189
+ // else: get rid of all the dust
190
+ let ejectionTarget = progression.add(portionBeingEjected.mul(1.02)); // buy 2% extra
191
+ if (ejectionTarget.gt(numbers_1.ONE)) {
192
+ ejectionTarget = numbers_1.ONE;
193
+ }
194
+ if (ejectionTarget.gt(rebalanceTarget)) {
195
+ rebalanceTarget = ejectionTarget;
196
+ }
197
+ }
206
198
  }
207
- if (rebalanceTarget.lt(progression)) {
208
- rebalanceTarget = numbers_1.ONE;
199
+ if (rebalanceTarget.lte(numbers_1.ZERO) || rebalanceTarget.gt(numbers_1.ONE)) {
200
+ throw new Error("something has gone very wrong");
209
201
  }
210
- if (logging) {
211
- console.log('rebalanceTarget', rebalanceTarget.toString());
202
+ if (debug) {
203
+ console.log("round", round);
204
+ console.log("rebalanceTarget", rebalanceTarget.toString());
212
205
  }
213
206
  // {1}
214
207
  const delta = numbers_1.ONE.sub(rebalanceTarget);
@@ -222,11 +215,21 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
222
215
  spot: (0, numbers_1.bn)(spotLimit.mul(numbers_1.D18d)),
223
216
  high: (0, numbers_1.bn)(spotLimit.add(spotLimit.mul(delta)).mul(numbers_1.D18d)),
224
217
  };
225
- if (round == AuctionRound.EJECT && rebalanceTarget.eq(numbers_1.ONE)) {
226
- // aim 1% higher if executed permissonlessly
227
- newLimits.spot += newLimits.spot * 1n / 100n;
218
+ // hold some surpluses aside if ejecting
219
+ if (round == AuctionRound.EJECT) {
220
+ // buy 0.1% more
221
+ newLimits.low += newLimits.low / 1000n;
222
+ // aim 1% higher
223
+ newLimits.spot += newLimits.spot / 100n;
228
224
  // leave 10% room to increase low in the future if ejection leaves dust behind
229
- newLimits.high += newLimits.high * 10n / 100n;
225
+ newLimits.high += newLimits.high / 10n;
226
+ }
227
+ else if (round == AuctionRound.FINAL && progression.gt(0.999)) {
228
+ // if it's the final round and we're within 0.1%, buy 10% more than we need to
229
+ const delta = (0, numbers_1.bn)(numbers_1.ONE.sub(progression).mul(numbers_1.D18d).div(10));
230
+ newLimits.low += (newLimits.low * delta) / 10n ** 18n;
231
+ newLimits.spot += (newLimits.spot * delta) / 10n ** 18n;
232
+ newLimits.high += (newLimits.high * delta) / 10n ** 18n;
230
233
  }
231
234
  // low
232
235
  if (newLimits.low < rebalance.limits.low) {
@@ -249,8 +252,8 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
249
252
  if (newLimits.high > rebalance.limits.high) {
250
253
  newLimits.high = rebalance.limits.high;
251
254
  }
252
- if (logging) {
253
- console.log('newLimits', newLimits);
255
+ if (debug) {
256
+ console.log("newLimits", newLimits);
254
257
  }
255
258
  // ================================================================
256
259
  // get new weights, constrained by extremes
@@ -263,10 +266,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
263
266
  // D27{tok/BU}
264
267
  const newWeights = rebalance.weights.map((weightRange, i) => {
265
268
  // {wholeTok/wholeBU} = {USD/wholeShare} * {1} / {wholeBU/wholeShare} / {USD/wholeTok}
266
- const idealWeight = shareValue
267
- .mul(targetBasket[i])
268
- .div(actualLimits.spot)
269
- .div(prices[i]);
269
+ const idealWeight = shareValue.mul(targetBasket[i]).div(actualLimits.spot).div(prices[i]);
270
270
  // D27{tok/BU} = {wholeTok/wholeBU} * D27 * {tok/wholeTok} / {BU/wholeBU}
271
271
  const newWeightsD27 = {
272
272
  low: (0, numbers_1.bn)(idealWeight
@@ -281,11 +281,21 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
281
281
  .mul(decimalScale[i])
282
282
  .div(numbers_1.D18d)),
283
283
  };
284
- if (round == AuctionRound.EJECT && rebalanceTarget.eq(numbers_1.ONE)) {
285
- // aim 1% higher if executed permissonlessly
286
- newWeightsD27.spot += newWeightsD27.spot * 1n / 100n;
284
+ // hold some surpluses aside if ejecting
285
+ if (round == AuctionRound.EJECT) {
286
+ // buy 0.1% more
287
+ newWeightsD27.low += newWeightsD27.low / 1000n;
288
+ // aim 1% higher
289
+ newWeightsD27.spot += newWeightsD27.spot / 100n;
287
290
  // leave 10% room to increase low in the future if ejection leaves dust behind
288
- newWeightsD27.high += newWeightsD27.high * 10n / 100n;
291
+ newWeightsD27.high += newWeightsD27.high / 10n;
292
+ }
293
+ else if (round == AuctionRound.FINAL && progression.gt(0.999)) {
294
+ // if it's the final round and we're within 0.1%, buy 10% more than we need to
295
+ const delta = (0, numbers_1.bn)(numbers_1.ONE.sub(progression).mul(numbers_1.D18d).div(10));
296
+ newWeightsD27.low += (newWeightsD27.low * delta) / 10n ** 18n;
297
+ newWeightsD27.spot += (newWeightsD27.spot * delta) / 10n ** 18n;
298
+ newWeightsD27.high += (newWeightsD27.high * delta) / 10n ** 18n;
289
299
  }
290
300
  if (newWeightsD27.low < weightRange.low) {
291
301
  newWeightsD27.low = weightRange.low;
@@ -307,8 +317,8 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
307
317
  }
308
318
  return newWeightsD27;
309
319
  });
310
- if (logging) {
311
- console.log('newWeights', newWeights);
320
+ if (debug) {
321
+ console.log("newWeights", newWeights);
312
322
  }
313
323
  // ================================================================
314
324
  // get new prices, constrained by extremes
@@ -317,7 +327,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
317
327
  // revert if price out of bounds
318
328
  const spotPrice = (0, numbers_1.bn)(prices[i].mul(numbers_1.D27d).div(decimalScale[i]));
319
329
  if (spotPrice < initialPrice.low || spotPrice > initialPrice.high) {
320
- throw new Error('spot price out of bounds! auction launcher MUST closeRebalance to prevent loss!');
330
+ throw new Error("spot price out of bounds! auction launcher MUST closeRebalance to prevent loss!");
321
331
  }
322
332
  if (rebalance.priceControl == types_1.PriceControl.NONE) {
323
333
  return initialPrice;
@@ -342,57 +352,57 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
342
352
  pricesD27.high = initialPrice.high;
343
353
  }
344
354
  if (pricesD27.low == pricesD27.high && priceError[i].gt(numbers_1.ZERO)) {
345
- throw new Error('no price range');
355
+ throw new Error("no price range");
346
356
  }
347
357
  return pricesD27;
348
358
  });
349
- if (logging) {
350
- console.log('newPrices', newPrices);
359
+ if (debug) {
360
+ console.log("newPrices", newPrices);
351
361
  }
352
362
  // ================================================================
353
363
  // calculate metrics
354
364
  // {USD} = {1} * {USD/wholeShare} * {wholeShare}
355
- const valueBeingTraded = rebalanceTarget
356
- .sub(progression)
357
- .mul(shareValue)
358
- .mul(supply);
365
+ const valueBeingTraded = rebalanceTarget.sub(progression).mul(shareValue).mul(supply);
359
366
  const surplusTokens = [];
360
367
  const deficitTokens = [];
361
368
  // update Decimal weightRanges
362
369
  // {wholeTok/wholeBU} = D27{tok/BU} * {BU/wholeBU} / {tok/wholeTok} / D27
363
370
  weightRanges = newWeights.map((range, i) => {
364
371
  return {
365
- low: new decimal_js_light_1.default(range.low.toString())
366
- .mul(numbers_1.D18d)
367
- .div(decimalScale[i])
368
- .div(numbers_1.D27d),
369
- spot: new decimal_js_light_1.default(range.spot.toString())
370
- .mul(numbers_1.D18d)
371
- .div(decimalScale[i])
372
- .div(numbers_1.D27d),
373
- high: new decimal_js_light_1.default(range.high.toString())
374
- .mul(numbers_1.D18d)
375
- .div(decimalScale[i])
376
- .div(numbers_1.D27d),
372
+ low: new decimal_js_light_1.default(range.low.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
373
+ spot: new decimal_js_light_1.default(range.spot.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
374
+ high: new decimal_js_light_1.default(range.high.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
377
375
  };
378
376
  });
379
377
  rebalance.tokens.forEach((token, i) => {
380
378
  // {wholeTok/wholeShare} = {wholeTok/wholeBU} * {wholeBU/wholeShare}
381
379
  const buyUpTo = weightRanges[i].low.mul(actualLimits.low);
382
380
  const sellDownTo = weightRanges[i].high.mul(actualLimits.high);
383
- if (folio[i].lt(buyUpTo)) {
381
+ if (rebalance.inRebalance[i] && folio[i].lt(buyUpTo)) {
384
382
  deficitTokens.push(token);
385
383
  }
386
- else if (folio[i].gt(sellDownTo)) {
384
+ else if (rebalance.inRebalance[i] && folio[i].gt(sellDownTo)) {
387
385
  surplusTokens.push(token);
388
386
  }
389
387
  });
388
+ // ================================================================
389
+ // only return tokens that are in the rebalance
390
+ const returnTokens = [];
391
+ const returnWeights = [];
392
+ const returnPrices = [];
393
+ for (let i = 0; i < rebalance.tokens.length; i++) {
394
+ if (rebalance.inRebalance[i]) {
395
+ returnTokens.push(rebalance.tokens[i]);
396
+ returnWeights.push(newWeights[i]);
397
+ returnPrices.push(newPrices[i]);
398
+ }
399
+ }
390
400
  return [
391
401
  {
392
402
  rebalanceNonce: rebalance.nonce,
393
- tokens: rebalance.tokens, // full set of tokens, not pruned to the active buy/sells
394
- newWeights: newWeights,
395
- newPrices: newPrices,
403
+ tokens: returnTokens,
404
+ newWeights: returnWeights,
405
+ newPrices: returnPrices,
396
406
  newLimits: newLimits,
397
407
  },
398
408
  {
@@ -1,4 +1,4 @@
1
- import { PriceRange, RebalanceLimits, WeightRange } from './types';
1
+ import { PriceRange, RebalanceLimits, WeightRange } from "./types";
2
2
  export interface StartRebalanceArgsPartial {
3
3
  weights: WeightRange[];
4
4
  prices: PriceRange[];
@@ -19,4 +19,4 @@ export interface StartRebalanceArgsPartial {
19
19
  * @param _dtfPrice {USD/wholeShare} DTF price
20
20
  * @param weightControl TRACKING=false, NATIVE=true
21
21
  */
22
- export declare const getStartRebalance: (_supply: bigint, tokens: string[], _folio: bigint[], decimals: bigint[], _targetBasket: bigint[], _prices: number[], _priceError: number[], weightControl: boolean, logging?: boolean) => StartRebalanceArgsPartial;
22
+ export declare const getStartRebalance: (_supply: bigint, tokens: string[], _folio: bigint[], decimals: bigint[], _targetBasket: bigint[], _prices: number[], _priceError: number[], weightControl: boolean, debug?: boolean) => StartRebalanceArgsPartial;
@@ -21,9 +21,9 @@ const numbers_1 = require("./numbers");
21
21
  * @param _dtfPrice {USD/wholeShare} DTF price
22
22
  * @param weightControl TRACKING=false, NATIVE=true
23
23
  */
24
- const getStartRebalance = (_supply, tokens, _folio, decimals, _targetBasket, _prices, _priceError, weightControl, logging) => {
25
- if (logging) {
26
- console.log('getStartRebalance', _supply, tokens, _folio, decimals, _targetBasket, _prices, _priceError, weightControl);
24
+ const getStartRebalance = (_supply, tokens, _folio, decimals, _targetBasket, _prices, _priceError, weightControl, debug) => {
25
+ if (debug) {
26
+ console.log("getStartRebalance", _supply, tokens, _folio, decimals, _targetBasket, _prices, _priceError, weightControl);
27
27
  }
28
28
  // {wholeTok/wholeShare} = D18{tok/share} * {share/wholeShare} / {tok/wholeTok} / D18
29
29
  const folio = _folio.map((c, i) => new decimal_js_light_1.default(c.toString()).div(new decimal_js_light_1.default(`1e${decimals[i]}`)));
@@ -43,24 +43,26 @@ const getStartRebalance = (_supply, tokens, _folio, decimals, _targetBasket, _pr
43
43
  const newWeights = [];
44
44
  const newPrices = [];
45
45
  const newLimits = {
46
- low: (0, numbers_1.bn)('1e18'),
47
- spot: (0, numbers_1.bn)('1e18'),
48
- high: (0, numbers_1.bn)('1e18'),
46
+ low: (0, numbers_1.bn)("1e18"),
47
+ spot: (0, numbers_1.bn)("1e18"),
48
+ high: (0, numbers_1.bn)("1e18"),
49
49
  };
50
50
  // ================================================================
51
51
  for (let i = 0; i < tokens.length; i++) {
52
52
  if (priceError[i].gte(numbers_1.ONE)) {
53
- throw new Error('cannot defer prices');
53
+ throw new Error("cannot defer prices");
54
54
  }
55
55
  // === newWeights ===
56
56
  // {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
57
- const dtfPrice = folio.map((f, i) => f.mul(prices[i])).reduce((a, b) => a.add(b));
57
+ const dtfPrice = folio
58
+ .map((f, i) => f.mul(prices[i]))
59
+ .reduce((a, b) => a.add(b));
58
60
  // {wholeTok/wholeShare} = {1} * {USD/wholeShare} / {USD/wholeTok}
59
61
  const spotWeight = targetBasket[i].mul(dtfPrice).div(prices[i]);
60
62
  // D27{tok/share}{wholeShare/wholeTok} = D27 * {tok/wholeTok} / {share/wholeShare}
61
63
  const limitMultiplier = numbers_1.D27d.mul(new decimal_js_light_1.default(`1e${decimals[i]}`)).div(numbers_1.D18d);
62
- if (logging) {
63
- console.log('limitMultiplier', limitMultiplier.toString());
64
+ if (debug) {
65
+ console.log("limitMultiplier", limitMultiplier.toString());
64
66
  }
65
67
  if (!weightControl) {
66
68
  // D27{tok/BU} = {wholeTok/wholeShare} * D27{tok/share}{wholeShare/wholeTok} / {BU/share}
@@ -101,16 +103,16 @@ const getStartRebalance = (_supply, tokens, _folio, decimals, _targetBasket, _pr
101
103
  .map((portion, i) => portion.mul(priceError[i]))
102
104
  .reduce((a, b) => a.add(b));
103
105
  if (totalPortion.gte(numbers_1.ONE)) {
104
- throw new Error('totalPortion > 1');
106
+ throw new Error("totalPortion > 1");
105
107
  }
106
108
  // D18{BU/share} = {1} * D18 * {BU/share}
107
109
  newLimits.low = (0, numbers_1.bn)(numbers_1.ONE.div(numbers_1.ONE.add(totalPortion)).mul(numbers_1.D18d));
108
110
  newLimits.high = (0, numbers_1.bn)(numbers_1.ONE.add(totalPortion).mul(numbers_1.D18d));
109
111
  }
110
- if (logging) {
112
+ if (debug) {
111
113
  console.log("newWeights", newWeights);
112
- console.log('newPrices', newPrices);
113
- console.log('newLimits', newLimits);
114
+ console.log("newPrices", newPrices);
115
+ console.log("newLimits", newLimits);
114
116
  }
115
117
  return {
116
118
  weights: newWeights,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reserve-protocol/dtf-rebalance-lib",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Rebalancing library for DTFs in typescript",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -17,7 +17,7 @@
17
17
  "prepublishOnly": "npm run build",
18
18
  "test": "npm run test:unit && npm run test:e2e",
19
19
  "test:unit": "node --test --require ts-node/register test/unit/*.test.ts",
20
- "test:e2e": "hardhat test --bail"
20
+ "test:e2e": "hardhat test test/e2e/*.test.ts --bail"
21
21
  },
22
22
  "publishConfig": {
23
23
  "access": "public"