swapnet-sdk-test-4
Version:
TypeScript SDK for SwapNet API.
140 lines (139 loc) • 5.64 kB
JavaScript
import Graph from "graph-data-structure";
const toSwap = (route, tokenOpsById)=>{
let liquidityInfo;
if (route.name.startsWith('UniswapV2') || route.name.startsWith('ThrusterV2-3k') || route.name.startsWith('ThrusterV2-10k') || route.name.startsWith('RingswapV2')) {
liquidityInfo = {
protocol: route.name,
address: route.address
};
} else if (route.name.startsWith('UniswapV3') || route.name.startsWith('ThrusterV3') || route.name.startsWith('RingswapV3')) {
if (route.details === undefined || route.details.fee === undefined) {
throw new Error(`Invalid Uniswap V3 route details!`);
}
let fee = BigInt(route.details.fee);
liquidityInfo = {
protocol: route.name,
address: route.address,
fee
};
} else if (route.name.startsWith('CurveV1')) {
liquidityInfo = {
protocol: route.name,
address: route.address
};
} else if (route.name.startsWith('Orderbook')) {
const details = route.details;
liquidityInfo = {
protocol: "LimitOrder",
address: details.maker,
maker: details.maker,
makerToken: details.makerToken,
takerToken: details.takerToken,
makerAmount: BigInt(details.makerAmount),
takerAmount: BigInt(details.takerAmount),
nonce: BigInt(details.nonce),
deadline: BigInt(details.deadline),
signature: details.signature
};
} else {
liquidityInfo = {
protocol: route.name,
address: route.address
};
// throw new Error(`Invalid route name ${route.name}!`);
}
const fromTokenOp = tokenOpsById.get(route.fromTokens[0].referenceId);
if (fromTokenOp === undefined) {
throw new Error(`Missing tokenOp with ID ${route.fromTokens[0]}.`);
}
const toTokenOp = tokenOpsById.get(route.toTokens[0].referenceId);
if (toTokenOp === undefined) {
throw new Error(`Missing tokenOp with ID ${route.toTokens[0]}.`);
}
return {
fromTokenOp,
toTokenOp,
amountIn: BigInt(route.fromTokens[0].amount),
amountOut: BigInt(route.toTokens[0].amount),
liquidityInfo
};
};
export const parse = (swapResponse)=>{
const tokenOpsById = new Map();
swapResponse.tokens.forEach((token)=>{
tokenOpsById.set(token.referenceId, {
tokenInfo: {
address: token.address,
name: token.name,
symbol: token.symbol,
decimals: token.decimals,
usdPrice: token.usdPrice
},
fromSwaps: [],
toSwaps: []
});
});
const swapsByToTokenId = new Map();
const graph = Graph();
swapResponse.routes.forEach((route)=>{
const fromTokenId = route.fromTokens[0].referenceId;
const toTokenId = route.toTokens[0].referenceId;
graph.addEdge(fromTokenId.toString(), toTokenId.toString());
if (!swapsByToTokenId.has(toTokenId)) {
swapsByToTokenId.set(toTokenId, []);
}
const swap = toSwap(route, tokenOpsById);
swap.fromTokenOp.toSwaps.push(swap);
swap.toTokenOp.fromSwaps.push(swap);
swapsByToTokenId.get(toTokenId).push(swap);
});
const sortedTokenOpIds = graph.topologicalSort().map((idString)=>parseInt(idString));
const tokenOps = [];
const swaps = [];
sortedTokenOpIds.forEach((tokenOpId)=>{
const tokenOp = tokenOpsById.get(tokenOpId);
if (tokenOp === undefined) {
throw new Error(`Cannot find token operation with ID ${tokenOpId}!`);
}
tokenOps.push(tokenOp);
const swapsToCurrentToken = swapsByToTokenId.get(tokenOpId);
if (swapsToCurrentToken === undefined) {
if (tokenOpId === swapResponse.sell.referenceId) {
return;
}
throw new Error(`Cannot find swaps to token operation with ID ${tokenOpId}!`);
}
swapsToCurrentToken.forEach((swap)=>{
swaps.push(swap);
});
});
const sellTokenInfo = swapResponse.tokens.find((token)=>token.referenceId === swapResponse.sell.referenceId);
const buyTokenInfo = swapResponse.tokens.find((token)=>token.referenceId === swapResponse.buy.referenceId);
return {
tokenOps,
swaps,
fromToken: sellTokenInfo.address,
toToken: buyTokenInfo.address,
amountIn: BigInt(swapResponse.sell.amount),
amountOut: BigInt(swapResponse.buy.amount)
};
};
export const printRoutingPlan = (routingPlan)=>{
const { tokenOps, swaps } = routingPlan;
const tokenOpToIndex = new Map();
const swapToIndex = new Map();
tokenOps.forEach((tokenOp, i)=>{
tokenOpToIndex.set(tokenOp, i);
});
swaps.forEach((swap, i)=>{
swapToIndex.set(swap, i);
});
console.log(`Routing plan:`);
console.log(`${routingPlan.amountIn} ${routingPlan.fromToken} => ${routingPlan.amountOut} ${routingPlan.toToken}`);
tokenOps.forEach((tokenOp, i)=>{
console.log(` ${i}: ${tokenOp.tokenInfo.symbol}, fromSwaps: ${tokenOp.fromSwaps.map((s)=>swapToIndex.get(s))}, toSwaps: ${tokenOp.toSwaps.map((s)=>swapToIndex.get(s))}`);
});
swaps.forEach((swap, i)=>{
console.log(` ${i}: ${swap.liquidityInfo.protocol} ${swap.liquidityInfo.address}, fromTokenOp: ${tokenOpToIndex.get(swap.fromTokenOp)} ${swap.amountIn}, toTokenOp: ${tokenOpToIndex.get(swap.toTokenOp)} ${swap.amountOut}`);
});
};