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) 11.4 kB
import{formatUnits as e,parseUnits as t,Decimal as a,tenPow as r,BigNumberMax as i,mulDiv as s}from"../../utils/numerics/index.js";import{MatchType as o}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 g}from"../../trade-matcher/trade/index.js";import{getDepths as l,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 _}from"../utils/index.js";import{decodeOrder as D}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=o.Fast,i){const s=v(a);let c;return c=t?d(O.from(e),s,[r],i):n(O.from(e),s,[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)),s=await this._decimals.fetchDecimals(a),o=e(i,s);return M.debug("getLiquidityByPair info:",{orders:r,liquidityWei:i,targetToken:a,decimals:s,liquidity:o}),o}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(g(t.y,t))),O.from(0)),s=await this._decimals.fetchDecimals(t),o=e(i,s);return M.debug("getMaxSourceAmountByPair info:",{orders:r,maxSourceAmountWei:i,sourceToken:t,decimals:s,maxSourceAmount:o}),o}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 getStrategiesByPairs(e){let t;M.debug("getStrategiesByPairs called",arguments),this._cache&&(t=await this._cache.getStrategiesByPairs(e)),t?M.debug("getStrategiesByPairs fetched from cache"):(M.debug("getStrategiesByPairs fetching from chain"),t=await this._api.reader.strategiesByPairs(e));const a=t.map((({pair:e,strategies:t})=>({pair:e,strategies:t.map(h)}))),r=await Promise.all(a.map((async({pair:e,strategies:t})=>({pair:e,strategies:await Promise.all(t.map((async e=>await p(e,this._decimals))))}))));return M.debug("getStrategiesByPairs info:",{pairs:e,encodedStrategies:t,decodedStrategies:a,strategies:r}),r}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),s=await Promise.all(i.map((async e=>await p(e,this._decimals))));return M.debug("getUserStrategies info:",{ids:t,encodedStrategies:a,decodedStrategies:i,strategies:s}),s}async getMatchParams(e,a,r,i){M.debug("getMatchParams called",arguments);const s=this._decimals,o=await s.fetchDecimals(e),c=await s.fetchDecimals(a),d=await this._cache.getOrdersByPair(e,a),n=t(r,i?c:o);return{orders:A(d),amountWei:n.toString(),sourceDecimals:o,targetDecimals:c}}async getTradeData(e,t,a,r,i=o.Fast,s){M.debug("getTradeData called",arguments);const{orders:c,amountWei:d}=await this.getMatchParams(e,t,a,r),n=j.getMatchActions(d,r,c,i,s),g=await this.getTradeDataFromActions(e,t,r,n);return M.debug("getTradeData info:",{orders:c,amount:a,amountWei:d,res:g}),g}async getTradeDataFromActions(t,i,s,o){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),g=await d.fetchDecimals(i),l=[],u=[];let m,y,h,p=O.from(0),S=O.from(0);if(o.forEach((t=>{l.push({strategyId:t.id,amount:t.input}),s?u.push({id:t.id,sourceAmount:e(f(t.output,c).floor().toFixed(0),n),targetAmount:e(t.input,g)}):u.push({id:t.id,sourceAmount:e(t.input,n),targetAmount:e(B(t.output,c).floor().toFixed(0),g)}),S=S.add(t.input),p=p.add(t.output)})),s?(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:l,actionsTokenRes:u,totalSourceAmount:"0",totalTargetAmount:"0",effectiveRate:"0",actionsWei:o};else{const t=new a(y).div(m).times(r(n,g)).toString();h={tradeActions:l,actionsTokenRes:u,totalSourceAmount:e(m,n),totalTargetAmount:e(y,g),effectiveRate:t,actionsWei:o}}return M.debug("getTradeDataFromActions info:",{sourceDecimals:n,targetDecimals:g,actionsWei:o,totalInput:S,totalOutput:p,tradingFeePPM:c,res:h}),h}async composeTradeByTargetTransaction(e,a,r,i,s,o){M.debug("composeTradeByTargetTransaction called",arguments);const c=await this._decimals.fetchDecimals(e);return this._api.composer.tradeByTargetAmount(e,a,r.map(k),i,t(s,c),o)}async composeTradeBySourceTransaction(e,a,r,i,s,o){M.debug("composeTradeBySourceTransaction called",arguments);const c=await this._decimals.fetchDecimals(a);return this._api.composer.tradeBySourceAmount(e,a,r.map(k),i,t(s,c),o)}async calculateOverlappingStrategySellBudget(e,t,a,r,i,s,o){M.debug("calculateOverlappingStrategySellBudget called",arguments);const c=this._decimals,d=await c.fetchDecimals(e),n=await c.fetchDecimals(t),g=S(d,n,a,r,i,s,o);return M.debug("calculateOverlappingStrategySellBudget info:",{baseDecimals:d,budget:g}),g}async calculateOverlappingStrategyBuyBudget(e,t,a,r,i,s,o){M.debug("calculateOverlappingStrategyBuyBudget called",arguments);const c=this._decimals,d=await c.fetchDecimals(e),n=await c.fetchDecimals(t),g=b(d,n,a,r,i,s,o);return M.debug("calculateOverlappingStrategyBuyBudget info:",{quoteDecimals:n,budget:g}),g}async createBuySellStrategy(e,t,a,r,i,s,o,c,d,n,g){M.debug("createBuySellStrategy called",arguments);const l=this._decimals,u=await l.fetchDecimals(e),m=await l.fetchDecimals(t),y=w(e,t,u,m,a,r,i,s,o,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,g)}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),s=P(i);return{token0:s.token0,token1:s.token1,order0:s.order0,order1:s.order1}})));return M.debug("batchCreateBuySellStrategies info:",{encStrategies:r}),this._api.composer.batchCreateStrategies(r,t)}async updateStrategy(e,t,{buyPriceLow:a,buyPriceHigh:r,buyBudget:o,sellPriceLow:c,sellPriceHigh:d,sellBudget:n},g,l,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(g)?g:r??y.buyPriceHigh,r??y.buyPriceHigh,o??y.buyBudget,c??y.sellPriceLow,R(l)?l:c??y.sellPriceLow,d??y.sellPriceHigh,n??y.sellBudget),_=P(b),D=x(t);return void 0===o&&void 0===a&&void 0===r&&void 0===g&&(_.order1.y=D.order1.y,_.order1.z=D.order1.z,_.order1.A=D.order1.A,_.order1.B=D.order1.B),void 0===n&&void 0===c&&void 0===d&&void 0===l&&(_.order0.y=D.order0.y,_.order0.z=D.order0.z,_.order0.A=D.order0.A,_.order0.B=D.order0.B),void 0===o&&(_.order1.y=D.order1.y),void 0===n&&(_.order0.y=D.order0.y),void 0===a&&void 0===r&&(_.order1.A=D.order1.A,_.order1.B=D.order1.B),void 0===c&&void 0===d&&(_.order0.A=D.order0.A,_.order0.B=D.order0.B),void 0!==o&&(R(g)||(g===z.maintain?D.order1.y.isZero()?_.order1.z=i(D.order1.z,_.order1.y):_.order1.z=s(D.order1.z,_.order1.y,D.order1.y):_.order1.z=_.order1.y)),void 0!==n&&(R(l)||(l===z.maintain?D.order0.y.isZero()?_.order0.z=i(D.order0.z,_.order0.y):_.order0.z=s(D.order0.z,_.order0.y,D.order0.y):_.order0.z=_.order0.y)),void 0===a&&void 0===r||g!==z.reset&&void 0!==g||(_.order1.z=_.order1.y),void 0===c&&void 0===d||l!==z.reset&&void 0!==l||(_.order0.z=_.order0.y),M.debug("updateStrategy info:",{baseDecimals:B,quoteDecimals:S,decodedOriginal:m,originalStrategy:y,newStrategy:b,newEncodedStrategy:_}),this._api.composer.updateStrategy(O.from(e),_.token0,_.token1,[D.order0,D.order1],[_.order0,_.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 s=Object.values(await this._cache.getOrdersByPair(t,r)).map(D),o=this._decimals,c=await o.fetchDecimals(t),d=await o.fetchDecimals(r),n=i.map((e=>new a(_(e,d,c)))),g=l(s,n).map((e=>e.floor().toFixed(0))),u=g.map((t=>e(t,d)));return M.debug("getRateLiquidityDepthByPair info:",{orders:s,depthsWei:g,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(D),r=u(a).toString(),i=this._decimals,s=await i.fetchDecimals(e),o=await i.fetchDecimals(t),c=_(r,s,o);return M.debug("getMinRateByPair info:",{orders:a,minRate:r,sourceDecimals:s,targetDecimals:o,normalizedRate:c}),c}async getMaxRateByPair(e,t){M.debug("getMaxRateByPair called",arguments);const a=Object.values(await this._cache.getOrdersByPair(e,t)).map(D),r=m(a).toString(),i=this._decimals,s=await i.fetchDecimals(e),o=await i.fetchDecimals(t),c=_(r,s,o);return M.debug("getMaxRateByPair info:",{orders:a,maxRate:r,sourceDecimals:s,targetDecimals:o,normalizedRate:c}),c}}export{z as MarginalPriceOptions,j as Toolkit,R as isMarginalPriceValue};