UNPKG

@bancor/carbon-sdk

Version:

The SDK is a READ-ONLY tool, intended to facilitate working with Carbon contracts. It's a convenient wrapper around our matching algorithm, allowing programs and users get a ready to use transaction data that will allow them to manage strategies and fulfi

2 lines (1 loc) 10.8 kB
import{formatUnits as e,parseUnits as t,Decimal as a,tenPow as r,BigNumberMax as i,mulDiv as o}from"../../utils/numerics/index.js";import{MatchType as s}from"../../common/types/index.js";import{Decimals as c}from"../../utils/decimals/index.js";import{matchByTargetAmount as d,matchBySourceAmount as n}from"../../trade-matcher/match/index.js";import{getEncodedTradeSourceAmount as l}from"../../trade-matcher/trade/index.js";import{getDepths as g,getMinRate as u,getMaxRate as m}from"../stats/index.js";import{Logger as y}from"../../common/logger/index.js";import{decodeStrategy as h,parseStrategy as p,addFee as f,subtractFee as B,calculateOverlappingSellBudget as S,calculateOverlappingBuyBudget as b,buildStrategyObject as w,encodeStrategy as P,normalizeRate as D}from"../utils/index.js";import{decodeOrder as _}from"../../utils/encoders/index.js";import{ordersMapStrToBN as v,matchActionBNToStr as T,ordersMapBNToStr as A,tradeActionStrToBN as k,encodedStrategyStrToBN as x}from"../../utils/serializers/index.js";import{BigNumber as O}from"@ethersproject/bignumber";const M=new y("Toolkit.ts");var z;function R(e){return void 0!==e&&e!==z.reset&&e!==z.maintain}!function(e){e.reset="RESET",e.maintain="MAINTAIN"}(z||(z={}));class j{_api;_decimals;_cache;constructor(e,t,a){M.debug("SDK class constructor called with",arguments),this._api=e,this._cache=t;this._decimals=new c((async e=>await(a?.(e))??await this._api.reader.getDecimalsByAddress(e)))}static getMatchActions(e,t,a,r=s.Fast,i){const o=v(a);let c;return c=t?d(O.from(e),o,[r],i):n(O.from(e),o,[r],i),c[r]?.map(T)??[]}async hasLiquidityByPair(e,t){M.debug("hasLiquidityByPair called",arguments);const a=await this._cache.getOrdersByPair(e,t);return M.debug("hasLiquidityByPair info:",{orders:a}),Object.keys(a).length>0}async getLiquidityByPair(t,a){M.debug("getLiquidityByPair called",arguments);const r=await this._cache.getOrdersByPair(t,a),i=Object.values(r).reduce(((e,{y:t})=>e.add(t)),O.from(0)),o=await this._decimals.fetchDecimals(a),s=e(i,o);return M.debug("getLiquidityByPair info:",{orders:r,liquidityWei:i,targetToken:a,decimals:o,liquidity:s}),s}async getMaxSourceAmountByPair(t,a){M.debug("getMaxSourceAmountByPair called",arguments);const r=await this._cache.getOrdersByPair(t,a),i=Object.values(r).reduce(((e,t)=>e.add(l(t.y,t))),O.from(0)),o=await this._decimals.fetchDecimals(t),s=e(i,o);return M.debug("getMaxSourceAmountByPair info:",{orders:r,maxSourceAmountWei:i,sourceToken:t,decimals:o,maxSourceAmount:s}),s}async getStrategyById(e){let t;M.debug("getStrategyById called",arguments),this._cache&&(t=await this._cache.getStrategyById(e)),t?M.debug("getStrategyById fetched from cache"):(M.debug("getStrategyById fetching from chain"),t=await this._api.reader.strategy(O.from(e)));const a=h(t),r=await p(a,this._decimals);return M.debug("getStrategyById info:",{id:e,encodedStrategy:t,decodedStrategy:a,strategy:r}),r}async getStrategiesByPair(e,t){let a;M.debug("getStrategiesByPair called",arguments),this._cache&&(a=await this._cache.getStrategiesByPair(e,t)),a?M.debug("getStrategiesByPair fetched from cache"):(M.debug("getStrategiesByPair fetching from chain"),a=await this._api.reader.strategiesByPair(e,t));const r=a.map(h),i=await Promise.all(r.map((async e=>await p(e,this._decimals))));return M.debug("getStrategiesByPair info:",{token0:e,token1:t,encodedStrategies:a,decodedStrategies:r,strategies:i}),i}async getUserStrategies(e){M.debug("getUserStrategies called",arguments);const t=await this._api.reader.tokensByOwner(e);let a=[],r=t;if(this._cache&&(r=t.reduce(((e,t)=>{const r=this._cache.getStrategyById(t);return r?a.push(r):e.push(t),e}),[])),r.length>0){const e=await this._api.reader.strategies(r);a=[...a,...e]}const i=a.map(h),o=await Promise.all(i.map((async e=>await p(e,this._decimals))));return M.debug("getUserStrategies info:",{ids:t,encodedStrategies:a,decodedStrategies:i,strategies:o}),o}async getMatchParams(e,a,r,i){M.debug("getMatchParams called",arguments);const o=this._decimals,s=await o.fetchDecimals(e),c=await o.fetchDecimals(a),d=await this._cache.getOrdersByPair(e,a),n=t(r,i?c:s);return{orders:A(d),amountWei:n.toString(),sourceDecimals:s,targetDecimals:c}}async getTradeData(e,t,a,r,i=s.Fast,o){M.debug("getTradeData called",arguments);const{orders:c,amountWei:d}=await this.getMatchParams(e,t,a,r),n=j.getMatchActions(d,r,c,i,o),l=await this.getTradeDataFromActions(e,t,r,n);return M.debug("getTradeData info:",{orders:c,amount:a,amountWei:d,res:l}),l}async getTradeDataFromActions(t,i,o,s){M.debug("getTradeDataFromActions called",arguments);const c=await this._cache.getTradingFeePPMByPair(t,i);if(void 0===c)throw new Error(`tradingFeePPM is undefined for this pair: ${t}-${i}`);const d=this._decimals,n=await d.fetchDecimals(t),l=await d.fetchDecimals(i),g=[],u=[];let m,y,h,p=O.from(0),S=O.from(0);if(s.forEach((t=>{g.push({strategyId:t.id,amount:t.input}),o?u.push({id:t.id,sourceAmount:e(f(t.output,c).floor().toFixed(0),n),targetAmount:e(t.input,l)}):u.push({id:t.id,sourceAmount:e(t.input,n),targetAmount:e(B(t.output,c).floor().toFixed(0),l)}),S=S.add(t.input),p=p.add(t.output)})),o?(m=f(p,c).floor().toFixed(0),y=S.toString()):(m=S.toString(),y=B(p,c).floor().toFixed(0)),new a(m).isZero()||new a(y).isZero())h={tradeActions:g,actionsTokenRes:u,totalSourceAmount:"0",totalTargetAmount:"0",effectiveRate:"0",actionsWei:s};else{const t=new a(y).div(m).times(r(n,l)).toString();h={tradeActions:g,actionsTokenRes:u,totalSourceAmount:e(m,n),totalTargetAmount:e(y,l),effectiveRate:t,actionsWei:s}}return M.debug("getTradeDataFromActions info:",{sourceDecimals:n,targetDecimals:l,actionsWei:s,totalInput:S,totalOutput:p,tradingFeePPM:c,res:h}),h}async composeTradeByTargetTransaction(e,a,r,i,o,s){M.debug("composeTradeByTargetTransaction called",arguments);const c=await this._decimals.fetchDecimals(e);return this._api.composer.tradeByTargetAmount(e,a,r.map(k),i,t(o,c),s)}async composeTradeBySourceTransaction(e,a,r,i,o,s){M.debug("composeTradeBySourceTransaction called",arguments);const c=await this._decimals.fetchDecimals(a);return this._api.composer.tradeBySourceAmount(e,a,r.map(k),i,t(o,c),s)}async calculateOverlappingStrategySellBudget(e,t,a,r,i,o,s){M.debug("calculateOverlappingStrategySellBudget called",arguments);const c=this._decimals,d=await c.fetchDecimals(e),n=await c.fetchDecimals(t),l=S(d,n,a,r,i,o,s);return M.debug("calculateOverlappingStrategySellBudget info:",{baseDecimals:d,budget:l}),l}async calculateOverlappingStrategyBuyBudget(e,t,a,r,i,o,s){M.debug("calculateOverlappingStrategyBuyBudget called",arguments);const c=this._decimals,d=await c.fetchDecimals(e),n=await c.fetchDecimals(t),l=b(d,n,a,r,i,o,s);return M.debug("calculateOverlappingStrategyBuyBudget info:",{quoteDecimals:n,budget:l}),l}async createBuySellStrategy(e,t,a,r,i,o,s,c,d,n,l){M.debug("createBuySellStrategy called",arguments);const g=this._decimals,u=await g.fetchDecimals(e),m=await g.fetchDecimals(t),y=w(e,t,u,m,a,r,i,o,s,c,d,n),h=P(y);return M.debug("createBuySellStrategy info:",{strategy:y,encStrategy:h}),this._api.composer.createStrategy(h.token0,h.token1,h.order0,h.order1,l)}async batchCreateBuySellStrategies(e,t){M.debug("batchCreateBuySellStrategies called",arguments);const a=this._decimals,r=await Promise.all(e.map((async e=>{const t=await a.fetchDecimals(e.baseToken),r=await a.fetchDecimals(e.quoteToken),i=w(e.baseToken,e.quoteToken,t,r,e.buyPriceLow,e.buyPriceMarginal,e.buyPriceHigh,e.buyBudget,e.sellPriceLow,e.sellPriceMarginal,e.sellPriceHigh,e.sellBudget),o=P(i);return{token0:o.token0,token1:o.token1,order0:o.order0,order1:o.order1}})));return M.debug("batchCreateBuySellStrategies info:",{encStrategies:r}),this._api.composer.batchCreateStrategies(r,t)}async updateStrategy(e,t,{buyPriceLow:a,buyPriceHigh:r,buyBudget:s,sellPriceLow:c,sellPriceHigh:d,sellBudget:n},l,g,u){M.debug("updateStrategy called",arguments);const m=h(x(t)),y=await p(m,this._decimals),f=this._decimals,B=await f.fetchDecimals(y.baseToken),S=await f.fetchDecimals(y.quoteToken),b=w(y.baseToken,y.quoteToken,B,S,a??y.buyPriceLow,R(l)?l:r??y.buyPriceHigh,r??y.buyPriceHigh,s??y.buyBudget,c??y.sellPriceLow,R(g)?g:c??y.sellPriceLow,d??y.sellPriceHigh,n??y.sellBudget),D=P(b),_=x(t);return void 0===s&&void 0===a&&void 0===r&&void 0===l&&(D.order1.y=_.order1.y,D.order1.z=_.order1.z,D.order1.A=_.order1.A,D.order1.B=_.order1.B),void 0===n&&void 0===c&&void 0===d&&void 0===g&&(D.order0.y=_.order0.y,D.order0.z=_.order0.z,D.order0.A=_.order0.A,D.order0.B=_.order0.B),void 0===s&&(D.order1.y=_.order1.y),void 0===n&&(D.order0.y=_.order0.y),void 0===a&&void 0===r&&(D.order1.A=_.order1.A,D.order1.B=_.order1.B),void 0===c&&void 0===d&&(D.order0.A=_.order0.A,D.order0.B=_.order0.B),void 0!==s&&(R(l)||(l===z.maintain?_.order1.y.isZero()?D.order1.z=i(_.order1.z,D.order1.y):D.order1.z=o(_.order1.z,D.order1.y,_.order1.y):D.order1.z=D.order1.y)),void 0!==n&&(R(g)||(g===z.maintain?_.order0.y.isZero()?D.order0.z=i(_.order0.z,D.order0.y):D.order0.z=o(_.order0.z,D.order0.y,_.order0.y):D.order0.z=D.order0.y)),void 0===a&&void 0===r||l!==z.reset&&void 0!==l||(D.order1.z=D.order1.y),void 0===c&&void 0===d||g!==z.reset&&void 0!==g||(D.order0.z=D.order0.y),M.debug("updateStrategy info:",{baseDecimals:B,quoteDecimals:S,decodedOriginal:m,originalStrategy:y,newStrategy:b,newEncodedStrategy:D}),this._api.composer.updateStrategy(O.from(e),D.token0,D.token1,[_.order0,_.order1],[D.order0,D.order1],u)}async deleteStrategy(e){return M.debug("deleteStrategy called",arguments),this._api.composer.deleteStrategy(O.from(e))}async getRateLiquidityDepthsByPair(t,r,i){M.debug("getRateLiquidityDepthByPair called",arguments);const o=Object.values(await this._cache.getOrdersByPair(t,r)).map(_),s=this._decimals,c=await s.fetchDecimals(t),d=await s.fetchDecimals(r),n=i.map((e=>new a(D(e,d,c)))),l=g(o,n).map((e=>e.floor().toFixed(0))),u=l.map((t=>e(t,d)));return M.debug("getRateLiquidityDepthByPair info:",{orders:o,depthsWei:l,targetDecimals:d,depthsInTargetDecimals:u}),u}async getMinRateByPair(e,t){M.debug("getMinRateByPair called",arguments);const a=Object.values(await this._cache.getOrdersByPair(e,t)).map(_),r=u(a).toString(),i=this._decimals,o=await i.fetchDecimals(e),s=await i.fetchDecimals(t),c=D(r,o,s);return M.debug("getMinRateByPair info:",{orders:a,minRate:r,sourceDecimals:o,targetDecimals:s,normalizedRate:c}),c}async getMaxRateByPair(e,t){M.debug("getMaxRateByPair called",arguments);const a=Object.values(await this._cache.getOrdersByPair(e,t)).map(_),r=m(a).toString(),i=this._decimals,o=await i.fetchDecimals(e),s=await i.fetchDecimals(t),c=D(r,o,s);return M.debug("getMaxRateByPair info:",{orders:a,maxRate:r,sourceDecimals:o,targetDecimals:s,normalizedRate:c}),c}}export{z as MarginalPriceOptions,j as Toolkit,R as isMarginalPriceValue};