Skip to content

Commit

Permalink
docs: static types for AMM
Browse files Browse the repository at this point in the history
in all but the one conflict between docs and code, the latent
types were straightforward
  • Loading branch information
dckc committed Oct 1, 2021
1 parent 1c82897 commit 2d72e7c
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 14 deletions.
16 changes: 11 additions & 5 deletions packages/zoe/src/contractSupport/bondingCurves.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,17 @@ export const getOutputPrice = (
return add(floorDivide(numerator, denominator), 1n);
};

// Calculate how many liquidity tokens we should be minting to send back to the
// user when adding liquidity. We provide new liquidity equal to the existing
// liquidity multiplied by the ratio of new central tokens to central tokens
// already held. If the current supply is zero, return the inputValue as the
// initial liquidity to mint is arbitrary.
/**
* Calculate how many liquidity tokens we should be minting to send back to the
* user when adding liquidity. We provide new liquidity equal to the existing
* liquidity multiplied by the ratio of new central tokens to central tokens
* already held. If the current supply is zero, return the inputValue as the
* initial liquidity to mint is arbitrary.
*
* @param {bigint} liqTokenSupply
* @param {bigint} inputValue
* @param {bigint} inputReserve
*/
export const calcLiqValueToMint = (
liqTokenSupply,
inputValue,
Expand Down
22 changes: 22 additions & 0 deletions packages/zoe/src/contracts/vpool-xyk-amm/doublePool.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
// input price, that brand will be the inPool; when they specify the output
// price that brand is the outPool.

/** @param {{ swapperGets: Amount, swapperGives: Amount }} prices */
const publicPrices = prices => {
return { amountIn: prices.swapperGives, amountOut: prices.swapperGets };
};
Expand Down Expand Up @@ -54,6 +55,10 @@ export const makeDoublePool = (
X`The central brands on the two pools must match: ${centralBrand}, ${outCentral.brand}`,
);

/**
* @param {ZCFSeat} seat
* @param {ReturnType<typeof getPriceForInput>} prices
*/
const allocateGainsAndLosses = (seat, prices) => {
const inPoolSeat = collateralInPool.getPoolSeat();
const outPoolSeat = collateralOutPool.getPoolSeat();
Expand All @@ -73,6 +78,10 @@ export const makeDoublePool = (
return `Swap successfully completed.`;
};

/**
* @param {Amount} amountIn
* @param {Amount} amountOut
*/
const getPriceForInput = (amountIn, amountOut) => {
// We must do two consecutive swapInPrice() calls,
// followed by a call to swapOutPrice().
Expand Down Expand Up @@ -120,15 +129,28 @@ export const makeDoublePool = (
});
};

/**
* @param {Amount} amountIn
* @param {Amount} amountOut
*/
const getInputPrice = (amountIn, amountOut) => {
return publicPrices(getPriceForInput(amountIn, amountOut));
};

/**
* @param {ZCFSeat} seat
* @param {Amount} amountIn
* @param {Amount} amountOut
*/
const swapIn = (seat, amountIn, amountOut) => {
const prices = getPriceForInput(amountIn, amountOut);
return allocateGainsAndLosses(seat, prices);
};

/**
* @param {Amount} amountIn
* @param {Amount} amountOut
*/
const getPriceForOutput = (amountIn, amountOut) => {
// We must do two consecutive swapOutPrice() calls, followed by a call to
// swapInPrice().
Expand Down
34 changes: 27 additions & 7 deletions packages/zoe/src/contracts/vpool-xyk-amm/multipoolMarketMaker.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,25 @@ import { makeDoublePool } from './doublePool';
* @type {ContractStartFn}
*/
const start = zcf => {
// This contract must have a "Central" keyword and issuer in the
// IssuerKeywordRecord.
// poolFee is the portion of the fees that go into the pool (in BP).
// protocolFee is the portion of the fees that are shared with validators
/**
* This contract must have a "Central" keyword and issuer in the
* IssuerKeywordRecord.
*
* @typedef {{
* brands: { Central: Brand },
* timer: TimerService,
* poolFee: BasisPoints, // portion of the fees that go into the pool
* protocolFee: BasisPoints, // portion of the fees that are shared with validators
* }} AMMTerms
*
* @typedef { bigint } BasisPoints -- hundredths of a percent
*/
const {
brands: { Central: centralBrand },
timer,
poolFee,
protocolFee,
} = zcf.getTerms();
} = /** @type { Terms & AMMTerms } */ (zcf.getTerms());
assertIssuerKeywords(zcf, ['Central']);
assert(centralBrand !== undefined, X`centralBrand must be present`);

Expand All @@ -84,7 +93,9 @@ const start = zcf => {
// something that will extract the fees.
const { zcfSeat: protocolSeat } = zcf.makeEmptySeatKit();

/** @param { Brand } brand */
const getLiquiditySupply = brand => getPool(brand).getLiquiditySupply();
/** @param { Brand } brand */
const getLiquidityIssuer = brand => getPool(brand).getLiquidityIssuer();
const addPool = makeAddPool(
zcf,
Expand All @@ -97,12 +108,14 @@ const start = zcf => {
poolFee,
protocolSeat,
);
/** @param { Brand } brand */
const getPoolAllocation = brand => {
return getPool(brand)
.getPoolSeat()
.getCurrentAllocation();
};

/** @param { Brand } brand */
const getPriceAuthorities = brand => {
const pool = getPool(brand);
return {
Expand All @@ -112,10 +125,9 @@ const start = zcf => {
};

/**
* @callback ProvideVPool
* @param {Brand} brandIn
* @param {Brand} brandOut
* @param {Ratio} poolFeeRatio
* @param {bigint} poolFeeRatio
* @returns {VPool}
*/
const provideVPool = (brandIn, brandOut, poolFeeRatio) => {
Expand All @@ -134,10 +146,18 @@ const start = zcf => {
return pool.getVPool();
};

/**
* @param {Amount} amountIn
* @param {Amount} amountOut
*/
const getInputPrice = (amountIn, amountOut) => {
const pool = provideVPool(amountIn.brand, amountOut.brand, poolFee);
return pool.getInputPrice(amountIn, amountOut);
};
/**
* @param {Amount} amountIn
* @param {Amount} amountOut
*/
const getOutputPrice = (amountIn, amountOut) => {
const pool = provideVPool(amountIn.brand, amountOut.brand, poolFee);
return pool.getOutputPrice(amountIn, amountOut);
Expand Down
13 changes: 13 additions & 0 deletions packages/zoe/src/contracts/vpool-xyk-amm/pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,35 @@ export const makeAddPool = (
poolFee,
protocolSeat,
) => {
/**
* @param {ZCFMint} liquidityZcfMint
* @param liquidityZcfMint
* @param {ZCFSeat} poolSeat
* @param {Brand} secondaryBrand
*/
const makePool = (liquidityZcfMint, poolSeat, secondaryBrand) => {
let liqTokenSupply = 0n;

const {
brand: liquidityBrand,
issuer: liquidityIssuer,
} = liquidityZcfMint.getIssuerRecord();
/** @type { NotifierRecord<Record<string, Amount>> } */
const { notifier, updater } = makeNotifierKit();

/** @param { XYKPool } pool */
const updateState = pool =>
// TODO: when governance can change the interest rate, include it here
updater.updateState({
central: pool.getCentralAmount(),
secondary: pool.getSecondaryAmount(),
});

/**
* @param {XYKPool} pool
* @param {ZCFSeat} zcfSeat
* @param {Amount} secondaryAmount
*/
const addLiquidityActual = (pool, zcfSeat, secondaryAmount) => {
const liquidityValueOut = calcLiqValueToMint(
liqTokenSupply,
Expand Down
4 changes: 2 additions & 2 deletions packages/zoe/src/contracts/vpool-xyk-amm/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@
* @property {(brand: Brand) => Issuer} getLiquidityIssuer
* @property {(brand: Brand) => bigint} getLiquiditySupply get the current value of
* liquidity in the pool for brand held by investors.
* @property {(amountIn: Amount, brandOut: Brand) => VPoolPriceQuote} getInputPrice
* @property {(amountIn: Amount, amountOut: Amount) => VPoolPriceQuote} getInputPrice
* calculate the amount of brandOut that will be returned if the amountIn is
* offered using makeSwapInInvitation at the current price.
* @property {(amountOut: Amount, brandIn: Brand) => VPoolPriceQuote} getOutputPrice
* @property {(amountOut: Amount, amountIn: Amount) => VPoolPriceQuote} getOutputPrice
* calculate the amount of brandIn that is required in order to get amountOut
* using makeSwapOutInvitation at the current price
* @property {(brand: Brand) => Record<string, Amount>} getPoolAllocation get an
Expand Down

0 comments on commit 2d72e7c

Please sign in to comment.