Add oracleProvider to Bank and PerpMarket (#491)

* Add oracleProvider to Bank and PerpMarket
This commit is contained in:
riordanp 2023-03-15 13:44:51 +00:00 committed by GitHub
parent fc1341f731
commit da473b00b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 5 deletions

View File

@ -3,6 +3,7 @@ import { utf8 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
import { PublicKey } from '@solana/web3.js';
import { I80F48, I80F48Dto, ZERO_I80F48 } from '../numbers/I80F48';
import { As, toUiDecimals } from '../utils';
import { OracleProvider } from './oracle';
export type TokenIndex = number & As<'token-index'>;
@ -58,6 +59,7 @@ export class Bank implements BankForHealth {
public _price: I80F48 | undefined;
public _uiPrice: number | undefined;
public _oracleLastUpdatedSlot: number | undefined;
public _oracleProvider: OracleProvider | undefined;
public collectedFeesNative: I80F48;
public loanFeeRate: I80F48;
public loanOriginationFeeRate: I80F48;
@ -235,6 +237,7 @@ export class Bank implements BankForHealth {
this._price = undefined;
this._uiPrice = undefined;
this._oracleLastUpdatedSlot = undefined;
this._oracleProvider = undefined;
}
toString(): string {
@ -360,6 +363,15 @@ export class Bank implements BankForHealth {
return this._oracleLastUpdatedSlot;
}
get oracleProvider(): OracleProvider {
if (!this._oracleProvider) {
throw new Error(
`Undefined oracleProvider for bank ${this.publicKey} with tokenIndex ${this.tokenIndex}!`,
);
}
return this._oracleProvider;
}
nativeDeposits(): I80F48 {
return this.indexedDeposits.mul(this.depositIndex);
}

View File

@ -19,6 +19,7 @@ import { Bank, MintInfo, TokenIndex } from './bank';
import {
isPythOracle,
isSwitchboardOracle,
OracleProvider,
parseSwitchboardOracle,
} from './oracle';
import { BookSide, PerpMarket, PerpMarketIndex } from './perp';
@ -331,7 +332,7 @@ export class Group {
throw new Error(
`Undefined accountInfo object in reloadBankOraclePrices for ${bank.oracle}!`,
);
const { price, uiPrice, lastUpdatedSlot } =
const { price, uiPrice, lastUpdatedSlot, provider } =
await this.decodePriceFromOracleAi(
coder,
bank.oracle,
@ -342,6 +343,7 @@ export class Group {
bank._price = price;
bank._uiPrice = uiPrice;
bank._oracleLastUpdatedSlot = lastUpdatedSlot;
bank._oracleProvider = provider;
}
}
}
@ -366,7 +368,7 @@ export class Group {
`Undefined ai object in reloadPerpMarketOraclePrices for ${perpMarket.oracle}!`,
);
const { price, uiPrice, lastUpdatedSlot } =
const { price, uiPrice, lastUpdatedSlot, provider } =
await this.decodePriceFromOracleAi(
coder,
perpMarket.oracle,
@ -377,6 +379,7 @@ export class Group {
perpMarket._price = price;
perpMarket._uiPrice = uiPrice;
perpMarket._oracleLastUpdatedSlot = lastUpdatedSlot;
perpMarket._oracleProvider = provider;
}),
);
}
@ -387,8 +390,13 @@ export class Group {
ai: AccountInfo<Buffer>,
baseDecimals: number,
client: MangoClient,
): Promise<{ price: I80F48; uiPrice: number; lastUpdatedSlot: number }> {
let price, uiPrice, lastUpdatedSlot;
): Promise<{
price: I80F48;
uiPrice: number;
lastUpdatedSlot: number;
provider: OracleProvider;
}> {
let price, uiPrice, lastUpdatedSlot, provider;
if (
!BorshAccountsCoder.accountDiscriminator('stubOracle').compare(
ai.data.slice(0, 8),
@ -398,11 +406,13 @@ export class Group {
price = new I80F48(stubOracle.price.val);
uiPrice = this.toUiPrice(price, baseDecimals);
lastUpdatedSlot = stubOracle.lastUpdated.val;
provider = OracleProvider.Stub;
} else if (isPythOracle(ai)) {
const priceData = parsePriceData(ai.data);
uiPrice = priceData.previousPrice;
price = this.toNativePrice(uiPrice, baseDecimals);
lastUpdatedSlot = parseInt(priceData.lastSlot.toString());
provider = OracleProvider.Pyth;
} else if (isSwitchboardOracle(ai)) {
const priceData = await parseSwitchboardOracle(
ai,
@ -411,12 +421,13 @@ export class Group {
uiPrice = priceData.price;
price = this.toNativePrice(uiPrice, baseDecimals);
lastUpdatedSlot = priceData.lastUpdatedSlot;
provider = OracleProvider.Switchboard;
} else {
throw new Error(
`Unknown oracle provider (parsing not implemented) for oracle ${oracle}, with owner ${ai.owner}!`,
);
}
return { price, uiPrice, lastUpdatedSlot };
return { price, uiPrice, lastUpdatedSlot, provider };
}
public async reloadVaults(client: MangoClient): Promise<void> {

View File

@ -13,6 +13,12 @@ const SBV1_MAINNET_PID = new PublicKey(
let sbv2DevnetProgram;
let sbv2MainnetProgram;
export enum OracleProvider {
Pyth,
Switchboard,
Stub,
}
export class StubOracle {
public price: I80F48;
public lastUpdated: BN;

View File

@ -21,6 +21,7 @@ import {
} from './bank';
import { Group } from './group';
import { MangoAccount } from './mangoAccount';
import { OracleProvider } from './oracle';
export type PerpMarketIndex = number & As<'perp-market-index'>;
@ -55,6 +56,8 @@ export class PerpMarket {
public _price: I80F48;
public _uiPrice: number;
public _oracleLastUpdatedSlot: number;
public _oracleProvider: OracleProvider;
public _bids: BookSide;
public _asks: BookSide;
@ -265,6 +268,15 @@ export class PerpMarket {
return this._oracleLastUpdatedSlot;
}
get oracleProvider(): OracleProvider {
if (!this._oracleProvider) {
throw new Error(
`Undefined oracleProvider for perpMarket ${this.publicKey} with marketIndex ${this.perpMarketIndex}!`,
);
}
return this._oracleProvider;
}
get minOrderSize(): number {
return this.baseLotsToUiConverter;
}