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