@tracer-protocol/pools-js
Version:
Javascript library for interacting with Tracer's Perpetual Pools
154 lines (128 loc) • 4.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _types = require("@tracer-protocol/perpetual-pools-contracts/types");
var _bignumber = _interopRequireDefault(require("bignumber.js"));
var _multicall = require("@0xsequence/multicall");
var _ethers = require("ethers");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const defaultSMAOracle = {
updateInterval: 60 * 60,
// 1 hour
numPeriods: 8
};
/**
* SMAOracle class constructor inputs
*/
/**
* SMAOracle class for interacting with ERC20 tokens
* The constructor is private so must be instantiated with {@linkcode SMAOracle.Create}
*/
class SMAOracle {
// assumes all SMA oracles use spot chainlink oracle wrapper
//update interval in seconds
// number of periods included in SMA calc
/**
* @private
*/
constructor() {
this.address = '';
this.type = undefined;
this.provider = undefined;
this.multicallProvider = undefined;
this.updateInterval = defaultSMAOracle.updateInterval;
this.numPeriods = defaultSMAOracle.numPeriods;
}
/**
* Replacement constructor pattern to support async initialisations
* @param tokenINfo {@link ISMAOracle | ISMAOracle interface props}
* @returns a Promise containing an initialised SMAOracle class ready to be used
*/
static Create = async oracleInfo => {
const oracle = new SMAOracle();
await oracle.init(oracleInfo);
return oracle;
};
/**
* Creates an empty SMAOracle that can be used as a default
* @returns default constructed token
*/
static CreateDefault = () => {
const oracle = new SMAOracle();
return oracle;
};
/**
* Private initialisation function called in {@link SMAOracle.Create}
* @private
* @param oracleInfo {@link ISMAOracle | ISMAOracle interface props}
*/
init = async oracleInfo => {
this.provider = oracleInfo.provider;
this.multicallProvider = new _multicall.providers.MulticallProvider(oracleInfo.provider);
this.address = oracleInfo.address;
const contract = _types.SMAOracle__factory.connect(oracleInfo.address, this.multicallProvider);
this._contract = contract; // default values (if not SMA, will assume spot and use this)
let updateInterval = 0;
let numPeriods = 0;
let type = 'Spot';
let underlyingOracleAddress = oracleInfo.address;
try {
const [_updateInterval, _numPeriods, _underlyingOracleAddress] = await Promise.all([contract.updateInterval(), contract.numPeriods(), contract.oracle()]);
updateInterval = _updateInterval.toNumber();
numPeriods = _numPeriods.toNumber();
type = 'SMA';
underlyingOracleAddress = _underlyingOracleAddress;
} catch (error) {
console.log(`failed to init sma details for oracle ${oracleInfo.address}, assuming spot oracle`);
}
this._underlyingOracle = _types.ChainlinkOracleWrapper__factory.connect(underlyingOracleAddress, this.multicallProvider);
this.updateInterval = updateInterval;
this.numPeriods = numPeriods;
this.type = type;
};
/**
* get the latest SMA price
* @returns the average of the most recent price data points
*/
getPrice = async () => {
if (!this._contract) {
throw Error("Failed to fetch oracle price: Contract not defined");
}
try {
const price = await this._contract.getPrice(); // OracleWrapper always scales feed decimals to 18 places
return new _bignumber.default(_ethers.ethers.utils.formatEther(price));
} catch (err) {
throw Error(`Failed to fetch oracle price: ${err}`);
}
};
/**
* get the current underlying spot price
* @returns the current price reported by the underlying price oracle
*/
getSpotPrice = async () => {
if (!this._underlyingOracle) {
throw Error("Failed to fetch sma spot price: underlying oracle not defined");
}
try {
const price = await this._underlyingOracle.getPrice();
return new _bignumber.default(_ethers.ethers.utils.formatEther(price));
} catch (err) {
throw Error(`Failed to fetch underlying oracle price: ${err}`);
}
};
/**
* Replaces the provider and connects the contract instance
* @param provider The new provider to connect to
*/
connect = provider => {
if (!provider) {
throw Error("Failed to connect SMAOracle: provider cannot be undefined");
}
this.provider = provider;
this.multicallProvider = new _multicall.providers.MulticallProvider(provider);
this._contract = this._contract?.connect(this.multicallProvider);
};
}
exports.default = SMAOracle;