From 094108d8063c1e9c0947a84b159ecfdf53a3babb Mon Sep 17 00:00:00 2001
From: Tim Olson <>
Date: Sat, 25 Nov 2023 16:21:42 -0400
Subject: [PATCH] complete store refactor; moved form inputs into store;
refactored components out of TimedOrderEntry
---
src/blockchain/contract.js | 1 -
src/blockchain/prices.js | 13 +-
src/blockchain/route.js | 2 +-
src/blockchain/uniswap.js | 1 -
src/blockchain/wallet.js | 7 +-
src/components/Amount.vue | 26 ++++
src/components/PairChoice.vue | 12 +-
src/components/RoutePrice.vue | 2 +-
src/components/TimedOrderEntry.vue | 70 ++--------
src/knownTokens.js | 2 +-
src/misc.js | 21 +++
src/socket.js | 10 +-
src/store/store.js | 199 +++++++++++++++++------------
13 files changed, 192 insertions(+), 174 deletions(-)
create mode 100644 src/components/Amount.vue
diff --git a/src/blockchain/contract.js b/src/blockchain/contract.js
index 1e2aeab..083f514 100644
--- a/src/blockchain/contract.js
+++ b/src/blockchain/contract.js
@@ -4,7 +4,6 @@ import {useStore} from "@/store/store.js";
export function vaultAddress( owner, num=0) {
- console.log('va', owner, num)
if( !owner )
return null
const s = useStore()
diff --git a/src/blockchain/prices.js b/src/blockchain/prices.js
index 990aa8a..73b92d6 100644
--- a/src/blockchain/prices.js
+++ b/src/blockchain/prices.js
@@ -15,10 +15,10 @@ export function subPrices( routes ) {
const subRoutes = []
let chainId = null
for( const route of routes ) {
- console.log('sub route', route, subscriptionCounts)
+ // console.log('sub route', route, subscriptionCounts)
if( !(route in subscriptionCounts) || subscriptionCounts[route] === 0 ) {
subscriptionCounts[route] = 1
- console.log('subscribing to pool', route.pool)
+ // console.log('subscribing to pool', route.pool)
subRoutes.push(route)
}
else {
@@ -33,9 +33,7 @@ export function subPrices( routes ) {
// perform a local query if necessary
for( const route of subRoutes ) {
const s = useStore()
- 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)
}
}
@@ -46,7 +44,7 @@ export function unsubPrices( routes ) {
let chainId = null
const unsubAddrs = []
for( const route of routes ) {
- console.log('unsub route', route, subscriptionCounts)
+ // console.log('unsub route', route, subscriptionCounts)
if( !(route in subscriptionCounts) ) {
console.error('unsubscribed to a nonexistent route', route)
}
@@ -56,7 +54,7 @@ export function unsubPrices( routes ) {
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)
+ // console.log('unsubscribing from pool', route.pool)
chainId = route.chainId
}
else if( subscriptionCounts[route] < 0 ) {
@@ -71,7 +69,6 @@ export function unsubPrices( routes ) {
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 store = useStore();
@@ -88,7 +85,7 @@ async function getPriceForRoute(route) {
price = FixedNumber.fromValue(price,0,WIDE_PRICE_FORMAT)
price = price.div(FixedNumber.fromValue(2n**(96n*2n),0,WIDE_PRICE_FORMAT))
price = price.round(18).toString()
- console.log(`price for ${route.token0.symbol}/${route.token1.symbol}`,price)
+ // console.log(`price for ${route.token0.symbol}/${route.token1.symbol}`,price)
store.poolPrices[addr] = price
return price
}
diff --git a/src/blockchain/route.js b/src/blockchain/route.js
index cd7cedb..8dc6a9e 100644
--- a/src/blockchain/route.js
+++ b/src/blockchain/route.js
@@ -10,7 +10,7 @@ export async function findRoute(tokenA, tokenB) {
const chainId = useStore().chainId
const rawRoutes = await helper.getRoutes(tokenA.address, tokenB.address)
// todo expose all available pools
- console.log('raw routes', rawRoutes)
+ // 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)
diff --git a/src/blockchain/uniswap.js b/src/blockchain/uniswap.js
index 17c0e50..9cb9d4c 100644
--- a/src/blockchain/uniswap.js
+++ b/src/blockchain/uniswap.js
@@ -18,7 +18,6 @@ export function uniswapV3PoolAddress(chainId, tokenAddrA, tokenAddrB, fee) {
const encoded = ethers.AbiCoder.defaultAbiCoder().encode(['address', 'address', 'uint24'], [addr0, addr1, fee]);
const salt = ethers.keccak256(encoded)
const factory = uniswapV3Addresses[chainId]?.factory
- console.log('uni3addr', addr0, addr1, fee, salt, factory)
if (!factory) {
console.log('no uniswap factory for chain', chainId)
return null
diff --git a/src/blockchain/wallet.js b/src/blockchain/wallet.js
index b1c3f1e..6c84e14 100644
--- a/src/blockchain/wallet.js
+++ b/src/blockchain/wallet.js
@@ -1,5 +1,5 @@
import {ethers} from "ethers";
-import {setProvider, useStore} from "@/store/store";
+import {useStore} from "@/store/store";
import {socket} from "@/socket.js";
import {contractOrNull, vaultAddress} from "@/blockchain/contract.js";
import {vaultAbi} from "@/blockchain/abi.js";
@@ -13,7 +13,7 @@ export function onChainChanged(chainId) {
store.chainId = chainId // touch the chainId last. will cause any clients of the store's provider getter to refresh
store.account = null
const provider = new ethers.BrowserProvider(window.ethereum, chainId);
- setProvider(provider, chainId)
+ store.provider = provider
provider.listAccounts().then((accounts)=>changeAccounts(accounts.map((a)=>a.address)))
}
}
@@ -30,12 +30,10 @@ function changeAccounts(accounts) {
const addr = accounts[0]
const store = useStore()
store.account = addr
- console.log('set store.account to', addr, store.account)
discoverVaults()
flushTransactions()
socket.emit('address', store.chainId, addr)
}
- console.log('changeAccounts ended')
}
function onAccountsChanged(accounts) {
@@ -102,7 +100,6 @@ function discoverVaults() {
s.vaults = []
else
_discoverVaults(owner).then((result)=>{
- console.log('read store.account', s.account)
if( s.account === owner ) { // double-check the account since it could have changed during our await
s.vaults = result
if( pendingOrders.length )
diff --git a/src/components/Amount.vue b/src/components/Amount.vue
new file mode 100644
index 0000000..602e1ee
--- /dev/null
+++ b/src/components/Amount.vue
@@ -0,0 +1,26 @@
+
+
+
+
+ {{ s.amountIsTokenA ? s.tokenA.symbol : s.tokenB.symbol }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/PairChoice.vue b/src/components/PairChoice.vue
index eff8d24..c0a226d 100644
--- a/src/components/PairChoice.vue
+++ b/src/components/PairChoice.vue
@@ -44,7 +44,7 @@ const tokenA = computed({
},
set(value) {
if( !s.tokenA || s.tokenA.address !== value.address ) {
- s.tokenA.value = value
+ s.tokenA = value
routeFinder.invoke()
}
}
@@ -64,25 +64,25 @@ const tokenB = computed({
const routes = computed({
get() {
- return s.routes.value
+ return s.routes
},
set(value) {
- console.log('setting new routes', s.routes.value, value)
- s.routes.value = value
+ console.log('setting new routes', s.routes, value)
+ s.routes = value
}
})
async function componentFindRoute() {
const tokenA = s.tokenA
const tokenB = s.tokenB
- console.log('finding route', tokenA, tokenB)
+ // console.log('finding route', tokenA, tokenB)
s.routes = []
if (!tokenA || !tokenB)
return
s.routesPending = true
try {
const result = await findRoute(tokenA, tokenB)
- console.log('found route', result)
+ // console.log('found route', result)
s.routes = result
}
catch (e) {
diff --git a/src/components/RoutePrice.vue b/src/components/RoutePrice.vue
index 6fa395d..823174a 100644
--- a/src/components/RoutePrice.vue
+++ b/src/components/RoutePrice.vue
@@ -21,7 +21,7 @@ const price = computed(()=>{
if( !route || !(route.pool in s.poolPrices) )
return ''
let p = s.poolPrices[route.pool]
- console.log('pool price is',typeof p, p)
+ // console.log('pool price is',typeof p, p)
if( !p )
return ''
p = FixedNumber.fromString(p, WIDE_PRICE_FORMAT).toUnsafeFloat()
diff --git a/src/components/TimedOrderEntry.vue b/src/components/TimedOrderEntry.vue
index d14bbcb..590da78 100644
--- a/src/components/TimedOrderEntry.vue
+++ b/src/components/TimedOrderEntry.vue
@@ -6,26 +6,13 @@
-
-
-
- {{ amountIsTokenA ? s.tokenA.symbol : s.tokenB.symbol }}
-
-
-
-
+
-
-
-
tranches
-
@@ -34,11 +21,11 @@
-
-
+
{{s.pairSymbol}}
@@ -64,9 +51,10 @@
import {useStore} from "@/store/store";
import {computed, ref} from "vue";
import PhoneCard from "@/components/PhoneCard.vue";
+import Amount from "@/components/Amount.vue"
// noinspection ES6UnusedImports
-import {routeInverted, SingletonCoroutine, vAutoSelect} from "@/misc.js";
-import {newLimitConstraint, newOrder, newTimeConstraint, sqrtX96, TimeMode} from "@/blockchain/orderlib.js";
+import {isEmpty, routeInverted, SingletonCoroutine, vAutoSelect, validateRequired, validateAmount} from "@/misc.js";
+import {newLimitConstraint, newOrder, newTimeConstraint, TimeMode} from "@/blockchain/orderlib.js";
import {FixedNumber} from "ethers";
import {pendOrder} from "@/blockchain/wallet.js";
import NeedsProvider from "@/components/NeedsProvider.vue";
@@ -76,21 +64,14 @@ import PairChoice from "@/components/PairChoice.vue";
const s = useStore()
-const amount = ref(100) // todo 0
-const amountIsTokenA = ref(false)
-const amountIsTotal = ref(true)
const tranches = ref(3)
-const inverted = ref(false)
const minPrice = ref(null)
const maxPrice = ref(null)
-const limitPrice = ref(null)
const interval = ref(1)
const intervalIsTotal = ref(true)
const timeUnits = ['minutes', 'hours', 'days']
const timeUnitIndex = ref(0)
-const limitIsMinimum = computed(() => !(s.buy ^ s.inverted))
-const validOrder = computed(()=>amount.value > 0 && s.routes.length > 0 )
-
+const validOrder = computed(()=>s.validOrder)
function toggleTimeUnits() {
timeUnitIndex.value++
@@ -99,18 +80,6 @@ function toggleTimeUnits() {
}
-function isEmpty(v) {
- return v === null || typeof v === 'string' && v.trim() === ''
-}
-
-
-function validateRequired(v) {
- if (isEmpty(v))
- return 'Required'
- return true
-}
-
-
function validateTranches(v) {
const i = parseInt(v)
if (parseFloat(v) !== i)
@@ -123,17 +92,6 @@ function validateTranches(v) {
}
-function validateAmount(v) {
- if (isEmpty(v))
- return true
- const floatRegex = /^-?\d*(?:[.,]\d*?)?$/
- if (!floatRegex.test(v))
- return 'Amount must be a number'
- if (parseFloat(v) <= 0)
- return 'Amount must be positive'
- return true
-}
-
function validateMax(v) {
if (!isEmpty(minPrice.value) && !isEmpty(v) && parseFloat(v) < parseFloat(minPrice.value))
return 'Must be greater than the minimum price'
@@ -152,9 +110,7 @@ function placeOrder() {
const tokenIn = s.buy ? tb.address : ta.address
const tokenOut = s.buy ? ta.address : tb.address
const route = s.route
- const amountToken = amountIsTokenA.value ? ta : tb
- const amt = FixedNumber.fromString(amount.value.toString(), {decimals: amountToken.decimals}).value
- const amountIsInput = amountIsTokenA.value !== s.buy
+ const amt = FixedNumber.fromString(s.amount.toString(), {decimals: s.amountToken.decimals}).value
// build tranches
const n = tranches.value // num tranches
@@ -173,20 +129,18 @@ function placeOrder() {
const ceil = oneHundredPercent % BigInt(n) ? 1n : 0n
const amtPerTranche = oneHundredPercent / BigInt(n) + ceil
duration -= 15 // subtract 15 seconds so the last tranche completes before the deadline
- console.log('duration', duration)
let priceConstraint = null
- if( limitPrice.value ) {
+ if( s.limitPrice ) {
const inverted = routeInverted(route)
- const isAbove = limitIsMinimum.value ^ inverted
+ const isAbove = s.limitIsMinimum ^ inverted
const isRatio = false // todo ratios
const decimals = 10 ** (s.tokenA.decimals - s.tokenB.decimals)
- const limit = inverted ? decimals/limitPrice.value : limitPrice.value/decimals
- priceConstraint = !limitPrice.value ? null : newLimitConstraint(isAbove, isRatio, limit)
+ const limit = inverted ? decimals/s.limitPrice : s.limitPrice/decimals
+ priceConstraint = !s.limitPrice ? null : newLimitConstraint(isAbove, isRatio, limit)
}
for (let i = 0; i < n; i++) {
const start = Math.floor(i * (duration / Math.max((n - 1), 1)))
const end = start + window
- console.log('tranche window', start, end, (end-start)/60)
const cs = [newTimeConstraint(TimeMode.SinceOrderStart, start, TimeMode.SinceOrderStart, end)]
if( priceConstraint !== null )
cs.push(priceConstraint)
diff --git a/src/knownTokens.js b/src/knownTokens.js
index a66cbeb..9965533 100644
--- a/src/knownTokens.js
+++ b/src/knownTokens.js
@@ -4,7 +4,7 @@ const known_chains = [
{
name: 'Arbitrum One',
id: 42161,
- image: null,
+ image: '/arbitrum-logo.svg',
}
]
diff --git a/src/misc.js b/src/misc.js
index 3fa8ead..0a1d766 100644
--- a/src/misc.js
+++ b/src/misc.js
@@ -58,3 +58,24 @@ export function routeInverted(route) {
const s = useStore()
return route && (route.token0 === s.tokenA) === s.inverted
}
+
+export function isEmpty(v) {
+ return v === null || typeof v === 'string' && v.trim() === ''
+}
+
+export function validateRequired(v) {
+ if (isEmpty(v))
+ return 'Required'
+ return true
+}
+
+export function validateAmount(v) {
+ if (isEmpty(v))
+ return true
+ const floatRegex = /^-?\d*(?:[.,]\d*?)?$/
+ if (!floatRegex.test(v))
+ return 'Amount must be a number'
+ if (parseFloat(v) <= 0)
+ return 'Amount must be positive'
+ return true
+}
\ No newline at end of file
diff --git a/src/socket.js b/src/socket.js
index 858f825..b294014 100644
--- a/src/socket.js
+++ b/src/socket.js
@@ -17,18 +17,10 @@ socket.on('disconnect', () => {
socket.on('welcome', async (data) => {
console.log('welcome', data)
- const mockCoins = data['chainInfo'][31337].mockCoins
- console.log('coin order:',
- mockCoins[1] > mockCoins[0] ? "coin1 > coin0" : "coin0 > coin1 (inverted)",
- mockCoins)
const s = useStore()
+ // todo put the vaultInitCodeHash into the chainInfo
s.chainInfo = data.chainInfo
s.vaultInitCodeHash = data.vaultInitCodeHash
- // set default tokens in pair choice dropdown
- if( s.tokenA === null && Object.values(s.tokens).length >= 1 )
- s.tokenA = Object.values(s.tokens)[0]
- if( s.tokenB === null && Object.values(s.tokens).length >= 2 )
- s.tokenB = Object.values(s.tokens)[1]
const p = new ethers.BrowserProvider(window.ethereum)
const network = await p.getNetwork()
if (network !== null)
diff --git a/src/store/store.js b/src/store/store.js
index 1fe0fa0..54ac958 100644
--- a/src/store/store.js
+++ b/src/store/store.js
@@ -3,90 +3,123 @@ import { defineStore } from 'pinia'
import {knownTokens} from "@/knownTokens.js";
import {computed, ref} from "vue";
-let rawProvider = null
-let rawProviderChainId = null
-export function setProvider( provider, chainId ) {
- rawProvider = provider
- rawProviderChainId = chainId
-}
+export const useStore = defineStore('app', ()=> {
+ const _chainId = ref(null)
+ const _chainInfo = ref({})
+ const tokenA = ref(null)
+ const tokenB = ref(null)
-export const useStore = defineStore('app', {
- state: () => ({
- chainId: null,
- chainInfo: {},
- vaultInitCodeHash: null,
- account: null,
- vaults: [],
- transactionSenders: [], // a list of function(signer) that send transactions
- errors: [
- // todo re-enable danger warning
- // {title: 'DANGER!', text: 'This is early development (alpha) software. There could be severe bugs that lose all your money. Thank you for testing a SMALL amount!', closeable: true}
- ],
- extraTokens: {},
- poolPrices: {},
- vaultBalances: {}, // indexed by vault addr then by token addr. value is an int
- orders: {}, // indexed by vault, value is another dictionary with orderIndex as key and order status values
+ function getTokenList() {
+ const chains = _chainId.value in _chainInfo.value && _chainInfo.value[_chainId.value].tokens !== undefined ?
+ _chainInfo.value[_chainId.value].tokens : []
+ let known = knownTokens[_chainId.value]
+ known = known ? Object.values(known) : []
+ let extras = extraTokens[_chainId.value]
+ extras = extras ? Object.values(extras) : []
+ return [...chains, ...known, ...extras]; // put chains first so the Mockcoin pool is automatically selected
+ }
+ function getTokens() {
+ const result = {}
+ const all = getTokenList();
+ for (const token of all)
+ result[token.address] = token
+ return result
+ }
+ function setDefaultTokens() {
+ const tokens = getTokenList()
+ if( tokens.length > 0 )
+ tokenA.value = tokens[0]
+ if( tokens.length > 1 )
+ tokenB.value = tokens[1]
+ }
+ const chainId = computed({
+ get() {return _chainId},
+ set(v) {_chainId.value=v; setDefaultTokens()}
+ })
+ const chainInfo = computed({
+ get() {return _chainInfo},
+ set(v) {_chainInfo.value=v; setDefaultTokens()}
+ })
+ const chain = computed(() => !_chainId.value ? null : (_chainInfo.value[_chainId.value] || null))
+ // making the provider directly reactive causes exceptions (calling private method...) when calling provider
+ // functions, so we use a separate ref to signal changes
+ let _provider = null
+ const _providerTouch = ref(false)
+ const provider = computed({
+ get() {_providerTouch.value; return _provider},
+ set(v) {_provider=v; _providerTouch.value = !_providerTouch.value}
+ })
+ const vaultInitCodeHash = ref(null)
+ const account = ref(null)
+ const vaults = ref([])
+ const transactionSenders = ref([]) // a list of function(signer) that send transactions
+ const errors = ref([])
+ const extraTokens = ref({})
+ const poolPrices = ref({})
+ const vaultBalances = ref({}) // indexed by vault addr then by token addr. value is an int
+ const orders = ref({}) // indexed by vault value is another dictionary with orderIndex as key and order status values
- // Order Input Forms
- tokenA: null,
- tokenB: null,
- routes: [],
- routesPending: false,
- inverted: false,
- }),
- getters: {
- vault: (s)=>s.vaults.length===0 ? null : s.vaults[0],
- provider: (s)=>s.chainId===rawProviderChainId ? rawProvider : null,
- chain: (s)=> !s.chainInfo ? null : (s.chainInfo[s.chainId] || null),
- tokens: (s)=>{
- const chains = s.chainId in s.chainInfo && s.chainInfo[s.chainId].tokens !== undefined ? s.chainInfo[s.chainId].tokens : []
- let known = knownTokens[s.chainId]
- known = known ? Object.values(known) : []
- let extras = s.extraTokens[s.chainId]
- extras = extras ? Object.values(extras) : []
- const result = {}
- const all = [...chains, ...known, ...extras]; // put chains first so the Mockcoin pool is automatically selected
- for( const token of all)
- result[token.address] = token
- return result
- },
- factory: (s)=>!s.chain?null:s.chain.factory,
- helper: (s)=>!s.chain?null:s.chain.helper,
- mockenv: (s)=>!s.chain?null:s.chain.mockenv,
- mockCoins: (s)=>!s.chain?[]:!s.chain.mockCoins?[]:s.chain.mockCoins,
- route: (s)=>s.routes.length===0 ? null : s.routes[0],
- pairSymbol: (s)=>s.base?.symbol+'\\'+s.quote?.symbol,
- base: (s)=>{
- const token = s.inverted ? s.tokenB : s.tokenA
- return !token?{}:token
- },
- quote: (s)=> {
- const token = s.inverted ? s.tokenA : s.tokenB
- return !token ? {} : token
- },
- },
- actions: {
- removeTransactionSender(sender) {
- this.transactionSenders = this.transactionSenders.filter((v) => v !== sender)
- },
- error(title, text, closeable=true) {
- this.errors.push({title, text, closeable})
- },
- closeError(title, text) {
- const result = []
- this.errors.forEach((i)=>{if(i.title!==title && i.text!==text) result.push(i)})
- this.errors = result
- },
- addToken(chainId, info) {
- this.$patch((s) => {
- let extras = s.extraTokens[chainId]
- if (extras === undefined) {
- extras = {}
- s.extraTokens[chainId] = extras
- }
- extras[info.address] = info
- })
- },
- },
+ // Order Input Forms
+ // const tokenA = ref(null) // defined at top
+ // const tokenB = ref(null)
+ const buy = ref(false)
+ const inverted = ref(false)
+ const amount = ref(100) // todo
+ const amountIsTokenA = ref(false) // todo
+ const amountIsTotal = ref(true)
+ const limitPrice = ref(null)
+ const routes = ref([])
+ const routesPending = ref(false)
+
+ const validOrder = computed(() => amount.value > 0 && routes.value.length > 0)
+ const vault = computed(() => vaults.value.length === 0 ? null : vaults.value[0])
+ const tokens = computed(getTokens)
+ const factory = computed(() => !chain.value ? null : chain.value.factory)
+ const helper = computed(() => !chain.value ? null : chain.value.helper)
+ const mockenv = computed(() => !chain.value ? null : chain.value.mockenv)
+ const mockCoins = computed(() => !chain.value ? [] : !chain.value.mockCoins ? [] : chain.value.mockCoins)
+ const route = computed(() => routes.value.length === 0 ? null : routes.value[0])
+ const base = computed(() => {
+ const token = inverted.value ? tokenB.value : tokenA.value
+ return !token ? {} : token
+ })
+ const quote = computed(() => {
+ const token = inverted.value ? tokenA.value : tokenB.value
+ return !token ? {} : token
+ })
+ const pairSymbol = computed(() => base.value?.symbol + '\\' + quote.value?.symbol)
+ const limitIsMinimum = computed(() => !(buy.value ^ inverted.value))
+ const amountToken = computed(() => amountIsTokenA.value ? tokenA.value : tokenB.value)
+ const amountIsInput = computed(() => amountIsTokenA.value !== buy.value)
+
+ function removeTransactionSender(sender) {
+ this.transactionSenders = this.transactionSenders.filter((v) => v !== sender)
+ }
+ function error(title, text, closeable=true) {
+ this.errors.push({title, text, closeable})
+ }
+ function closeError(title, text) {
+ const result = []
+ this.errors.forEach((i)=>{if(i.title!==title && i.text!==text) result.push(i)})
+ this.errors = result
+ }
+ function addToken(chainId, info) {
+ this.$patch(() => {
+ let extras = extraTokens[chainId]
+ if (extras === undefined) {
+ extras = {}
+ extraTokens[chainId] = extras
+ }
+ extras[info.address] = info
+ })
+ }
+
+ return {
+ chainId, chainInfo, chain, provider, vaultInitCodeHash, account, vaults, transactionSenders, errors, extraTokens,
+ poolPrices, vaultBalances, orders, tokenA, tokenB, routes, routesPending, inverted, amount, amountIsTokenA,
+ amountIsTotal, limitPrice, validOrder, vault, tokens, factory, helper, mockenv, mockCoins, route,
+ pairSymbol, base, quote, limitIsMinimum, amountToken, amountIsInput, removeTransactionSender, error, closeError,
+ addToken,
+ }
})