ABI's from //contract/out URLs; arbsep; placement fee considers upcoming fee changes; vault detection bugfixes; order placement bugfixes; BETA
This commit is contained in:
2
build.sh
2
build.sh
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# build.sh sets these env vars as output:
|
||||
# build sets these env vars as output:
|
||||
# DEXORDER_WEB_VERSION
|
||||
# DEXORDER_WEB_IMAGE
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
source ./build.sh $@
|
||||
# build.sh sets these env vars:
|
||||
source ./build.sh "$@"
|
||||
# build sets these env vars:
|
||||
# DEXORDER_WEB_VERSION
|
||||
# DEXORDER_WEB_IMAGE
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
|
||||
export const factoryAbi = [
|
||||
'function deployVault() returns (address payable vault)',
|
||||
'function deployVault(uint8 num) returns (address payable vault)',
|
||||
'function deployVault(address owner) returns (address payable vault)',
|
||||
'function deployVault(address owner, uint8 num) returns (address payable vault)',
|
||||
'function logic() view returns (address)',
|
||||
'function upgrader() view returns (address)',
|
||||
'function proposedLogicActivationTimestamp() view returns (uint32)',
|
||||
'function proposedLogic() view returns (address)',
|
||||
'function upgradeLogic(address newLogic)',
|
||||
]
|
||||
|
||||
export const queryHelperAbi = [
|
||||
'function getRoutes(address tokenA,address tokenB) view returns((uint8,uint24,address)[])',
|
||||
]
|
||||
|
||||
export const uniswapV3PoolAbi = [
|
||||
// {
|
||||
// // the current price
|
||||
// uint160 sqrtPriceX96;
|
||||
// // the current tick
|
||||
// int24 tick;
|
||||
// // the most-recently updated index of the observations array
|
||||
// uint16 observationIndex;
|
||||
// // the current maximum number of observations that are being stored
|
||||
// uint16 observationCardinality;
|
||||
// // the next maximum number of observations to store, triggered in observations.write
|
||||
// uint16 observationCardinalityNext;
|
||||
// // the current protocol fee as a percentage of the swap fee taken on withdrawal
|
||||
// // represented as an integer denominator (1/x)%
|
||||
// uint8 feeProtocol;
|
||||
// // whether the pool is locked
|
||||
// bool unlocked;
|
||||
// }
|
||||
'function slot0() view returns(uint160,int24,uint16,uint16,uint16,uint8,bool)',
|
||||
'function token0() view returns(address)',
|
||||
'function token1() view returns(address)',
|
||||
]
|
||||
|
||||
export const erc20Abi = [
|
||||
'function name() view returns (string)',
|
||||
'function symbol() view returns (string)',
|
||||
'function decimals() view returns (uint8)',
|
||||
'function totalSupply() view returns (uint256)',
|
||||
'function balanceOf(address) view returns (uint256)',
|
||||
'function transfer(address,uint256) returns (bool)',
|
||||
'function transferFrom(address,address,uint256) returns (bool)',
|
||||
'function approve(address,uint256) returns (bool success)',
|
||||
'function allowance(address,address) view returns (uint256)',
|
||||
'event Transfer(address indexed,address indexed,uint256)',
|
||||
'event Approval(address indexed,address indexed,uint256)',
|
||||
]
|
||||
|
||||
export const mockErc20Abi = [...erc20Abi,
|
||||
'function mint(address,uint256)',
|
||||
]
|
||||
|
||||
const Route = '(uint8 exchange, uint24 fee)'
|
||||
const Tranche = `(
|
||||
uint16 fraction,
|
||||
bool startTimeIsRelative,
|
||||
bool endTimeIsRelative,
|
||||
bool minIsBarrier,
|
||||
bool maxIsBarrier,
|
||||
bool marketOrder,
|
||||
bool minIsRatio,
|
||||
bool maxIsRatio,
|
||||
bool _reserved7,
|
||||
uint16 rateLimitFraction,
|
||||
uint24 rateLimitPeriod,
|
||||
uint32 startTime,
|
||||
uint32 endTime,
|
||||
uint32 minIntercept,
|
||||
uint32 minSlope,
|
||||
uint32 maxIntercept,
|
||||
uint32 maxSlope
|
||||
)`
|
||||
|
||||
const SwapOrder = `(
|
||||
address tokenIn,
|
||||
address tokenOut,
|
||||
${Route} route,
|
||||
uint256 amount,
|
||||
uint256 minFillAmount,
|
||||
bool amountIsInput,
|
||||
bool outputDirectlyToOwner,
|
||||
uint64 conditionalOrder,
|
||||
${Tranche}[] tranches
|
||||
)`
|
||||
|
||||
export const vaultAbi = [
|
||||
'function version() pure returns (uint8)',
|
||||
'function logic() view returns (address)',
|
||||
'function upgrade(address)',
|
||||
'function feeManager() view returns (address)',
|
||||
'function withdraw(uint256 amount)',
|
||||
'function withdrawTo(address payable recipient, uint256 amount)',
|
||||
'function withdraw(address token, uint256 amount)',
|
||||
'function withdrawTo(address token, address recipient, uint256 amount)',
|
||||
'function numSwapOrders() view returns (uint64 num)',
|
||||
`function placementFee(${SwapOrder} order) view returns (uint256 orderFee, uint256 gasFee)`,
|
||||
`function placeDexorder(${SwapOrder}) payable`,
|
||||
`function placeDexorders(${SwapOrder}[], uint8 ocoMode) payable`,
|
||||
'function cancelDexorder(uint64 orderIndex)',
|
||||
'function cancelAllDexorders()',
|
||||
// `function swapOrderStatus(uint64 orderIndex) view returns (${SwapOrderStatus} memory status)`,
|
||||
'function orderCanceled(uint64 orderIndex) view returns (bool)',
|
||||
]
|
||||
@@ -1,5 +1,7 @@
|
||||
import {ethers} from "ethers";
|
||||
import {queryHelperAbi} from "@/blockchain/abi.js";
|
||||
import {AbiURLCache} from "../common.js";
|
||||
|
||||
export const abiCache = new AbiURLCache('/contract/out/')
|
||||
|
||||
|
||||
export function vaultAddress( factory, vaultInitCodeHash, owner, num=0) {
|
||||
@@ -20,6 +22,23 @@ export function contractOrNull(addr,abi,provider) {
|
||||
}
|
||||
|
||||
export async function queryHelperContract(helper, provider) {
|
||||
return contractOrNull(helper, queryHelperAbi, provider)
|
||||
return newContract(helper, 'QueryHelper', provider)
|
||||
}
|
||||
|
||||
|
||||
// do not supply extensions with name or file: e.g.
|
||||
// use newContract(addr, 'IVaultLogic', provider, 'IVault') to get the ABI from IVault.sol/IVaultLogic.json
|
||||
export async function newContract(addr, name, provider) {
|
||||
const abi = await abiCache.get(name)
|
||||
return new ethers.Contract(addr, abi, provider)
|
||||
}
|
||||
|
||||
|
||||
export async function erc20Contract(addr, provider) {
|
||||
return newContract(addr, 'IERC20Metadata', provider)
|
||||
}
|
||||
|
||||
|
||||
export async function vaultContract(addr, provider) {
|
||||
return await newContract(addr, 'IVault', provider)
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ export function newTranche({
|
||||
endTime = DISTANT_FUTURE,
|
||||
minIsBarrier = false,
|
||||
minIsRatio = false,
|
||||
minIntercept = 0,
|
||||
slippage = 0, // may also set minIntercept instead
|
||||
minIntercept = 0,
|
||||
minSlope = 0,
|
||||
maxIsBarrier = false,
|
||||
maxIsRatio = false,
|
||||
@@ -200,3 +200,14 @@ export function parseTranche(tranche) {
|
||||
startTime, endTime, minIntercept, minSlope, maxIntercept, maxSlope,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function parseFeeSchedule(sched) {
|
||||
const [orderFee, orderExp, gasFee, gasExp, fillFeeHalfBps] = sched
|
||||
return {
|
||||
orderFee: orderFee << orderExp, // orderFee is in native (ETH) currency
|
||||
gasFee: gasFee << gasExp, // gasFee is in native (ETH) currency
|
||||
fillFee: fillFeeHalfBps/1_000_000 // fillFee is a multiplier on the filled volume. 0.0001 = 0.1% of the output token taken as a fee
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,9 @@ 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 {uniswapV3PoolAbi} from "@/blockchain/abi.js";
|
||||
import {subOHLCs} from "@/blockchain/ohlcs.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
import {newContract} from "@/blockchain/contract.js";
|
||||
|
||||
const subscriptionCounts = {} // key is route and value is a subscription counter
|
||||
export const WIDE_PRICE_FORMAT = {decimals:38, width:512, signed:false}; // 38 decimals is 127 bits
|
||||
@@ -84,7 +83,7 @@ async function getPriceForRoute(route) {
|
||||
console.error('provider was null during getPriceForRoute')
|
||||
return null
|
||||
}
|
||||
const pool = new ethers.Contract(addr, uniswapV3PoolAbi, provider)
|
||||
const pool = newContract(addr, 'IUniswapV3Pool', provider)
|
||||
const got = await pool.slot0()
|
||||
const [sqrtPrice,,,,,,] = got
|
||||
const spn = BigInt(sqrtPrice)
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import {socket} from "@/socket.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {erc20Abi} from "@/blockchain/abi.js";
|
||||
import {ethers} from "ethers";
|
||||
import {metadataMap} from "@/version.js";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
import {newContract} from "@/blockchain/contract.js";
|
||||
|
||||
|
||||
// synchronous version may return null but will trigger a lookup
|
||||
@@ -64,7 +63,7 @@ export async function addExtraToken(chainId, addr) {
|
||||
resolve(null)
|
||||
}
|
||||
else {
|
||||
const token = new ethers.Contract(addr, erc20Abi, provider)
|
||||
const token = newContract(addr, 'IERC20Metadata', provider)
|
||||
Promise.all( [token.name(), token.symbol(), token.decimals()] ).then((name,symbol,decimals)=>{
|
||||
info = {
|
||||
a: addr,
|
||||
|
||||
@@ -2,13 +2,16 @@ import {ethers} from "ethers";
|
||||
|
||||
const UNISWAPV3_POOL_INIT_CODE_HASH = '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54'
|
||||
const uniswapV3Addresses = {
|
||||
1337: {
|
||||
31337: { // Mockchain
|
||||
factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
|
||||
},
|
||||
42161: {
|
||||
1337: { // Dexorder Alpha
|
||||
factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
|
||||
},
|
||||
31337: {
|
||||
421614: { // Arbitrum Sepolia
|
||||
factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
|
||||
},
|
||||
42161: { // Arbitrum
|
||||
factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import {BrowserProvider, ethers} from "ethers";
|
||||
import {useStore} from "@/store/store";
|
||||
import {socket} from "@/socket.js";
|
||||
import {contractOrNull, vaultAddress} from "@/blockchain/contract.js";
|
||||
import {SingletonCoroutine, uuid} from "@/misc.js";
|
||||
import {factoryAbi, vaultAbi} from "@/blockchain/abi.js";
|
||||
import {newContract, vaultAddress, vaultContract} from "@/blockchain/contract.js";
|
||||
import {SingletonCoroutine, timestamp, uuid} from "@/misc.js";
|
||||
import {defineStore} from "pinia";
|
||||
import {ref} from "vue";
|
||||
import {metadataMap, version} from "@/version.js";
|
||||
@@ -217,7 +216,7 @@ async function _discoverVaults(owner) {
|
||||
console.log('No provider')
|
||||
return // do not change whatever was already found
|
||||
}
|
||||
const vault = new ethers.Contract(addr, vaultAbi, provider)
|
||||
const vault = await vaultContract(addr, provider)
|
||||
try {
|
||||
const version = Number(await vault.version())
|
||||
console.log(`found vault #${num} v${version} at ${addr}`)
|
||||
@@ -295,11 +294,24 @@ export const PendingOrderState = {
|
||||
Sent: -102, // tx is awaiting blockchain mining
|
||||
}
|
||||
|
||||
const placementFeeSelector = 'placementFee((address,address,(uint8,uint24),uint256,uint256,bool,bool,uint64,(uint16,bool,bool,bool,bool,bool,bool,bool,bool,uint16,uint24,uint32,uint32,uint32,uint32,uint32,uint32)[]),(uint8,uint8,uint8,uint8,uint8))'
|
||||
|
||||
export async function placementFee(vault, order) {
|
||||
const v = new ethers.Contract(vault, vaultAbi, provider)
|
||||
const [orderFee, gasFee] = await v.placementFee(order)
|
||||
console.log('computed fees', orderFee, gasFee)
|
||||
export async function placementFee(vault, order, window=300) {
|
||||
// If the fees are about to change within `window` seconds of now, we send the higher native amount of the two fees.
|
||||
// If the fees sent are too much, the vault will refund the sender.
|
||||
const v = await vaultContract(vault, provider)
|
||||
const feeManagerAddr = await v.feeManager()
|
||||
const feeManager = await newContract(feeManagerAddr, 'IFeeManager', provider)
|
||||
const [sched, changeTimestamp] = await Promise.all([feeManager.fees(), feeManager.proposedFeeActivationTime()])
|
||||
console.log('sched', order, sched)
|
||||
let [orderFee, gasFee] = await v[placementFeeSelector](order, [...sched])
|
||||
console.log('placementFee', orderFee, gasFee)
|
||||
if (Number(changeTimestamp) - timestamp() < window) {
|
||||
const nextSched = await feeManager.proposedFees()
|
||||
const [nextOrderFee, nextGasFee] = await v[placementFeeSelector](order, [...nextSched])
|
||||
if (nextOrderFee + nextGasFee > orderFee + gasFee)
|
||||
[orderFee, gasFee] = [nextOrderFee, nextGasFee]
|
||||
}
|
||||
return [orderFee, gasFee]
|
||||
}
|
||||
|
||||
@@ -324,7 +336,7 @@ export async function pendOrder(order, fee=null) {
|
||||
export async function cancelOrder(vault, orderIndex) {
|
||||
console.log('cancel order', vault, orderIndex)
|
||||
pendTransaction(async (signer)=> {
|
||||
const contract = contractOrNull(vault, vaultAbi, signer)
|
||||
const contract = await vaultContract(vault, signer)
|
||||
if( contract === null ) {
|
||||
console.error('vault contract was null while canceling order', vault, orderIndex)
|
||||
return null
|
||||
@@ -335,7 +347,7 @@ export async function cancelOrder(vault, orderIndex) {
|
||||
|
||||
export async function cancelAll(vault) {
|
||||
pendTransaction(async (signer)=> {
|
||||
const contract = contractOrNull(vault, vaultAbi, signer)
|
||||
const contract = await vaultContract(vault, signer)
|
||||
if( contract === null ) {
|
||||
console.error('vault contract was null while canceling order', vault)
|
||||
return null
|
||||
@@ -364,8 +376,12 @@ export function flushOrders(vault) {
|
||||
|
||||
function pendOrderAsTransaction(pend) {
|
||||
pendTransaction(async (signer)=> {
|
||||
const contract = contractOrNull(pend.vault, vaultAbi, signer)
|
||||
if( contract === null ) {
|
||||
// console.log('pendTransaction')
|
||||
let contract
|
||||
try {
|
||||
contract = await vaultContract(pend.vault, signer)
|
||||
}
|
||||
catch (e) {
|
||||
console.error('vault contract was null while sending order transaction', pend.vault)
|
||||
return null
|
||||
}
|
||||
@@ -491,15 +507,17 @@ export async function detectUpgrade() {
|
||||
}
|
||||
try {
|
||||
console.log('factory', info.factory)
|
||||
const factory = new ethers.Contract(info.factory, factoryAbi, provider)
|
||||
const vault = new ethers.Contract(s.vault, vaultAbi, provider)
|
||||
const [factory, vault] = await Promise.all([
|
||||
newContract(info.factory, 'IVaultFactory', provider),
|
||||
newContract(s.vault, 'IVault', provider),
|
||||
])
|
||||
const vaultLogic = await vault.logic()
|
||||
const latestLogic = await factory.logic()
|
||||
// const [vaultLogic, latestLogic] = await Promise.all( vault.logic(), factory.logic() )
|
||||
console.log('vaultLogic / latestLogic', vaultLogic, latestLogic)
|
||||
if ( vaultLogic !== latestLogic ) {
|
||||
s.upgrade = latestLogic
|
||||
const logic = new ethers.Contract(latestLogic, vaultAbi, provider)
|
||||
const logic = await newContract(latestLogic, 'IVault', provider)
|
||||
const version = await logic.version()
|
||||
console.log(`found vault version ${version}`)
|
||||
return version
|
||||
@@ -514,7 +532,7 @@ export async function detectUpgrade() {
|
||||
|
||||
function upgradeSender(vault, logic) {
|
||||
return async function (signer) {
|
||||
const v = new ethers.Contract(vault, vaultAbi, signer)
|
||||
const v = await vaultContract(vault, signer)
|
||||
v.upgrade(logic)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import * as fs from "node:fs";
|
||||
|
||||
export function mixin(child, ...parents) {
|
||||
// child is modified directly, assigning fields from parents that are missing in child. parents fields are
|
||||
// assigned by parents order, highest priority first
|
||||
@@ -41,3 +43,99 @@ export function decodeIEE754(value) {
|
||||
view.setUint32(0, value, false)
|
||||
return view.getFloat32(0, false)
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// AsyncCache
|
||||
//
|
||||
|
||||
export class AsyncCache {
|
||||
// fetch(key) returns a value
|
||||
constructor(fetch) {
|
||||
this.cache = {}
|
||||
this.fetchLocks = {}
|
||||
this.fetch = fetch
|
||||
}
|
||||
|
||||
async get(key) {
|
||||
if (this.cache[key]) {
|
||||
return this.cache[key]
|
||||
}
|
||||
if (this.fetchLocks[key]) {
|
||||
return await this.fetchLocks[key]
|
||||
}
|
||||
const fetchPromise = this.fetch(key)
|
||||
this.fetchLocks[key] = fetchPromise
|
||||
const result = await fetchPromise
|
||||
this.cache[key] = result
|
||||
delete this.fetchLocks[key]
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AsyncAbiCache extends AsyncCache {
|
||||
constructor(fetch) {
|
||||
super(async (key)=>{
|
||||
const result = await fetch(key)
|
||||
return result.abi
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AsyncURLCache extends AsyncAbiCache {
|
||||
constructor(urlForKey) {
|
||||
super(async (key) => {
|
||||
const URL = this.urlForKey(key)
|
||||
const response = await fetch(URL)
|
||||
if (!response.ok)
|
||||
throw new Error(`Could not fetch ${URL} (status ${response.status})`)
|
||||
return await response.json()
|
||||
})
|
||||
this.urlForKey = urlForKey
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AsyncFileCache extends AsyncAbiCache {
|
||||
constructor(pathForKey) {
|
||||
super(async (key) => {
|
||||
const path = this.pathForKey(key)
|
||||
const data = fs.readFileSync(path, 'utf8');
|
||||
return JSON.parse(data);
|
||||
})
|
||||
this.pathForKey = pathForKey
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AbiURLCache extends AsyncURLCache {
|
||||
constructor(baseUrl) {
|
||||
super((name)=>{
|
||||
return this.baseUrl+abiPath(name)
|
||||
})
|
||||
this.baseUrl = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AbiFileCache extends AsyncFileCache {
|
||||
constructor(basePath) {
|
||||
super((name)=>{
|
||||
return this.basePath+abiPath(name)
|
||||
})
|
||||
this.basePath = basePath.endsWith('/') ? basePath : basePath + '/'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const files = {
|
||||
// If a contract is in a file different than its name, put the exception here
|
||||
// 'IVaultLogic' : 'IVault', // for example
|
||||
}
|
||||
|
||||
function abiPath(name) {
|
||||
const file = files[name]
|
||||
return `${file?file:name}.sol/${name}.json`
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<template>
|
||||
<v-chip text="ALPHA" size='x-small' color="red" class="align-self-start" variant="text"/>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'alpha'
|
||||
}
|
||||
</script>
|
||||
8
src/components/Beta.vue
Normal file
8
src/components/Beta.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<v-chip text="BETA" size='x-small' color="red" class="align-self-start" variant="text"/>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'beta'
|
||||
}
|
||||
</script>
|
||||
@@ -2,16 +2,16 @@
|
||||
<span class="d-inline-flex align-center">
|
||||
<v-icon icon="mdi-arrow-up-bold" color="primary" class="arrow"/>
|
||||
<span class="logo">dexorder</span>
|
||||
<alpha v-if="alpha"/>
|
||||
<beta v-if="showTag"/>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import Alpha from "@/components/Alpha.vue";
|
||||
import Beta from "@/components/Beta.vue";
|
||||
|
||||
const props = defineProps({
|
||||
alpha: {type: Boolean, default: false}
|
||||
showTag: {type: Boolean, default: false}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<v-card v-if="!loggedIn" rounded="0">
|
||||
<v-card-title>
|
||||
<!-- <v-icon icon="mdi-hand-wave" color="grey"/>-->
|
||||
Welcome to Dexorder Alpha!
|
||||
Welcome to Dexorder Beta!
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
This alpha test runs on the Dexorder Testnet blockchain, which gives you free testnet tokens to trade.
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
import {useStore} from "@/store/store";
|
||||
import {computed, ref} from "vue";
|
||||
import {tokenFloat} from "@/misc.js";
|
||||
import {contractOrNull} from "@/blockchain/contract.js"
|
||||
import {vaultAbi} from "@/blockchain/abi.js";
|
||||
import {vaultContract} from "@/blockchain/contract.js"
|
||||
import {pendTransaction} from "@/blockchain/wallet.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
|
||||
@@ -50,7 +49,7 @@ function withdraw() {
|
||||
if( amount === 0n )
|
||||
return
|
||||
pendTransaction(async (signer)=>{
|
||||
const vault = contractOrNull(vaultAddr, vaultAbi, signer)
|
||||
const vault = await vaultContract(vaultAddr, signer)
|
||||
return await vault['withdraw(address,uint256)'](props.token.a, amount)
|
||||
})
|
||||
floatAmount.value = 0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="d-flex mb-1 align-center w-100">
|
||||
<logo class="d-flex align-end clickable logo-large" @click="nav('Order')" :alpha="true"/>
|
||||
<logo class="d-flex align-end clickable logo-large" @click="nav('Order')" :show-tag="true"/>
|
||||
<slot/>
|
||||
<div class="ml-auto d-flex align-center">
|
||||
<span class="title mr-4">{{title}}</span>
|
||||
@@ -19,7 +19,7 @@ import {useStore} from "@/store/store.js";
|
||||
import {useChartOrderStore} from "@/orderbuild.js";
|
||||
import {useTheme} from "vuetify";
|
||||
import ToolbarButton from "@/components/chart/ToolbarButton.vue";
|
||||
import Alpha from "@/components/Alpha.vue";
|
||||
import beta from "@/components/Beta.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
<v-list>
|
||||
<v-list-item>
|
||||
<uniswap-logo class="mr-2"/>
|
||||
Supports Uniswap v3 <alpha/>
|
||||
Supports Uniswap v3 <beta/>
|
||||
</v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-ray-vertex" class="mr-2"/> Limit Orders <alpha/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-clock-outline" class="mr-2"/> DCA and TWAP Orders <alpha/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-vector-line" class="mr-2"/> Diagonal Limit Orders <alpha/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-ray-vertex" class="mr-2"/> Limit Orders <beta/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-clock-outline" class="mr-2"/> DCA and TWAP Orders <beta/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-vector-line" class="mr-2"/> Diagonal Limit Orders <beta/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-chart-timeline-variant-shimmer" class="mr-2"/> Stop Loss / Take Profit <soon/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-format-list-checks" class="mr-2"/> One-Cancels-the-Other (OCO) Groups <soon/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-cancel" class="mr-2"/> Single-transaction Cancel All <soon/></v-list-item>
|
||||
@@ -33,17 +33,14 @@
|
||||
|
||||
<script setup>
|
||||
import {useTheme} from "vuetify";
|
||||
import Alpha from "@/components/Alpha.vue";
|
||||
import beta from "@/components/Beta.vue";
|
||||
import Soon from "@/components/Soon.vue";
|
||||
import HowItWorks from "@/corp/HowItWorks.vue";
|
||||
import HomeActions from "@/corp/HomeActions.vue";
|
||||
import UniswapLogo from "@/corp/UniswapLogo.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
import AppBtn from "@/corp/AppBtn.vue";
|
||||
|
||||
const theme = useTheme().current
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -71,11 +71,7 @@
|
||||
|
||||
<script setup>
|
||||
|
||||
import Alpha from "@/components/Alpha.vue";
|
||||
import Soon from "@/components/Soon.vue";
|
||||
import UniswapLogo from "@/corp/UniswapLogo.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import HomeActions from "@/corp/HomeActions.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
import AppBtn from "@/corp/AppBtn.vue";
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user