Skip to content
This repository was archived by the owner on Jan 18, 2023. It is now read-only.

Commit 82af579

Browse files
authored
Add function for calling update allocation with TWAP. (#379)
Add function for calling update allocation with TWAP.
1 parent 840c065 commit 82af579

File tree

14 files changed

+768
-11
lines changed

14 files changed

+768
-11
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "setprotocol.js",
3-
"version": "1.2.8-rc9",
3+
"version": "1.2.8-rc10",
44
"description": "A javascript library for interacting with the Set protocol",
55
"keywords": [
66
"setProtocol.js",
@@ -71,7 +71,7 @@
7171
"set-protocol-oracles": "^1.0.16",
7272
"set-protocol-strategies": "^1.1.39",
7373
"set-protocol-viewers": "^1.0.13",
74-
"set-protocol-utils": "^1.1.2",
74+
"set-protocol-utils": "^1.1.3",
7575
"timekeeper": "^2.1.2",
7676
"tiny-promisify": "^1.0.0",
7777
"truffle": "^5.1.12",

src/api/SocialTradingAPI.ts

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2018 Set Labs Inc.
2+
Copyright 2019 Set Labs Inc.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -26,8 +26,10 @@ import {
2626
ProtocolViewerWrapper,
2727
RebalancingSetTokenV2Wrapper,
2828
RebalancingSetTokenV3Wrapper,
29+
SocialAllocatorWrapper,
2930
SocialTradingManagerWrapper,
30-
SocialTradingManagerV2Wrapper
31+
SocialTradingManagerV2Wrapper,
32+
TWAPLiquidatorWrapper,
3133
} from '../wrappers';
3234
import { Assertions } from '../assertions';
3335
import { coreAPIErrors } from '../errors';
@@ -38,7 +40,8 @@ import {
3840
SetProtocolConfig,
3941
Tx,
4042
EntryFeePaid,
41-
RebalanceFeePaid
43+
RebalanceFeePaid,
44+
Bounds
4245
} from '../types/common';
4346

4447
import {
@@ -61,12 +64,14 @@ const { SetProtocolUtils: SetUtils } = setProtocolUtils;
6164
export class SocialTradingAPI {
6265
private web3: Web3;
6366
private assert: Assertions;
67+
private performanceFeeCalculator: PerformanceFeeCalculatorWrapper;
6468
private protocolViewer: ProtocolViewerWrapper;
69+
private socialAllocator: SocialAllocatorWrapper;
6570
private socialTradingManager: SocialTradingManagerWrapper;
6671
private socialTradingManagerV2: SocialTradingManagerV2Wrapper;
6772
private rebalancingSetV2: RebalancingSetTokenV2Wrapper;
6873
private rebalancingSetV3: RebalancingSetTokenV3Wrapper;
69-
private performanceFeeCalculator: PerformanceFeeCalculatorWrapper;
74+
private twapLiquidator: TWAPLiquidatorWrapper;
7075

7176
/**
7277
* Instantiates a new RebalancingManagerAPI instance that contains methods for issuing and redeeming Sets
@@ -79,11 +84,13 @@ export class SocialTradingAPI {
7984
constructor(web3: Web3, assertions: Assertions, config: SetProtocolConfig) {
8085
this.web3 = web3;
8186
this.protocolViewer = new ProtocolViewerWrapper(web3, config.protocolViewerAddress);
87+
this.socialAllocator = new SocialAllocatorWrapper(web3);
8288
this.socialTradingManager = new SocialTradingManagerWrapper(web3);
8389
this.socialTradingManagerV2 = new SocialTradingManagerV2Wrapper(web3);
8490
this.rebalancingSetV2 = new RebalancingSetTokenV2Wrapper(web3);
8591
this.rebalancingSetV3 = new RebalancingSetTokenV3Wrapper(web3);
8692
this.performanceFeeCalculator = new PerformanceFeeCalculatorWrapper(web3);
93+
this.twapLiquidator = new TWAPLiquidatorWrapper(web3);
8794

8895
this.assert = assertions;
8996
}
@@ -291,6 +298,47 @@ export class SocialTradingAPI {
291298
);
292299
}
293300

301+
/**
302+
* Calls SocialTradingManager's updateAllocation function. This function creates a new collateral Set and
303+
* calls startRebalance on RebalancingSetTokenV2 using a TWAPLiquidator Updates allocation state on Manager
304+
* contract.
305+
*
306+
* @param manager Address of the social trading manager contract
307+
* @param tradingPool Address of tradingPool being updated
308+
* @param newAllocation New allocation amount in base asset percentage
309+
* @param chunkSize Value to be auctioned in each chunk
310+
* @param chunkAuctionPeriod Time between chunk auctions
311+
* @param txOpts Transaction options object conforming to `Tx` with signer, gas, and
312+
* gasPrice data
313+
* @return The hash of the resulting transaction.
314+
*/
315+
public async updateAllocationWithTWAPAsync(
316+
manager: Address,
317+
tradingPool: Address,
318+
newAllocation: BigNumber,
319+
chunkSize: BigNumber,
320+
chunkAuctionPeriod: BigNumber,
321+
txOpts: Tx,
322+
): Promise<string> {
323+
await this.assertUpdateAllocationWithTWAP(
324+
manager,
325+
tradingPool,
326+
newAllocation,
327+
chunkSize,
328+
chunkAuctionPeriod,
329+
txOpts
330+
);
331+
332+
const liquidatorData = SetUtils.generateTWAPLiquidatorCalldata(chunkSize, chunkAuctionPeriod);
333+
return this.socialTradingManager.updateAllocation(
334+
manager,
335+
tradingPool,
336+
newAllocation,
337+
liquidatorData,
338+
txOpts
339+
);
340+
}
341+
294342
/**
295343
* Calls tradingPool to accrue fees to manager.
296344
*
@@ -711,6 +759,15 @@ export class SocialTradingAPI {
711759

712760
/* ============ Private Functions ============ */
713761

762+
private async getTradingPoolAssetPair(
763+
allocator: Address
764+
): Promise<[Address, Address]> {
765+
const baseAsset = await this.socialAllocator.baseAsset(allocator);
766+
const quoteAsset = await this.socialAllocator.quoteAsset(allocator);
767+
768+
return [baseAsset, quoteAsset];
769+
}
770+
714771
private createNewTradingPoolObject(
715772
newPoolInfo: any,
716773
): NewTradingPoolInfo {
@@ -935,6 +992,29 @@ export class SocialTradingAPI {
935992
this.assertValidAllocation(newAllocation);
936993
}
937994

995+
private async assertUpdateAllocationWithTWAP(
996+
manager: Address,
997+
tradingPool: Address,
998+
newAllocation: BigNumber,
999+
chunkSize: BigNumber,
1000+
chunkAuctionPeriod: BigNumber,
1001+
txOpts: Tx,
1002+
): Promise <void> {
1003+
const poolInfo = await this.fetchNewTradingPoolV2DetailsAsync(tradingPool);
1004+
1005+
const assetPair = await this.getTradingPoolAssetPair(poolInfo.allocator);
1006+
const chunkSizeBounds: Bounds = await this.twapLiquidator.chunkSizeWhiteList(
1007+
poolInfo.liquidator,
1008+
assetPair[0],
1009+
assetPair[1]
1010+
);
1011+
this.assert.socialTrading.chunkSizeIsBetweenBounds(chunkSizeBounds, chunkSize);
1012+
1013+
this.assert.socialTrading.chunkAuctionPeriodGreaterOrEqualToZero(chunkAuctionPeriod);
1014+
1015+
await this.assertUpdateAllocation(manager, tradingPool, newAllocation, txOpts);
1016+
}
1017+
9381018
private async assertInitiateEntryFeeChange(
9391019
manager: Address,
9401020
tradingPool: Address,

src/assertions/SocialTradingAssertions.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
import { CommonAssertions } from './CommonAssertions';
2828
import { coreAPIErrors, socialTradingErrors } from '../errors';
2929
import { BigNumber, ether } from '../util';
30+
import { Bounds } from '../types/common';
3031
import { ZERO } from '../constants';
3132

3233
const moment = require('moment');
@@ -128,6 +129,31 @@ export class SocialTradingAssertions {
128129
);
129130
}
130131

132+
/**
133+
* Throws if chunkSize is not between bounds
134+
*
135+
* @param bounds Asset pair volume bounds
136+
* @param chunkSize Value of each chunk
137+
*/
138+
public chunkSizeIsBetweenBounds(bounds: Bounds, chunkSize: BigNumber): void {
139+
if (chunkSize > bounds.upper || chunkSize < bounds.lower) {
140+
throw new Error(socialTradingErrors.INVALID_CHUNK_SIZE(bounds));
141+
}
142+
}
143+
144+
/**
145+
* Throws if chunkAuctionPeriod less than 0.
146+
*
147+
* @param chunkAuctionPeriod Time between chunk auctions
148+
*/
149+
public chunkAuctionPeriodGreaterOrEqualToZero(chunkAuctionPeriod: BigNumber): void {
150+
this.commonAssertions.isGreaterOrEqualThan(
151+
chunkAuctionPeriod,
152+
ZERO,
153+
coreAPIErrors.QUANTITY_NEEDS_TO_BE_POSITIVE(chunkAuctionPeriod)
154+
);
155+
}
156+
131157
/**
132158
* Throws if caller is not the trader of tradingPool
133159
*

src/errors/socialTradingErrors.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
'use strict';
1818
import { Address } from 'set-protocol-utils';
1919
import { BigNumber } from '../util';
20+
import { Bounds } from '../types/common';
2021

2122
export const socialTradingErrors = {
2223
ALLOCATION_EXCEEDS_ONE_HUNDERED_PERCENT: (allocation: BigNumber) => `Provided allocation ` +
@@ -31,4 +32,6 @@ export const socialTradingErrors = {
3132
FEE_UPDATE_NOT_INITIATED: () => `Must call initiateEntryFeeChange first to start fee update process.`,
3233
INSUFFICIENT_TIME_PASSED: (validUpdateTimestamp: string) => `Attempting to finalize fee update too soon. ` +
3334
`Update available at ${validUpdateTimestamp}`,
35+
INVALID_CHUNK_SIZE: (bounds: Bounds) => `Passed chunk size must be between ${bounds.lower} and` +
36+
` ${bounds.upper}.`,
3437
};

src/types/common.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ export const BidderHelperType = {
4545
CTOKEN: new BigNumber(1),
4646
};
4747

48+
export interface Bounds {
49+
lower: BigNumber;
50+
upper: BigNumber;
51+
}
52+
4853
export interface EntryFeePaid {
4954
transactionHash: string;
5055
feeRecipient: Address;

src/wrappers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export { MovingAverageOracleWrapper } from './strategies/MovingAverageOracleWrap
5252
export { MACOStrategyManagerWrapper } from './strategies/MACOStrategyManagerWrapper';
5353
export { MACOStrategyManagerV2Wrapper } from './strategies/MACOStrategyManagerV2Wrapper';
5454
export { OracleProxyWrapper } from './strategies/OracleProxyWrapper';
55+
export { SocialAllocatorWrapper } from './strategies/SocialAllocatorWrapper';
5556
export { SocialTradingManagerWrapper } from './strategies/SocialTradingManagerWrapper';
5657
export { SocialTradingManagerV2Wrapper } from './strategies/SocialTradingManagerV2Wrapper';
5758
export { StrategyContractWrapper } from './strategies/StrategyContractWrapper';

src/wrappers/set_protocol/TWAPLiquidatorWrapper.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,26 @@ export class TWAPLiquidatorWrapper {
5858
txOpts
5959
);
6060
}
61+
62+
/**
63+
* Returns chunk size asset bounds for a pair of assets
64+
*
65+
* @param liquidatorAddress Address of TWAPLiquidator contract
66+
* @param assetOne Address of Asset one in pair
67+
* @param assetTwo Address of Asset two in pair
68+
*/
69+
public async chunkSizeWhiteList(
70+
liquidatorAddress: Address,
71+
assetOne: Address,
72+
assetTwo: Address,
73+
): Promise<any> {
74+
const liquidatorInstance = await this.contracts.loadTWAPLiquidatorContract(
75+
liquidatorAddress
76+
);
77+
78+
return await liquidatorInstance.chunkSizeWhiteList.callAsync(
79+
assetOne,
80+
assetTwo
81+
);
82+
}
6183
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
Copyright 2020 Set Labs Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
'use strict';
18+
19+
import Web3 from 'web3';
20+
21+
import { StrategyContractWrapper } from './StrategyContractWrapper';
22+
import { Address } from '../../types/common';
23+
24+
/**
25+
* @title SocialAllocatorWrapper
26+
* @author Set Protocol
27+
*
28+
* The SocialAllocatorWrapper handles all functions on the SocialAllocator contract
29+
*
30+
*/
31+
export class SocialAllocatorWrapper {
32+
public web3: Web3;
33+
public contracts: StrategyContractWrapper;
34+
35+
public constructor(web3: Web3) {
36+
this.web3 = web3;
37+
this.contracts = new StrategyContractWrapper(this.web3);
38+
}
39+
40+
/**
41+
* Get base asset of a social allocator
42+
*
43+
* @param socialAllocator Address of the SocialAllocator contract
44+
* @return Base asset addresss
45+
*/
46+
public async baseAsset(
47+
allocatorAddress: Address,
48+
): Promise<Address> {
49+
const allocatorInstance = await this.contracts.loadSocialAllocatorContractAsync(
50+
allocatorAddress
51+
);
52+
53+
return allocatorInstance.baseAsset.callAsync();
54+
}
55+
56+
/**
57+
* Get quote asset of a social allocator
58+
*
59+
* @param socialAllocator Address of the SocialAllocator contract
60+
* @return Quote asset addresss
61+
*/
62+
public async quoteAsset(
63+
allocatorAddress: Address,
64+
): Promise<Address> {
65+
const allocatorInstance = await this.contracts.loadSocialAllocatorContractAsync(
66+
allocatorAddress
67+
);
68+
69+
return allocatorInstance.quoteAsset.callAsync();
70+
}
71+
}

src/wrappers/strategies/StrategyContractWrapper.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
ETHDaiRebalancingManagerContract,
3636
MACOStrategyManagerContract,
3737
MACOStrategyManagerV2Contract,
38+
SocialAllocatorContract,
3839
SocialTradingManagerContract,
3940
SocialTradingManagerV2Contract
4041
} from 'set-protocol-strategies';
@@ -343,6 +344,32 @@ export class StrategyContractWrapper {
343344
}
344345
}
345346

347+
/**
348+
* Load a SocialAllocator contract
349+
*
350+
* @param socialAllocator Address of the SocialAllocator contract
351+
* @param transactionOptions Options sent into the contract deployed method
352+
* @return The SocialAllocator Contract
353+
*/
354+
public async loadSocialAllocatorContractAsync(
355+
socialAllocator: Address,
356+
transactionOptions: object = {},
357+
): Promise<SocialAllocatorContract> {
358+
const cacheKey = `socialAllocator_${socialAllocator}`;
359+
360+
if (cacheKey in this.cache) {
361+
return this.cache[cacheKey] as SocialAllocatorContract;
362+
} else {
363+
const socialAllocatorContract = await SocialAllocatorContract.at(
364+
socialAllocator,
365+
this.web3,
366+
transactionOptions,
367+
);
368+
this.cache[cacheKey] = socialAllocatorContract;
369+
return socialAllocatorContract;
370+
}
371+
}
372+
346373
/**
347374
* Load a SocialTradingManager contract
348375
*

0 commit comments

Comments
 (0)