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.
@@ -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: chainlinkAccounts[network],
57
- oraclePyth: pythAccounts[network],
58
- oracleSwitchboard: switchboardAccounts[network],
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('FmAmfoyPXiA8Vhhe6MZTr3U6rZfEZ1ctEHay1ysqCqcf'),
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('DpoK8Zz69APV9ntjuY9C4LZCxANYMV56M2cbXEdkjxME'),
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
- repayAmount * -1,
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
- withdrawAmount * -1,
76
- 0,
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: number
23
+ deposited = new BN(0)
24
24
 
25
25
  /** The outstanding debt of the vault (in USH Lamports). Denormalized to time 0. */
26
- denormalizedDebt: number
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
- this.deposited = vault.deposited?.toNumber()
54
- this.denormalizedDebt = vault.denormalizedDebt?.toNumber()
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
- * Get the collateral value in SOL
85
- *
86
- * @returns collateral value in SOL
87
- */
88
- public inSol(): number {
89
- return this.deposited / LAMPORTS_PER_SOL
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 / LAMPORTS_PER_SOL
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
- public addDebt(additionalDebt: Decimal, vaultTypeAccount: VaultType) {
113
- let loanFee = new Decimal(0)
114
- if (additionalDebt.isPositive()){
115
- loanFee = vaultTypeAccount.loanInitFee.mul(additionalDebt)
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
- const totalNormalizedLoan = additionalDebt.add(loanFee)
119
- const denormalizedNewDebt = totalNormalizedLoan.div(new Decimal(vaultTypeAccount.cumulativeRate.toString()))
120
- this.denormalizedDebt = denormalizedNewDebt.add(new Decimal(this.denormalizedDebt)).floor().toNumber()
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
- public addDeposit(depositAmount: number) {
124
- this.deposited += depositAmount
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
- this.denormalizedDebt = vaultTypeAccountData.debtRedistributionProduct
178
+ this.denormalizedDebt = new BN(
179
+ vaultTypeAccountData.debtRedistributionProduct
141
180
  .div(this.debtProductSnapshotBytes)
142
- .mul(new Decimal(this.denormalizedDebt))
143
- .toNumber()
181
+ .mul(new Decimal(this.denormalizedDebt.toString()))
182
+ .floor()
183
+ .toString()
184
+ )
144
185
 
145
186
  const extraCollateralDeposited =
146
- this.denormalizedDebt * vaultTypeAccountData.collateralRedistributionAccumulator.sub(this.collateralAccumulatorSnapshotBytes).toNumber()
147
- this.deposited += extraCollateralDeposited
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 > 0) {
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.denormalizedDebt
170
- } Collat: ${this.deposited} Ratio: ${collateralRatio} ${arrow} `
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: number,
21
- loanAmount: number,
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 > 0 && vault.deposited > 0
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
- vaults[indexBefore].addDebt(newNormalizedDebt, vaultType)
123
- vaults[indexBefore].addDeposit(depositAmount)
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 === 0) {
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 / a.denormalizedDebt
184
- const bRatio = b.deposited / b.denormalizedDebt
185
- if (aRatio === bRatio) {
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 - bRatio
206
+ return aRatio.greaterThan(bRatio) ? 1 : -1
189
207
  }
190
208
 
191
209
  async function getMiniVaults(program: Program<Vault>, vaultTypePublicKey: PublicKey) {