Published
Edited
May 6, 2021
Importers
1 star
Insert cell
Insert cell
Insert cell
chart(examplePair, delta0)
Insert cell
examplePair = new Pair("wBTC", "ETH", 9709, 316615)
Insert cell
amountOut = examplePair.getAmountOut(
delta0,
examplePair.token0Reserve,
examplePair.token1Reserve
)
Insert cell
Insert cell
examplePair.spotPriceFor("eth")
Insert cell
examplePair.swapTokensForTokens(1, "wBTC")
Insert cell
Insert cell
Insert cell
class Pair {
constructor(token0, token1, token0Reserve, token1Reserve) {
this.token0 = token0.toUpperCase();
this.token1 = token1.toUpperCase();
this.token0Reserve = token0Reserve;
this.token1Reserve = token1Reserve;
this.product = this.token0Reserve * this.token1Reserve;
}

static newFromPrice(token0, token1, token0Reserve, token0Price, token1Price) {
return new this(
token0,
token1,
token0Reserve,
(token0Reserve * token0Price) / token1Price
);
}

quote(amountA, reserveA, reserveB) {
assert(amountA > 0, 'INSUFFICIENT_AMOUNT');
assert(reserveA > 0 && reserveB > 0, 'INSUFFICIENT_LIQUIDITY');
return (amountA * reserveB) / reserveA;
}

getAmountOut(amountIn, reserveIn, reserveOut) {
assert(amountIn > 0, 'INSUFFICIENT_AMOUNT');
assert(reserveIn > 0 && reserveOut > 0, 'INSUFFICIENT_LIQUIDITY');
const amountInWithFee = amountIn * 0.997;
const numerator = amountInWithFee * reserveOut;
const denominator = reserveIn + amountInWithFee;
const amountOut = numerator / denominator;
return amountOut;
}

getAmountIn(amountOut, reserveIn, reserveOut) {
assert(amountOut > 0, 'INSUFFICIENT_AMOUNT');
assert(reserveIn > 0 && reserveOut > 0, 'INSUFFICIENT_LIQUIDITY');
const numerator = reserveIn * amountOut * 1000;
const denominator = (reserveOut - amountOut) * 997;
return numerator / denominator + 1;
}

priceImpact(amountIn, tokenInName) {
const pricePrior = this.quote(1, this.token0Reserve, this.token1Reserve);
let priceAfter = 0;
if (this.token0.toUpperCase() === tokenInName.toUpperCase()) {
const delta = this.getAmountOut(
amountIn,
this.token0Reserve,
this.token1Reserve
);
priceAfter = this.quote(
1,
this.token0Reserve,
this.token1Reserve - delta
);
}

if (this.token1.toUpperCase() === tokenInName.toUpperCase()) {
const delta = this.getAmountOut(
amountIn,
this.token1Reserve,
this.token0Reserve
);
priceAfter = this.quote(
1,
this.token0Reserve,
this.token1Reserve + delta
);
}

return (priceAfter - pricePrior) / pricePrior;
}

swapTokensForTokens(amountIn, tokenInName) {
if (this.token0 === tokenInName.toUpperCase() && amountIn > 0) {
const tokenOut = this.getAmountOut(
amountIn,
this.token0Reserve,
this.token1Reserve
);
this.token1Reserve -= tokenOut;

return tokenOut;
}

if (this.token1 === tokenInName.toUpperCase() && amountIn > 0) {
const tokenOut = this.getAmountOut(
amountIn,
this.token1Reserve,
this.token0Reserve
);
this.token0Reserve -= tokenOut;

return tokenOut;
}

return undefined;
}

changeLiquidityInToken(amount, name) {
if (this.token0 === name.toUpperCase() && this.token0Reserve + amount > 0) {
const oldToken0Reserve = this.token0Reserve;
this.token0Reserve = this.token0Reserve + amount;

const tokenMultiple = this.token0Reserve / oldToken0Reserve;
this.token1Reserve = this.token1Reserve * tokenMultiple;

this.product = this.token0Reserve * this.token1Reserve;

return true;
}

if (this.token0 === name.toUpperCase() && this.token1Reserve + amount > 0) {
const oldToken1Reserve = this.token1Reserve;
this.token1Reserve = this.token1Reserve + amount;

const tokenMultiple = this.token1Reserve / oldToken1Reserve;
this.token0Reserve = this.token0Reserve * tokenMultiple;

this.product = this.token0Reserve * this.token1Reserve;

return true;
}

return false;
}

spotPriceFor(name) {
const token0Price = this.token0Reserve / this.token1Reserve;

if (this.token0 === name.toUpperCase()) {
return token0Price;
}

if (this.token1 === name.toUpperCase()) {
return 1 / token0Price;
}
}
}
Insert cell
viewof delta0 = Input(1000)
Insert cell
Insert cell
import { Input, Range, bind, Radio } from "@observablehq/inputs"
Insert cell
ethers = require("https://cdn.ethers.io/lib/ethers-5.0.umd.min.js")
Insert cell
d3 = require("d3@^6.1")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more