mirror of
https://github.com/luxfi/uma.git
synced 2026-11-03 10:55:24 +00:00
246 lines
8.0 KiB
JavaScript
246 lines
8.0 KiB
JavaScript
const { web3 } = require("hardhat");
|
|
const { assert } = require("chai");
|
|
const { DominationFinancePriceFeed } = require("../../dist/price-feed/DominationFinancePriceFeed");
|
|
const { NetworkerMock } = require("../../dist/price-feed/NetworkerMock");
|
|
const winston = require("winston");
|
|
|
|
describe("DominationFinancePriceFeed.js", function () {
|
|
let priceFeed;
|
|
let invertedPriceFeed;
|
|
let mockTime = 1588376548;
|
|
let networker;
|
|
|
|
const pair = "test-pair";
|
|
const lookback = 120; // 2 minutes.
|
|
const getTime = () => mockTime;
|
|
const minTimeBetweenUpdates = 60;
|
|
|
|
const { toBN, toWei } = web3.utils;
|
|
|
|
// Fake data to inject.
|
|
//
|
|
const earliestTick = 1588376400;
|
|
|
|
const historicalResponse = {
|
|
status: "success",
|
|
data: {
|
|
rows: [
|
|
[earliestTick + 0 * 60, "1.1"],
|
|
[earliestTick + 1 * 60, "1.2"],
|
|
[earliestTick + 2 * 60, "1.3"],
|
|
],
|
|
},
|
|
};
|
|
|
|
const priceResponse = { status: "success", timestamp: 1588376583, price: "1.5" };
|
|
|
|
const validResponses = [priceResponse, historicalResponse];
|
|
|
|
beforeEach(async function () {
|
|
networker = new NetworkerMock();
|
|
const dummyLogger = winston.createLogger({ level: "info", transports: [new winston.transports.Console()] });
|
|
priceFeed = new DominationFinancePriceFeed(
|
|
dummyLogger,
|
|
web3,
|
|
pair,
|
|
lookback,
|
|
networker,
|
|
getTime,
|
|
minTimeBetweenUpdates,
|
|
false,
|
|
18 // Prove that this will not break existing functionality
|
|
);
|
|
invertedPriceFeed = new DominationFinancePriceFeed(
|
|
dummyLogger,
|
|
web3,
|
|
pair,
|
|
lookback,
|
|
networker,
|
|
getTime,
|
|
minTimeBetweenUpdates,
|
|
true,
|
|
10 // Add arbitrary decimal conversion and prove this works.
|
|
);
|
|
});
|
|
|
|
it("Inverted current price", async function () {
|
|
networker.getJsonReturns = [...validResponses];
|
|
await invertedPriceFeed.update();
|
|
|
|
assert.equal(
|
|
// Should be equal to: toWei(1/1.5)
|
|
invertedPriceFeed.getCurrentPrice().toString(),
|
|
toBN(toWei("1"))
|
|
.mul(toBN(toWei("1")))
|
|
.div(toBN(toWei("1.5")))
|
|
// we need this last division to convert final result to correct decimals
|
|
// in this case its from 18 decimals to 10 decimals.
|
|
// You will see this in the rest of the inverted tests.
|
|
.div(toBN("10").pow(toBN(18 - 10)))
|
|
.toString()
|
|
);
|
|
});
|
|
|
|
it("Inverted historical price", async function () {
|
|
networker.getJsonReturns = [...validResponses];
|
|
await invertedPriceFeed.update();
|
|
|
|
// Before period 1 should return fail.
|
|
assert.equal(earliestTick, historicalResponse.data.rows[0][0]);
|
|
assert.isTrue(await invertedPriceFeed.getHistoricalPrice(earliestTick - 15).catch(() => true));
|
|
|
|
// During period 1.
|
|
assert.equal(
|
|
// Should be equal to: toWei(1/1.1)
|
|
(await invertedPriceFeed.getHistoricalPrice(earliestTick)).toString(),
|
|
toBN(toWei("1"))
|
|
.mul(toBN(toWei("1")))
|
|
.div(toBN(toWei("1.1")))
|
|
.div(toBN("10").pow(toBN(18 - 10)))
|
|
.toString()
|
|
);
|
|
|
|
// During period 2.
|
|
assert.equal(
|
|
// Should be equal to: toWei(1/1.2)
|
|
(await invertedPriceFeed.getHistoricalPrice(historicalResponse.data.rows[1][0] + 5)).toString(),
|
|
toBN(toWei("1"))
|
|
.mul(toBN(toWei("1")))
|
|
.div(toBN(toWei("1.2")))
|
|
.div(toBN("10").pow(toBN(18 - 10)))
|
|
.toString()
|
|
);
|
|
|
|
// During period 3.
|
|
assert.equal(
|
|
// Should be equal to: toWei(1/1.3)
|
|
(await invertedPriceFeed.getHistoricalPrice(historicalResponse.data.rows[2][0] + 5)).toString(),
|
|
toBN(toWei("1"))
|
|
.mul(toBN(toWei("1")))
|
|
.div(toBN(toWei("1.3")))
|
|
.div(toBN("10").pow(toBN(18 - 10)))
|
|
.toString()
|
|
);
|
|
|
|
// After period 3 should return the most recent price.
|
|
assert.equal(
|
|
// Should be equal to: toWei(1/1.5)
|
|
await invertedPriceFeed.getHistoricalPrice(historicalResponse.data.rows[2][0] + 95),
|
|
toBN(toWei("1"))
|
|
.mul(toBN(toWei("1")))
|
|
.div(toBN(toWei("1.5")))
|
|
.div(toBN("10").pow(toBN(18 - 10)))
|
|
.toString()
|
|
);
|
|
});
|
|
|
|
it("No update", async function () {
|
|
assert.equal(priceFeed.getCurrentPrice(), undefined);
|
|
assert.isTrue(await priceFeed.getHistoricalPrice(1000).catch(() => true));
|
|
assert.equal(priceFeed.getLastUpdateTime(), undefined);
|
|
assert.equal(priceFeed.getLookback(), lookback);
|
|
});
|
|
|
|
it("Basic historical price", async function () {
|
|
// Inject data.
|
|
networker.getJsonReturns = [...validResponses];
|
|
|
|
await priceFeed.update();
|
|
|
|
// Before period 1 should fail.
|
|
assert.equal(earliestTick, historicalResponse.data.rows[0][0]);
|
|
assert.isTrue(await priceFeed.getHistoricalPrice(earliestTick - 15).catch(() => true));
|
|
|
|
// During period 1.
|
|
assert.equal((await priceFeed.getHistoricalPrice(historicalResponse.data.rows[0][0] + 5)).toString(), toWei("1.1"));
|
|
|
|
// During period 2.
|
|
assert.equal((await priceFeed.getHistoricalPrice(historicalResponse.data.rows[1][0] + 5)).toString(), toWei("1.2"));
|
|
|
|
// During period 3.
|
|
assert.equal((await priceFeed.getHistoricalPrice(historicalResponse.data.rows[2][0] + 5)).toString(), toWei("1.3"));
|
|
|
|
// After period 3 should return the most recent price.
|
|
assert.equal(
|
|
(await priceFeed.getHistoricalPrice(historicalResponse.data.rows[2][0] + 90)).toString(),
|
|
toWei("1.5")
|
|
);
|
|
});
|
|
|
|
it("Basic current price", async function () {
|
|
// Inject data.
|
|
networker.getJsonReturns = [...validResponses];
|
|
|
|
await priceFeed.update();
|
|
|
|
// Should return the current price in the data.
|
|
assert.equal(priceFeed.getCurrentPrice().toString(), toWei("1.5"));
|
|
});
|
|
|
|
it("Last update time", async function () {
|
|
// Inject data.
|
|
networker.getJsonReturns = [...validResponses];
|
|
|
|
await priceFeed.update();
|
|
|
|
// Should return the mock time.
|
|
assert.equal(priceFeed.getLastUpdateTime(), mockTime);
|
|
});
|
|
|
|
it("No or bad response", async function () {
|
|
// Bad price response.
|
|
networker.getJsonReturns = [
|
|
{
|
|
status: "success",
|
|
data: {
|
|
rows: [], // Valid response, just no data points.
|
|
},
|
|
},
|
|
{ status: "error" },
|
|
];
|
|
|
|
// Update should throw errors in both cases.
|
|
assert.isTrue(await priceFeed.update().catch(() => true), "Update didn't throw");
|
|
assert.isTrue(await invertedPriceFeed.update().catch(() => true), "Update didn't throw");
|
|
|
|
assert.equal(priceFeed.getCurrentPrice(), undefined);
|
|
assert.isTrue(await priceFeed.getHistoricalPrice(earliestTick).catch(() => true));
|
|
assert.equal(invertedPriceFeed.getCurrentPrice(), undefined);
|
|
assert.isTrue(await invertedPriceFeed.getHistoricalPrice(earliestTick).catch(() => true));
|
|
|
|
// Bad historical ohlc response.
|
|
networker.getJsonReturns = [{ status: "error" }, { status: "success", price: "64.21" }];
|
|
|
|
assert.isTrue(await priceFeed.update().catch(() => true), "Update didn't throw");
|
|
|
|
assert.equal(priceFeed.getCurrentPrice(), undefined);
|
|
assert.isTrue(await priceFeed.getHistoricalPrice(earliestTick).catch(() => true));
|
|
|
|
// Inverted price feed returns undefined for prices equal to 0 since it cannot divide by 0
|
|
networker.getJsonReturns = [{ status: "error" }, { status: "success", price: "0.00" }];
|
|
|
|
assert.isTrue(await invertedPriceFeed.update().catch(() => true), "Update didn't throw");
|
|
|
|
assert.equal(invertedPriceFeed.getCurrentPrice(), undefined);
|
|
assert.isTrue(await invertedPriceFeed.getHistoricalPrice(earliestTick).catch(() => true));
|
|
});
|
|
|
|
it("Update frequency", async function () {
|
|
networker.getJsonReturns = [...validResponses];
|
|
|
|
await priceFeed.update();
|
|
|
|
networker.getJsonReturns = [...validResponses];
|
|
|
|
// Update the return price to ensure it new data doesn't show up in the output.
|
|
networker.getJsonReturns[0].price = "1.4";
|
|
|
|
const originalMockTime = mockTime;
|
|
mockTime += minTimeBetweenUpdates - 1;
|
|
|
|
await priceFeed.update();
|
|
assert.equal(priceFeed.getLastUpdateTime(), originalMockTime);
|
|
assert.equal(priceFeed.getCurrentPrice().toString(), toWei("1.5"));
|
|
});
|
|
});
|