Skip to content

Commit 4039843

Browse files
committed
Create new PerpV2LeverageViewerAPI for PerpModule Viewer contract
1 parent c86243e commit 4039843

10 files changed

+585
-51
lines changed

src/Set.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ import {
3131
DebtIssuanceAPI,
3232
DebtIssuanceV2API,
3333
SlippageIssuanceAPI,
34+
PerpV2LeverageAPI,
35+
PerpV2LeverageViewerAPI,
3436
} from './api/index';
35-
import PerpV2LeverageAPI from './api/PerpV2LeverageAPI';
3637

3738
const ethersProviders = require('ethers').providers;
3839

@@ -116,10 +117,17 @@ class Set {
116117
/**
117118
* An instance of the PerpV2LeverageAPI class. Contains getters for fetching
118119
* positional (per Set) and notional (across all Sets) units for collateral, vAssets, and debt.
119-
* Initially used for Perpetual Leverage Tokens.
120+
* Getters return low level data; for more abstracted data use the PerpV2LeverageViewerAPI.
120121
*/
121122
public perpV2Leverage: PerpV2LeverageAPI;
122123

124+
/**
125+
* An instance of the PerpV2LeverageViewerAPI class. Contains getters for fetching total
126+
* collateral balance (which includes PnL and funding), virtual component leverage ratios,
127+
* and maximum issuance quantity computed from token supply.
128+
*/
129+
public perpV2LeverageViewer: PerpV2LeverageViewerAPI;
130+
123131
/**
124132
* An instance of the BlockchainAPI class. Contains interfaces for
125133
* interacting with the blockchain
@@ -154,6 +162,7 @@ class Set {
154162
this.debtIssuanceV2 = new DebtIssuanceV2API(ethersProvider, config.debtIssuanceModuleV2Address);
155163
this.slippageIssuance = new SlippageIssuanceAPI(ethersProvider, config.slippageIssuanceModuleAddress);
156164
this.perpV2Leverage = new PerpV2LeverageAPI(ethersProvider, config.perpV2LeverageModuleAddress);
165+
this.perpV2LeverageViewer = new PerpV2LeverageViewerAPI(ethersProvider, config.perpV2LeverageModuleViewerAddress);
157166
this.blockchain = new BlockchainAPI(ethersProvider, assertions);
158167
}
159168
}

src/api/PerpV2LeverageAPI.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,6 @@ export default class PerpV2LeverageAPI {
8080
return await this.perpV2LeverageModuleWrapper.collateralToken(callerAddress);
8181
}
8282

83-
/**
84-
* Gets decimals of the collateral token
85-
*
86-
* @param callerAddress The address of user transferring from (optional)
87-
* @return The decimals of the ERC20 collateral token
88-
*/
89-
public async getCollateralDecimalsAsync(
90-
callerAddress: Address = undefined,
91-
): Promise<Number> {
92-
return await this.perpV2LeverageModuleWrapper.collateralDecimals(callerAddress);
93-
}
94-
9583
/**
9684
* Returns a tuple of arrays representing all positions open for the SetToken.
9785
*

src/api/PerpV2LeverageViewerAPI.ts

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
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 } 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+
import { BigNumber } from 'ethers/lib/ethers';
24+
import { VAssetDisplayInfo } from '../types';
25+
26+
import PerpV2LeverageModuleViewerWrapper from '../wrappers/set-protocol-v2/PerpV2LeverageModuleViewerWrapper';
27+
import Assertions from '../assertions';
28+
29+
/**
30+
* @title PerpV2LeverageViewerAPI
31+
* @author Set Protocol
32+
*
33+
* The PerpV2LeverageViewerAPI exposes issue and redeem functionality for Sets that contain poitions that accrue
34+
* interest per block. The getter function syncs the position balance to the current block, so subsequent blocks
35+
* will cause the position value to be slightly out of sync (a buffer is needed). This API is primarily used for Sets
36+
* that rely on the ALM contracts to manage debt. The manager can define arbitrary issuance logic
37+
* in the manager hook, as well as specify issue and redeem fees.
38+
*
39+
*/
40+
export default class PerpV2LeverageViewerAPI {
41+
private perpV2LeverageModuleViewerWrapper: PerpV2LeverageModuleViewerWrapper;
42+
private assert: Assertions;
43+
44+
public constructor(provider: Provider, perpV2LeverageModuleViewerAddress: Address, assertions?: Assertions) {
45+
this.perpV2LeverageModuleViewerWrapper = new PerpV2LeverageModuleViewerWrapper(
46+
provider,
47+
perpV2LeverageModuleViewerAddress
48+
);
49+
this.assert = assertions || new Assertions();
50+
}
51+
52+
/**
53+
* Initializes the PerpV2LeverageModuleViewer to the SetToken. Only callable by the SetToken's manager.
54+
*
55+
* @param setTokenAddress Address of the SetToken to initialize
56+
* @param callerAddress The address of user transferring from (optional)
57+
* @param txOpts Overrides for transaction (optional)
58+
*
59+
* @return Transaction hash of the initialize transaction
60+
*/
61+
public async initializeAsync(
62+
setTokenAddress: Address,
63+
callerAddress: Address = undefined,
64+
txOpts: TransactionOverrides = {}
65+
): Promise<ContractTransaction> {
66+
this.assert.schema.isValidAddress('setTokenAddress', setTokenAddress);
67+
68+
return await this.perpV2LeverageModuleViewerWrapper.initialize(
69+
setTokenAddress,
70+
callerAddress,
71+
txOpts,
72+
);
73+
}
74+
75+
/**
76+
* Gets the address of the collateral token
77+
*
78+
* @param callerAddress The address of user transferring from (optional)
79+
* @return The address of the ERC20 collateral token
80+
*/
81+
public async getCollateralTokenAsync(
82+
callerAddress: Address = undefined,
83+
): Promise<Address> {
84+
return await this.perpV2LeverageModuleViewerWrapper.collateralToken(callerAddress);
85+
}
86+
87+
/**
88+
* Returns the maximum amount of Sets that can be issued. Because upon issuance we lever up the Set
89+
* before depositing collateral there is a ceiling on the amount of Sets that can be issued before the max
90+
* leverage ratio is met. In order to accurately predict this amount the user must pass in an expected
91+
* slippage amount, this amount should be calculated relative to Index price(s) of vAssets held by the Set,
92+
* not the mid-market prices. The formulas used here are based on the "conservative" definition of free
93+
* collateral as defined in PerpV2's docs.
94+
*
95+
* @param setTokenAddress Instance of SetToken
96+
* @param slippage Expected slippage from entering position in precise units (1% = 10^16)
97+
* @param callerAddress Address of the method caller
98+
*
99+
* @return Maximum amount of Sets that can be issued
100+
*/
101+
public async getMaximumSetTokenIssueAmountAsync(
102+
setTokenAddress: Address,
103+
slippage: BigNumber,
104+
callerAddress: Address = undefined,
105+
): Promise<BigNumber> {
106+
this.assert.schema.isValidAddress('setTokenAddress', setTokenAddress);
107+
108+
return await this.perpV2LeverageModuleViewerWrapper.getMaximumSetTokenIssueAmount(
109+
setTokenAddress,
110+
slippage,
111+
callerAddress,
112+
);
113+
}
114+
115+
/**
116+
* Returns the position unit for total collateral value as defined by Perpetual Protocol.
117+
*
118+
* @param setTokenAddress Instance of SetToken
119+
* @param callerAddress Address of the method caller
120+
*
121+
* @return Collateral token address
122+
* @return Total collateral value position unit
123+
*/
124+
public async getTotalCollateralUnitAsync(
125+
setTokenAddress: Address,
126+
callerAddress: Address = undefined,
127+
): Promise<[Address, BigNumber]> {
128+
this.assert.schema.isValidAddress('setTokenAddress', setTokenAddress);
129+
130+
return await this.perpV2LeverageModuleViewerWrapper.getTotalCollateralUnit(
131+
setTokenAddress,
132+
callerAddress,
133+
);
134+
}
135+
136+
/**
137+
* Returns relevant data for displaying current positions. Identifying info for each position plus current
138+
* size, index price, and leverage of each vAsset with an open position is returned. The sum quantity of vUSDC
139+
* is returned along with identifying info in last index of array.
140+
*
141+
* @param setTokenAddress Instance of the SetToken
142+
* @param callerAddress Address of the method caller
143+
*
144+
* @return Array of info concerning size and leverage of current vAsset positions
145+
*/
146+
public async getVirtualAssetsDisplayInfoAsync(
147+
setTokenAddress: Address,
148+
callerAddress: Address = undefined,
149+
): Promise<VAssetDisplayInfo[]> {
150+
this.assert.schema.isValidAddress('setTokenAddress', setTokenAddress);
151+
152+
return await this.perpV2LeverageModuleViewerWrapper.getVirtualAssetsDisplayInfo(
153+
setTokenAddress,
154+
callerAddress,
155+
);
156+
}
157+
}

src/api/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import DebtIssuanceAPI from './DebtIssuanceAPI';
1111
import DebtIssuanceV2API from './DebtIssuanceV2API';
1212
import SlippageIssuanceAPI from './SlippageIssuanceAPI';
1313
import PerpV2LeverageAPI from './PerpV2LeverageAPI';
14+
import PerpV2LeverageViewerAPI from './PerpV2LeverageViewerAPI';
1415
import {
1516
TradeQuoter,
1617
CoinGeckoDataService,
@@ -31,6 +32,7 @@ export {
3132
DebtIssuanceV2API,
3233
SlippageIssuanceAPI,
3334
PerpV2LeverageAPI,
35+
PerpV2LeverageViewerAPI,
3436
TradeQuoter,
3537
CoinGeckoDataService,
3638
GasOracleService

src/types/common.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export interface SetJSConfig {
2222
debtIssuanceModuleV2Address: Address;
2323
slippageIssuanceModuleAddress: Address;
2424
perpV2LeverageModuleAddress: Address;
25+
perpV2LeverageModuleViewerAddress: Address;
2526
}
2627

2728
export type SetDetails = {
@@ -89,3 +90,12 @@ export enum ModuleState {
8990
'PENDING',
9091
'INITIALIZED',
9192
}
93+
94+
// For PerpV2LeverageModuleViewerWrapper
95+
export type VAssetDisplayInfo = {
96+
symbol: string;
97+
address: Address;
98+
positionUnit: BigNumber;
99+
indexPrice: BigNumber;
100+
currentLeverageRatio: BigNumber;
101+
};

src/wrappers/set-protocol-v2/ContractWrapper.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
TradeModule,
3434
NavIssuanceModule,
3535
PerpV2LeverageModule,
36+
PerpV2LeverageModuleViewer,
3637
PriceOracle,
3738
} from '@setprotocol/set-protocol-v2/typechain';
3839
import { BasicIssuanceModule__factory } from '@setprotocol/set-protocol-v2/dist/typechain/factories/BasicIssuanceModule__factory';
@@ -48,6 +49,7 @@ import { StreamingFeeModule__factory } from '@setprotocol/set-protocol-v2/dist/t
4849
import { TradeModule__factory } from '@setprotocol/set-protocol-v2/dist/typechain/factories/TradeModule__factory';
4950
import { NavIssuanceModule__factory } from '@setprotocol/set-protocol-v2/dist/typechain/factories/NavIssuanceModule__factory';
5051
import { PerpV2LeverageModule__factory } from '@setprotocol/set-protocol-v2/dist/typechain/factories/PerpV2LeverageModule__factory';
52+
import { PerpV2LeverageModuleViewer__factory } from '@setprotocol/set-protocol-v2/dist/typechain/factories/PerpV2LeverageModuleViewer__factory';
5153
import { PriceOracle__factory } from '@setprotocol/set-protocol-v2/dist/typechain/factories/PriceOracle__factory';
5254

5355
/**
@@ -450,4 +452,31 @@ export default class ContractWrapper {
450452
return perpV2LeverageModuleContract;
451453
}
452454
}
455+
456+
/**
457+
* Load PerpV2LeverageModuleViewer contract
458+
*
459+
* @param perpV2LeverageModuleViewerAddress Address of the Perp V2 Leverage module viewer
460+
* @param callerAddress Address of caller, uses first one on node if none provided.
461+
* @return PerpV2LeverageModuleViewer contract instance
462+
*/
463+
public async loadPerpV2LeverageModuleViewerAsync(
464+
perpV2LeverageModuleViewerAddress: Address,
465+
callerAddress?: Address,
466+
): Promise<PerpV2LeverageModuleViewer> {
467+
const signer = (this.provider as JsonRpcProvider).getSigner(callerAddress);
468+
const cacheKey = `PerpV2LeverageModuleViewer_${perpV2LeverageModuleViewerAddress}_${await signer.getAddress()}`;
469+
470+
if (cacheKey in this.cache) {
471+
return this.cache[cacheKey] as PerpV2LeverageModuleViewer;
472+
} else {
473+
const perpV2LeverageModuleViewerContract = PerpV2LeverageModuleViewer__factory.connect(
474+
perpV2LeverageModuleViewerAddress,
475+
signer
476+
);
477+
478+
this.cache[cacheKey] = perpV2LeverageModuleViewerContract;
479+
return perpV2LeverageModuleViewerContract;
480+
}
481+
}
453482
}

0 commit comments

Comments
 (0)