hedge-web3 0.2.8 → 0.2.11
Sign up to get free protection for your applications and to get access to all the features.
- package/declarations/Constants.d.ts +47 -0
- package/declarations/idl/pyth.d.ts +80 -0
- package/declarations/idl/vault.d.ts +41 -3
- package/declarations/state/VaultAccount.d.ts +33 -10
- package/declarations/utils/getLinkedListAccounts.d.ts +17 -2
- package/lib/Constants.js +47 -0
- package/lib/idl/pyth.js +82 -0
- package/lib/idl/vault.js +41 -3
- package/lib/instructions/depositVault.js +1 -1
- package/lib/instructions/liquidateVault.js +1 -1
- package/lib/instructions/loanVault.js +1 -1
- package/lib/instructions/redeemVault.js +1 -1
- package/lib/instructions/refreshOraclePrice.js +6 -5
- package/lib/instructions/repayVault.js +1 -1
- package/lib/instructions/withdrawVault.js +1 -1
- package/lib/state/VaultAccount.js +69 -30
- package/lib/utils/getLinkedListAccounts.js +26 -10
- package/package.json +1 -1
- package/src/Constants.ts +50 -4
- package/src/idl/pyth.ts +159 -0
- package/src/idl/vault.ts +82 -6
- package/src/instructions/depositVault.ts +4 -3
- package/src/instructions/liquidateVault.ts +4 -3
- package/src/instructions/loanVault.ts +4 -3
- package/src/instructions/redeemVault.ts +4 -3
- package/src/instructions/refreshOraclePrice.ts +6 -5
- package/src/instructions/repayVault.ts +4 -3
- package/src/instructions/withdrawVault.ts +4 -3
- package/src/state/VaultAccount.ts +79 -36
- package/src/utils/getLinkedListAccounts.ts +31 -13
@@ -67,11 +67,12 @@ export async function redeemVault(
|
|
67
67
|
|
68
68
|
const [oldSmallerPublicKey, newSmallerPublicKey, newLargerPublicKey] = await getLinkedListAccounts(
|
69
69
|
program,
|
70
|
-
provider,
|
71
70
|
vaultAccount.vaultType,
|
72
71
|
vaultPublicKey,
|
73
|
-
0,
|
74
|
-
0,
|
72
|
+
new BN(0),
|
73
|
+
new BN(0),
|
74
|
+
new BN(0),
|
75
|
+
new BN(0),
|
75
76
|
true,
|
76
77
|
false
|
77
78
|
)
|
@@ -44,6 +44,7 @@ export async function refreshOraclePriceInstruction(
|
|
44
44
|
[enc.encode(collateralType), enc.encode('State')],
|
45
45
|
HEDGE_PROGRAM_PUBLICKEY
|
46
46
|
)
|
47
|
+
const oracleInfo = await program.account.oracleInfoForCollateralType.fetch(oracleInfoAccount)
|
47
48
|
|
48
49
|
return await program.methods
|
49
50
|
.refreshOraclePrice(
|
@@ -53,9 +54,9 @@ export async function refreshOraclePriceInstruction(
|
|
53
54
|
.accounts({
|
54
55
|
oracleInfoAccount: oracleInfoAccount,
|
55
56
|
vaultTypeAccount: vaultTypeAccount,
|
56
|
-
oracleChainlink:
|
57
|
-
oraclePyth:
|
58
|
-
oracleSwitchboard:
|
57
|
+
oracleChainlink: oracleInfo.oracleChainlink,
|
58
|
+
oraclePyth: oracleInfo.oraclePyth,
|
59
|
+
oracleSwitchboard: oracleInfo.oracleSwitchboard,
|
59
60
|
systemProgram: SystemProgram.programId,
|
60
61
|
chainlinkProgram: CHAINLINK_PROGRAM_ID,
|
61
62
|
})
|
@@ -75,12 +76,12 @@ const pythAccounts = {
|
|
75
76
|
}
|
76
77
|
const chainlinkAccounts = {
|
77
78
|
Testing: SystemProgram.programId,
|
78
|
-
Devnet: new PublicKey('
|
79
|
+
Devnet: new PublicKey('HgTtcbcmp5BeThax5AU8vg4VwK79qAvAKKFMs8txMLW6'),
|
79
80
|
MainnetBeta: SystemProgram.programId, // CHAINLINK NOT ON MAINNET YET
|
80
81
|
}
|
81
82
|
const switchboardAccounts = {
|
82
83
|
Testing: SystemProgram.programId,
|
83
84
|
// Devnet: new PublicKey('GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR'),
|
84
|
-
Devnet: new PublicKey('
|
85
|
+
Devnet: new PublicKey('GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR'),
|
85
86
|
MainnetBeta: SystemProgram.programId, // Switchboard V2 NOT ON MAINNET YET
|
86
87
|
}
|
@@ -49,11 +49,12 @@ export async function repayVault(
|
|
49
49
|
|
50
50
|
const [oldSmallerPublicKey, newSmallerPublicKey, newLargerPublicKey] = await getLinkedListAccounts(
|
51
51
|
program,
|
52
|
-
provider,
|
53
52
|
vaultAccount.vaultType,
|
54
53
|
vaultPublicKey,
|
55
|
-
0,
|
56
|
-
|
54
|
+
new BN(0),
|
55
|
+
new BN(0),
|
56
|
+
new BN(0),
|
57
|
+
new BN(Math.abs(repayAmount)),
|
57
58
|
false,
|
58
59
|
false
|
59
60
|
)
|
@@ -69,11 +69,12 @@ export async function withdrawVault(
|
|
69
69
|
|
70
70
|
const [oldSmallerPublicKey, newSmallerPublicKey, newLargerPublicKey] = await getLinkedListAccounts(
|
71
71
|
program,
|
72
|
-
provider,
|
73
72
|
vaultAccount.vaultType,
|
74
73
|
vaultPublicKey,
|
75
|
-
|
76
|
-
|
74
|
+
new BN(0),
|
75
|
+
new BN(Math.abs(withdrawAmount)),
|
76
|
+
new BN(0),
|
77
|
+
new BN(0),
|
77
78
|
false,
|
78
79
|
false
|
79
80
|
)
|
@@ -20,10 +20,10 @@ export class VaultAccount {
|
|
20
20
|
pdaSalt: string
|
21
21
|
|
22
22
|
/** The deposited collateral of the vault (in SOL Lamports). */
|
23
|
-
deposited
|
23
|
+
deposited = new BN(0)
|
24
24
|
|
25
25
|
/** The outstanding debt of the vault (in USH Lamports). Denormalized to time 0. */
|
26
|
-
denormalizedDebt
|
26
|
+
denormalizedDebt = new BN(0)
|
27
27
|
|
28
28
|
/** The ordered number of when this vault was created. */
|
29
29
|
vaultNumber = 0
|
@@ -50,8 +50,10 @@ export class VaultAccount {
|
|
50
50
|
this.publicKey = publicKey
|
51
51
|
this.vaultOwner = vault.vaultOwner
|
52
52
|
this.pdaSalt = vault.pdaSalt
|
53
|
-
|
54
|
-
this.
|
53
|
+
|
54
|
+
this.deposited = vault.deposited
|
55
|
+
this.denormalizedDebt = vault.denormalizedDebt
|
56
|
+
|
55
57
|
if (vault.vaultNumber) {
|
56
58
|
this.vaultNumber = vault.vaultNumber.toNumber()
|
57
59
|
}
|
@@ -80,14 +82,15 @@ export class VaultAccount {
|
|
80
82
|
return publicKey && publicKey.toString() === this.vaultOwner.toString()
|
81
83
|
}
|
82
84
|
|
83
|
-
/**
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
public inSol(): number {
|
89
|
-
|
90
|
-
|
85
|
+
// /**
|
86
|
+
// * Get the collateral value in SOL
|
87
|
+
// *
|
88
|
+
// * @returns collateral value in SOL
|
89
|
+
// */
|
90
|
+
// public inSol(): number {
|
91
|
+
// This should not be LAMPORTS_PER_SOL. Should be collateral units like Ray
|
92
|
+
// return new Decimal(this.deposited.toString()).div(LAMPORTS_PER_SOL).toNumber()
|
93
|
+
// }
|
91
94
|
|
92
95
|
/**
|
93
96
|
* Get the debt value in USH
|
@@ -95,7 +98,7 @@ export class VaultAccount {
|
|
95
98
|
* @returns debt value in USH
|
96
99
|
*/
|
97
100
|
public inUsd(): number {
|
98
|
-
return this.denormalizedDebt
|
101
|
+
return new Decimal(this.denormalizedDebt.toString()).div(LAMPORTS_PER_SOL).toNumber()
|
99
102
|
}
|
100
103
|
|
101
104
|
/**
|
@@ -109,42 +112,82 @@ export class VaultAccount {
|
|
109
112
|
.substring(this.publicKey.toString().length - 6)}`
|
110
113
|
}
|
111
114
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
115
|
+
/**
|
116
|
+
* Add additional debt to the vault.
|
117
|
+
*
|
118
|
+
* @param {BN} additionalDebt - Additional normalized debt to add in (USH) lamports.
|
119
|
+
* @param {VaultType} vaultTypeAccount - Vault's vaultType
|
120
|
+
*
|
121
|
+
*/
|
122
|
+
public addDebt(additionalDebt: BN, vaultTypeAccount: VaultType) {
|
123
|
+
const additionalDebtAsDecimal = new Decimal(additionalDebt.toString())
|
124
|
+
// Calculate the fee on the loan
|
125
|
+
const loanFee = vaultTypeAccount.loanInitFee.mul(additionalDebtAsDecimal)
|
117
126
|
|
118
|
-
|
119
|
-
const
|
120
|
-
|
127
|
+
// TODO: There's a chance this needs to be .Floor()
|
128
|
+
const totalNormalizedLoan = additionalDebtAsDecimal.add(loanFee)
|
129
|
+
|
130
|
+
const denormalizedNewDebt = new BN(totalNormalizedLoan.div(vaultTypeAccount.cumulativeRate).floor().toString())
|
131
|
+
this.denormalizedDebt = this.denormalizedDebt.add(denormalizedNewDebt)
|
121
132
|
}
|
122
133
|
|
123
|
-
|
124
|
-
|
134
|
+
/**
|
135
|
+
* Repay debt on a vault
|
136
|
+
*
|
137
|
+
* @param {BN} repayAmount - Normalized debt to repay in (USH) lamports.
|
138
|
+
* @param {VaultType} vaultTypeAccount - Vault's vaultType
|
139
|
+
*
|
140
|
+
*/
|
141
|
+
public repayDebt(repayAmount: BN, vaultTypeAccount: VaultType) {
|
142
|
+
const denormalizedRepayment = new Decimal(repayAmount.toString()).div(vaultTypeAccount.cumulativeRate).floor()
|
143
|
+
|
144
|
+
this.denormalizedDebt = this.denormalizedDebt.sub(new BN(denormalizedRepayment.toString()))
|
145
|
+
}
|
146
|
+
|
147
|
+
/**
|
148
|
+
* Deposit Collateral
|
149
|
+
*
|
150
|
+
* @param {BN} depositAmount - Amount to deposit in (CollateralMint) lamports
|
151
|
+
*
|
152
|
+
*/
|
153
|
+
public depositCollateral(depositAmount: BN) {
|
154
|
+
this.deposited = this.deposited.add(depositAmount)
|
155
|
+
}
|
156
|
+
/**
|
157
|
+
* Withdraw Collateral
|
158
|
+
*
|
159
|
+
* @param {BN} withdrawAmount - Amount to withdraw in (CollateralMint) lamports
|
160
|
+
*
|
161
|
+
*/
|
162
|
+
public withdrawCollateral(withdrawAmount: BN) {
|
163
|
+
this.deposited = this.deposited.sub(withdrawAmount)
|
125
164
|
}
|
126
165
|
|
127
166
|
public redeem() {
|
128
167
|
// TODO - Calculate actual redeem amount and adust correctly
|
129
|
-
this.denormalizedDebt = 0
|
168
|
+
this.denormalizedDebt = new BN(0)
|
130
169
|
this.vaultStatus = 'initialized'
|
131
170
|
}
|
132
171
|
public liquidate() {
|
133
172
|
// TODO - Calculate actual liquidate amount and adust correctly
|
134
|
-
this.denormalizedDebt = 0
|
173
|
+
this.denormalizedDebt = new BN(0)
|
135
174
|
this.vaultStatus = 'liquidated'
|
136
175
|
}
|
137
176
|
|
138
177
|
public updateDebtAndCollateral(vaultTypeAccountData: VaultType) {
|
139
|
-
|
140
|
-
|
178
|
+
this.denormalizedDebt = new BN(
|
179
|
+
vaultTypeAccountData.debtRedistributionProduct
|
141
180
|
.div(this.debtProductSnapshotBytes)
|
142
|
-
.mul(new Decimal(this.denormalizedDebt))
|
143
|
-
.
|
181
|
+
.mul(new Decimal(this.denormalizedDebt.toString()))
|
182
|
+
.floor()
|
183
|
+
.toString()
|
184
|
+
)
|
144
185
|
|
145
186
|
const extraCollateralDeposited =
|
146
|
-
this.denormalizedDebt
|
147
|
-
|
187
|
+
new Decimal(this.denormalizedDebt.toString()).mul(
|
188
|
+
vaultTypeAccountData.collateralRedistributionAccumulator.sub(this.collateralAccumulatorSnapshotBytes).toNumber()
|
189
|
+
).floor()
|
190
|
+
this.deposited = this.deposited.add(new BN(extraCollateralDeposited.toString()))
|
148
191
|
|
149
192
|
this.collateralAccumulatorSnapshotBytes = vaultTypeAccountData.collateralRedistributionAccumulator
|
150
193
|
this.debtProductSnapshotBytes = vaultTypeAccountData.debtRedistributionProduct
|
@@ -156,8 +199,8 @@ export class VaultAccount {
|
|
156
199
|
arrow = ' <----!!'
|
157
200
|
}
|
158
201
|
let collateralRatio = 'Infinite'
|
159
|
-
if (this.denormalizedDebt
|
160
|
-
collateralRatio = new Decimal(this.deposited).div(new Decimal(this.denormalizedDebt)).toString()
|
202
|
+
if (this.denormalizedDebt.gt(new BN(0))) {
|
203
|
+
collateralRatio = new Decimal(this.deposited.toString()).div(new Decimal(this.denormalizedDebt.toString())).toString()
|
161
204
|
}
|
162
205
|
|
163
206
|
let nextVault = 'None'
|
@@ -165,9 +208,9 @@ export class VaultAccount {
|
|
165
208
|
nextVault = this.nextVaultToRedeem.toString().substring(0, 6)
|
166
209
|
}
|
167
210
|
|
168
|
-
return `${this.publicKey.toString().substring(0, 6)}. Debt: ${
|
169
|
-
this.
|
170
|
-
}
|
211
|
+
return `${this.publicKey.toString().substring(0, 6)}. Debt: ${this.denormalizedDebt} Collat: ${
|
212
|
+
this.deposited
|
213
|
+
} Ratio: ${collateralRatio} ${arrow} `
|
171
214
|
}
|
172
215
|
/**
|
173
216
|
* Creates a VaultAccount from a slice of data
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Program, Provider } from '@project-serum/anchor'
|
1
|
+
import { Program, Provider, BN } from '@project-serum/anchor'
|
2
2
|
import { PublicKey, Signer } from '@solana/web3.js'
|
3
3
|
import _ from 'underscore'
|
4
4
|
import { getVaultSystemStatePublicKey, getVaultTypeOracleAccountPublicKey, HEDGE_PROGRAM_PUBLICKEY } from '../Constants'
|
@@ -12,13 +12,28 @@ import * as borsh from '@project-serum/borsh'
|
|
12
12
|
import base58 from 'bs58'
|
13
13
|
import VaultType from '../state/VaultType'
|
14
14
|
|
15
|
+
/**
|
16
|
+
* Get the accounts the left and right for re-inserting in the linked list
|
17
|
+
*
|
18
|
+
* @param {Program<Vault>} program - Anchor program <Vault ILD>
|
19
|
+
* @param {PublicKey} vaultTypeAccountPublicKey - Vault Type Account PublicKey
|
20
|
+
* @param {PublicKey} vaultPublicKey - Vault Account PublicKey
|
21
|
+
* @param {BN} depositAmount - Amount that will be deposited into vault with instruction
|
22
|
+
* @param {BN} withdrawAmount - Amount that will be withdrawn from vault with instruction
|
23
|
+
* @param {BN} loanAmount - Amount that will be deposited into vault with transaction (sans fees)
|
24
|
+
* @param {BN} repayAmount - Amount that will be repaid into vault with transaction
|
25
|
+
* @param {boolean} redeem - True if vault is going to be redeemed fully
|
26
|
+
* @param {boolean} liquidate - True if vault is going to be liquidated fully
|
27
|
+
* @param {VaultAccount[]} cachedVaults - Optional list of cached vaults. Saves a request to the on-chain data.
|
28
|
+
*/
|
15
29
|
export async function getLinkedListAccounts(
|
16
30
|
program: Program<Vault>,
|
17
|
-
provider: Provider,
|
18
31
|
vaultTypeAccountPublicKey: PublicKey,
|
19
32
|
vaultPublicKey: PublicKey,
|
20
|
-
depositAmount:
|
21
|
-
|
33
|
+
depositAmount: BN,
|
34
|
+
withdrawAmount: BN,
|
35
|
+
loanAmount: BN,
|
36
|
+
repayAmount: BN,
|
22
37
|
redeem: boolean,
|
23
38
|
liquidate: boolean,
|
24
39
|
cachedVaults?: VaultAccount[]
|
@@ -58,7 +73,7 @@ export async function getLinkedListAccounts(
|
|
58
73
|
|
59
74
|
// Remove any vaults with no debt or collateral
|
60
75
|
vaults = _.filter(vaults, (vault) => {
|
61
|
-
return vault.denormalizedDebt
|
76
|
+
return vault.denormalizedDebt.gt(new BN(0)) && vault.deposited.gt(new BN(0))
|
62
77
|
})
|
63
78
|
|
64
79
|
// Sort them
|
@@ -117,10 +132,13 @@ export async function getLinkedListAccounts(
|
|
117
132
|
|
118
133
|
// Now that we know it's def in the list, iterate the list and update
|
119
134
|
// this vault with the operation we're going to apply
|
120
|
-
const newNormalizedDebt = new Decimal(loanAmount)
|
121
135
|
vaults[indexBefore].updateDebtAndCollateral(vaultType)
|
122
|
-
|
123
|
-
vaults[indexBefore].
|
136
|
+
|
137
|
+
vaults[indexBefore].addDebt(loanAmount, vaultType)
|
138
|
+
vaults[indexBefore].repayDebt(repayAmount, vaultType)
|
139
|
+
|
140
|
+
vaults[indexBefore].depositCollateral(depositAmount)
|
141
|
+
vaults[indexBefore].withdrawCollateral(withdrawAmount)
|
124
142
|
|
125
143
|
if (liquidate) {
|
126
144
|
vaults[indexBefore].liquidate()
|
@@ -129,7 +147,7 @@ export async function getLinkedListAccounts(
|
|
129
147
|
vaults[indexBefore].redeem()
|
130
148
|
}
|
131
149
|
|
132
|
-
if (vaults[indexBefore].denormalizedDebt
|
150
|
+
if (vaults[indexBefore].denormalizedDebt.isZero()) {
|
133
151
|
vaults.splice(indexBefore, 1)
|
134
152
|
}
|
135
153
|
|
@@ -180,12 +198,12 @@ export async function getLinkedListAccounts(
|
|
180
198
|
// Sort function we can use to sort the vaults
|
181
199
|
// Sorted by collateral ratio. If two are the same, newer vault first
|
182
200
|
function sortVaults(a: VaultAccount, b: VaultAccount) {
|
183
|
-
const aRatio = a.deposited
|
184
|
-
const bRatio = b.deposited
|
185
|
-
if (aRatio
|
201
|
+
const aRatio = new Decimal(a.deposited.toString()).div(new Decimal(a.denormalizedDebt.toString()))
|
202
|
+
const bRatio = new Decimal(b.deposited.toString()).div(new Decimal(b.denormalizedDebt.toString()))
|
203
|
+
if (aRatio.equals(bRatio)) {
|
186
204
|
return a.publicKey.toString() > b.publicKey.toString() ? 1 : -1
|
187
205
|
}
|
188
|
-
return aRatio -
|
206
|
+
return aRatio.greaterThan(bRatio) ? 1 : -1
|
189
207
|
}
|
190
208
|
|
191
209
|
async function getMiniVaults(program: Program<Vault>, vaultTypePublicKey: PublicKey) {
|