goosefx-amm-sdk
Version:
SDK for the GooseFx AMM
2 lines • 6.43 kB
JavaScript
import R from"bn.js";import p from"bn.js";import g from"decimal.js-light";import h from"bn.js";var y=new h(0);function C(d,e){if(e.isZero())throw Error("divisor is zero");return d.mod(e)}function f(d,e){if(e.isZero())throw Error("rhs is zero");let t=d.div(e);return t.isZero()?[t,e]:d.sub(t.mul(e)).isZero()?[t,e]:[t.add(new h(1)),e]}function b(d,e){return d.gt(e)?d.sub(e):new h(0)}var G=new p(100),w=new p(1e6),H=100,J=new p(3600),U=new p(1e5),K=new p(3e5),v=class{static calculateDynamicFee(e,t,i,c,o,r,n){let a=this.calculateDynamicFeeRate(t,i,c,o,r,n),[s,u]=f(e.mul(a),w);return s}static calculatePreDynamicFee(e,t,i,c,o,r,n){let a=this.calculateDynamicFeeRate(t,i,c,o,r,n);if(a.isZero())return e;let s=w.sub(a);if(s.isZero())throw new Error("Fee rate equals denominator, causing division by zero");return e.mul(w).add(s).sub(new p(1)).div(s)}static calculateDynamicFeeRate(e,t,i,c,o,r){switch(i){case"volatility":return this.calculateVolatileFee(e,t,c,o,r)}}static calculateVolatileFee(e,t,i,c,o){let{minPrice:r,maxPrice:n,twapPrice:a}=this.getPriceRange(t,e,J);if(r.eqn(0)||n.eqn(0)||a.eqn(0)||a.eqn(1))return i;let s=new g(n.toString()).ln(),u=new g(r.toString()).ln(),m=new g(a.toString()).ln(),l=s.sub(u),S=m.abs();if(S.eq(0))return i;let A=l.div(S),B=c.eqn(0)?K:c,_=new g(B.toString()).mul(A),N=new g(i.toString()).add(_),D=new p(N.lessThan(new g(U.toString()))?N.toString():U.toString());if(o){let F=b(D,G);return i.gt(F)?i:F}else return D}static getPriceRange(e,t,i){let c=new p(1).ushln(128).subn(1),o=new p(0),r=e.observations.map((m,l)=>({observation:m,idx:l})).filter(({observation:m})=>{m.blockTimestamp.eqn(0)&&!m.cumulativeToken0PriceX32.eqn(0)&&!m.cumulativeToken1PriceX32.eqn(0)&&t.sub(m.blockTimestamp)<=i}).map(({observation:m,idx:l})=>({index:l,observation:m}));if(r.length<2)return{minPrice:new p(0),maxPrice:new p(0),twapPrice:new p(0)};r.sort((m,l)=>l.observation.blockTimestamp.cmp(m.observation.blockTimestamp));let n=r[0],a=r[r.length-1],s=b(n.observation.blockTimestamp,a.observation.blockTimestamp);if(s.eqn(0))return{minPrice:new p(0),maxPrice:new p(0),twapPrice:new p(0)};let u=n.observation.cumulativeToken0PriceX32.sub(a.observation.cumulativeToken0PriceX32).div(s);for(let m of r){let l;if(m.index==0?l=e.observations[H-1]:l=e.observations[m.index-1],l.blockTimestamp.eqn(0))continue;if(l.blockTimestamp>m.observation.blockTimestamp)break;let S=m.observation,A=b(S.blockTimestamp,l.blockTimestamp);if(A.eqn(0))continue;let B=S.cumulativeToken0PriceX32.sub(l.cumulativeToken0PriceX32).div(A);c=p.min(c,B),o=p.max(o,B)}return{minPrice:c,maxPrice:o,twapPrice:u}}static calculatePreFeeAmount(e,t,i,c,o,r,n){let a=this.calculateDynamicFeeRate(e,i,c,o,r,n);if(a.eqn(0))return t;{let s=t.mul(w),u=w.sub(a);return s.add(u).subn(1).div(u)}}};import M from"bn.js";import X from"bn.js";var P=class{static validate_supply(e,t){if(e.isZero())throw Error("tokenAmount0 is zero");if(t.isZero())throw Error("tokenAmount1 is zero")}static swapBaseIn(e,t,i,c,o,r,n=!1){let a=v.calculateDynamicFee(e,new X(new Date().getTime()/1e3),o,"volatility",c,r,n),s=e.sub(a),{sourceAmountSwapped:u,destinationAmountSwapped:m}=T.swapWithoutFees(s,t,i),l=u.add(a);return{newSwapSourceAmount:t.add(l),newSwapDestinationAmount:i.sub(m),sourceAmountSwapped:l,destinationAmountSwapped:m,tradeFee:a}}static swapBaseOut(e,t,i,c,o,r,n=!1){if(e.isZero())throw new Error("destinationAmount is zero");if(e.gt(i))throw new Error("destinationAmount exceeds available destination reserve");let{sourceAmountSwapped:a,destinationAmountSwapped:s}=T.swapWithoutFeesBaseOut(e,t,i),u=v.calculatePreDynamicFee(a,new X(new Date().getTime()/1e3),o,"volatility",c,r,n);return{newSwapSourceAmount:t.add(u),newSwapDestinationAmount:i.sub(s),sourceAmountSwapped:u,destinationAmountSwapped:s,tradeFee:u.sub(a)}}};var T=class{static swapWithoutFees(e,t,i){let c=t.mul(i),o=t.add(e),[r,n]=f(c,o),a=n.sub(t),s=i.sub(r);if(s.isZero())throw Error("destinationAmountSwapped is zero");return{sourceAmountSwapped:a,destinationAmountSwapped:s}}static swapWithoutFeesBaseOut(e,t,i){if(e.isZero())throw new Error("destinationAmount is zero");if(e.gt(i))throw new Error("destinationAmount exceeds available destination reserve");let c=t.mul(e),o=i.sub(e);if(o.isZero())throw new Error("denominator is zero");let[r]=f(c,o);return{sourceAmountSwapped:r,destinationAmountSwapped:e}}static lpTokensToTradingTokens(e,t,i,c,o){let r=e.mul(i).div(t),n=e.mul(c).div(t);if(o===0)return{tokenAmount0:r,tokenAmount1:n};if(o===1)return C(e.mul(i),t).gt(y)&&r.gt(y)&&(r=r.add(new M(1))),C(e.mul(c),t).gt(y)&&n.gt(y)&&(n=n.add(new M(1))),{tokenAmount0:r,tokenAmount1:n};throw Error("roundDirection value error")}};var k=new R(Math.pow(10,9)),$=k.mul(k),O=class{static validate_supply(e,t){return P.validate_supply(e,t)}static swap(e,t,i,c,o,r,n,a=!1){let s=t?i:c,u=t?c:i,m=n.oraclePriceUpdatedAt,l=new R(new Date().getTime()/1e3);if(b(l,m).gtn(n.maxOraclePriceUpdateTimeDiff)||l.lt(m)||m.eqn(0)||n.oraclePriceToken0ByToken1.eqn(0))return P.swapBaseIn(e,s,u,o,r,n.volatilityFactor,a);let A=u.mul(k).div(s),B=t?$.div(n.oraclePriceToken0ByToken1):n.oraclePriceToken0ByToken1;if(O.getSpotPriceAndOraclePriceRateDifference(B,A).gtn(n.acceptablePriceDifference))return P.swapBaseIn(e,s,u,o,r,n.volatilityFactor,a);let N=O.getAmountToBeSwappedAtOraclePrice(e,s,u,B,n),D=e.sub(N);if(N.eqn(0))return P.swapBaseIn(e,s,u,o,r,n.volatilityFactor,a);let F=v.calculateDynamicFeeRate(l,r,"volatility",o,n.volatilityFactor,a),V=F.gten(n.minTradeRateAtOraclePrice)?F:new R(n.minTradeRateAtOraclePrice),q=f(N.mul(V),w)[0],Y=N.sub(q),Z=O.getExecutionOraclePrice(B,new R(n.pricePremiumForSwapAtOraclePrice)).mul(Y).div(k),Q=s.add(N),j=u.sub(Z),I=f(D.mul(F),w)[0],L=b(D,I),W=new R(0);L.isZero()||(W=T.swapWithoutFees(L,Q,j).destinationAmountSwapped);let z=Z.add(W);return{newSwapSourceAmount:s.add(e),newSwapDestinationAmount:u.sub(z),sourceAmountSwapped:e,destinationAmountSwapped:z,tradeFee:I.add(q)}}static getAmountToBeSwappedAtOraclePrice(e,t,i,c,o){let r=t.muln(o.maxAmountSwappableAtOraclePrice).div(w),n=w.subn(o.acceptablePriceDifference),a=c.mul(n).div(w),s=a.mul(t).sub(i.mul(k)).abs(),u=c.add(a),m=s.div(u),l=m.gt(r)?r:m;return l.gt(e)?e:l}static getSpotPriceAndOraclePriceRateDifference(e,t){return t.sub(e).abs().mul(w).div(e)}static getExecutionOraclePrice(e,t){let i=e.mul(t).div(w);return e.add(i)}};export{O as OracleBasedCurveCalculator};
//# sourceMappingURL=oracleCalculator.mjs.map