@perk.money/perk-swap-core
Version:
This npm package contains core logic of Perk Aggregator build on top of NEAR blockchain
3 lines (2 loc) • 43.2 kB
JavaScript
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("@tonic-foundation/token-list"),e=require("jsbi"),n=require("bn.js"),o=require("near-api-js"),a=require("decimal.js"),r=require("near-api-js/lib/providers/json-rpc-provider"),i=require("near-units"),s=require("near-api-js/lib/transaction"),u=require("near-api-js/lib/utils/rpc_errors"),p=require("near-api-js/lib/utils"),c=require("near-api-js/lib/key_stores"),d=require("near-api-js/lib/providers/provider"),l=require("near-api-js/lib/constants");function m(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var f=m(e),g=m(n),h=m(a);const w=f.default.BigInt(0),I="v1.orderbook.near",k="150000000000000";var y;exports.SwapMode=void 0,(y=exports.SwapMode||(exports.SwapMode={})).ExactIn="ExactIn",y.ExactOut="ExactOut";const _=f.default.BigInt(10),v=(t,e)=>{const n=e instanceof f.default?e:f.default.BigInt(e),o=f.default.exponentiate(_,n);return f.default.multiply(t,o)},M=(t,e)=>{const n=e instanceof f.default?e:f.default.BigInt(e),o=f.default.exponentiate(_,n);return f.default.divide(t,o)},S=(t,e,n)=>M(v(t,n),e),O=(t,e)=>t.reduce(((t,n,o)=>t.set(n,e[o])),new Map),A=t=>O(t.token_account_ids,t.amounts.map((t=>f.default.BigInt(t)))),b=t=>O(t.token_account_ids,t.c_amounts.map((t=>f.default.BigInt(t)))),E=t=>{const e=(t=>t.filter((t=>"0"!==t.shares_total_supply)))(t),n=(t=>{const e=t.reduce(((t,e)=>{const n=e.token_account_ids.sort(),o=`${n[0]}_${n[1]}`;if(t.has(o)){const n=t.get(o)||[];t.set(o,[...n,e])}else t.set(o,[e]);return t}),new Map);return Array.from(e.values()).flatMap((t=>t.sort(((t,e)=>{const[n,o]=t.token_account_ids;return f.default.greaterThan(f.default.BigInt(e.reserves.get(n)||w),f.default.BigInt(t.reserves.get(n)||w))&&f.default.greaterThan(f.default.BigInt(e.reserves.get(o)||w),f.default.BigInt(t.reserves.get(o)||w))?1:-1}))[0]))})(e.filter((t=>"SIMPLE_POOL"===t.pool_kind)));return n},x=(t,e)=>({...t,id:e,reserves:A(t)}),B=async({provider:t,ammId:e,poolId:n})=>{const o=await t.query({request_type:"call_function",account_id:e,method_name:"get_pool",args_base64:Buffer.from(JSON.stringify({pool_id:n})).toString("base64"),finality:"optimistic"}).then((t=>JSON.parse(Buffer.from(t.result).toString())));return x(o,n)},P=async({provider:t,ammId:e,poolId:n,poolKind:o})=>{if(!o)return await B({provider:t,ammId:e,poolId:n});switch(o){case"STABLE_SWAP":return await q(t,e,n);case"RATED_SWAP":return await F(t,e,n);default:return await B({provider:t,ammId:e,poolId:n})}},T=async({provider:t,ammId:e,index:n=0,limit:o})=>await t.query({request_type:"call_function",account_id:e,method_name:"get_pools",args_base64:Buffer.from(JSON.stringify({from_index:n,limit:o})).toString("base64"),finality:"optimistic"}).then((t=>JSON.parse(Buffer.from(t.result).toString())));async function q(t,e,n){return o=await t.query({request_type:"call_function",account_id:e,method_name:"get_stable_pool",args_base64:Buffer.from(JSON.stringify({pool_id:n})).toString("base64"),finality:"optimistic"}).then((t=>JSON.parse(Buffer.from(t.result).toString()))),a=n,{...o,id:a,reserves:A(o),cAmountReserves:b(o),decimals:O(o.token_account_ids,o.decimals),rates:O(o.token_account_ids,o.c_amounts.map((()=>v(f.default.BigInt(1),18)))),pool_kind:"STABLE_SWAP"};var o,a}async function F(t,e,n){return((t,e)=>({...t,id:e,reserves:A(t),cAmountReserves:b(t),decimals:O(t.token_account_ids,t.decimals),rates:O(t.token_account_ids,t.rates.map((t=>f.default.BigInt(t)))),pool_kind:"RATED_SWAP"}))(await t.query({request_type:"call_function",account_id:e,method_name:"get_rated_pool",args_base64:Buffer.from(JSON.stringify({pool_id:n})).toString("base64"),finality:"optimistic"}).then((t=>JSON.parse(Buffer.from(t.result).toString()))),n)}const N=async({provider:t,ammId:e})=>{const n=await(async({provider:t,ammId:e})=>await t.query({request_type:"call_function",account_id:e,method_name:"get_number_of_pools",args_base64:Buffer.from(JSON.stringify({})).toString("base64"),finality:"optimistic"}).then((t=>JSON.parse(Buffer.from(t.result).toString()))))({provider:t,ammId:e});let o=0,a=[];for(;n>o;){const n=T({provider:t,ammId:e,index:o,limit:500});a.push(n),o+=500}const r=(await Promise.all(a)).flat().map(((t,e)=>x(t,e))),i=r.filter((t=>"SIMPLE_POOL"===t.pool_kind)),s=r.filter((t=>"SIMPLE_POOL"!==t.pool_kind));return{simplePools:i,stablePools:await Promise.all(s.map((n=>"STABLE_SWAP"===n.pool_kind?q(t,e,n.id):F(t,e,n.id))))}};async function L({user:t,swapSteps:e}){const n=[],o=e.map(((t,e,n)=>{const{amm:o,inputMint:a,outputMint:r,amountIn:i,minAmountOut:s}=t,u={pool_id:o.instanceId,token_in:a,token_out:r};return n.length>1?0===e?{...u,amount_in:i.toString(),min_amount_out:"0"}:{pool_id:o.instanceId,token_in:a,token_out:r,min_amount_out:s.toString()}:{...u,amount_in:i.toString(),min_amount_out:s.toString()}})),{amm:a,inputMint:r,amountIn:i}=e[0];return n.push({receiverId:r,signerId:t,actions:[{type:"FunctionCall",params:{methodName:"ft_transfer_call",args:{receiver_id:a.contractId,amount:i.toString(),msg:JSON.stringify({force:0,actions:o}),memo:"perk"},gas:k,deposit:"1"}}]}),n}const R=f.default.BigInt(1e4);function C({reserves:t,poolFee:e=0,slippage:n,inputMint:o,outputMint:a,inputAmount:r}){const i=t.get(o)||w,s=t.get(a)||w;if(f.default.equal(i,w)||f.default.equal(s,w))return{amountIn:r,amountOut:w,minAmountOut:w,feeAmount:w,notEnoughLiquidity:!0,priceImpact:0};const u=f.default.divide(f.default.multiply(f.default.BigInt(e),r),R),p=f.default.subtract(r,u),c=f.default.multiply(p,s),d=f.default.add(i,p),l=f.default.divide(c,d),m=n.getFor(l),g=+i.toString()/+s.toString(),h=+r.toString()/+l.toString();return{notEnoughLiquidity:!1,amountIn:r,amountOut:l,minAmountOut:m,feeAmount:u,priceImpact:(h-g)/h}}function j({reserves:t,poolFee:e=0,slippage:n,inputMint:o,outputMint:a,outputAmount:r}){const i=t.get(o)||w,s=t.get(a)||w;if(f.default.equal(i,w)||f.default.equal(s,w))return{amountIn:w,amountOut:r,minAmountOut:r,feeAmount:w,notEnoughLiquidity:!0,priceImpact:0};const u=f.default.multiply(r,i),p=f.default.subtract(s,r),c=f.default.divide(u,p),d=f.default.divide(f.default.multiply(f.default.BigInt(e),c),R),l=f.default.add(c,d),m=f.default.divide(f.default.multiply(r,n.numerator),n.denominator),g=f.default.subtract(r,m),h=+i.toString()/+s.toString(),I=+l.toString()/+r.toString();return{notEnoughLiquidity:!1,amountIn:l,amountOut:r,minAmountOut:g,feeAmount:d,priceImpact:(I-h)/I}}function D({tokenInId:t,tokenOutId:e,slippage:n,amountIn:o,stablePool:a}){const r="STABLE_SWAP"===a.pool_kind?18:24,i=a.decimals.get(t)||null,s=a.decimals.get(e)||null;if(null===i||null===s)throw console.error({inputTokenDecimals:i,outputTokenDecimals:s,stablePool:a,tokenInId:t,tokenOutId:e}),new Error("No info about decimals of tokens");const u=Array.from(a.cAmountReserves.entries()).map((([t,e])=>{const n=a.rates.get(t)||null;if(!n)throw new Error("No rate for token");return[t,M(f.default.multiply(e,n),r)]})).reduce(((t,[e,n])=>t.set(e,n)),new Map),p={...a,cAmountReserves:u},c=S(o,i,r),d=u.get(t)||w,l=u.get(e)||w;if(f.default.equal(d,w)||f.default.equal(l,w))return{amountIn:o,amountOut:w,minAmountOut:w,feeAmount:w,notEnoughLiquidity:!0,priceImpact:0};const[m,g]=function({pool:t,tokenInId:e,tokenOutId:n,amountIn:o}){const a=t.cAmountReserves.get(e)||"0",r=(({pool:t,x_c_amount:e,tokenInId:n,tokenOutId:o})=>{const a=t.cAmountReserves.size,r=t.amp*a**a,i=(({pool:t})=>{const{amp:e,cAmountReserves:n}=t,o=n.size,a=Array.from(n.values()).map((t=>+t.toString())),r=a.reduce(((t,e)=>t+e),0);let i=0,s=r;for(let t=0;t<256;t++){let t=s;for(const e of a)t=t*s/(e*o);i=s;const n=e*o**o;if(s=i*(t*o+n*r)/(i*(n-1)+t*(o+1)),Math.abs(s-i)<=1)break}return s})({pool:t});let s=e,u=i*i/e;for(const[e,a]of t.cAmountReserves)if(e!==n&&e!==o){const t=+a.toString();s+=t,u=u*i/t}u=u*i/(r*a**a);const p=i/r+s;let c=0,d=i;for(let t=0;t<256&&(c=d,d=(d**2+u)/(2*d+p-i),!(Math.abs(d-c)<=1));t++);return d})({pool:t,x_c_amount:+f.default.add(o,f.default.BigInt(a)).toString(),tokenInId:e,tokenOutId:n}),i=t.cAmountReserves.get(n)||"0",s=f.default.BigInt(+i.toString()-r),u=(p=s,c=f.default.BigInt(t.total_fee),f.default.divide(f.default.multiply(p,c),f.default.BigInt(1e4)));var p,c;return[f.default.subtract(s,u),u]}({tokenInId:t,amountIn:c,tokenOutId:e,pool:p}),h=a.rates.get(t)||null,I=a.rates.get(e)||null;if(!h||!I)throw new Error("No rate for in or out token");const k=f.default.divide(v(m,r),I),y=f.default.divide(v(g,r),I),_=S(k,r,s),O=S(y,r,s),A=n.getFor(_),b=+I.toString()/+h.toString(),E=+c.toString()/+m.toString();return{notEnoughLiquidity:!1,amountIn:o,amountOut:_,minAmountOut:A,feeAmount:O,priceImpact:(E-b)/E}}const K=t=>{const{stablePool:e,tokenInId:n,tokenOutId:o,outputAmount:a,slippage:r,appproxInputAmount:i,minAmountMultiplier:s=0,maxAmountMultiplier:u=2,numberOfSteps:p=200}=t,c=(t=>{const{stablePool:e,tokenInId:n,tokenOutId:o,slippage:a,minAmount:r,maxAmount:i,numberOfSteps:s=200}=t,u=f.default.divide(f.default.subtract(i,r),f.default.BigInt(s));return Array.from(Array(s).keys()).map((t=>t+1)).map((t=>{const i=f.default.add(r,f.default.multiply(u,f.default.BigInt(t))),{notEnoughLiquidity:s,amountOut:p,minAmountOut:c,feeAmount:d,priceImpact:l}=D({amountIn:i,tokenOutId:o,tokenInId:n,slippage:a,stablePool:e});return{priceImpact:l,notEnoughLiquidity:s,amountIn:i,amountOut:p,minAmountOut:c,feeAmount:d}}))})({stablePool:e,tokenInId:n,tokenOutId:o,slippage:r,minAmount:M(f.default.multiply(i,f.default.BigInt(1e3*s)),3),maxAmount:M(f.default.multiply(i,f.default.BigInt(1e3*u)),3),numberOfSteps:p});return c.map((t=>{const{amountOut:e}=t,n=f.default.subtract(e,a),o=f.default.lessThan(n,w)?f.default.unaryMinus(n):n;return{...t,swapAmountOutDiff:o}})).sort(((t,e)=>f.default.equal(t.swapAmountOutDiff,e.swapAmountOutDiff)?0:f.default.lessThan(t.swapAmountOutDiff,e.swapAmountOutDiff)?-1:1))[0]},J=({tokenInId:t,tokenOutId:e,amountOut:n,slippage:o,stablePool:a})=>{const r=n;let i=null;for(let s=0;s<2;s+=1)i=K(i?{stablePool:a,tokenInId:t,tokenOutId:e,slippage:o,outputAmount:n,appproxInputAmount:i.amountIn,minAmountMultiplier:.95,maxAmountMultiplier:1.05,numberOfSteps:200}:{stablePool:a,tokenInId:t,tokenOutId:e,slippage:o,outputAmount:n,appproxInputAmount:r,numberOfSteps:200});if(!i)throw new Error("No best option for getInputAmount");return i};class U{constructor(t){this.id=void 0,this.contractId=void 0,this.instanceId=void 0,this.label=void 0,this.pool=void 0,this.isSimplePool=void 0,this.reserves=void 0,this.label="Jumbo",this.id=`${t.id}`,this.contractId="v1.jumbo_exchange.near",this.instanceId=t.id,this.pool=t,this.isSimplePool="SIMPLE_POOL"===t.pool_kind,this.reserves=t.reserves}static async loadPools({provider:t}){try{const{simplePools:e,stablePools:n}=await N({provider:t,ammId:"v1.jumbo_exchange.near"});return[...E(e),...n].map((t=>new U(t)))}catch(t){console.log("Error loading pools for Ref Finance",t)}return[]}getQuote(t){const{inputMint:e,outputMint:n,amount:o,slippage:a,swapMode:r}=t,i=this.pool.total_fee/1e4;if(r===exports.SwapMode.ExactIn){if(this.isSimplePool){const{notEnoughLiquidity:t,amountIn:r,amountOut:s,minAmountOut:u,feeAmount:p,priceImpact:c}=C({reserves:this.pool.reserves,poolFee:this.pool.total_fee,inputMint:e,outputMint:n,inputAmount:o,slippage:a});return{notEnoughLiquidity:t,amountIn:r,amountOut:s,minAmountOut:u,feePct:i,feeMint:e,feeAmount:p,priceImpact:c}}{const{notEnoughLiquidity:t,amountIn:r,amountOut:s,minAmountOut:u,feeAmount:p,priceImpact:c}=D({tokenInId:e,tokenOutId:n,slippage:a,stablePool:this.pool,amountIn:o});return{notEnoughLiquidity:t,amountIn:r,amountOut:s,minAmountOut:u,feePct:i,feeMint:e,feeAmount:p,priceImpact:c}}}if(r===exports.SwapMode.ExactOut){if(this.isSimplePool){const{amountIn:t,amountOut:r,minAmountOut:s,feeAmount:u,priceImpact:p,notEnoughLiquidity:c}=j({reserves:this.pool.reserves,poolFee:this.pool.total_fee,inputMint:e,outputMint:n,outputAmount:o,slippage:a});return{notEnoughLiquidity:c,amountIn:t,amountOut:r,minAmountOut:s,feePct:i,feeMint:e,feeAmount:u,priceImpact:p}}{const{notEnoughLiquidity:t,feeAmount:r,amountIn:s,amountOut:u,minAmountOut:p,priceImpact:c}=J({tokenInId:e,tokenOutId:n,slippage:a,stablePool:this.pool,amountOut:o});return{notEnoughLiquidity:t,amountIn:s,amountOut:u,minAmountOut:p,feePct:i,feeMint:e,feeAmount:r,priceImpact:c}}}throw new Error("Unknown swap mode type")}async getPromiseForUpdate({provider:t}){return P({provider:t,ammId:this.contractId,poolId:this.instanceId,poolKind:this.pool.pool_kind}).then((t=>{this.pool=t}))}async createSwapInstructions(t){const{user:e,swapStep:n}=t,o=await L({user:e,swapSteps:[n]});return console.log("swapTransactions",o),o}async createSwapRouteInstructions(t){const{user:e,swapRoute:n}=t,o=await L({user:e,swapSteps:n.steps});return console.log("swapTransactions",o),o}get reserveTokenMints(){return this.pool.token_account_ids}}class ${constructor(t){this.id=void 0,this.contractId=void 0,this.instanceId=void 0,this.pool=void 0,this.isSimplePool=void 0,this.label=void 0,this.label="Ref.Finance",this.id=`${t.id}`,this.contractId="v2.ref-finance.near",this.instanceId=t.id,this.pool=t,this.isSimplePool="SIMPLE_POOL"===t.pool_kind}static async loadPools({provider:t}){try{const{simplePools:e,stablePools:n}=await N({provider:t,ammId:"v2.ref-finance.near"});return[...E(e),...n].map((t=>new $(t)))}catch(t){console.log("Error loading pools for Ref Finance",t)}return[]}getQuote(t){const{inputMint:e,outputMint:n,amount:o,slippage:a,swapMode:r}=t,i=this.pool.total_fee/1e4;if(r===exports.SwapMode.ExactIn){if(this.isSimplePool){const{notEnoughLiquidity:t,amountIn:r,amountOut:s,minAmountOut:u,feeAmount:p,priceImpact:c}=C({reserves:this.pool.reserves,poolFee:this.pool.total_fee,inputMint:e,outputMint:n,inputAmount:o,slippage:a});return{notEnoughLiquidity:t,amountIn:r,amountOut:s,minAmountOut:u,feePct:i,feeMint:e,feeAmount:p,priceImpact:c}}{const{notEnoughLiquidity:t,amountIn:r,amountOut:s,minAmountOut:u,feeAmount:p,priceImpact:c}=D({tokenInId:e,tokenOutId:n,slippage:a,stablePool:this.pool,amountIn:o});return{notEnoughLiquidity:t,amountIn:r,amountOut:s,minAmountOut:u,feePct:i,feeMint:e,feeAmount:p,priceImpact:c}}}if(r===exports.SwapMode.ExactOut){if(this.isSimplePool){const{amountIn:t,amountOut:r,minAmountOut:s,feeAmount:u,priceImpact:p,notEnoughLiquidity:c}=j({reserves:this.pool.reserves,poolFee:this.pool.total_fee,inputMint:e,outputMint:n,outputAmount:o,slippage:a});return{notEnoughLiquidity:c,amountIn:t,amountOut:r,minAmountOut:s,feePct:i,feeMint:e,feeAmount:u,priceImpact:p}}{const{notEnoughLiquidity:t,feeAmount:r,amountIn:s,amountOut:u,minAmountOut:p,priceImpact:c}=J({tokenInId:e,tokenOutId:n,slippage:a,stablePool:this.pool,amountOut:o});return{notEnoughLiquidity:t,amountIn:s,amountOut:u,minAmountOut:p,feePct:i,feeMint:e,feeAmount:r,priceImpact:c}}}throw new Error("Unknown swap mode type")}async getPromiseForUpdate({provider:t}){return P({provider:t,ammId:this.contractId,poolId:this.instanceId,poolKind:this.pool.pool_kind}).then((t=>{this.pool=t}))}async createSwapInstructions(t){const{user:e,swapStep:n}=t,o=await L({user:e,swapSteps:[n]});return console.log("swapTransactions",o),o}async createSwapRouteInstructions(t){const{user:e,swapRoute:n}=t,o=await L({user:e,swapSteps:n.steps});return console.log("swapTransactions",o),o}get reserveTokenMints(){return this.pool.token_account_ids}}class z{constructor(t,e){this.numerator=void 0,this.denominator=void 0,this.toString=()=>`${this.numerator.toString()}/${this.denominator.toString()}`,this.numerator=t,this.denominator=e}static fromSlippageNumber(t){return new z(f.default.BigInt(1e4*t),f.default.BigInt(1e6))}static fromFeeBpsNumber(t){return new z(f.default.BigInt(t),f.default.BigInt(1e5))}getFor(t){const e=f.default.BigInt(this.numerator.toString()),n=f.default.BigInt(this.denominator.toString());return f.default.divide(f.default.multiply(t,f.default.subtract(n,e)),n)}getFrom(t){const e=f.default.BigInt(this.numerator.toString()),n=f.default.BigInt(this.denominator.toString());return f.default.divide(f.default.multiply(t,e),n)}}const Q=async({provider:t,tokenId:e,tokenOwnerId:n})=>{if(!e||!n)return console.error("No token id or token owner id for loading account storage balance",`tokenId: ${e}`,`tokenOwnerId: ${n}`),{tokenId:e,existing:!1,storageBalance:null};const o=await t.query({request_type:"call_function",account_id:e,method_name:"storage_balance_of",args_base64:Buffer.from(JSON.stringify({account_id:n})).toString("base64"),finality:"optimistic"}).then((t=>JSON.parse(Buffer.from(t.result).toString())));return{tokenId:e,existing:null!==o,storageBalance:o}};async function W(t,e,n){const o=new Array,{storageBalance:a}=await Q({provider:t,tokenId:e,tokenOwnerId:n});if(!a)return o.push({type:"FunctionCall",params:{methodName:"storage_deposit",args:{registration_only:!0,account_id:n},gas:k,deposit:"100000000000000000000000"}}),{receiverId:e,signerId:n,actions:o}}const G=async(t,e)=>{const n=new Array,o=await W(t.connection.provider,"wrap.near",t.accountId);let a=e;if(o)n.push(...o.actions);else{const n=await t.viewFunction("wrap.near","ft_balance_of",{account_id:t.accountId});if(f.default.greaterThanOrEqual(f.default.BigInt(n),a))return[];console.log("NEAR account found, balance:",n),a=f.default.subtract(e,f.default.BigInt(n))}return n.push({type:"FunctionCall",params:{methodName:"near_deposit",args:{},gas:k,deposit:a.toString()}}),n},H=async t=>{const e=new Array,n=t.toString();return e.push({type:"FunctionCall",params:{methodName:"near_withdraw",args:{amount:n},gas:k,deposit:"1"}}),e},V=async(t,e)=>({receiverId:"wrap.near",signerId:t,actions:await H(e)}),X=async t=>{const{provider:e,accountId:n,method:o,args:a={}}=t,r=await e.query({request_type:"call_function",account_id:n,method_name:o,args_base64:Buffer.from(JSON.stringify(a)).toString("base64"),finality:"optimistic"});return JSON.parse(Buffer.from(r.result).toString())};class Y{constructor(t){this.rawMarket=void 0,this.label="Spin Finance",this.id=void 0,this.reserveTokenMints=void 0,this.contractId="spot.spin-fi.near",this.instanceId=void 0,this.orderBook=void 0,this.rawMarket=t,this.id=`${t.id}`,this.instanceId=t.id,this.reserveTokenMints=[t.base.address,t.quote.address].map((t=>"near.near"===t?"wrap.near":t))}static async loadUserDeposits({user:t,provider:e}){return await X({provider:e,accountId:"spot.spin-fi.near",method:"get_deposits",args:{account_id:t}})}static createWithdrawFromDepositsTransaction({user:t,token:e,amount:n}){const o="near.near"===e;return{receiverId:"spot.spin-fi.near",signerId:t,actions:[{type:"FunctionCall",params:{methodName:"withdraw",args:{token:o?"near.near":e,amount:n},gas:k,deposit:o?"0":"1"}}]}}async createSwapInstructions(t){const{user:e,swapStep:n,provider:o}=t,a=[],r=await Y.loadUserDeposits({user:e,provider:o}),i=f.default.BigInt(r["wrap.near"===n.inputMint?"near.near":n.inputMint]||"0"),{address:s}=this.rawMarket.base,{address:u}=this.rawMarket.quote,p=s===n.inputMint||"near.near"===s&&"wrap.near"===n.inputMint,c="near.near"===s||"near.near"===u;if(f.default.lessThan(i,n.amountIn)){const t=f.default.subtract(n.amountIn,i);c&&"wrap.near"===n.inputMint?(a.push(await V(e,t)),a.push({receiverId:"spot.spin-fi.near",signerId:e,actions:[{type:"FunctionCall",params:{methodName:"deposit_near",args:{},gas:k,deposit:t.toString()}}]})):a.push({receiverId:n.inputMint,signerId:e,actions:[{type:"FunctionCall",params:{methodName:"ft_transfer_call",args:{receiver_id:"spot.spin-fi.near",amount:t.toString(),msg:""},gas:k,deposit:"1"}}]})}const d=p?"place_ask":"place_bid",l=10**this.rawMarket.quote.decimal,m=new h.default(this.rawMarket.limits.step_size);let g=new h.default((p?n.amountIn:n.minAmountOut).toString()).div(m).floor().mul(m);p||(g=g.add(n.feeAmount.toString()).div(m).ceil().mul(m));const w=new h.default((p?n.minAmountOut:n.amountIn).toString()).div(l),I=new h.default(this.rawMarket.limits.tick_size),y=w.mul(l).div(I).div(g.div(10**this.rawMarket.base.decimal)).floor().mul(I);a.push({receiverId:"spot.spin-fi.near",signerId:e,actions:[{type:"FunctionCall",params:{methodName:d,args:{market_id:this.rawMarket.id,price:y.ceil().toFixed(0),quantity:g.toFixed(0),market_order:!0,memo:"perk"},gas:k,deposit:"0"}}]});const _=n.minAmountOut.toString();return a.push(Y.createWithdrawFromDepositsTransaction({user:e,token:"wrap.near"===n.outputMint?"near.near":n.outputMint,amount:_})),c&&"wrap.near"===n.outputMint&&a.push({receiverId:"wrap.near",signerId:e,actions:[{type:"FunctionCall",params:{methodName:"near_deposit",args:{},gas:k,deposit:_}}]}),a}async createSwapRouteInstructions(t){const{provider:e,user:n,swapRoute:o}=t,a=[];for(let t of o.steps){const o=await t.amm.createSwapInstructions({provider:e,user:n,swapStep:t});a.push(...o)}return a}async getPromiseForUpdate({provider:t}){try{const e=await X({provider:t,accountId:"spot.spin-fi.near",method:"get_orderbook",args:{market_id:this.rawMarket.id,limit:100}});this.orderBook=e}catch(t){console.log("error getPromiseForUpdate spin for market",this.rawMarket.id)}}getQuote(t){if(!this.orderBook)throw new Error(`Order book for market ${this.rawMarket.ticker} is not loaded`);const e=t.inputMint===this.rawMarket.base.address||"wrap.near"===t.inputMint&&"near.near"===this.rawMarket.base.address,n=e?this.orderBook.bid_orders:this.orderBook.ask_orders,o=e&&t.swapMode===exports.SwapMode.ExactIn||!e&&t.swapMode===exports.SwapMode.ExactOut;let a=new h.default(t.amount.toString()),r=new h.default(0),i=new h.default(0);const s=new h.default(10).pow(this.rawMarket.base.decimal),u=new h.default(this.rawMarket.limits.step_size),p=new h.default(this.rawMarket.fees.taker_fee).div(10**this.rawMarket.fees.decimals);for(const c of n){const n=new h.default(c.price),d=o?a.div(u).floor().mul(u):a.mul(s).div(n).div(u).floor().mul(u),l=new h.default(c.quantity),m=h.default.min(d,l),g=m.mul(n).div(s);r=r.add(e?m:g),i=i.add(e?g:m);const w=i.mul(p),I=i.sub(w).floor();let k=new h.default(t.slippage.getFor(f.default.BigInt(I.floor().toString())).toString());if(e||(k=k.div(u).floor().mul(u)),a=a.sub(o?m:g),m.lessThanOrEqualTo(0)){const n=e?r:k,o=e?k:r,a=n.greaterThanOrEqualTo(new h.default(this.rawMarket.limits.min_base_quantity)),i=n.lessThanOrEqualTo(new h.default(this.rawMarket.limits.max_base_quantity)),s=o.greaterThanOrEqualTo(new h.default(this.rawMarket.limits.min_quote_quantity)),u=o.lessThanOrEqualTo(new h.default(this.rawMarket.limits.max_quote_quantity));return{amountIn:f.default.BigInt(r.floor().toString()),amountOut:f.default.BigInt(I.floor().toString()),minAmountOut:f.default.BigInt(k.floor().toString()),feeAmount:f.default.BigInt(w.floor().toString()),feeMint:t.outputMint,feePct:parseFloat(this.rawMarket.fees.taker_fee)/10**this.rawMarket.base.decimal,notEnoughLiquidity:!(a&&i&&s&&u),priceImpact:0}}}const c=i.mul(p);return{amountIn:f.default.BigInt(r.floor().toString()),amountOut:f.default.BigInt(i.sub(c).floor().toString()),minAmountOut:t.slippage.getFor(f.default.BigInt(i.floor().toString())),feeAmount:f.default.BigInt(c.floor().toString()),feeMint:t.inputMint,feePct:parseFloat(this.rawMarket.fees.taker_fee)/10**this.rawMarket.base.decimal,notEnoughLiquidity:!0,priceImpact:0}}static async loadMarkets(t){const{provider:e}=t;return(await X({accountId:"spot.spin-fi.near",method:"get_markets",provider:e})).map((t=>new Y(t)))}}const Z=(t,e,n=!1)=>(f.default.BigInt(e),n?t.div(e).ceil().mul(e):t.div(e).floor().mul(e));class tt{constructor(t){this.market=void 0,this.label="Tonic",this.id=void 0,this.contractId=I,this.instanceId=void 0,this.reserveTokenMints=void 0,this.orderBook=void 0,this.market=t,this.id=this.market.id,this.instanceId=Math.round(1e6*Math.random()),this.orderBook=this.market.orderbook,this.reserveTokenMints=["ft"===this.market.base_token.token_type.type?this.market.base_token.token_type.account_id:"wrap.near","ft"===this.market.quote_token.token_type.type?this.market.quote_token.token_type.account_id:"wrap.near"]}async getPromiseForUpdate({provider:t}){const e=await X({accountId:I,method:"get_orderbook",args:{market_id:this.id,depth:128},provider:t});this.orderBook=e}resolveQuote(t){const{amountOut:e,amountIn:n,fee:o,slippage:a,stepSize:r,outputMint:i,notEnoughLiquidity:s,swapMode:u,isSellBase:p}=t,c=e.mul(o),d=e.sub(c).floor().toString(),l=f.default.BigInt(d),m=u===exports.SwapMode.ExactIn?n.floor():n.ceil(),g=p?Z(m,r.toString(),u===exports.SwapMode.ExactOut):m,w=p?new h.default(l.toString()):Z(new h.default(l.toString()),r.toString()),I=p?new h.default(a.getFor(l).toString()):Z(new h.default(a.getFor(l).toString()),r.toString());return{amountIn:f.default.BigInt(g.floor().toString()),amountOut:f.default.BigInt(w.floor().toString()),minAmountOut:f.default.BigInt(I.floor().toString()),feeAmount:f.default.BigInt(c.floor().toString()),feeMint:i,feePct:this.market.taker_fee_base_rate/1e4,notEnoughLiquidity:s,priceImpact:0}}getQuote(t){if(!this.orderBook)throw new Error(`Order book for market ${this.market.id} is not loaded`);const{inputMint:e,outputMint:n,amount:o,swapMode:a}=t,r="ft"===this.market.base_token.token_type.type&&e===this.market.base_token.token_type.account_id||"wrap.near"===e&&"near"===this.market.base_token.token_type.type,i=r?this.orderBook.bids:this.orderBook.asks,s=r&&a===exports.SwapMode.ExactIn||!r&&a===exports.SwapMode.ExactOut;let u=new h.default(o.toString());const p=new h.default(this.market.taker_fee_base_rate).div(1e4);t.swapMode===exports.SwapMode.ExactOut&&(u=u.mul(p.add(1)));let c=new h.default(0),d=new h.default(0);const l=new h.default(10).pow(this.market.base_token.decimals),m=new h.default(this.market.base_token.lot_size);for(const e of i){const o=new h.default(e.limit_price),a=s?u.div(m).floor().mul(m):u.mul(l).div(o),i=new h.default(e.open_quantity),f=h.default.min(a,i),g=f.mul(o).div(l);c=c.add(r?f:g),d=d.add(r?g:f),u=u.sub(s?f:g);const w=r?c:d,I=r?d:c;if(f.lessThanOrEqualTo(0))return this.resolveQuote({amountIn:c,amountOut:d,fee:p,stepSize:m,slippage:t.slippage,outputMint:n,notEnoughLiquidity:!w.greaterThanOrEqualTo(new h.default(this.market.base_token.lot_size))||!I.greaterThanOrEqualTo(new h.default(this.market.quote_token.lot_size)),swapMode:t.swapMode,isSellBase:r})}return this.resolveQuote({amountIn:c,amountOut:d,fee:p,stepSize:m,slippage:t.slippage,outputMint:n,notEnoughLiquidity:!0,swapMode:t.swapMode,isSellBase:r})}async createSwapInstructions(t){const e=[],{base_token:{token_type:{type:n}},quote_token:{token_type:{type:o}}}=this.market,{user:a,swapStep:{amountIn:r,minAmountOut:i,inputMint:s,outputMint:u}}=t,p="near"===n||"near"===o,c=p&&"wrap.near"===s,d=p&&"wrap.near"===u,l={action:"Swap",params:[{type:"Swap",market_id:this.market.id,side:"ft"===this.market.base_token.token_type.type&&s===this.market.base_token.token_type.account_id||"near"===this.market.base_token.token_type.type&&"wrap.near"===s?"Sell":"Buy",min_output_token:i.toString()}]};return c&&e.push(await V(a,r)),e.push(c?{receiverId:I,signerId:t.user,actions:[{type:"FunctionCall",params:{methodName:"swap_near",args:{swaps:l.params},gas:k,deposit:r.toString()}}]}:{receiverId:s,signerId:t.user,actions:[{type:"FunctionCall",params:{methodName:"ft_transfer_call",args:{receiver_id:I,amount:r.toString(),msg:JSON.stringify(l),memo:"perk"},gas:k,deposit:"1"}}]}),d&&e.push({receiverId:"wrap.near",signerId:a,actions:[{type:"FunctionCall",params:{methodName:"near_deposit",args:{},gas:k,deposit:i.toString()}}]}),e}async createSwapRouteInstructions(t){const{provider:e,user:n,swapRoute:o}=t,a=[];for(let t of o.steps){const o=await t.amm.createSwapInstructions({provider:e,user:n,swapStep:t});a.push(...o)}return a}static async loadMarkets(t){const{provider:e}=t;return(await X({accountId:I,method:"list_markets",args:{from_index:0,limit:9999},provider:e})).filter((t=>"Active"===t.state)).map((t=>new tt(t)))}}const et=async t=>[...await $.loadPools({provider:t}),...await U.loadPools({provider:t}),...await Y.loadMarkets({provider:t}),...await tt.loadMarkets({provider:t})];async function nt(t,e){const n=new Map;e.forEach((e=>{e.forEach((({amm:e})=>{n.set(`${e.label}-${e.id}`,e.getPromiseForUpdate({provider:t}))}))}));const o=Array.from(n.values());await Promise.all(o)}const ot=["Ref.Finance","Jumbo"],at=t=>t.length>1&&t[0].label===t[1].label&&!!t.every((t=>ot.some((e=>t.label===e)))),rt={steps:[],inputMint:"",outputMint:"",amountIn:w,amountOut:w,minAmountOut:w,swapMode:exports.SwapMode.ExactIn,notEnoughLiquidity:!0,priceImpact:0,depositAndNetworkFee:w,platformFee:{amount:w,token:"",pct:0}},it=({routes:t,amount:e,swapMode:n=exports.SwapMode.ExactIn,inputMint:o,outputMint:a,feeBps:r,slippage:i,userTokensMap:s})=>{if(0===t.length)return[rt];const u=t=>f.default.greaterThan(t.amountIn,w)&&f.default.greaterThan(t.amountOut,w)&&f.default.greaterThan(t.steps[t.steps.length-1].amountOut,w)&&Math.abs(t.priceImpact)<.9&&!t.notEnoughLiquidity;if(n===exports.SwapMode.ExactIn){const p=t.map((t=>(({route:t,feeBps:e,swapMode:n,amountIn:o,slippage:a,inputMint:r,outputMint:i,userTokensMap:s})=>{const u=[],p=at(t.map((t=>t.amm)));let c=o,d=0;for(const{amm:e,inputToken:o,outputToken:r}of t){if(!e)return rt;const t=z.fromSlippageNumber(0),i=0===d&&p?t:a,{amountIn:s,amountOut:l,minAmountOut:m,feeAmount:f,feeMint:g,priceImpact:h,notEnoughLiquidity:w}=e.getQuote({inputMint:o,outputMint:r,amount:c,swapMode:n,slippage:i});u.push({amm:e,inputMint:o,outputMint:r,amountIn:s,amountOut:l,minAmountOut:m,feeAmount:f,feeMint:g,priceImpact:h,notEnoughLiquidity:w}),c=m,d++}const l=u.length>0?u[u.length-1].amountOut:w,m=e.getFrom(l),g=f.default.subtract(l,m),h=u.length>0?u[u.length-1].minAmountOut:w,I=u.some((t=>t.notEnoughLiquidity)),y=1-u.reduce(((t,e)=>t*(1-e.priceImpact)),1),_=u.reduce(((t,e)=>{const{existing:n}=s.get(e.outputMint)||{existing:!1};return n?t:f.default.add(t,f.default.BigInt("100000000000000000000000"))}),w),v=f.default.multiply(f.default.BigInt(k),f.default.BigInt(u.length));return{steps:u,amountIn:o,amountOut:g,minAmountOut:h,inputMint:r,outputMint:i,swapMode:n,notEnoughLiquidity:I,priceImpact:y,depositAndNetworkFee:f.default.add(_,v),platformFee:{amount:m,token:i,pct:+e.numerator.toString()/100}}})({route:t,amountIn:e,slippage:i,inputMint:o,outputMint:a,swapMode:n,feeBps:r,userTokensMap:s})));return p.filter(u).sort(((t,e)=>f.default.greaterThanOrEqual(e.amountOut,t.amountOut)?1:-1))}if(n===exports.SwapMode.ExactOut){const p=t.map((t=>(({route:t,feeBps:e,swapMode:n,amountOut:o,slippage:a,inputMint:r,outputMint:i,userTokensMap:s})=>{const u=[],p=at(t.map((t=>t.amm)));let c=o,d=0;const l=t.reverse();for(const{amm:t,inputToken:e,outputToken:o}of l){if(!t)return rt;const r=z.fromSlippageNumber(0),i=0===d&&p?r:a,{amountIn:s,amountOut:l,minAmountOut:m,feeAmount:f,feeMint:g,notEnoughLiquidity:h,priceImpact:w}=t.getQuote({inputMint:e,outputMint:o,amount:c,swapMode:n,slippage:i});u.push({amm:t,inputMint:e,outputMint:o,amountIn:s,amountOut:l,minAmountOut:m,feeAmount:f,feeMint:g,priceImpact:w,notEnoughLiquidity:h}),c=s,d++}const m=u.reverse().reduce(((t,e,n)=>{if(0===n)return t.push(e),t;const o={...e,amountIn:t[t.length-1].minAmountOut};return t.push(o),t}),[]),g=m.length>0?m[0].amountIn:w,h=m.length>0?m[m.length-1].minAmountOut:w,I=e.getFrom(g),y=f.default.add(g,I);m[0].amountIn=y;const _=u.some((t=>t.notEnoughLiquidity)),v=1-u.reduce(((t,e)=>t*(1-e.priceImpact)),1),M=m.reduce(((t,e)=>{const{existing:n}=s.get(e.outputMint)||{existing:!1};return n?t:f.default.add(t,f.default.BigInt("100000000000000000000000"))}),w),S=f.default.multiply(f.default.BigInt(k),f.default.BigInt(m.length));return{steps:m,amountIn:y,amountOut:o,minAmountOut:h,inputMint:r,outputMint:i,swapMode:n,notEnoughLiquidity:_,priceImpact:v,depositAndNetworkFee:f.default.add(M,S),platformFee:{amount:I,token:r,pct:+e.numerator.toString()/100}}})({route:t,amountOut:e,slippage:i,inputMint:o,outputMint:a,swapMode:n,feeBps:r,userTokensMap:s})));return p.filter(u).sort(((t,e)=>f.default.lessThanOrEqual(e.amountIn,t.amountIn)?1:-1))}return[rt]};function st(t){const e=new Map;return t.forEach((t=>{var n;(n=t.reserveTokenMints).reduce(((t,e)=>(n.forEach((n=>{e!==n&&t.push([e,n])})),t)),[]).forEach((([n,o])=>{!function(t,e,n,o){let a=o.get(t);a||(a=new Map([[e,[]]]),o.set(t,a));let r=a.get(e);r||(r=[],a.set(e,r)),r.push({inputToken:t,outputToken:e,amm:n})}(n,o,t,e)}))})),e}function ut({inputMint:t,outputMint:e,tokenRouteSegments:n,intermediateTokens:o}){const a=[],r=n.get(t)||new Map;(r.get(e)||[]).forEach((t=>{a.push([t])}));const i=n.get(e)||new Map;for(const[t,e]of r.entries()){if(o&&!o.includes(t))continue;const n=i.get(t)||[];for(const t of e)for(const e of n)a.push([t,{amm:e.amm,inputToken:e.outputToken,outputToken:e.inputToken}])}return a}const pt={feeBps:0,feeAccountId:"",feeAccountTokens:new Map};h.default.config({precision:36,rounding:8,toExpNeg:-40,toExpPos:40});const ct={finality:"optimistic"},dt=new Map;class lt extends r.JsonRpcProvider{static from(t){const e="string"==typeof t?t:t.rpcAddr;return dt.has(e)||dt.set(e,new lt({url:e})),dt.get(e)}static fromNetwork(t){switch(t){case"mainnet":return ft;case"testnet":return mt;default:throw new TypeError("Invalid network only mainnet or testnet")}}async viewCode(t,e){return Buffer.from(await this.viewCodeRaw(t,e),"base64")}async viewCodeRaw(t,e=ct){const{code_base64:n}=await this.query({request_type:"view_code",account_id:t,...e});return n}async viewAccount(t,e=ct){return this.query({request_type:"view_account",account_id:t,...e})}async accountExists(t,e){try{return await this.viewAccount(t,e),!0}catch{return!1}}async viewAccessKey(t,e,n=ct){return this.query({request_type:"view_access_key",account_id:t,public_key:"string"==typeof e?e:e.toString(),...n})}async protocolConfig(t=ct){return this.experimental_protocolConfig(t)}async accountBalance(t,e){const n=await this.protocolConfig(e),o=await this.viewAccount(t,e),a=i.NEAR.from(n.runtime_config.storage_amount_per_byte),r=i.NEAR.from(o.storage_usage).mul(a),s=i.NEAR.from(o.locked),u=i.NEAR.from(o.amount).add(s),p=u.sub(s.max(r));return{total:u,stateStaked:r,staked:s,available:p}}async viewCall(t,e,n,o){const a=s.stringifyJsonOrBytes(n);return this.viewCallRaw(t,e,a.toString("base64"),o)}async viewCallRaw(t,e,n,o=ct){return this.query({request_type:"call_function",account_id:t,method_name:e,args_base64:n,...o})}async viewState(t,e,n){return(await this.viewStateRaw(t,e,n)).map((({key:t,value:e})=>({key:Buffer.from(t,"base64"),value:Buffer.from(e,"base64")})))}async viewStateRaw(t,e,n){const{values:o}=await this.query({request_type:"view_state",...null!=n?n:{finality:"optimistic"},account_id:t,prefix_base64:Buffer.from(e).toString("base64")});return o}}const mt=new lt({url:"https://rpc.testnet.near.org"}),ft=new lt({url:"https://rpc.mainnet.near.org"});class gt{constructor(t,e,n,o,a,r,i,s,u){this.wrapNear=void 0,this.near=void 0,this.provider=void 0,this.tokenMap=void 0,this.availableTokens=void 0,this.tokenRouteSegments=void 0,this.platformFeeAndAccounts=void 0,this.routeCacheDuration=void 0,this.intermediateTokens=void 0,this.user=void 0,this.routeCache=void 0,this.userTokensMapCache=void 0,this.wrapNear=u,this.provider=e,this.near=t,this.tokenMap=n,this.availableTokens=o,this.tokenRouteSegments=a,this.platformFeeAndAccounts=r,this.routeCacheDuration=i,this.intermediateTokens=s,this.user=null,this.routeCache=new Map,this.userTokensMapCache=new Map}static async load({provider:e=ft,user:n,privateKey:a,platformFeeAndAccounts:r=pt,routeCacheDuration:i=0,wrapNear:s=!0}){const u=new o.keyStores.InMemoryKeyStore;if(n&&a){const t=o.KeyPair.fromString(a);await u.setKey("mainnet",n,t)}const p=await o.connect({networkId:"mainnet",nodeUrl:"https://rpc.mainnet.near.org",keyStore:u,headers:{}}),[c,d]=await gt.fetchTokenRouteSegments(e),l=await(new t.TokenListProvider).resolve().then((t=>t.filterByNearEnv("mainnet").getList().reduce(((t,e)=>(t.set(e.address,e),t)),new Map))),m=gt.getIntermediateTokens(),f=new gt(p,e,l,d,c,r,i,m,s);return n&&f.setUserPublicKey(n),f}static async fetchTokenRouteSegments(t){const e=await et(t);return[st(e),Array.from(new Set(e.flatMap((t=>t.reserveTokenMints))))]}static getIntermediateTokens(){return["wrap.near","usn","dac17f958d2ee523a2206206994597c13d831ec7.factory.bridge.near","a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.factory.bridge.near","token.pembrock.near"]}setUserPublicKey(t){this.user=t}async loadAndSavePlatformFeeTokenData(t){try{const{storageBalance:e}=await Q({provider:this.provider,tokenId:t,tokenOwnerId:this.platformFeeAndAccounts.feeAccountId});return this.platformFeeAndAccounts.feeAccountTokens.set(t,e),e}catch(t){return console.warn("Unable to load token data for platform fee account",t),null}}async getPlatformFeeBpsForToken(t){return(this.platformFeeAndAccounts.feeAccountTokens.has(t)?this.platformFeeAndAccounts.feeAccountTokens.get(t):await this.loadAndSavePlatformFeeTokenData(t))?this.platformFeeAndAccounts.feeBps:0}async computeRoutes({inputMint:t,outputMint:e,amount:n,slippage:o=0,forceFetch:a=!1,swapMode:r=exports.SwapMode.ExactIn,simpleRoutesOnly:i=!1}){const s=await this.getPlatformFeeBpsForToken(e),u=z.fromFeeBpsNumber(s),p=(new Date).getTime(),c=[t,e,i?"simple":"complex"].sort(((t,e)=>t.localeCompare(e))).join(""),d=this.routeCache.get(c),l=ut({inputMint:t,outputMint:e,tokenRouteSegments:this.tokenRouteSegments,intermediateTokens:this.intermediateTokens}).filter((t=>{if(i){const e=1===t.length,n=at(t.map((t=>t.amm)));return!t.some((t=>t.amm instanceof Y))&&(e||n)}return!0}));let m=!1;if(-1===this.routeCacheDuration)m=!1;else if(0===this.routeCacheDuration)m=!0;else if(d){const{fetchTimestamp:t}=d;p-t>this.routeCacheDuration&&(m=!0)}else m=!0;(a||m)&&(await nt(this.provider,l),this.routeCache.set(c,{fetchTimestamp:(new Date).getTime()}));try{const i=this.userTokensMapCache.get(c),s=i||new Map;if(null!==this.user&&!i){const t=[];l.forEach((e=>e.forEach((({amm:e})=>e.reserveTokenMints.forEach((e=>t.push(e))))))),(await Promise.all(t.map((t=>Q({provider:this.provider,tokenId:t,tokenOwnerId:this.user}))))).forEach((({tokenId:t,existing:e,storageBalance:n})=>s.set(t,{existing:e,data:n}))),this.userTokensMapCache.set(c,s)}const d=z.fromSlippageNumber(o);return{routesInfos:it({routes:l,inputMint:t,outputMint:e,amount:n,userTokensMap:s,slippage:d,feeBps:u,swapMode:r}),cached:!(a||m)}}catch(t){throw t}finally{this.routeCache.forEach((({fetchTimestamp:t},e)=>{t-p>this.routeCacheDuration&&this.routeCache.delete(e)}))}}async buildTransactions({route:t}){const e=[],n=at(t.steps.map((t=>t.amm))),a=n?[[]]:t.steps.map((()=>[])),r=await this.getPlatformFeeBpsForToken(t.outputMint),i=z.fromFeeBpsNumber(r);if(!this.user)throw new Error("No user provided");const s=this.user,u=new o.Account(this.near.connection,this.user),p=new Set;if(this.wrapNear&&"wrap.near"===t.inputMint){console.log("Wrap near: ",t.amountIn.toString());const n=await(async(t,e)=>({receiverId:"wrap.near",signerId:t.accountId,actions:await G(t,e)}))(u,t.amountIn);n.actions.length>0&&(e.push(n),a[0].push(n),p.add("wrap.near"))}t.steps.forEach((t=>p.add(t.outputMint)));const c=[...p.values()],d=(await Promise.all(c.map((t=>W(this.provider,t,s))))).filter((t=>!!t));if(e.push(...d),a[0].push(...d),n){const n=t.steps[0].amm,o=await n.createSwapRouteInstructions({provider:this.provider,user:this.user,swapRoute:t});e.push(...o),a[a.length-1].push(...o)}else{let n=0;for(let o of t.steps){const t=await o.amm.createSwapInstructions({provider:this.provider,user:this.user,swapStep:o});e.push(...t),a[n].push(...t),n++}}let l=t.minAmountOut;if(0!==r&&this.platformFeeAndAccounts.feeAccountId){const n=t.swapMode===exports.SwapMode.ExactIn?t.outputMint:t.inputMint,o=t.swapMode===exports.SwapMode.ExactIn?t.amountOut:t.amountIn,a=i.getFrom(f.default.BigInt(o));e.push((({tokenId:t,accountFrom:e,accountTo:n,amount:o})=>({receiverId:t,signerId:e,actions:[{type:"FunctionCall",params:{methodName:"ft_transfer",args:{receiver_id:n,amount:o.toString(),memo:"perk"},gas:k,deposit:"1"}}]}))({tokenId:n,accountFrom:this.user,accountTo:this.platformFeeAndAccounts.feeAccountId,amount:a})),t.swapMode===exports.SwapMode.ExactIn&&(l=f.default.subtract(l,a))}if(this.wrapNear&&"wrap.near"===t.outputMint){const t=await V(s,l);e.push(t),a[a.length-1].push(t)}return c.length>0&&this.userTokensMapCache.clear(),{transactions:e,transactionsBySteps:a}}async exchange({route:t}){const{transactions:e}=await this.buildTransactions({route:t});if(!this.user)throw new Error("No user provided");const o=await this.near.account(this.user),a=[];for(const t of e)for(const e of t.actions){if("FunctionCall"!==e.type)throw new Error("Non function call in exchange");const r=await o.functionCall({contractId:t.receiverId,methodName:e.params.methodName,args:e.params.args,gas:new n.BN(e.params.gas),attachedDeposit:new n.BN(e.params.deposit)});a.push(r)}return a}}Object.defineProperty(exports,"Connection",{enumerable:!0,get:function(){return o.Connection}}),Object.defineProperty(exports,"KeyPair",{enumerable:!0,get:function(){return o.KeyPair}}),Object.defineProperty(exports,"JSONRpc",{enumerable:!0,get:function(){return r.JsonRpcProvider}}),Object.defineProperty(exports,"AccessKey",{enumerable:!0,get:function(){return s.AccessKey}}),Object.defineProperty(exports,"Action",{enumerable:!0,get:function(){return s.Action}}),Object.defineProperty(exports,"addKey",{enumerable:!0,get:function(){return s.addKey}}),Object.defineProperty(exports,"createAccount",{enumerable:!0,get:function(){return s.createAccount}}),Object.defineProperty(exports,"deleteAccount",{enumerable:!0,get:function(){return s.deleteAccount}}),Object.defineProperty(exports,"deleteKey",{enumerable:!0,get:function(){return s.deleteKey}}),Object.defineProperty(exports,"deployContract",{enumerable:!0,get:function(){return s.deployContract}}),Object.defineProperty(exports,"fullAccessKey",{enumerable:!0,get:function(){return s.fullAccessKey}}),Object.defineProperty(exports,"functionCall",{enumerable:!0,get:function(){return s.functionCall}}),Object.defineProperty(exports,"stake",{enumerable:!0,get:function(){return s.stake}}),Object.defineProperty(exports,"transfer",{enumerable:!0,get:function(){return s.transfer}}),Object.defineProperty(exports,"ServerError",{enumerable:!0,get:function(){return u.ServerError}}),Object.defineProperty(exports,"KeyPairEd25519",{enumerable:!0,get:function(){return p.KeyPairEd25519}}),Object.defineProperty(exports,"PublicKey",{enumerable:!0,get:function(){return p.PublicKey}}),Object.defineProperty(exports,"KeyStore",{enumerable:!0,get:function(){return c.KeyStore}}),Object.defineProperty(exports,"DEFAULT_FUNCTION_CALL_GAS",{enumerable:!0,get:function(){return l.DEFAULT_FUNCTION_CALL_GAS}}),exports.BN=class extends g.default{toJSON(){return this.toString(10)}},exports.Jumbo=U,exports.MAINNET_RPC_ADDR="https://rpc.mainnet.near.org",exports.NO_PLATFORM_FEE=pt,exports.Perk=gt,exports.RefFinance=$,exports.SPIN_CONTRACT_ADDRESS="spot.spin-fi.near",exports.SpinFinanceMarket=Y,exports.TESTNET_RPC_ADDR="https://rpc.testnet.near.org",exports.computeRoutes=ut,exports.getAllAmms=et,exports.getSwapRoutes=it,exports.getTokenRouteSegments=st,exports.updateRoutesPools=nt,Object.keys(d).forEach((function(t){"default"===t||exports.hasOwnProperty(t)||Object.defineProperty(exports,t,{enumerable:!0,get:function(){return d[t]}})}));
//# sourceMappingURL=perk-swap-core.cjs.production.min.js.map