diff --git a/index.html b/index.html index cd32b0b..3b524b8 100644 --- a/index.html +++ b/index.html @@ -9,8 +9,7 @@
- - + diff --git a/src/blockchain/abi.js b/src/blockchain/abi.js index f090ae9..6c7c7b4 100644 --- a/src/blockchain/abi.js +++ b/src/blockchain/abi.js @@ -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}[])` diff --git a/src/blockchain/orderlib.js b/src/blockchain/orderlib.js index 85b4207..c0d409f 100644 --- a/src/blockchain/orderlib.js +++ b/src/blockchain/orderlib.js @@ -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)))) +} + diff --git a/src/blockchain/prices.js b/src/blockchain/prices.js index df509f9..316368f 100644 --- a/src/blockchain/prices.js +++ b/src/blockchain/prices.js @@ -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}`) diff --git a/src/blockchain/route.js b/src/blockchain/route.js index 0eb6cd3..cd7cedb 100644 --- a/src/blockchain/route.js +++ b/src/blockchain/route.js @@ -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] -} \ No newline at end of file + return result ? [result] : [] +} diff --git a/src/components/Faucet.vue b/src/components/Faucet.vue new file mode 100644 index 0000000..30e208b --- /dev/null +++ b/src/components/Faucet.vue @@ -0,0 +1,45 @@ + +