price constraints working
This commit is contained in:
@@ -43,6 +43,10 @@ export const erc20Abi = [
|
||||
'event Approval(address indexed,address indexed,uint256)',
|
||||
]
|
||||
|
||||
export const mockErc20Abi = [...erc20Abi,
|
||||
'function mint(address,uint256)',
|
||||
]
|
||||
|
||||
const Route = '(uint8,uint24)'
|
||||
const Constraint = '(uint8,bytes)'
|
||||
const Tranche = `(uint64,${Constraint}[])`
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import {uint32max, uint64max} from "@/misc.js";
|
||||
import {ethers} from "ethers";
|
||||
|
||||
@@ -49,18 +48,14 @@ export const Exchange = {
|
||||
}
|
||||
|
||||
// enum ConstraintMode {
|
||||
// Time, // 0
|
||||
// Limit, // 1
|
||||
// Trailing, // 2
|
||||
// Barrier, // 3
|
||||
// Line // 4
|
||||
// Time, // 0
|
||||
// Line, // 1
|
||||
// Barrier // 2
|
||||
// }
|
||||
export const ConstraintMode = {
|
||||
Time: 0,
|
||||
Limit: 1,
|
||||
Trailing: 2,
|
||||
Barrier: 3,
|
||||
Line: 4,
|
||||
Line: 1,
|
||||
Barrier: 2,
|
||||
}
|
||||
|
||||
// struct Constraint {
|
||||
@@ -98,12 +93,6 @@ export function newTimeConstraint(startMode, start, endMode, end) {
|
||||
)
|
||||
}
|
||||
|
||||
// struct PriceConstraint {
|
||||
// bool isAbove;
|
||||
// bool isRatio;
|
||||
// uint160 valueSqrtX96;
|
||||
// }
|
||||
|
||||
// struct LineConstraint {
|
||||
// bool isAbove;
|
||||
// bool isRatio;
|
||||
@@ -112,3 +101,19 @@ export function newTimeConstraint(startMode, start, endMode, end) {
|
||||
// int160 slopeSqrtX96; // price change per second
|
||||
// }
|
||||
|
||||
export function newLimitConstraint( isAbove, isRatio, price ) {
|
||||
return newLineConstraint(isAbove, isRatio, 0, price, 0)
|
||||
}
|
||||
|
||||
export function newLineConstraint( isAbove, isRatio, time, price, slope ) {
|
||||
return encodeConstraint(
|
||||
ConstraintMode.Line,
|
||||
['bool', 'bool', 'uint32', 'uint160', 'int160'],
|
||||
[isAbove, isRatio, time, sqrtX96(price), sqrtX96(slope)]
|
||||
)
|
||||
}
|
||||
|
||||
export function sqrtX96(value) {
|
||||
return BigInt(Math.round(Math.sqrt(value * 2 ** (96*2))))
|
||||
}
|
||||
|
||||
|
||||
@@ -2,35 +2,40 @@ import {socket} from "@/socket.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {Exchange} from "@/blockchain/orderlib.js";
|
||||
import {uniswapV3PoolAddress} from "@/blockchain/uniswap.js";
|
||||
import {ethers, FixedNumber} from "ethers";
|
||||
import {erc20Abi, uniswapV3PoolAbi} from "@/blockchain/abi.js";
|
||||
import {ethers} from "ethers";
|
||||
import {uniswapV3PoolAbi} from "@/blockchain/abi.js";
|
||||
|
||||
const subs = {} // key is route and value is a subscription counter
|
||||
const subscriptionCounts = {} // key is route and value is a subscription counter
|
||||
|
||||
|
||||
export function subPrices( routes ) {
|
||||
if( !routes.length )
|
||||
return
|
||||
const subRoutes = []
|
||||
let chainId = null
|
||||
for( const route of routes ) {
|
||||
if( !(route in subRoutes) || subRoutes[route] === 0 ) {
|
||||
subRoutes[route] = 1
|
||||
console.log('sub route', route, subscriptionCounts)
|
||||
if( !(route in subscriptionCounts) || subscriptionCounts[route] === 0 ) {
|
||||
subscriptionCounts[route] = 1
|
||||
console.log('subscribing to pool', route.pool)
|
||||
subRoutes.push(route)
|
||||
}
|
||||
else {
|
||||
subRoutes[route]++
|
||||
if( chainId !== null && route.chainId !== chainId )
|
||||
throw Error('cannot mix chainIds in a subscription list')
|
||||
chainId = route.chainId
|
||||
subscriptionCounts[route]++
|
||||
}
|
||||
if( chainId !== null && route.chainId !== chainId )
|
||||
throw Error('cannot mix chainIds in a subscription list')
|
||||
chainId = route.chainId
|
||||
}
|
||||
if( subRoutes.length ) {
|
||||
socket.emit('subPools', chainId, routes.map((r)=>r.address) )
|
||||
socket.emit('subPools', chainId, routes.map((r)=>r.pool) )
|
||||
// perform a local query if necessary
|
||||
for( const route of subRoutes ) {
|
||||
const s = useStore()
|
||||
if( !(route.address in s.poolPrices) ) {
|
||||
getPriceForRoute(route).then((price)=>s.poolPrices[route.address]=price)
|
||||
console.log('route in prices?', route.pool in s.poolPrices, route.pool, s.poolPrices)
|
||||
if( !(route.pool in s.poolPrices) ) {
|
||||
console.log('querying initial route price', route.pool)
|
||||
getPriceForRoute(route).then((price)=>s.poolPrices[route.pool]=price)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,21 +45,22 @@ export function unsubPrices( routes ) {
|
||||
let chainId = null
|
||||
const unsubAddrs = []
|
||||
for( const route of routes ) {
|
||||
if( !(route in subs) ) {
|
||||
console.log('unsub route', route, subscriptionCounts)
|
||||
if( !(route in subscriptionCounts) ) {
|
||||
console.error('unsubscribed to a nonexistent route', route)
|
||||
}
|
||||
else {
|
||||
subs[route]--
|
||||
if( subs[route] === 0 ) {
|
||||
subscriptionCounts[route]--
|
||||
if( subscriptionCounts[route] === 0 ) {
|
||||
unsubAddrs.push(route.pool)
|
||||
if( chainId !== null && route.chainId !== chainId )
|
||||
throw Error('cannot mix chainIds in a subscription list')
|
||||
console.log('unsubscribing from pool', route.pool)
|
||||
chainId = route.chainId
|
||||
}
|
||||
else if( subs[route] < 0 ) {
|
||||
else if( subscriptionCounts[route] < 0 ) {
|
||||
console.error('unsubscribed to an already unsubbed route', route)
|
||||
subs[route] = 0 // fix
|
||||
subscriptionCounts[route] = 0 // fix
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +73,8 @@ async function getPriceForRoute(route) {
|
||||
console.log('route is',route)
|
||||
if( route.exchange === Exchange.UniswapV3 ) {
|
||||
const addr = uniswapV3PoolAddress(route.chainId, route.token0.address, route.token1.address, route.fee)
|
||||
const provider = useStore().provider;
|
||||
const store = useStore();
|
||||
const provider = store.provider;
|
||||
if( provider === null ) {
|
||||
console.error('provider was null during getPriceForRoute')
|
||||
return null
|
||||
@@ -78,6 +85,8 @@ async function getPriceForRoute(route) {
|
||||
const spn = Number(sqrtPrice)
|
||||
const price = spn*spn/2**(96*2) * 10**(route.token0.decimals-route.token1.decimals)
|
||||
console.log(`price for ${route.token0.symbol}/${route.token1.symbol}`,price)
|
||||
store.poolPrices[addr] = price
|
||||
return price
|
||||
}
|
||||
else
|
||||
throw Error(`Unsupported exchange ${route.exchange}`)
|
||||
|
||||
@@ -10,14 +10,15 @@ export async function findRoute(tokenA, tokenB) {
|
||||
const chainId = useStore().chainId
|
||||
const rawRoutes = await helper.getRoutes(tokenA.address, tokenB.address)
|
||||
// todo expose all available pools
|
||||
let result = {} // we actually only find a single pool for now
|
||||
console.log('raw routes', rawRoutes)
|
||||
let result = null // we actually only find a single pool for now
|
||||
for (let [exchange, fee, pool] of rawRoutes) {
|
||||
exchange = Number(exchange)
|
||||
fee = Number(fee)
|
||||
if (result.fee === undefined || result.fee > fee) {
|
||||
if (!result || result.fee > fee) {
|
||||
switch (exchange) {
|
||||
case 0: // UniswapV2
|
||||
break
|
||||
throw Error('Uniswap V2 not yet supported')
|
||||
case 1: // UniswapV3
|
||||
const [token0, token1] = tokenA.address < tokenB.address ? [tokenA, tokenB] : [tokenB, tokenA]
|
||||
result = {chainId, exchange: Exchange.UniswapV3, pool, fee, token0, token1}
|
||||
@@ -25,5 +26,5 @@ export async function findRoute(tokenA, tokenB) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return [result]
|
||||
}
|
||||
return result ? [result] : []
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user