Skip to content

Commit 8e9aee6

Browse files
authored
Add DelegatedManagerSystem API (#107)
1 parent fd40d90 commit 8e9aee6

20 files changed

+2153
-10
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "set.js",
3-
"version": "0.5.1",
3+
"version": "0.5.2",
44
"description": "A javascript library for interacting with the Set Protocol v2",
55
"keywords": [
66
"set.js",
@@ -58,7 +58,8 @@
5858
"@0xproject/types": "^1.1.4",
5959
"@0xproject/typescript-typings": "^3.0.2",
6060
"@0xproject/utils": "^2.0.2",
61-
"@setprotocol/set-protocol-v2": "^0.1.10",
61+
"@setprotocol/set-protocol-v2": "^0.1.15",
62+
"@setprotocol/set-v2-strategies": "^0.0.7",
6263
"@types/chai-as-promised": "^7.1.3",
6364
"@types/jest": "^26.0.5",
6465
"@types/web3": "^1.2.2",

src/Set.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
'use strict';
1818

19-
import { SetJSConfig } from './types';
19+
import { SetJSConfig, DelegatedManagerSystemExtensions } from './types';
2020
import Assertions from './assertions';
2121
import {
2222
BlockchainAPI,
@@ -34,6 +34,10 @@ import {
3434
PerpV2LeverageAPI,
3535
PerpV2LeverageViewerAPI,
3636
UtilsAPI,
37+
DelegatedManagerFactoryAPI,
38+
IssuanceExtensionAPI,
39+
TradeExtensionAPI,
40+
StreamingFeeExtensionAPI,
3741
} from './api/index';
3842

3943
const ethersProviders = require('ethers').providers;
@@ -142,17 +146,28 @@ class Set {
142146
public perpV2BasisTradingViewer: PerpV2LeverageViewerAPI;
143147

144148
/**
145-
* An instance of the BlockchainAPI class. Contains interfaces for
146-
* interacting with the blockchain
149+
* An instance of DelegatedManagerFactory class. Contains methods for deploying and initializing
150+
* DelegatedManagerSystem deployed SetTokens and Manager contracts
147151
*/
148-
public blockchain: BlockchainAPI;
152+
public delegatedManagerFactory: DelegatedManagerFactoryAPI;
153+
154+
/**
155+
* Group of extension for interacting with SetTokens managed by with DelegatedManager system contracts
156+
*/
157+
public extensions: DelegatedManagerSystemExtensions;
149158

150159
/**
151160
* An instance of the UtilsAPI class. Contains interfaces for fetching swap quotes from 0x Protocol,
152161
* prices and token metadata from coingecko, and network gas prices from various sources
153162
*/
154163
public utils: UtilsAPI;
155164

165+
/**
166+
* An instance of the BlockchainAPI class. Contains interfaces for
167+
* interacting with the blockchain
168+
*/
169+
public blockchain: BlockchainAPI;
170+
156171
/**
157172
* Instantiates a new Set instance that provides the public interface to the Set.js library
158173
*/
@@ -187,6 +202,17 @@ class Set {
187202
config.perpV2BasisTradingModuleViewerAddress);
188203
this.blockchain = new BlockchainAPI(ethersProvider, assertions);
189204
this.utils = new UtilsAPI(ethersProvider, config.zeroExApiKey, config.zeroExApiUrls);
205+
206+
this.delegatedManagerFactory = new DelegatedManagerFactoryAPI(
207+
ethersProvider,
208+
config.delegatedManagerFactoryAddress
209+
);
210+
211+
this.extensions = {
212+
streamingFeeExtension: new StreamingFeeExtensionAPI(ethersProvider, config.streamingFeeExtensionAddress),
213+
issuanceExtension: new IssuanceExtensionAPI(ethersProvider, config.issuanceExtensionAddress),
214+
tradeExtension: new TradeExtensionAPI(ethersProvider, config.tradeExtensionAddress),
215+
};
190216
}
191217
}
192218

src/api/DelegatedManagerFactoryAPI.ts

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
Copyright 2022 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 { ContractTransaction, BigNumberish, BytesLike } from 'ethers';
20+
import { Provider } from '@ethersproject/providers';
21+
import { Address } from '@setprotocol/set-protocol-v2/utils/types';
22+
import { TransactionOverrides } from '@setprotocol/set-protocol-v2/dist/typechain';
23+
24+
import DelegatedManagerFactoryWrapper from '../wrappers/set-v2-strategies/DelegatedManagerFactoryWrapper';
25+
import Assertions from '../assertions';
26+
27+
/**
28+
* @title DelegatedManagerFactoryAPI
29+
* @author Set Protocol
30+
*
31+
* The DelegatedManagerFactoryAPI exposes methods to create and initialized new SetTokens bundled with
32+
* Manager contracts and extensions which encode fee management and rebalance trading logic. The API also
33+
* provides some helper methods to generate bytecode data packets that encode module and extension
34+
* initialization method calls.
35+
*
36+
*/
37+
export default class DelegatedManagerFactoryAPI {
38+
private DelegatedManagerFactoryWrapper: DelegatedManagerFactoryWrapper;
39+
private assert: Assertions;
40+
41+
public constructor(
42+
provider: Provider,
43+
delegatedManagerFactoryAddress: Address,
44+
assertions?: Assertions) {
45+
this.DelegatedManagerFactoryWrapper = new DelegatedManagerFactoryWrapper(provider, delegatedManagerFactoryAddress);
46+
this.assert = assertions || new Assertions();
47+
}
48+
49+
/**
50+
* Deploys a new SetToken and DelegatedManager. Sets some temporary metadata about the deployment
51+
* which will be consumed during a subsequent intialization step (see `initialize` method) which
52+
* wires everything together.
53+
*
54+
* To interact with the DelegateManager system after this transaction is executed it's necessary
55+
* to get the address of the created SetToken via a SetTokenCreated event logged .
56+
*
57+
* An ethers.js recipe for programatically retrieving the relevant log can be found in `set-protocol-v2`'s
58+
* protocol utilities here:
59+
*
60+
* https://github.com/SetProtocol/set-protocol-v2/blob/master/utils/common/protocolUtils.ts
61+
*
62+
* @param components Addresses of components for initial Positions
63+
* @param units Units. Each unit is the # of components per 10^18 of a SetToken
64+
* @param name Name of the SetToken
65+
* @param symbol Symbol of the SetToken
66+
* @param owner Address to set as the DelegateManager's `owner` role
67+
* @param methodologist Address to set as the DelegateManager's methodologist role
68+
* @param modules Modules to enable. All modules must be approved by the Controller
69+
* @param operators Operators authorized for the DelegateManager
70+
* @param assets Assets DelegateManager can trade. When empty, asset allow list is not enforced
71+
* @param extensions Extensions authorized for the DelegateManager
72+
* @param callerAddress Address of caller (optional)
73+
* @param txOpts Overrides for transaction (optional)
74+
*
75+
* @return Transaction hash of the initialize transaction
76+
*/
77+
public async createSetAndManagerAsync(
78+
components: Address[],
79+
units: BigNumberish[],
80+
name: string,
81+
symbol: string,
82+
owner: Address,
83+
methodologist: Address,
84+
modules: Address[],
85+
operators: Address[],
86+
assets: Address[],
87+
extensions: Address[],
88+
callerAddress: Address = undefined,
89+
txOpts: TransactionOverrides = {}
90+
): Promise<ContractTransaction> {
91+
this.assert.schema.isValidAddressList('components', components);
92+
this.assert.schema.isValidNumberList('units', units);
93+
this.assert.schema.isValidString('name', name);
94+
this.assert.schema.isValidString('symbol', symbol);
95+
this.assert.schema.isValidAddress('methodologist', methodologist);
96+
this.assert.schema.isValidAddressList('modules', modules);
97+
this.assert.schema.isValidAddressList('operators', operators);
98+
this.assert.schema.isValidAddressList('assets', assets);
99+
this.assert.schema.isValidAddressList('extensions', extensions);
100+
101+
this.assert.common.isNotEmptyArray(
102+
components,
103+
'Component addresses must contain at least one component.'
104+
);
105+
this.assert.common.isEqualLength(
106+
components,
107+
units,
108+
'Component addresses and units must be equal length.'
109+
);
110+
111+
return await this.DelegatedManagerFactoryWrapper.createSetAndManager(
112+
components,
113+
units,
114+
name,
115+
symbol,
116+
owner,
117+
methodologist,
118+
modules,
119+
operators,
120+
assets,
121+
extensions,
122+
callerAddress,
123+
txOpts
124+
);
125+
}
126+
127+
/**
128+
* Wires SetToken, DelegatedManager, global manager extensions, and modules together into a functioning
129+
* package. `initializeTargets` and `initializeBytecode` params are isomorphic, e.g the arrays must
130+
* be the same length and the bytecode at `initializeBytecode[i]` will be called on `initializeTargets[i]`;
131+
*
132+
* Use the generateBytecode methods provided by this API to prepare parameters for calls to `initialize`
133+
* as below:
134+
*
135+
* ```
136+
* tradeModuleBytecodeData = api.getTradeModuleInitializationBytecode(setTokenAddress)
137+
* initializeTargets.push(tradeModuleAddress);
138+
* initializeBytecode.push(tradeModuleBytecodeData);
139+
* ```
140+
*
141+
* @param setTokenAddress Address of deployed SetToken to initialize
142+
* @param ownerFeeSplit % of fees in precise units (10^16 = 1%) sent to owner, rest to methodologist
143+
* @param ownerFeeRecipient Address which receives operator's share of fees when they're distributed
144+
* @param initializeTargets Addresses of extensions or modules which should be initialized
145+
* @param initializeBytecode Array of encoded calls to a target's initialize function
146+
* @param callerAddress Address of caller (optional)
147+
* @param txOpts Overrides for transaction (optional)
148+
*
149+
* @return Transaction hash of the initialize transaction
150+
*/
151+
public async initializeAsync(
152+
setTokenAddress: Address,
153+
ownerFeeSplit: BigNumberish,
154+
ownerFeeRecipient: Address,
155+
initializeTargets: Address[],
156+
initializeBytecode: BytesLike[],
157+
callerAddress: Address = undefined,
158+
txOpts: TransactionOverrides = {}
159+
): Promise<ContractTransaction> {
160+
this.assert.schema.isValidAddress('setTokenAddress', setTokenAddress);
161+
this.assert.schema.isValidNumber('ownerFeeSplit', ownerFeeSplit);
162+
this.assert.schema.isValidAddress('ownerFeeRecipient', ownerFeeRecipient);
163+
this.assert.schema.isValidAddressList('initializeTargets', initializeTargets);
164+
this.assert.schema.isValidBytesList('initializeBytecode', initializeBytecode);
165+
166+
this.assert.common.isNotEmptyArray(
167+
initializeTargets,
168+
'initializationTargets array must contain at least one element.'
169+
);
170+
171+
this.assert.common.isEqualLength(
172+
initializeTargets,
173+
initializeBytecode,
174+
'initializeTargets and initializeBytecode arrays must be equal length.'
175+
);
176+
177+
return await this.DelegatedManagerFactoryWrapper.initialize(
178+
setTokenAddress,
179+
ownerFeeSplit,
180+
ownerFeeRecipient,
181+
initializeTargets,
182+
initializeBytecode,
183+
callerAddress,
184+
txOpts
185+
);
186+
}
187+
}

0 commit comments

Comments
 (0)