Compare commits
10 Commits
a65bc94dac
...
19a8ffbbd4
| Author | SHA1 | Date | |
|---|---|---|---|
| 19a8ffbbd4 | |||
| a689766f37 | |||
| bb4f7d4607 | |||
| a9bf23ddbb | |||
| 43891434c5 | |||
| 99a6cc1742 | |||
| 28dd64b1cf | |||
| cfcba95445 | |||
| 61101fcf0a | |||
| a7a1628f3c |
@@ -18,8 +18,10 @@
|
||||
"core-js": "^3.29.0",
|
||||
"ethers": "^6.7.1",
|
||||
"flexsearch": "^0.7.43",
|
||||
"lru-cache": "^11.0.2",
|
||||
"luxon": "^3.4.4",
|
||||
"pinia": "2.1.6",
|
||||
"pinia-plugin-persistedstate": "^4.1.3",
|
||||
"roboto-fontface": "*",
|
||||
"socket.io-client": "^4.7.2",
|
||||
"vue": "^3.2.0",
|
||||
|
||||
@@ -31,7 +31,7 @@ export async function queryHelperContract(helper, provider) {
|
||||
// use newContract(addr, 'IVaultImpl', provider, 'IVault') to get the ABI from IVault.sol/IVaultImpl.json
|
||||
export async function newContract(addr, name, provider) {
|
||||
const abi = await abiCache.get(name)
|
||||
console.log(`${name} ABI`, abi)
|
||||
// console.log(`${name} ABI`, abi)
|
||||
return new ethers.Contract(addr, abi, provider)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {uint32max, uint64max} from "@/misc.js";
|
||||
import {decodeIEE754, encodeIEE754} from "@/common.js";
|
||||
import {encodeIEE754} from "@/common.js";
|
||||
|
||||
export const MAX_FRACTION = 65535;
|
||||
export const NO_CONDITIONAL_ORDER = uint64max;
|
||||
@@ -151,10 +151,11 @@ export function parseOrderStatus(chainId, status) {
|
||||
order = parseOrder(order)
|
||||
filledIn = BigInt(filledIn)
|
||||
filledOut = BigInt(filledOut)
|
||||
trancheStatus = trancheStatus.map((obj)=>parseTrancheStatus(obj))
|
||||
const filled = order.amountIsInput ? filledIn : filledOut
|
||||
trancheStatus = trancheStatus.map((obj)=>parseTrancheStatus(obj, order.amountIsInput))
|
||||
const result = {
|
||||
chainId, order, fillFeeHalfBps, state, startTime, startPrice, ocoGroup,
|
||||
filledIn, filledOut, trancheStatus,
|
||||
filledIn, filledOut, filled, trancheStatus,
|
||||
};
|
||||
console.log('SwapOrderStatus', result)
|
||||
return result
|
||||
@@ -162,20 +163,23 @@ export function parseOrderStatus(chainId, status) {
|
||||
|
||||
function parseFill(obj) {
|
||||
let [tx, time, filledIn, filledOut, fee] = obj
|
||||
time = new Date(time * 1000)
|
||||
filledIn = BigInt(filledIn)
|
||||
filledOut = BigInt(filledOut)
|
||||
const filled = obj.amountIsInput ? filledIn : filledOut
|
||||
fee = BigInt(fee)
|
||||
return {tx, time, filledIn, filledOut, fee}
|
||||
return {tx, time, filledIn, filledOut, filled, fee}
|
||||
}
|
||||
|
||||
function parseTrancheStatus(obj) {
|
||||
function parseTrancheStatus(obj, amountIsInput) {
|
||||
let [filledIn, filledOut, activationTime, startTime, endTime, rawFills,] = obj
|
||||
filledIn = BigInt(filledIn)
|
||||
filledOut = BigInt(filledOut)
|
||||
const fills = []
|
||||
for (const fill of rawFills)
|
||||
fills.push(parseFill(fill))
|
||||
return {filledIn, filledOut, activationTime, startTime, endTime, fills}
|
||||
fills.push(parseFill(fill, amountIsInput))
|
||||
const filled = amountIsInput ? filledIn : filledOut
|
||||
return {filledIn, filledOut, filled, activationTime, startTime, endTime, fills}
|
||||
}
|
||||
|
||||
export function parseOrder(order) {
|
||||
|
||||
@@ -61,21 +61,28 @@ export async function addExtraToken(chainId, addr) {
|
||||
}
|
||||
else {
|
||||
if( provider===null ) {
|
||||
console.log('warning: token lookup cancelled due to null provider', addr)
|
||||
console.warn('warning: token lookup cancelled due to null provider', addr)
|
||||
resolve(null)
|
||||
}
|
||||
else {
|
||||
const token = await newContract(addr, 'IERC20Metadata', provider)
|
||||
Promise.all( [token.name(), token.symbol(), token.decimals()] ).then((name,symbol,decimals)=>{
|
||||
info = {
|
||||
a: addr,
|
||||
n: name,
|
||||
s: symbol,
|
||||
d: decimals,
|
||||
for( let tries=1; tries<=5; tries++ ) {
|
||||
try {
|
||||
const token = await newContract(addr, 'IERC20Metadata', provider)
|
||||
const [name, symbol, decimals] = await Promise.all([token.name(), token.symbol(), token.decimals()])
|
||||
info = {
|
||||
a: addr,
|
||||
n: name,
|
||||
s: symbol,
|
||||
d: decimals,
|
||||
}
|
||||
s.addToken(chainId, info)
|
||||
resolve(info)
|
||||
break
|
||||
}
|
||||
s.addToken(chainId, info)
|
||||
resolve(info)
|
||||
})
|
||||
catch (e) {
|
||||
console.warn(`Could not lookup token ${addr}`, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
279
src/blockchain/transaction.js
Normal file
279
src/blockchain/transaction.js
Normal file
@@ -0,0 +1,279 @@
|
||||
import {nav, timestamp, uuid} from "@/misc.js";
|
||||
import {newContract, vaultContract} from "@/blockchain/contract.js";
|
||||
import {ensureVault, provider, switchChain, useWalletStore} from "@/blockchain/wallet.js";
|
||||
import {toRaw} from "vue";
|
||||
import {useChartOrderStore} from "@/orderbuild.js";
|
||||
|
||||
export const TransactionState = {
|
||||
Created: 0, // user requested a transaction
|
||||
Proposed: 1, // tx is sent to the wallet
|
||||
Signed: 2, // tx is awaiting blockchain mining
|
||||
Rejected: 3, // user refused to sign the tx
|
||||
Error: 3, // unknown error sending the tx to the wallet
|
||||
Mined: 4, // transaction has been confirmed on-chain
|
||||
}
|
||||
|
||||
export const TransactionType = {
|
||||
PlaceOrder: 1,
|
||||
CancelOrder: 2,
|
||||
CancelAll: 3,
|
||||
Wrap: 4,
|
||||
Unwrap: 5,
|
||||
WithdrawNative: 6,
|
||||
Withdraw: 7,
|
||||
}
|
||||
|
||||
export class Transaction {
|
||||
constructor(chainId, type) {
|
||||
this.id = uuid()
|
||||
this.type = type
|
||||
this.state = TransactionState.Created
|
||||
this.tx = null
|
||||
this.chainId = chainId
|
||||
this.owner = null
|
||||
this.vault = null
|
||||
this.error = null
|
||||
}
|
||||
|
||||
submit() {
|
||||
useWalletStore().transaction = this
|
||||
ensureVault()
|
||||
}
|
||||
|
||||
propose(owner, vault) {
|
||||
if (this.vault !== null && this.vault !== vault) {
|
||||
this.failed('proposed vault did not match withdrawl vault', vault, this.vault)
|
||||
return
|
||||
}
|
||||
this.owner = owner
|
||||
this.vault = vault
|
||||
this.send().catch(this.catchSend.bind(this))
|
||||
this.state = TransactionState.Proposed
|
||||
}
|
||||
|
||||
async createTx(vaultContract) {
|
||||
throw Error('unimplemented')
|
||||
}
|
||||
|
||||
signed(tx) {
|
||||
this.tx = tx
|
||||
this.state = TransactionState.Signed
|
||||
}
|
||||
|
||||
rejected() {
|
||||
this.tx = null
|
||||
this.chainId = null
|
||||
this.owner = null
|
||||
this.vault = null
|
||||
this.end(TransactionState.Rejected)
|
||||
console.log('transaction rejected', this.id)
|
||||
}
|
||||
|
||||
failed(e) {
|
||||
this.error = e
|
||||
this.end(TransactionState.Error)
|
||||
console.log('transaction failed', this.id, e)
|
||||
}
|
||||
|
||||
mined(receipt) {
|
||||
this.receipt = receipt
|
||||
this.end(TransactionState.Mined)
|
||||
console.log('mined transaction', this.id, receipt)
|
||||
}
|
||||
|
||||
isOpen() {
|
||||
return this.state >= TransactionState.Rejected
|
||||
}
|
||||
|
||||
isClosed() {
|
||||
return this.state < TransactionState.Rejected
|
||||
}
|
||||
|
||||
|
||||
end(state) {
|
||||
this.state = state
|
||||
useWalletStore().transaction = null
|
||||
}
|
||||
|
||||
|
||||
async send() {
|
||||
console.log('sendTransaction', this)
|
||||
try {
|
||||
await switchChain(this.chainId)
|
||||
} catch (e) {
|
||||
if (e.code === 4001) {
|
||||
this.rejected()
|
||||
return null
|
||||
} else {
|
||||
this.failed(e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
let signer
|
||||
try {
|
||||
signer = await provider.getSigner();
|
||||
} catch (e) {
|
||||
// {
|
||||
// "code": -32002,
|
||||
// "message": "Already processing eth_requestAccounts. Please wait."
|
||||
// }
|
||||
this.rejected()
|
||||
return null
|
||||
}
|
||||
let contract
|
||||
try {
|
||||
contract = await vaultContract(this.vault, signer)
|
||||
} catch (e) {
|
||||
this.failed('vault contract was null while sending order transaction')
|
||||
return null
|
||||
}
|
||||
const tx = toRaw(await this.createTx(contract))
|
||||
this.signed(tx)
|
||||
console.log(`sent transaction`, tx)
|
||||
tx.wait().then(this.mined.bind(this)).catch(this.failed.bind(this))
|
||||
return this.tx
|
||||
}
|
||||
|
||||
|
||||
catchSend(e) {
|
||||
this.error = e
|
||||
if (e.info?.error?.code === 4001) {
|
||||
console.log(`wallet refused transaction`, this.id)
|
||||
this.rejected()
|
||||
} else {
|
||||
this.failed(e)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export class PlaceOrderTransaction extends Transaction {
|
||||
constructor(chainId, order) {
|
||||
super(chainId, TransactionType.PlaceOrder)
|
||||
this.order = order
|
||||
this.placementTime = Date.now()/1000
|
||||
this.fee = null // dexorder place and gas fee total
|
||||
}
|
||||
|
||||
|
||||
async createTx(vaultContract) {
|
||||
this.fee = await placementFee(this.vault, this.order)
|
||||
console.log('placing order', this.id, this.fee, this.order)
|
||||
return await vaultContract.placeDexorder(this.order, {value: this.fee.reduce((a, b) => a + b)})
|
||||
}
|
||||
|
||||
|
||||
end(state) {
|
||||
super.end(state)
|
||||
if (state === TransactionState.Mined) {
|
||||
useChartOrderStore().resetOrders()
|
||||
nav('Status')
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// todo move to orderlib
|
||||
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)
|
||||
// single order placement selector
|
||||
const placementFeeSelector = 'placementFee((address,address,(uint8,uint24),uint256,uint256,bool,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))'
|
||||
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]
|
||||
}
|
||||
|
||||
|
||||
export class CancelOrderTransaction extends Transaction {
|
||||
constructor(chainId, index) {
|
||||
super(chainId, TransactionType.CancelOrder)
|
||||
this.index = index
|
||||
}
|
||||
|
||||
|
||||
async createTx(vaultContract) {
|
||||
return await vaultContract.cancelDexorder(this.index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class CancelAllTransaction extends Transaction {
|
||||
constructor(chainId, vault) {
|
||||
super(chainId, TransactionType.CancelAll)
|
||||
this.vault = vault
|
||||
}
|
||||
|
||||
|
||||
async createTx(vaultContract) {
|
||||
return await vaultContract.cancelAllDexorders()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class WithdrawTransaction extends Transaction {
|
||||
constructor(chainId, vault, token, amount) {
|
||||
super(chainId, TransactionType.Withdraw)
|
||||
this.token = token
|
||||
this.amount = amount
|
||||
this.vault = vault
|
||||
}
|
||||
|
||||
|
||||
async createTx(vaultContract) {
|
||||
return await vaultContract['withdraw(address,uint256)'](this.token.a, this.amount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class WithdrawNativeTransaction extends Transaction {
|
||||
constructor(chainId, vault, amount) {
|
||||
super(chainId, TransactionType.WithdrawNative)
|
||||
this.amount = amount
|
||||
this.vault = vault
|
||||
}
|
||||
|
||||
|
||||
async createTx(vaultContract) {
|
||||
return await vaultContract['withdraw(uint256)'](this.amount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class WrapTransaction extends Transaction {
|
||||
constructor(chainId, vault, amount) {
|
||||
super(chainId, TransactionType.Wrap)
|
||||
this.vault = vault
|
||||
this.amount = amount
|
||||
}
|
||||
|
||||
async createTx(vaultContract) {
|
||||
return await vaultContract.wrap(this.amount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class UnwrapTransaction extends Transaction {
|
||||
constructor(chainId, vault, amount) {
|
||||
super(chainId, TransactionType.Unwrap)
|
||||
this.amount = amount
|
||||
}
|
||||
|
||||
async createTx(vaultContract) {
|
||||
return await vaultContract.unwrap(this.amount)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
import {BrowserProvider, ethers} from "ethers";
|
||||
import {useStore} from "@/store/store";
|
||||
import {socket} from "@/socket.js";
|
||||
import {SingletonCoroutine, timestamp, uuid} from "@/misc.js";
|
||||
import {SingletonCoroutine} from "@/misc.js";
|
||||
import {newContract, vaultAddress, vaultContract} from "@/blockchain/contract.js";
|
||||
import {defineStore} from "pinia";
|
||||
import {ref} from "vue";
|
||||
import {metadataMap, version} from "@/version.js";
|
||||
import {CancelAllTransaction, TransactionState} from "@/blockchain/transaction.js";
|
||||
|
||||
|
||||
export let provider = null
|
||||
|
||||
|
||||
// DEPRECATED
|
||||
export const useWalletStore = defineStore('wallet', ()=>{
|
||||
// this is what the wallet is logged into. it could be different than the application's store.chainId.
|
||||
const chainId = ref(0)
|
||||
|
||||
// Pending Order Format
|
||||
// OLD Pending Order Format
|
||||
// {
|
||||
// chainId: 31337, // must never be null, even if no wallet plugin exists. chosen by app, not wallet.
|
||||
// placementTime: Date.now(),
|
||||
@@ -26,8 +28,11 @@ export const useWalletStore = defineStore('wallet', ()=>{
|
||||
// }
|
||||
const pendingOrders = ref([])
|
||||
|
||||
// NEW Format is a single Transaction class
|
||||
const transaction = ref(null)
|
||||
|
||||
return {
|
||||
chainId, pendingOrders,
|
||||
chainId, pendingOrders, transaction,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -165,7 +170,7 @@ function discoverVaults(owner) {
|
||||
doDiscoverVaults.invoke(owner)
|
||||
}
|
||||
|
||||
const doDiscoverVaults = new SingletonCoroutine(_discoverVaults, 50, false)
|
||||
const doDiscoverVaults = new SingletonCoroutine(_discoverVaults, 50)
|
||||
async function _discoverVaults(owner) {
|
||||
const result = []
|
||||
const versions = []
|
||||
@@ -204,11 +209,12 @@ async function _discoverVaults(owner) {
|
||||
if( s.account === owner ) { // double-check the account since it could have changed during our await
|
||||
s.vaults = result
|
||||
s.vaultVersions = versions
|
||||
if( useWalletStore().pendingOrders.length ) {
|
||||
if( useWalletStore().transaction ) {
|
||||
const num = 0 // todo multiple vaults
|
||||
if (result.length)
|
||||
flushOrders(result[0])
|
||||
flushOrders(s.chainId, owner, num, result[0])
|
||||
else
|
||||
ensureVault2(s.chainId, owner, 0)
|
||||
ensureVault2(s.chainId, owner, num)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,7 +254,7 @@ async function doEnsureVault(chainId, owner, num) {
|
||||
if (s.vaults.length <= num)
|
||||
await _discoverVaults(owner)
|
||||
if( s.vaults[num] )
|
||||
flushOrders(s.vaults[num])
|
||||
flushOrders(chainId, owner, num, s.vaults[num])
|
||||
else {
|
||||
console.log(`requesting vault ${owner} ${num}`)
|
||||
socket.emit('ensureVault', chainId, owner, num)
|
||||
@@ -258,53 +264,6 @@ async function doEnsureVault(chainId, owner, num) {
|
||||
const ensureVaultRoutine = new SingletonCoroutine(doEnsureVault, 100)
|
||||
|
||||
|
||||
export const PendingOrderState = {
|
||||
Submitted: -100, // user clicked Place Order but the tx isn't sent to the wallet yet
|
||||
Signing: 0, // tx is sent to the wallet
|
||||
Rejected: -101, // user refused to sign the tx
|
||||
Sent: -102, // tx is awaiting blockchain mining
|
||||
}
|
||||
|
||||
// single order placement selector
|
||||
const placementFeeSelector = 'placementFee((address,address,(uint8,uint24),uint256,uint256,bool,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, 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]
|
||||
}
|
||||
|
||||
|
||||
export async function pendOrder(order, fee=null) {
|
||||
const s = useStore()
|
||||
const pend = {
|
||||
id: uuid(),
|
||||
chainId: s.chainId,
|
||||
placementTime: Date.now()/1000,
|
||||
fee: fee, // dexorder place and gas fee total
|
||||
vault: s.vaults.length ? s.vaults[0] : null,
|
||||
state: PendingOrderState.Submitted,
|
||||
order
|
||||
};
|
||||
useWalletStore().pendingOrders.splice(0,0, pend)
|
||||
console.log('pended order', pend.id, JSON.stringify(order))
|
||||
ensureVault()
|
||||
}
|
||||
|
||||
|
||||
export async function cancelOrder(vault, orderIndex) {
|
||||
console.log('cancel order', vault, orderIndex)
|
||||
pendTransaction(async (signer)=> {
|
||||
@@ -318,18 +277,13 @@ export async function cancelOrder(vault, orderIndex) {
|
||||
}
|
||||
|
||||
export async function cancelAll(vault) {
|
||||
pendTransaction(async (signer)=> {
|
||||
const contract = await vaultContract(vault, signer)
|
||||
if( contract === null ) {
|
||||
console.error('vault contract was null while canceling order', vault)
|
||||
return null
|
||||
}
|
||||
return await contract.cancelAllDexorders()
|
||||
})
|
||||
new CancelAllTransaction(useStore().chainId, vault).submit()
|
||||
}
|
||||
|
||||
export function flushOrders(vault) {
|
||||
export function flushOrders(chainId, owner, num, vault) {
|
||||
const ws = useWalletStore();
|
||||
if (ws.transaction!==null && ws.transaction.state < TransactionState.Proposed)
|
||||
ws.transaction.propose(owner, vault)
|
||||
let needsFlush = false
|
||||
for( const pend of ws.pendingOrders ) {
|
||||
if (pend.vault === null)
|
||||
@@ -337,7 +291,7 @@ export function flushOrders(vault) {
|
||||
if (pend.state === PendingOrderState.Submitted) {
|
||||
console.log('flushing order', pend.id)
|
||||
pendOrderAsTransaction(pend)
|
||||
pend.state = PendingOrderState.Signing
|
||||
setPendState(pend, PendingOrderState.Signing)
|
||||
needsFlush = true
|
||||
}
|
||||
}
|
||||
@@ -363,7 +317,7 @@ function pendOrderAsTransaction(pend) {
|
||||
catch (e) {
|
||||
if(e.code===4001) {
|
||||
console.log('user refused chain switch')
|
||||
pend.state = PendingOrderState.Rejected
|
||||
setPendState(pend, PendingOrderState.Rejected)
|
||||
return null
|
||||
}
|
||||
else {
|
||||
@@ -378,7 +332,7 @@ function pendOrderAsTransaction(pend) {
|
||||
console.log('placing order', pend.id, pend.fee, pend.order)
|
||||
const tx = await contract.placeDexorder(pend.order, {value:pend.fee})
|
||||
pend.tx = tx
|
||||
pend.state = PendingOrderState.Sent
|
||||
setPendState(pend, PendingOrderState.Sent)
|
||||
console.log(`order ${pend.id} sent transaction`, tx)
|
||||
tx.wait().then((txReceipt)=>{
|
||||
console.log('mined order', pend.id, txReceipt)
|
||||
@@ -391,7 +345,7 @@ function pendOrderAsTransaction(pend) {
|
||||
(e) => {
|
||||
if( e.info?.error?.code === 4001 ) {
|
||||
console.log(`wallet refused order`, pend.id)
|
||||
pend.state = PendingOrderState.Rejected
|
||||
setPendState(pend, PendingOrderState.Rejected)
|
||||
return true // returning true means we handled the error. any other return value will dump to console.
|
||||
}
|
||||
})
|
||||
@@ -464,18 +418,18 @@ function doSendTransaction(sender, signer, errHandler) {
|
||||
export async function detectUpgrade() {
|
||||
if (!provider) {
|
||||
console.log('no provider!')
|
||||
return 0
|
||||
return null
|
||||
}
|
||||
const s = useStore()
|
||||
if (!s.vault) {
|
||||
console.log('no vault logged in')
|
||||
return 0
|
||||
return null
|
||||
}
|
||||
|
||||
const info = version.chainInfo[s.chainId]
|
||||
if (!info) {
|
||||
console.log(`couldn't get chainInfo for ${s.chainId}`)
|
||||
return 0
|
||||
return null
|
||||
}
|
||||
try {
|
||||
console.log('factory', info.factory)
|
||||
@@ -497,7 +451,7 @@ export async function detectUpgrade() {
|
||||
catch (e) {
|
||||
console.log('ignorable error while querying for an upgrade', e)
|
||||
}
|
||||
return 0
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,14 +23,11 @@ export function removeSymbolChangedCallback(cb) {
|
||||
}
|
||||
|
||||
function symbolChanged(symbol) {
|
||||
if (symbol===null)
|
||||
co.selectedSymbol = null
|
||||
else {
|
||||
const info = lookupSymbol(symbol.ticker)
|
||||
symbolChangedCbs.forEach((cb) => cb(info))
|
||||
co.selectedSymbol = info
|
||||
}
|
||||
const info = symbol===null ? null : lookupSymbol(symbol.ticker)
|
||||
co.selectedSymbol = info
|
||||
symbolChangedCbs.forEach((cb) => cb(info))
|
||||
updateFeeDropdown()
|
||||
console.log('symbol changed', info)
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +128,9 @@ function selectPool(fee) {
|
||||
|
||||
export function initWidget(el) {
|
||||
widget = window.tvWidget = new TradingView.widget({
|
||||
|
||||
// Widget Options
|
||||
// https://www.tradingview.com/charting-library-docs/latest/api/interfaces/Charting_Library.ChartingLibraryWidgetOptions
|
||||
library_path: "/charting_library/",
|
||||
// debug: true,
|
||||
autosize: true,
|
||||
@@ -144,6 +144,13 @@ export function initWidget(el) {
|
||||
drawings_access: {type: 'white', tools: [],}, // show no tools
|
||||
custom_themes: tvCustomThemes,
|
||||
theme: useStore().theme,
|
||||
|
||||
// Chart Overrides
|
||||
// https://www.tradingview.com/charting-library-docs/latest/customization/overrides/chart-overrides
|
||||
overrides: {
|
||||
// "mainSeriesProperties.priceAxisProperties.log": false,
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// debug dump all events
|
||||
|
||||
@@ -240,7 +240,6 @@ function invertTicker(ticker) {
|
||||
}
|
||||
|
||||
export function lookupSymbol(ticker) { // lookup by ticker which is "0xbaseAddress/0xquoteAddress"
|
||||
// todo tim lookup default base/quote pool
|
||||
const symbols = getAllSymbols();
|
||||
if (!(ticker in symbols)) {
|
||||
// check the inverted symbol
|
||||
@@ -411,7 +410,7 @@ export const DataFeed = {
|
||||
|
||||
async getBars(symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) {
|
||||
const { from, to, firstDataRequest } = periodParams;
|
||||
log('[getBars]: Method call', symbolInfo, resolution, from, to);
|
||||
log('[getBars]: Method call', symbolInfo, resolution, new Date(from*1000), new Date(to*1000));
|
||||
try {
|
||||
// todo need to consider the selected fee tier
|
||||
await getAllSymbols()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {ohlcStart} from "@/charts/chart-misc.js";
|
||||
import {LRUCache} from "lru-cache";
|
||||
|
||||
|
||||
// support for Dexorder OHLC data files
|
||||
@@ -43,19 +44,36 @@ function singleFile(resName) {
|
||||
}
|
||||
|
||||
|
||||
function nextDay(timestamp) {
|
||||
function addDay(timestamp) {
|
||||
const date = new Date(timestamp*1000)
|
||||
return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + 1) / 1000
|
||||
}
|
||||
|
||||
function addMonth(timestamp) {
|
||||
const date = new Date(timestamp*1000)
|
||||
const result = Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()) / 1000
|
||||
console.log('addMonth', timestamp, result, new Date(timestamp*1000), new Date(result*1000))
|
||||
return result
|
||||
}
|
||||
|
||||
function addYear(timestamp) {
|
||||
const date = new Date(timestamp*1000)
|
||||
return Date.UTC(date.getUTCFullYear() + 1, date.getUTCMonth(), date.getUTCDate()) / 1000
|
||||
}
|
||||
|
||||
function nextDay(timestamp) {
|
||||
const date = new Date(timestamp*1000)
|
||||
return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + 1, 0, 0, 0) / 1000
|
||||
}
|
||||
|
||||
function nextMonth(timestamp) {
|
||||
const date = new Date(timestamp*1000)
|
||||
return Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()) / 1000
|
||||
return Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1, 0, 0, 0) / 1000
|
||||
}
|
||||
|
||||
function nextYear(timestamp) {
|
||||
const date = new Date(timestamp*1000)
|
||||
return Date.UTC(date.getUTCFullYear() + 1, date.getUTCMonth(), date.getUTCDate()) / 1000
|
||||
return Date.UTC(date.getUTCFullYear() + 1, 1, 1, 0, 0, 0) / 1000
|
||||
}
|
||||
|
||||
|
||||
@@ -66,21 +84,21 @@ function never(_timestamp) {
|
||||
|
||||
// noinspection PointlessArithmeticExpressionJS
|
||||
const resolutions = [
|
||||
{ seconds: 1 * 60, name: '1m', tvRes: '1', filename: dailyFile( '1m'), nextStart: nextDay, },
|
||||
{ seconds: 3 * 60, name: '3m', tvRes: '3', filename: dailyFile( '3m'), nextStart: nextDay, },
|
||||
{ seconds: 5 * 60, name: '5m', tvRes: '5', filename: dailyFile( '5m'), nextStart: nextDay, },
|
||||
{ seconds: 10 * 60, name: '10m', tvRes: '10', filename: dailyFile('10m'), nextStart: nextDay, },
|
||||
{ seconds: 15 * 60, name: '15m', tvRes: '15', filename: dailyFile('15m'), nextStart: nextDay, },
|
||||
{ seconds: 30 * 60, name: '30m', tvRes: '30', filename: dailyFile('30m'), nextStart: nextDay, },
|
||||
{ seconds: 60 * 60, name: '1H', tvRes: '60', filename: monthlyFile( '1H'), nextStart: nextMonth, },
|
||||
{ seconds: 120 * 60, name: '2H', tvRes: '120', filename: monthlyFile( '2H'), nextStart: nextMonth, },
|
||||
{ seconds: 240 * 60, name: '4H', tvRes: '240', filename: monthlyFile( '4H'), nextStart: nextMonth, },
|
||||
{ seconds: 480 * 60, name: '8H', tvRes: '480', filename: monthlyFile( '8H'), nextStart: nextMonth, },
|
||||
{ seconds: 720 * 60, name: '12H', tvRes: '720', filename: monthlyFile('12H'), nextStart: nextMonth, },
|
||||
{ seconds: 1440 * 60, name: '1D', tvRes: '1D', filename: yearlyFile( '1D'), nextStart: nextYear, },
|
||||
{ seconds: 2880 * 60, name: '2D', tvRes: '2D', filename: yearlyFile( '2D'), nextStart: nextYear, },
|
||||
{ seconds: 4320 * 60, name: '3D', tvRes: '3D', filename: yearlyFile( '3D'), nextStart: nextYear, },
|
||||
{ seconds: 10080 * 60, name: '1W', tvRes: '1W', filename: singleFile( '1W'), nextStart: never, },
|
||||
{ seconds: 1 * 60, name: '1m', tvRes: '1', filename: dailyFile( '1m'), add: addDay, nextStart: nextDay, },
|
||||
{ seconds: 3 * 60, name: '3m', tvRes: '3', filename: dailyFile( '3m'), add: addDay, nextStart: nextDay, },
|
||||
{ seconds: 5 * 60, name: '5m', tvRes: '5', filename: dailyFile( '5m'), add: addDay, nextStart: nextDay, },
|
||||
{ seconds: 10 * 60, name: '10m', tvRes: '10', filename: dailyFile('10m'), add: addDay, nextStart: nextDay, },
|
||||
{ seconds: 15 * 60, name: '15m', tvRes: '15', filename: dailyFile('15m'), add: addDay, nextStart: nextDay, },
|
||||
{ seconds: 30 * 60, name: '30m', tvRes: '30', filename: dailyFile('30m'), add: addDay, nextStart: nextDay, },
|
||||
{ seconds: 60 * 60, name: '1H', tvRes: '60', filename: monthlyFile( '1H'), add: addMonth, nextStart: nextMonth, },
|
||||
{ seconds: 120 * 60, name: '2H', tvRes: '120', filename: monthlyFile( '2H'), add: addMonth, nextStart: nextMonth, },
|
||||
{ seconds: 240 * 60, name: '4H', tvRes: '240', filename: monthlyFile( '4H'), add: addMonth, nextStart: nextMonth, },
|
||||
{ seconds: 480 * 60, name: '8H', tvRes: '480', filename: monthlyFile( '8H'), add: addMonth, nextStart: nextMonth, },
|
||||
{ seconds: 720 * 60, name: '12H', tvRes: '720', filename: monthlyFile('12H'), add: addMonth, nextStart: nextMonth, },
|
||||
{ seconds: 1440 * 60, name: '1D', tvRes: '1D', filename: yearlyFile( '1D'), add: addYear, nextStart: nextYear, },
|
||||
{ seconds: 2880 * 60, name: '2D', tvRes: '2D', filename: yearlyFile( '2D'), add: addYear, nextStart: nextYear, },
|
||||
{ seconds: 4320 * 60, name: '3D', tvRes: '3D', filename: yearlyFile( '3D'), add: addYear, nextStart: nextYear, },
|
||||
{ seconds: 10080 * 60, name: '1W', tvRes: '1W', filename: singleFile( '1W'), add: (x)=>x, nextStart: never, },
|
||||
]
|
||||
|
||||
const tvResMap = {}
|
||||
@@ -93,14 +111,21 @@ for (const res of resolutions)
|
||||
|
||||
|
||||
const seriesStarts = {}
|
||||
const ohlcCache = new LRUCache({max:20,ttl:3600*1000,})
|
||||
|
||||
|
||||
async function getUrl(url) {
|
||||
let result = ohlcCache[url]
|
||||
if (result)
|
||||
return result
|
||||
try {
|
||||
const response = await fetch(url)
|
||||
// console.log('got response', response)
|
||||
if (response.ok)
|
||||
return await response.text()
|
||||
if (response.ok) {
|
||||
result = await response.text()
|
||||
ohlcCache[url] = result
|
||||
return result
|
||||
}
|
||||
else
|
||||
console.error(`could not fetch ${url}: status ${response.statusText}`)
|
||||
}
|
||||
@@ -112,7 +137,7 @@ async function getUrl(url) {
|
||||
|
||||
|
||||
export async function loadOHLC (symbol, contract, from, to, tvRes) {
|
||||
// console.log('loadOHLC', tvRes, new Date(1000*from), new Date(1000*to), symbol, contract);
|
||||
console.log('loadOHLC', tvRes, new Date(1000*from), new Date(1000*to), symbol, contract);
|
||||
let chainId
|
||||
let bars = [];
|
||||
let inverted = false;
|
||||
@@ -123,8 +148,10 @@ export async function loadOHLC (symbol, contract, from, to, tvRes) {
|
||||
if (latest===null) return
|
||||
const [latestTime, price] = latest
|
||||
end = ohlcStart(end, period)
|
||||
const start = ohlcStart(latestTime+period, period);
|
||||
for (let now= start; now < end; now += period ) {
|
||||
const start = ohlcStart(latestTime+period, period)
|
||||
// if (start<end)
|
||||
// console.log('filling', latestTime, price, new Date(start*1000), new Date(end*1000))
|
||||
for (let now=start; now < end; now += period ) {
|
||||
bars.push({time:now * 1000, open:price, high:price, low:price, close:price})
|
||||
latest = [now, price]
|
||||
}
|
||||
@@ -144,14 +171,14 @@ export async function loadOHLC (symbol, contract, from, to, tvRes) {
|
||||
|
||||
const res = tvResMap[tvRes]
|
||||
const fetches = []
|
||||
let start = from
|
||||
if (!(baseUrl in seriesStarts)) {
|
||||
try {
|
||||
// console.log('getting quote', baseUrl+'quote.csv')
|
||||
const response = await getUrl(baseUrl+'quote.csv')
|
||||
if (response.length) {
|
||||
seriesStarts[baseUrl] = parseInt(response.split(',')[0])
|
||||
// console.log(`Series ${baseUrl} starts at ${new Date(start*1000)}`)
|
||||
const [start,end,price] = response.split(',')
|
||||
seriesStarts[baseUrl] = parseInt(start)
|
||||
console.log(`Series ${baseUrl} starts at ${new Date(start*1000)}`)
|
||||
}
|
||||
else {
|
||||
console.error(`Bad response while fetching ${baseUrl+'quote.csv'}`)
|
||||
@@ -161,85 +188,93 @@ export async function loadOHLC (symbol, contract, from, to, tvRes) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
let start = from
|
||||
if (baseUrl in seriesStarts)
|
||||
start = Math.max(start, seriesStarts[baseUrl])
|
||||
|
||||
for(let now = start; now < to; now = res.nextStart(now)) {
|
||||
const end = res.nextStart(to)
|
||||
for(let now = start; now < end; now = res.nextStart(now)) {
|
||||
const url = baseUrl + res.filename(contract, now);
|
||||
const prom = getUrl(url)
|
||||
fetches.push(prom);
|
||||
}
|
||||
|
||||
const responses = await Promise.all(fetches)
|
||||
for (const response of responses) {
|
||||
if (response.length) {
|
||||
let lineNum = 0
|
||||
response.split('\n').forEach((line) => {
|
||||
lineNum++
|
||||
const row = line.split(',')
|
||||
let time, open, high, low, close=null
|
||||
switch (row.length) {
|
||||
case 1:
|
||||
if (row[0].length !== 0)
|
||||
console.log(`Warning: weird nonempty row at OHLC line ${lineNum}: "${line}"`)
|
||||
let finished = false
|
||||
for( let ri=0; !finished && ri<responses.length; ri++ ) {
|
||||
let lineNum = 0
|
||||
const rows = responses[ri].split('\n')
|
||||
for( let rj=0; rj<rows.length; rj++) {
|
||||
const line = rows[rj];
|
||||
const row = line.split(',')
|
||||
let time, open, high, low, close=null
|
||||
switch (row.length) {
|
||||
case 1:
|
||||
if (row[0].length !== 0)
|
||||
console.log(`Warning: weird nonempty row at OHLC line ${lineNum}: "${line}"`)
|
||||
break
|
||||
case 2:
|
||||
time = parseInt(row[0])
|
||||
let price = parseFloat(row[1])
|
||||
if (inverted)
|
||||
price = 1/price
|
||||
open = latest === null ? price : latest[1]
|
||||
high = low = close = price
|
||||
break
|
||||
case 3:
|
||||
time = parseInt(row[0])
|
||||
if (time < from || time >= to)
|
||||
break
|
||||
case 2:
|
||||
time = parseInt(row[0])
|
||||
if (time < start || time >= to)
|
||||
break
|
||||
let price = parseFloat(row[1])
|
||||
if (inverted)
|
||||
price = 1/price
|
||||
open = latest === null ? price : latest[1]
|
||||
high = low = close = price
|
||||
break
|
||||
case 3:
|
||||
time = parseInt(row[0])
|
||||
if (time < start || time >= to)
|
||||
break
|
||||
open = parseFloat(row[1])
|
||||
close = parseFloat(row[2])
|
||||
if (inverted) {
|
||||
open = 1/open
|
||||
close = 1/close
|
||||
}
|
||||
high = Math.max(open, close)
|
||||
low = Math.min(open,close)
|
||||
if (latest!==null)
|
||||
open = latest[1]
|
||||
break
|
||||
case 5:
|
||||
time = parseInt(row[0])
|
||||
if (time < start || time >= to)
|
||||
break
|
||||
open = parseFloat(row[1])
|
||||
high = parseFloat(row[2])
|
||||
low = parseFloat(row[3])
|
||||
close = parseFloat(row[4])
|
||||
if (inverted) {
|
||||
open = 1/open
|
||||
const h = high
|
||||
high = 1/low
|
||||
low = 1/h
|
||||
close = 1/close
|
||||
}
|
||||
break
|
||||
default:
|
||||
console.log(`Warning: could not parse line ${lineNum} of OHLC file:\n${line}`)
|
||||
open = parseFloat(row[1])
|
||||
close = parseFloat(row[2])
|
||||
if (inverted) {
|
||||
open = 1/open
|
||||
close = 1/close
|
||||
}
|
||||
high = Math.max(open, close)
|
||||
low = Math.min(open,close)
|
||||
if (latest!==null)
|
||||
open = latest[1]
|
||||
break
|
||||
case 5:
|
||||
time = parseInt(row[0])
|
||||
if (time < from || time >= to)
|
||||
break
|
||||
open = parseFloat(row[1])
|
||||
high = parseFloat(row[2])
|
||||
low = parseFloat(row[3])
|
||||
close = parseFloat(row[4])
|
||||
if (inverted) {
|
||||
open = 1/open
|
||||
const h = high
|
||||
high = 1/low
|
||||
low = 1/h
|
||||
close = 1/close
|
||||
}
|
||||
break
|
||||
default:
|
||||
console.log(`Warning: could not parse line ${lineNum} of OHLC file:\n${line}`)
|
||||
break
|
||||
}
|
||||
if (time!==null) {
|
||||
if (time >= to) {
|
||||
console.log('time is past end of request:', time)
|
||||
finished = true
|
||||
break
|
||||
}
|
||||
if (close!==null) {
|
||||
if (time >= from) {
|
||||
fill(time, res.seconds)
|
||||
const bar = {time:time*1000, open, high, low, close};
|
||||
const bar = {time: time * 1000, open, high, low, close};
|
||||
bars.push(bar)
|
||||
latest = [time, close]
|
||||
}
|
||||
})
|
||||
// console.log(`processed ${lineNum} lines`)
|
||||
}
|
||||
}
|
||||
// else { console.log('response was empty') }
|
||||
console.log(`processed ${lineNum} lines`)
|
||||
}
|
||||
// console.log('loadOHLC prefill bars', bars)
|
||||
fill(to, res.seconds)
|
||||
// console.log('loadOHLC bars', bars)
|
||||
return bars
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {DISTANT_FUTURE, DISTANT_PAST} from "@/blockchain/orderlib.js";
|
||||
import {DISTANT_FUTURE, DISTANT_PAST, MAX_FRACTION} from "@/blockchain/orderlib.js";
|
||||
import {allocationText, DLine, HLine} from "@/charts/shape.js";
|
||||
import {createShape, deleteShapeId} from "@/charts/chart.js";
|
||||
import {timestamp} from "@/misc.js";
|
||||
import {sideColor, timestamp} from "@/misc.js";
|
||||
import {useChartOrderStore} from "@/orderbuild.js";
|
||||
|
||||
export class OrderShapes {
|
||||
@@ -16,9 +16,11 @@ export class OrderShapes {
|
||||
for (const old of this.trancheShapes)
|
||||
old.delete()
|
||||
this.status = orderStatus
|
||||
this.trancheShapes = [];
|
||||
for (let i = 0; i < orderStatus.trancheStatus.length; i++)
|
||||
this.trancheShapes.push(new TrancheShapes(this.symbol, this.status, i));
|
||||
this.trancheShapes = []
|
||||
const maxAllocation = Math.max(...orderStatus.order.tranches.map((ts)=>ts.fraction)) / MAX_FRACTION
|
||||
if (orderStatus.trancheStatus !== undefined)
|
||||
for (let i = 0; i < orderStatus.trancheStatus.length; i++)
|
||||
this.trancheShapes.push(new TrancheShapes(this.symbol, this.status, i, maxAllocation));
|
||||
}
|
||||
|
||||
show() {for (const t of this.trancheShapes) t.show();}
|
||||
@@ -28,8 +30,7 @@ export class OrderShapes {
|
||||
|
||||
|
||||
class TrancheShapes {
|
||||
constructor(symbol, orderStatus, trancheIndex) {
|
||||
// todo validate base/quote
|
||||
constructor(symbol, orderStatus, trancheIndex, maxAllocation) {
|
||||
if (symbol.inverted !== orderStatus.order.inverted) {
|
||||
console.log('OrderShapes.createLine(): symbol has wrong inverson for this order')
|
||||
return
|
||||
@@ -38,14 +39,16 @@ class TrancheShapes {
|
||||
this.status = orderStatus
|
||||
this.trancheIndex = trancheIndex
|
||||
this.tranche = orderStatus.order.tranches[trancheIndex]
|
||||
this.trancheStatus = orderStatus.trancheStatus[trancheIndex]
|
||||
this.shapes = []
|
||||
this.fills = []
|
||||
this.createShapes();
|
||||
this.maxAllocation = maxAllocation
|
||||
this.createShapes()
|
||||
}
|
||||
|
||||
createShapes() {
|
||||
// todo amounts
|
||||
const t = this.tranche
|
||||
|
||||
// console.log('create tranche shapes', t)
|
||||
if (t.marketOrder) {
|
||||
if (t.startTime !== DISTANT_PAST) {
|
||||
@@ -53,8 +56,10 @@ class TrancheShapes {
|
||||
}
|
||||
} else {
|
||||
// check lines
|
||||
this.createLine(t.minLine.slope, t.minLine.intercept);
|
||||
this.createLine(t.maxLine.slope, t.maxLine.intercept);
|
||||
const amount = this.status.order.amount * BigInt(t.fraction) / BigInt(MAX_FRACTION)
|
||||
const buy = this.status.order.tokenIn === this.symbol.quote.a
|
||||
this.createLine(t.minLine.slope, t.minLine.intercept, amount, buy);
|
||||
this.createLine(t.maxLine.slope, t.maxLine.intercept, amount, !buy);
|
||||
}
|
||||
for (const f of this.status.trancheStatus[this.trancheIndex].fills)
|
||||
this.createFillPoint(f)
|
||||
@@ -72,67 +77,78 @@ class TrancheShapes {
|
||||
* 10 ** -(amountIsBase ? this.symbol.base.d : this.symbol.quote.d)
|
||||
const weight = Number(filledAmount) / Number(this.status.order.amount)
|
||||
const amountSymbol = amountIsBase ? this.symbol.base.s : this.symbol.quote.s
|
||||
console.log('fillpoint', buy, filledAmount, this.status.order, this.symbol)
|
||||
// console.log('fillpoint', buy, filledAmount, this.status.order, this.symbol)
|
||||
const time = f.time
|
||||
const out = Number(f.filledOut) / (1-this.status.order.route.fee/1000000)
|
||||
let price = out / Number(f.filledIn)
|
||||
if (buy)
|
||||
price = 1/price
|
||||
price *= scale
|
||||
console.log('price', price)
|
||||
// console.log('price', price)
|
||||
const channel = buy?'low':'high';
|
||||
const text = (buy ? 'Buy ' : 'Sell ') + allocationText(weight, amount, amountSymbol, '\n')
|
||||
const s = createShape(buy?'arrow_up':'arrow_down', {time, price}, {channel,text,lock:true})
|
||||
console.log('created fill shape at', time, price)
|
||||
// console.log('created fill shape at', time, price)
|
||||
this.fills.push(s)
|
||||
}
|
||||
|
||||
createLine(slope, intercept, amount) {
|
||||
createLine(slope, intercept, amountBigInt, breakout) {
|
||||
if (intercept === 0 && slope === 0) return
|
||||
const t = this.tranche
|
||||
const status = this.status
|
||||
const symbol = this.symbol
|
||||
const scale = 10**symbol.decimals;
|
||||
const buy = status.order.tokenIn === this.symbol.quote.a
|
||||
amount = Number(amount)
|
||||
* 10 ** -(buy ? this.symbol.base.d : this.symbol.quote.d)
|
||||
const decimals = buy ? this.symbol.base.d : this.symbol.quote.d;
|
||||
amountBigInt = BigInt(amountBigInt)
|
||||
const amount = Number(amountBigInt) * 10 ** - decimals
|
||||
const amountSymbol = buy ? this.symbol.base.s : this.symbol.quote.s
|
||||
const color = buy ? 'green' : 'red'
|
||||
if (intercept !== 0 || slope !== 0) {
|
||||
// console.log('tranche line', intercept, slope)
|
||||
// line active
|
||||
if (slope === 0) {
|
||||
let price = intercept
|
||||
price *= scale
|
||||
// horizontal line
|
||||
// console.log('hline', price)
|
||||
const model = {price, color, maxAllocation: status.order.amount, amount, amountSymbol};
|
||||
const s = new HLine(model, null, null, null, true)
|
||||
this.shapes.push(s)
|
||||
} else {
|
||||
// diagonal line
|
||||
let startTime = t.startTime
|
||||
if (startTime === DISTANT_PAST)
|
||||
startTime = timestamp() - useChartOrderStore().intervalSecs * 20 // 20 bars ago
|
||||
let endTime = t.endTime
|
||||
if (endTime === DISTANT_FUTURE)
|
||||
endTime = timestamp() // use "now" as the drawing point's time
|
||||
let startPrice = (intercept + slope * startTime);
|
||||
let endPrice = (intercept + slope * endTime);
|
||||
startPrice *= scale
|
||||
endPrice *= scale
|
||||
// console.log('dline', startTime, endTime, DISTANT_FUTURE, startPrice, endPrice)
|
||||
// noinspection EqualityComparisonWithCoercionJS
|
||||
const model = {
|
||||
pointA: {time: startTime, price: startPrice},
|
||||
pointB: {time: endTime, price: endPrice},
|
||||
extendLeft: t.startTime === DISTANT_PAST,
|
||||
extendRight: t.endTime === DISTANT_FUTURE,
|
||||
color,
|
||||
maxAllocation: status.order.amount, amount, amountSymbol,
|
||||
};
|
||||
const s = new DLine(model, null, null, null, true)
|
||||
this.shapes.push(s)
|
||||
const color = sideColor(buy)
|
||||
const maxAllocation = this.maxAllocation
|
||||
const allocation = t.fraction / MAX_FRACTION
|
||||
const ts = this.trancheStatus
|
||||
let sum = 0n
|
||||
for (let i=0; i<ts.fills.length; i++)
|
||||
sum += ts.fills[i].filled
|
||||
const completed = (amountBigInt - sum) < status.order.minFillAmount
|
||||
const extraText = completed ? '✓' : null
|
||||
const textLocation = breakout === buy ? 'above' : 'below'
|
||||
// line active
|
||||
if (slope === 0) {
|
||||
let price = intercept
|
||||
price *= scale
|
||||
// horizontal line
|
||||
// console.log('hline', price)
|
||||
const model = {
|
||||
price, breakout, color, extraText, textLocation,
|
||||
allocation, maxAllocation, amount, amountSymbol,
|
||||
}
|
||||
const s = new HLine(model, null, null, null, true)
|
||||
this.shapes.push(s)
|
||||
} else {
|
||||
// diagonal line
|
||||
let startTime = t.startTime
|
||||
if (startTime === DISTANT_PAST)
|
||||
startTime = timestamp() - useChartOrderStore().intervalSecs * 20 // 20 bars ago
|
||||
let endTime = t.endTime
|
||||
if (endTime === DISTANT_FUTURE)
|
||||
endTime = timestamp() // use "now" as the drawing point's time
|
||||
let startPrice = (intercept + slope * startTime);
|
||||
let endPrice = (intercept + slope * endTime);
|
||||
startPrice *= scale
|
||||
endPrice *= scale
|
||||
// console.log('dline', startTime, endTime, DISTANT_FUTURE, startPrice, endPrice)
|
||||
// noinspection EqualityComparisonWithCoercionJS
|
||||
const model = {
|
||||
pointA: {time: startTime, price: startPrice},
|
||||
pointB: {time: endTime, price: endPrice},
|
||||
extendLeft: t.startTime === DISTANT_PAST,
|
||||
extendRight: t.endTime === DISTANT_FUTURE,
|
||||
breakout, color, extraText, textLocation,
|
||||
allocation, maxAllocation, amount, amountSymbol,
|
||||
}
|
||||
const s = new DLine(model, null, null, null, true)
|
||||
this.shapes.push(s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import {invokeCallback, mixin} from "@/common.js";
|
||||
import {chart, createShape, deleteShapeId, dragging, draggingShapeIds, drawShape, widget} from "@/charts/chart.js";
|
||||
import Color from "color";
|
||||
import {dirtyItems, dirtyPoints, nearestOhlcStart} from "@/charts/chart-misc.js";
|
||||
import {computeInterceptSlope} from "@/misc.js";
|
||||
import {defined} from "@/misc.js";
|
||||
|
||||
|
||||
//
|
||||
@@ -40,6 +40,7 @@ export const ShapeType = {
|
||||
|
||||
|
||||
export function allocationText(weight, amount, symbol, separator = ' ') {
|
||||
// set breakout=true for a buy breakout and breakout=false for a sell breakout
|
||||
const hasAmount = amount !== null && amount !== undefined && amount > 0
|
||||
if (hasAmount)
|
||||
amount = Number(amount)
|
||||
@@ -109,7 +110,7 @@ export class Shape {
|
||||
this.model.amount = null
|
||||
this.model.amountSymbol = null
|
||||
this.model.extraText = null
|
||||
this.model.textLocation = 'above'
|
||||
this.model.textLocation = null // defaults to 'above' if not set
|
||||
|
||||
// LEAF SUBCLASSES MUST CALL setModel(model) AFTER ALL CONSTRUCTION.
|
||||
}
|
||||
@@ -119,19 +120,21 @@ export class Shape {
|
||||
//
|
||||
|
||||
setModel(model) {
|
||||
if (model.color)
|
||||
if (defined(model.color))
|
||||
this.model.color = model.color
|
||||
if (model.allocation !== null && model.allocation !== undefined)
|
||||
if (defined(model.allocation))
|
||||
this.model.allocation = model.allocation
|
||||
if (model.maxAllocation !== null && model.maxAllocation !== undefined)
|
||||
if (defined(model.maxAllocation))
|
||||
this.model.maxAllocation = model.maxAllocation
|
||||
if (model.amount !== null && model.amount !== undefined)
|
||||
if (defined(model.amount))
|
||||
this.model.amount = model.amount
|
||||
if (model.amountSymbol)
|
||||
if (defined(model.amountSymbol))
|
||||
this.model.amountSymbol = model.amountSymbol
|
||||
if (model.extraText)
|
||||
if (defined(model.extraText))
|
||||
this.model.extraText = model.extraText
|
||||
if (model.textLocation)
|
||||
if (defined(model.breakout))
|
||||
this.model.breakout = model.breakout
|
||||
if (defined(model.textLocation))
|
||||
this.model.textLocation = model.textLocation
|
||||
|
||||
const newProps = {}
|
||||
@@ -141,7 +144,7 @@ export class Shape {
|
||||
newProps.textcolor = color
|
||||
|
||||
// line color
|
||||
if (this.model.allocation && this.model.maxAllocation) {
|
||||
if (defined(this.model.allocation) && defined(this.model.maxAllocation)) {
|
||||
const w = this.model.allocation / this.model.maxAllocation
|
||||
if (!w)
|
||||
newProps.linecolor = 'rgba(0,0,0,0)'
|
||||
@@ -158,6 +161,8 @@ export class Shape {
|
||||
|
||||
// text label
|
||||
let text = allocationText(this.model.allocation, this.model.amount, this.model.amountSymbol)
|
||||
if (this.model.breakout)
|
||||
text += ' ' + (this.model.textLocation==='above' ? '▲Breakout▲' : '▼Breakout▼')
|
||||
if (this.model.extraText)
|
||||
text += ' '+this.model.extraText
|
||||
if (this.debug) text = `${this.id} ` + text
|
||||
@@ -199,10 +204,13 @@ export class Shape {
|
||||
const p = this.type.drawingProp
|
||||
const lc = this.model.lineColor ? this.model.lineColor : this.model.color;
|
||||
const tc = this.model.textColor ? this.model.textColor : this.model.color;
|
||||
const tl = this.model.textLocation ? this.model.textLocation : 'above';
|
||||
if (lc)
|
||||
o[p+".linecolor"] = lc
|
||||
if (tc)
|
||||
o[p+".textcolor"] = tc
|
||||
if (tl)
|
||||
o[p+".textlocation"] = tl
|
||||
return o
|
||||
}
|
||||
|
||||
|
||||
@@ -133,3 +133,11 @@ export function abiPath(name) {
|
||||
}
|
||||
|
||||
|
||||
export function parseFill(obj) {
|
||||
let [tx, time, filledIn, filledOut, fee] = obj
|
||||
time = new Date(time * 1000)
|
||||
filledIn = BigInt(filledIn)
|
||||
filledOut = BigInt(filledOut)
|
||||
fee = BigInt(fee)
|
||||
return {tx, time, filledIn, filledOut, fee}
|
||||
}
|
||||
|
||||
38
src/components/ApproveRegion.vue
Normal file
38
src/components/ApproveRegion.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<slot v-if="s.regionApproved"/>
|
||||
<v-card v-if="s.regionApproved===null" title="Loading..." prepend-icon="mdi-clock-outline"
|
||||
text="If loading takes more than a second, please refresh your browser or contact support@dexorder.trade"/>
|
||||
<v-card v-if="s.regionApproved===false" title="Restricted" prepend-icon="mdi-alert"
|
||||
text="Dexorder is not available in your region."/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import {socket} from "@/socket.js";
|
||||
import {useRoute} from "vue-router";
|
||||
|
||||
const s = useStore()
|
||||
|
||||
let timer = null
|
||||
|
||||
const bypass = useRoute().query.approval
|
||||
|
||||
function tryApproval() {
|
||||
console.log('approval query', bypass)
|
||||
if (timer!==null) {
|
||||
clearTimeout(timer)
|
||||
timer = null
|
||||
}
|
||||
if (s.regionApproved===null) {
|
||||
socket.emit('approveRegion', bypass)
|
||||
timer = setTimeout(tryApproval, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
tryApproval()
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -1,35 +0,0 @@
|
||||
<template>
|
||||
<slot v-if="s.allowed"/>
|
||||
<v-card v-if="!s.allowed" rounded="0" title="Dexorder Closed Beta">
|
||||
<v-card-item><v-text-field v-model="password" label="Beta Password" class="maxw"/></v-card-item>
|
||||
<v-card-text>
|
||||
Follow our social media for public release updates!
|
||||
</v-card-text>
|
||||
<v-card-item><social/></v-card-item>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import Social from "@/components/Social.vue";
|
||||
import {ref, watchEffect} from "vue";
|
||||
import {hashMessage} from "ethers";
|
||||
|
||||
const s = useStore()
|
||||
|
||||
const password = ref(null)
|
||||
const passHash = '0x3e6e96bd824dd0a5e5361853719ef051e939b91f3fc6fd0f685b4c414c7ba89e'
|
||||
|
||||
watchEffect(()=>{
|
||||
if (!password.value) return
|
||||
const canonical = password.value.replace(/[^a-zA-Z]/g, '').toLowerCase();
|
||||
const hash = hashMessage(canonical);
|
||||
if (hash===passHash)
|
||||
s.allowed = true
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
<script setup>
|
||||
import {useOrderStore, useStore} from "@/store/store";
|
||||
import {routeInverted} from "@/misc.js";
|
||||
import RoutePrice from "@/components/RoutePrice.vue";
|
||||
import {validateAmount, validateRequired} from "@/validate.js";
|
||||
import {computed} from "vue";
|
||||
// noinspection ES6UnusedImports
|
||||
import {vAutoSelect} from "@/misc.js";
|
||||
import {routeInverted} from "@/misc.js";
|
||||
|
||||
const os = useOrderStore()
|
||||
const props = defineProps({
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
<script setup>
|
||||
|
||||
import PairPrice from "@/components/PairPrice.vue";
|
||||
import {computed} from "vue";
|
||||
import {computed, defineAsyncComponent} from "vue";
|
||||
import {useStore} from "@/store/store.js";
|
||||
const PairPrice = defineAsyncComponent(()=>import("@/components/PairPrice.vue"))
|
||||
|
||||
const props = defineProps(['base', 'quote', 'm', 'b', 'isBreakout', 'showBtn', 'buy'])
|
||||
const s = useStore()
|
||||
|
||||
@@ -26,9 +26,8 @@
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import {computed, ref} from "vue";
|
||||
import {vaultContract} from "@/blockchain/contract.js"
|
||||
import {pendTransaction} from "@/blockchain/wallet.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {WrapTransaction} from "@/blockchain/transaction.js";
|
||||
|
||||
const s = useStore()
|
||||
const props = defineProps(['modelValue', 'vault', 'maxAmount'])
|
||||
@@ -45,10 +44,7 @@ function wrapNative() {
|
||||
if( amount === 0n )
|
||||
return
|
||||
console.log('pending wrap', valueStr, amount)
|
||||
pendTransaction(async (signer)=>{
|
||||
const vault = await vaultContract(vaultAddr, signer)
|
||||
return await vault.wrap(amount)
|
||||
})
|
||||
new WrapTransaction(s.chainId, vaultAddr, amount).submit()
|
||||
floatAmount.value = 0
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<beta-signin>
|
||||
<approve-region>
|
||||
<slot v-if="status===Status.OK" v-bind="$props"/>
|
||||
<v-card v-if="status!==Status.OK" rounded="0">
|
||||
<v-card-title>
|
||||
@@ -33,7 +33,8 @@
|
||||
</v-card-actions>
|
||||
|
||||
</v-card>
|
||||
</beta-signin>
|
||||
<terms-of-service v-if="status===Status.OK"/>
|
||||
</approve-region>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -42,7 +43,8 @@ import {computed, ref} from "vue";
|
||||
import {addNetwork, connectWallet, switchChain} from "@/blockchain/wallet.js";
|
||||
import Btn from "@/components/Btn.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import BetaSignin from "@/components/BetaSignin.vue";
|
||||
import ApproveRegion from "@/components/ApproveRegion.vue";
|
||||
import TermsOfService from "@/components/TermsOfService.vue";
|
||||
|
||||
const s = useStore()
|
||||
const disabled = ref(false)
|
||||
|
||||
@@ -23,11 +23,9 @@ import {useOrderStore, useStore} from "@/store/store";
|
||||
import PhoneCard from "@/components/PhoneCard.vue";
|
||||
import Amount from "@/components/Amount.vue"
|
||||
// noinspection ES6UnusedImports
|
||||
import {nav, routeInverted, SingletonCoroutine, vAutoSelect} from "@/misc.js";
|
||||
import {nav, SingletonCoroutine, vAutoSelect} from "@/misc.js";
|
||||
import {newOrder} from "@/blockchain/orderlib.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {pendOrder} from "@/blockchain/wallet.js";
|
||||
import router from "@/router/index.js";
|
||||
import PairChoice from "@/components/PairChoice.vue";
|
||||
import NeedsSigner from "@/components/NeedsSigner.vue";
|
||||
import {useChartOrderStore} from "@/orderbuild.js";
|
||||
|
||||
@@ -33,10 +33,9 @@
|
||||
import TokenChoice from "@/components/TokenChoice.vue"
|
||||
import {useOrderStore, useStore} from "@/store/store";
|
||||
import RoutePrice from "@/components/RoutePrice.vue";
|
||||
import {findRoute, routeFinder} from "@/blockchain/route.js";
|
||||
import {SingletonCoroutine, routeInverted} from "@/misc.js";
|
||||
import {computed, ref} from "vue";
|
||||
import {queryHelperContract} from "@/blockchain/contract.js";
|
||||
import {routeFinder} from "@/blockchain/route.js";
|
||||
import {computed} from "vue";
|
||||
import {routeInverted} from "@/misc.js";
|
||||
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
|
||||
@@ -18,7 +18,6 @@ import {flipInversionPreference, inversionPreference} from "@/misc.js";
|
||||
const props = defineProps(['value', 'base', 'quote', 'showBtn'])
|
||||
|
||||
const s = useStore()
|
||||
const prefs = usePrefStore()
|
||||
|
||||
async function token(obj) {
|
||||
if (!obj) return null
|
||||
|
||||
@@ -7,8 +7,8 @@ import {useOrderStore, useStore} from "@/store/store";
|
||||
import {subPrices, unsubPrices, WIDE_PRICE_FORMAT} from "@/blockchain/prices.js";
|
||||
import {computed, onBeforeUnmount} from "vue";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {routeInverted} from "@/misc.js";
|
||||
import {subOHLCs} from "@/blockchain/ohlcs.js";
|
||||
import {routeInverted} from "@/misc.js";
|
||||
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
|
||||
@@ -142,5 +142,6 @@ body {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
min-height: 5em;
|
||||
max-height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -71,10 +71,12 @@
|
||||
</suspense>
|
||||
</template>
|
||||
<template v-slot:item.state="{ item }">
|
||||
<!--
|
||||
<v-chip v-if="item.state===PendingOrderState.Submitted || item.state===PendingOrderState.Signing"
|
||||
prepend-icon="mdi-signature">Wallet Signing</v-chip>
|
||||
<v-chip v-if="item.state===PendingOrderState.Rejected" prepend-icon="mdi-cancel">Rejected</v-chip>
|
||||
<v-chip v-if="item.state===PendingOrderState.Sent" prepend-icon="mdi-send">Sent</v-chip>
|
||||
-->
|
||||
<v-chip v-if="item.state===OrderState.Open" class="d-none d-lg-inline-flex" prepend-icon="mdi-dots-horizontal"
|
||||
color="green">Open
|
||||
</v-chip>
|
||||
@@ -176,8 +178,7 @@ import LinePrice from "@/components/LinePrice.vue";
|
||||
import {useStore} from "@/store/store";
|
||||
import {computed, defineAsyncComponent, onUnmounted, ref, watch} from "vue";
|
||||
import Btn from "@/components/Btn.vue"
|
||||
import {cancelOrder, PendingOrderState, useWalletStore} from "@/blockchain/wallet.js";
|
||||
import {timestampString} from "@/misc.js";
|
||||
import {cancelOrder, useWalletStore} from "@/blockchain/wallet.js";
|
||||
import {DISTANT_FUTURE, isOpen, OrderState} from "@/blockchain/orderlib.js";
|
||||
import Pulse from "@/components/Pulse.vue";
|
||||
import {OrderShapes} from "@/charts/ordershapes.js";
|
||||
@@ -185,6 +186,7 @@ import {useChartOrderStore} from "@/orderbuild.js";
|
||||
import {lookupSymbol, tickerForOrder} from "@/charts/datafeed.js";
|
||||
import {setSymbol} from "@/charts/chart.js";
|
||||
import {uniswapV3AveragePrice} from "@/blockchain/uniswap.js";
|
||||
import {timestampString} from "@/misc.js";
|
||||
|
||||
const PairPrice = defineAsyncComponent(()=>import("@/components/PairPrice.vue"))
|
||||
const TokenAmount = defineAsyncComponent(()=>import('./TokenAmount.vue'))
|
||||
@@ -214,9 +216,7 @@ watch(selected, async ()=>{
|
||||
// switch symbol
|
||||
deleteOrderShapes()
|
||||
await setSymbol(symbol)
|
||||
console.log('change symbol completed')
|
||||
}
|
||||
console.log('creating order shape', id)
|
||||
orderShapes[id] = new OrderShapes(symbol, status)
|
||||
}
|
||||
}
|
||||
@@ -228,14 +228,12 @@ function deleteOrderShapes(keepSet={}) {
|
||||
const keys = [...Object.keys(orderShapes)]
|
||||
for (const id of keys) {
|
||||
if (!(id in keepSet)) {
|
||||
console.log('deleting order shape', id)
|
||||
orderShapes[id].delete()
|
||||
delete orderShapes[id]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const orderShapes = {}
|
||||
|
||||
onUnmounted(()=>{
|
||||
|
||||
700
src/components/TermsOfService.vue
Normal file
700
src/components/TermsOfService.vue
Normal file
@@ -0,0 +1,700 @@
|
||||
<template>
|
||||
<v-dialog v-model="show" max-width="500px" persistent>
|
||||
<v-card>
|
||||
<v-card-title class="text-center">Dexorder Terms of Service</v-card-title>
|
||||
<v-card-text class="text-center">Last Updated November 18, 2024</v-card-text>
|
||||
|
||||
<v-card-text>
|
||||
Please read these Terms of Service (the “<b>Terms</b>”) and our Privacy Policy carefully because they govern your use of the
|
||||
website (and all subdomains and subpages thereon) located at dexorder.trade, including without limitation the
|
||||
subdomains app.dexorder.trade and www.dexorder.trade (collectively, the “<b>Site</b>”), and the Dexorder web
|
||||
application graphical user interface and any other services accessible via the Site (together with the Site, web
|
||||
application, and other services, collectively, the “<b>Dexorder Service</b>”) offered by Dexorder Trading Services Ltd.
|
||||
(“<b>Dexorder</b>,” “<b>we</b>,” “<b>our</b>,” or “<b>us</b>”).
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text>
|
||||
<b>
|
||||
BY USING THE DEXORDER SERVICE, YOU REPRESENT THAT (I) YOU ARE NOT LOCATED WITHIN THE UNITED
|
||||
STATES; AND (II) YOU ARE NOT A PERSON OR ENTITY WHO IS RESIDENT IN, A CITIZEN OF, IS LOCATED IN, IS
|
||||
INCORPORATED IN, OR HAS A REGISTERED OFFICE IN ANY RESTRICTED TERRITORY, AS DEFINED BELOW (ANY
|
||||
SUCH PERSON OR ENTITY FROM WITHIN THE UNITED STATES OR A RESTRICTED TERRITORY, IS REFERRED TO
|
||||
HEREIN AS A “RESTRICTED PERSON”).
|
||||
</b>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text>
|
||||
WHEN YOU AGREE TO THESE TERMS, YOU ARE AGREEING (WITH LIMITED EXCEPTION) TO RESOLVE ANY DISPUTE
|
||||
BETWEEN YOU AND DEXORDER THROUGH BINDING, INDIVIDUAL ARBITRATION RATHER THAN IN COURT. PLEASE
|
||||
REVIEW CAREFULLY SECTION 16 (DISPUTE RESOLUTION) BELOW FOR DETAILS REGARDING ARBITRATION. HOWEVER, IF
|
||||
YOU ARE A RESIDENT OF A JURISDICTION WHERE APPLICABLE LAW PROHIBITS ARBITRATION OF DISPUTES, THE
|
||||
AGREEMENT TO ARBITRATE IN SECTION 16 WILL NOT APPLY TO YOU, BUT THE PROVISIONS OF SECTION 15
|
||||
(GOVERNING LAW) WILL APPLY INSTEAD.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>1. Description of Dexorder Service</v-card-title>
|
||||
<v-card-text>
|
||||
(a) The Dexorder Service allows you to access an online web application graphical user
|
||||
interface (the “<b>App</b>”) which enables you to interact with a protocol consisting of a set of smart contracts (the
|
||||
“<b>Smart Contracts</b>”) and to create and interact with a user controlled smart contract involving digital assets over
|
||||
which only you have upgrade authority (a “<b>Vault</b>” and together with the Smart Contracts, the “<b>Protocol</b>”). You
|
||||
may use your Vault to send signals to, interact with, and initiate actions on third party smart contract blockchain
|
||||
protocols (“<b>Interactions</b>”) operating on decentralized exchanges (e.g., Uniswap) (“<b>DEXs</b>”). Certain Interactions
|
||||
may require threshold parameters to be met and that a third party transmit an oracle related activation signal
|
||||
(the “<b>Activation Signal</b>”) to the Vault in order to effectuate your commands (such party being an “<b>Oracle</b>”).
|
||||
Dexorder may in the ordinary course of events be an Oracle (“<b>Dexorder Oracle</b>”), but bears no obligation nor
|
||||
promise to do so on an ongoing basis, and you may send such Activation Signal yourself or utilize a third-party
|
||||
Oracle to do so. Further, Dexorder is not and does not offer a digital wallet, and has no custody or control over
|
||||
your digital wallet, which is never accessible by Dexorder, and only users, and not Dexorder, may provide or
|
||||
withdraw tokens to be held by Vault. From time to time, the Services may include making recommendations
|
||||
with respect to technical changes that only you may accept and implement.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text>
|
||||
(b) <b>Interface</b>. The Dexorder Service provides you with access to the Protocol, which is a user
|
||||
controlled, non-custodial protocol, upgradeable only by your actions and consent, deployed on the blockchains
|
||||
indicated on our Site, and provides information and interaction capabilities with other blockchain related service
|
||||
providers. All information provided in connection with your access and use of the Dexorder Service is for
|
||||
informational purposes only. You should not take, or refrain from taking, any action based on any information
|
||||
contained on the Dexorder Service or any other information that we make available at any time, including blog
|
||||
posts, data, articles, links to third-party content, Discord content, news feeds, tutorials, tweets, and videos.
|
||||
Before you make any financial, legal, technical, or other decisions involving the Dexorder Service, you should
|
||||
seek independent professional advice from a licensed and qualified individual in the area for which such advice
|
||||
would be appropriate. Because the Dexorder Service provides information about the Protocol, these Terms also
|
||||
provide some information about the use of the Protocol. This information is not intended to be comprehensive
|
||||
or address all aspects of the Protocol.
|
||||
</v-card-text>
|
||||
|
||||
|
||||
<v-card-text>
|
||||
(c) <b>Our Relationship</b>. You acknowledge and agree that Dexorder is an online platform
|
||||
provider and not a financial institution, broker dealer, exchange or money services business. Dexorder does not
|
||||
direct or control the day-to-day activities of users accessing the Dexorder Service. Neither we nor any affiliated
|
||||
entity is a party to any transaction on the blockchain network underlying the Protocol; we do not have
|
||||
possession, custody or control over any cryptoassets appearing on the Dexorder Service or on the Protocol; and
|
||||
we do not have possession, custody, or control over any user’s funds or cryptoassets. Further, we do not store,
|
||||
send, or receive any funds or cryptoassets on your behalf. You understand that when you interact with any
|
||||
Protocol smart contracts, you retain control over your cryptoassets at all times. You are solely responsible for
|
||||
evaluating any proposed technical changes and how such changes may alter current or future Interactions.
|
||||
Furthermore, you understand and acknowledge that only you have absolute and ultimate authority over the
|
||||
implementation of any such changes and the responsibility therefor. The private key associated with your Vault
|
||||
is the only private key that can control the cryptoassets in the Vault. You alone are responsible for securing your
|
||||
private keys. We do not have access to your private keys. Because the Protocol is non-custodial, we are not
|
||||
intermediaries, agents, advisors, or custodians, and we do not have a fiduciary relationship or obligation to you
|
||||
regarding any other decisions or activities that you affect when using the Dexorder Service or interacting with
|
||||
the Protocol. You acknowledge that we, for the avoidance of doubt, do not have any information regarding any
|
||||
users, users’ identities, or services beyond what is available, obtainable publicly via the blockchain, or shared by
|
||||
you when you access the Dexorder Service. We are not responsible for any activities you engage in when using
|
||||
the Dexorder Service, and you should understand the risks associated with cryptoassets, blockchain technology
|
||||
generally, and the Interface.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>
|
||||
2. Agreement to Terms
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
By using our Dexorder Service, you agree to be bound by these Terms. If you don’t agree to be bound by these Terms,
|
||||
do not use the Dexorder Service.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>3. Changes to these Terms or the Dexorder Service</v-card-title>
|
||||
<v-card-text>
|
||||
We may update the Terms, including any addendum terms, from time to time in our sole discretion. If we do, we’ll let
|
||||
you know by posting the updated Terms on the Site and/or may also send other communications. It’s important that
|
||||
you review the Terms whenever we update them or you use the Dexorder Service. If you continue to use the Dexorder
|
||||
Service after we have posted updated Terms it means that you accept and agree to the changes. If you don’t agree to
|
||||
be bound by the changes, you may not use the Dexorder Service anymore. Because our Dexorder Service is evolving
|
||||
over time we may change or discontinue all or any part of the Dexorder Service, at any time and without notice, at our
|
||||
sole discretion.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>4. Who May Use the Dexorder Service?</v-card-title>
|
||||
<v-card-text>
|
||||
(a) <u>Eligibility</u>. The Dexorder Service is only available to users in certain jurisdictions outside
|
||||
of the United States and that are at least 18 years old, capable of forming a binding contract with the Dexorder
|
||||
and not otherwise barred from using the Dexorder Service under Applicable Law. You may not attempt to access
|
||||
or use the Dexorder Service if you are not permitted to do so (including without limitation if you are a Restricted
|
||||
Person).
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(b) <u>Compliance</u>. You certify that you will comply with all Applicable Law when using the
|
||||
Dexorder Service. You are solely responsible for ensuring that your access and use of the Dexorder Service in
|
||||
such country, territory, or jurisdiction does not violate any Applicable Laws. You must not use any software or
|
||||
networking techniques, including use of a virtual private network (“<b>VPN</b>”) to circumvent or attempt to
|
||||
circumvent this prohibition. We reserve the right to monitor the locations from which our Dexorder Service is
|
||||
accessed. Furthermore, we reserve the right, at any time, in our sole discretion, to block access to the Dexorder
|
||||
Service, in whole or in part, from any geographic location, IP addresses, and unique device identifiers
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>5. Use of the Dexorder Service</v-card-title>
|
||||
<v-card-text>
|
||||
(a) <u>User Representations and Warranties</u>. As a condition to accessing or using the Dexorder
|
||||
Service, you represent and warrant to Dexorder that:
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(i) if you are entering into these Terms as an individual, then you are of legal age in
|
||||
the jurisdiction in which you reside and you have the legal capacity to enter into these Terms and be bound by
|
||||
them and if you are entering into these Terms as an entity, then you must have the legal authority to accept
|
||||
these Terms on that entity’s behalf, in which case “you” (except as used in this paragraph) will mean that entity;
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(ii) you are not in or residing in the United States;
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(iii) you are not in or residing in Cuba, Iran, North Korea, Syria, Belarus, Russia, and
|
||||
the Crimea, Luhansk, Donetsk, Zaporizhzhia, and Kherson regions of Ukraine, or any other country or jurisdiction
|
||||
to which the Cayman Islands, the United Kingdom, United States, the United Nations Security Council, or the
|
||||
European Union embargoes goods or imposes similar sanctions (collectively, “<b>Restricted Territories</b>”);
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(iv) you are not on any sanctions list or equivalent maintained by the Cayman
|
||||
Islands, the United Kingdom, United States, the United Nations Security Council, or the European Union
|
||||
(collectively, “<b>Sanctions Lists Persons</b>”) and you do not intend to transact with any Restricted Person or
|
||||
Sanctions List Person;
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(v) you do not, and will not, use VPN software or any other privacy or
|
||||
anonymization tools or techniques to circumvent, or attempt to circumvent, any restrictions that apply to the
|
||||
Dexorder Service;
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(vi) you have obtained all required consents from any individual whose personal
|
||||
information you transfer to us in connection with your use of the Dexorder Service; and
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(vii) all information that you provide through the Dexorder Service is current,
|
||||
complete, true, and accurate and you will maintain the security and confidentiality of your private keys
|
||||
associated with your public wallet address, passwords, API keys, passwords or other information associated with
|
||||
your Vault or otherwise, as applicable.
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(viii) your access to the Dexorder Service is not: (a) prohibited by and does not
|
||||
otherwise violate or assist you to violate any domestic or foreign law, rule, statute, regulation, by-law, order,
|
||||
protocol, code, decree, or another directive, requirement, or guideline, published or in force that applies to or is
|
||||
otherwise intended to govern or regulate any person, property, transaction, activity, event or other matter,
|
||||
including any rule, order, judgment, directive or other requirement or guideline issued by any domestic or
|
||||
foreign federal, provincial or state, municipal, local or other governmental, regulatory, judicial or administrative
|
||||
authority having jurisdiction over Dexorder, you, the Site or the Dexorder Service, or as otherwise duly enacted,
|
||||
enforceable by law, the common law or equity (collectively, “<b>Applicable Laws</b>”); or (b) contribute to or facilitate
|
||||
any illegal activity.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text>
|
||||
(b) <u>Limitations</u>. As a condition to accessing or using the Dexorder Service or the Site, you
|
||||
acknowledge, understand, and agree to the following:
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(i) Subject to your compliance with these Terms, Dexorder will use its commercially
|
||||
reasonable efforts to provide you with access to the Dexorder Service and to cause your Interactions to be
|
||||
executed on the applicable DEX in accordance with Dexorder’s Execution Policy located at
|
||||
<a href="https://dexorder.trade/home/execution_policy">https://dexorder.trade/home/execution_policy</a>
|
||||
(“<b>Execution Policy</b>”), however from time to time the Site and the Dexorder Service may be inaccessible or inoperable for any
|
||||
reason, including, without limitation: (a) if an Interaction repeatedly fails to be executed (such as due to an error
|
||||
in Interaction execution or a malfunction in the Dexorder Service); (b) equipment malfunctions; (c) periodic
|
||||
maintenance procedures or repairs that Dexorder or any of its suppliers or contractors may undertake from time
|
||||
to time; (d) causes beyond Dexorder’s control or that Dexorder could not reasonably foresee; (e) disruptions and
|
||||
temporary or permanent unavailability of underlying blockchain infrastructure; (f) unavailability of third-party
|
||||
service providers or external partners for any reason; or (g) an Activation Signal not being sent.
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(ii) the Site and the Dexorder Service may evolve, which means Dexorder may apply
|
||||
changes, replace, or discontinue (temporarily or permanently) the Dexorder Service at any time in its sole
|
||||
discretion;
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(iii) Dexorder does not act as an agent for you or any other user of the Site or the Dexorder Service;
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(iv) you are solely responsible for your use of the Dexorder Service; and
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(v) we owe no fiduciary duties or liabilities to you or any other party, and that to
|
||||
the extent any such duties or liabilities may exist at law or in equity, you hereby irrevocably disclaim, waive, and
|
||||
eliminate those duties and liabilities.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>6. Interactions; Fees</v-card-title>
|
||||
<v-card-text>
|
||||
(a) <u>Interactions</u>. In order to effectuate Interactions, you may need to transfer digital assets
|
||||
(e.g., tokens) to the Vault. You acknowledge that you may use the Dexorder Services to process and cause
|
||||
Interactions to be operate with an applicable DEX, including without limitation the transfer of digital assets via
|
||||
the DEX in accordance with the Interaction. For clarity, the Vault is a smart contract automatically controlled by
|
||||
the blockchain. Dexorder is an interface to that smart contract, and does not offer a digital wallet and has no
|
||||
custody or control over your digital wallet or any digital assets or cryptocurrency, which is never accessible by
|
||||
Dexorder.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(b) <u>Fees</u>.
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(i) Dexorder charges fees upfront for usage of the Dexorder Services at the time of
|
||||
user Interactions (“<b>Fees</b>”). You agree to pay all applicable Fees upfront to Dexorder, in the amounts
|
||||
communicated or presented to you via the Dexorder Service in connection with usage of the Dexorder Service.
|
||||
Each party shall be responsible for all Taxes imposed on its income or property.
|
||||
</v-card-text>
|
||||
<v-card-text class="ii">
|
||||
(ii) There may be associated fees in connection with transactions enacted on a
|
||||
blockchain. All transactions using blockchains require the payment of gas fees, which are essentially transaction
|
||||
fees paid on every transaction that occurs on the selected blockchain network. We do not collect any such fees.
|
||||
Please note that accessing the Protocol may result in you incurring gas fees, which are non-refundable, and are
|
||||
paid by you in all circumstances. You pay all gas fees incurred by you as relating to interacting with the Protocol.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text>
|
||||
(c) <u>Tax Records and Reporting</u>. You are solely responsible for all costs incurred by you in
|
||||
using the Dexorder Service, and for determining, collecting, reporting, and paying all applicable Taxes that you
|
||||
may be required by law to collect and remit to any governmental or regulatory agencies. As used herein,
|
||||
“<b>Taxes</b>” means the taxes, duties, levies, tariffs, and other charges imposed by any federal, state, multinational or
|
||||
local governmental or regulatory authority. We reserve the right to report any activity occurring using the
|
||||
Dexorder Service to relevant tax authorities as required under Applicable Law. You are solely responsible for
|
||||
maintaining all relevant Tax records and complying with any reporting requirements you may have as related to
|
||||
our Dexorder Service. You are further solely responsible for independently maintaining the accuracy of any
|
||||
record submitted to any tax authority including any information derived from the Dexorder Service.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(d) Suspensions or Terminations. In addition to the other suspension and termination rights
|
||||
in these Terms, we may suspend or terminate your access to the Dexorder Service, or any and all Interactions, at
|
||||
any time in connection with any Interaction or transaction (i) as required by Applicable Law or any governmental
|
||||
authority, (ii) if we are unable to process or execute an Interaction or transaction after several attempts (as
|
||||
described in the Execution Policy or otherwise in Dexorder’s reasonable discretion), or (iii) if we in our sole and
|
||||
reasonable discretion determine you are violating the terms of any third-party service provider or these Terms,
|
||||
including, without limitation, if we reasonably believe any of your representations and warranties may be untrue
|
||||
or inaccurate or you are violating or have violated any of the geographical restrictions that apply to the
|
||||
Dexorder Service, and in any case we will not be liable to you for any losses or damages you may suffer as a
|
||||
result of or in connection with the Dexorder Service being inaccessible to you at any time or for any reason. Such
|
||||
suspension or termination shall not constitute a breach of these Terms by Dexorder. In accordance with its anti-
|
||||
money laundering, anti-terrorism, anti-fraud, and other compliance policies and practices, we may impose
|
||||
limitations and controls on the ability of you or any beneficiary to utilize the Dexorder Service. Such limitations
|
||||
may include rejecting transaction requests, freezing funds in any case where Dexorder has such ability, or
|
||||
otherwise restricting you from using the Dexorder Service, all to the extent of our ability to do so.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>7. General Prohibitions and Dexorder’s Enforcement Rights.</v-card-title>
|
||||
<v-card-text>
|
||||
You agree not to do any of the
|
||||
following:
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(a) Engage in or induce others to engage in any form of unauthorized access, hacking, or
|
||||
social engineering, including without limitation any distributed denial or service or DDoS attack, of Dexorder, the
|
||||
Dexorder Service, or any users of the foregoing;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(b) Use, display, mirror or frame the Dexorder Service or any individual element within the
|
||||
Dexorder Service, Dexorder’s name, any Dexorder trademark, logo or other proprietary information, or the
|
||||
layout and design of any page or form contained on a page, without Dexorder’s express written consent;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(c) Access, tamper with, or use non-public areas of the Dexorder Service, Dexorder’s
|
||||
computer systems, or the technical delivery systems of Dexorder’s providers;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(d) Attempt to probe, scan or test the vulnerability of any Dexorder system or network or
|
||||
breach any security or authentication measures;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(e) Avoid, bypass, remove, deactivate, impair, descramble or otherwise circumvent any
|
||||
technological measure implemented by Dexorder or any of Dexorder’s providers or any other third party
|
||||
(including another user) to protect the Dexorder Service;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(f) Attempt to access or search the Dexorder Service or download content from the
|
||||
Dexorder Service using any engine, software, tool, agent, device or mechanism (including spiders, robots,
|
||||
crawlers, data mining tools or the like) other than the software and/or search agents provided by Dexorder or
|
||||
other generally available third-party web browsers;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(g) Use any meta tags or other hidden text or metadata utilizing a Dexorder trademark,
|
||||
logo, URL or product name without Dexorder’s express written consent;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(h) Forge any TCP/IP packet header or any part of the header information in any email or
|
||||
newsgroup posting, or in any way use the Dexorder Service to send altered, deceptive or false source-identifying
|
||||
information;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(i) Attempt to decipher, decompile, disassemble or reverse engineer any of the software
|
||||
used to provide the Dexorder Service;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(j) Interfere with, or attempt to interfere with, the access of any user, host or network,
|
||||
including, without limitation, sending a virus, exploiting any bug, overloading, flooding, spamming, or mail-
|
||||
bombing the Dexorder Service;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(k) Use the Dexorder Service for benchmarking or analysis in a manner that could, directly
|
||||
or indirectly, interfere with, detract from, or otherwise harm the Dexorder Service or DEX;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(l) Collect or store any personally identifiable information from the Dexorder Service from
|
||||
other users of the Dexorder Service without their express permission;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(m) Impersonate or misrepresent your affiliation with any person or entity;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(n) Create or list any counterfeit items (including digital assets);
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(o) Fabricate in any way any transaction or process related thereto;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(p) Engage or assist in any activity that violates any law, statute, ordinance, regulation, or
|
||||
sanctions program, , or that involves proceeds of any unlawful activity (including but not limited to money
|
||||
laundering, terrorist financing or deliberately engaging in activities designed to adversely affect the performance
|
||||
of the Dexorder Service);
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(q) Engage in deceptive or manipulative trading activities;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(r) Disguise or interfere in any way with the IP address of the computer you are using to
|
||||
access or use the Dexorder Service or that otherwise prevents us from correctly identifying the IP address of the
|
||||
computer you are using to access the Dexorder Service;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(s) Transmit, exchange, or otherwise support the direct or indirect proceeds of criminal or
|
||||
fraudulent activity;
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(t) Violate any Applicable Law or regulation; or
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(u) Encourage or enable any other individual to do any of the foregoing.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
Dexorder is not obligated to monitor access to or use of the Dexorder Service or to review or edit any content.
|
||||
However, we have the right to do so for the purpose of operating the Dexorder Service, to ensure compliance with
|
||||
these Terms and to comply with Applicable Law or other legal requirements. We reserve the right, but are not
|
||||
obligated, to suspend or terminate access to the Dexorder Service at any time if we believe you are violating these
|
||||
Terms. We have the right to investigate violations of these Terms or conduct that affects the Dexorder Service. We
|
||||
may also consult and cooperate with law enforcement authorities to prosecute users who violate the law.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>8. Feedback</v-card-title>
|
||||
<v-card-text>
|
||||
We appreciate feedback, comments, ideas, proposals and suggestions for improvements to the Dexorder Service
|
||||
(“<b>Feedback</b>”). If you choose to submit Feedback, you agree that we are free to use it (and permit others to use it)
|
||||
without any restriction or compensation to you.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>9. Links to Third Party Websites or Resources</v-card-title>
|
||||
<v-card-text>
|
||||
The Dexorder Service may allow you to access third-party websites, integrations, or other resources, including the DEX,
|
||||
services providing Activation Signals, and any bridge between the DEX and any third party protocols (collectively,
|
||||
“<b>Third Party Resources</b>”). We provide access only as a convenience and are not responsible for the content, products
|
||||
or services on or available from those resources or links displayed on such websites. You acknowledge sole
|
||||
responsibility for and assume all risk arising from, your use of any third-party resources. Our provision of access to
|
||||
Third Party Resources does not constitute approval, endorsement, or control of such Third Party Resource.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>10. Termination</v-card-title>
|
||||
<v-card-text>
|
||||
We may suspend or terminate your access to and use of the Dexorder Service, at our sole discretion, at any time and
|
||||
without notice to you. You acknowledge and agree that we shall have no liability or obligation to you in such event and
|
||||
that you will not be entitled to a refund of any amounts that you have already paid to us or any third party, to the
|
||||
fullest extent permitted by Applicable Law. Upon any termination, discontinuation, or cancellation of the Dexorder
|
||||
Service or your account, the following Sections will survive: 6.(d) , 7 , 8 , 10 , 11 , 13 , 14 , 15 , 16 , and 17 .
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>11. Warranty Disclaimers</v-card-title>
|
||||
<v-card-text>
|
||||
THE DEXORDER SERVICE (INCLUDING WITHOUT LIMITATION THE VAULT) AND ANY CONTENT CONTAINED THEREIN, AS
|
||||
WELL AS THE PROTOCOL, THE DEXORDER ORACLE, AND ANY ASSOCIATED PROTOCOL OR BLOCKCHAIN MESSAGING
|
||||
FUNCTIONALITY SUCH AS ACTIVATION SIGNALS UNDERLYING THE DEXORDER SERVICE (TOGETHER, THE “<b>UTILITIES</b>”),
|
||||
ARE PROVIDED “AS IS,” WITHOUT WARRANTY OF ANY KIND. WITHOUT LIMITING THE FOREGOING, WE EXPLICITLY
|
||||
DISCLAIM ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
|
||||
ENJOYMENT AND NON-INFRINGEMENT, AND ANY WARRANTIES ARISING OUT OF COURSE OF DEALING OR USAGE OF
|
||||
TRADE. WE MAKE NO WARRANTY THAT THE UTILITIES WILL MEET YOUR REQUIREMENTS, BE AVAILABLE ON AN
|
||||
UNINTERRUPTED, SECURE, OR ERROR-FREE BASIS. WE MAKE NO WARRANTY REGARDING THE QUALITY, ACCURACY,
|
||||
TIMELINESS, TRUTHFULNESS, COMPLETENESS OR RELIABILITY OF ANY INFORMATION OR CONTENT ON THE UTILITIES.
|
||||
DEXORDER FURTHER EXPRESSLY DISCLAIMS ALL LIABILITY OR RESPONSIBILITY IN CONNECTION WITH THIRD PARTY
|
||||
SERVICES. NOTHING HEREIN NOR ANY USE OF THE UTILITIES IN CONNECTION WITH THIRD PARTY SERVICES
|
||||
CONSTITUTES OUR ENDORSEMENT, RECOMMENDATION OR ANY OTHER AFFILIATION OF OR WITH ANY THIRD PARTY
|
||||
SERVICES.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
DEXORDER DOES NOT REPRESENT OR WARRANT THAT ANY CONTENT ON THE UTILITIES IS ACCURATE, COMPLETE,
|
||||
RELIABLE, CURRENT OR ERROR-FREE. WE WILL NOT BE LIABLE FOR ANY LOSS OF ANY KIND FROM ANY ACTION TAKEN
|
||||
OR TAKEN IN RELIANCE ON MATERIAL OR INFORMATION CONTAINED ON THE UTILITIES. DEXORDER CANNOT AND
|
||||
DOES NOT REPRESENT OR WARRANT THAT THE UTILITIES, ANY CONTENT THEREIN, OR OUR SERVERS ARE FREE OF
|
||||
VIRUSES OR OTHER HARMFUL COMPONENTS.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
WE CANNOT GUARANTEE THE SECURITY OF ANY DATA THAT YOU DISCLOSE ONLINE. YOU ACCEPT THE INHERENT
|
||||
SECURITY RISKS OF PROVIDING INFORMATION AND DEALING ONLINE OVER THE INTERNET AND WILL NOT HOLD US
|
||||
RESPONSIBLE FOR ANY BREACH OF SECURITY.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
DEXORDER WILL NOT BE RESPONSIBLE OR LIABLE TO YOU FOR ANY LOSS AND TAKES NO RESPONSIBILITY FOR, AND
|
||||
WILL NOT BE LIABLE TO YOU FOR, ANY USE OF THE UTILITIES, INCLUDING BUT NOT LIMITED TO ANY LOSSES,
|
||||
DAMAGES OR CLAIMS ARISING FROM: (I) USER ERROR SUCH AS FORGOTTEN PASSWORDS, INCORRECTLY
|
||||
CONSTRUCTED TRANSACTIONS, EXCEEDING TRANSFER LIMITS OF THIRD PARTY RESOURCES OR THE DEX, OR
|
||||
MISTYPED WALLET ADDRESSES; (II) SERVER FAILURE OR DATA LOSS; (III) BLOCKCHAIN NETWORKS, CRYPTOCURRENCY
|
||||
WALLETS, CORRUPT FILES, SOFTWARE ERRORS, OR BUGS; (IV) UNAUTHORIZED ACCESS TO THE UTILITIES; OR (V) ANY
|
||||
THIRD PARTY UTILITIES, INCLUDING WITHOUT LIMITATION THE USE OF VIRUSES, PHISHING, BRUTEFORCING OR OTHER
|
||||
MEANS OF ATTACK AGAINST ANY BLOCKCHAIN NETWORK UNDERLYING THE UTILITIES.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
THE UTILITIES MAY INCLUDE THE PLACEMENT OR EXECUTION OF AN ACTIVATION SIGNAL TO A USER VAULT WITH
|
||||
RESPECT TO USER DEFINED INTERACTIONS (E.G., VIA TRANSMITTING AN ACTIVATION SIGNAL WHICH TRIGGERS
|
||||
INTERACTION EXECUTION), HOWEVER, ANYONE, INCLUDING YOU OR ANY THIRD PARTY, MAY CAUSE AN INTERACTION
|
||||
TO BE EXECUTED (SUCH AS BY TRANSMITTING THE APPLICABLE ACTIVATION SIGNAL), AND NOTWITHSTANDING
|
||||
ANYTHING TO THE CONTRARY IN THESE TERMS, DEXORDER DOES NOT GUARANTEE THE PLACEMENT OR EXECUTION
|
||||
OR ANY INTERACTION, INCLUDING WITHOUT LIMITATION THAT DEXORDER WILL TRANSMIT ANY PARTICULAR
|
||||
ACTIVATION SIGNAL TO TRIGGER EXECUTION OF ANY INTERACTION, OR THAT AN INTERACTION WILL OTHERWISE BE
|
||||
PROPERLY CARRIED OUT PURSUANT TO A VAULT. YOU ACKNOWLEDGE AND AGREE THAT YOU WILL NOT RELY ON THE
|
||||
UTILITIES TO CARRY OUT PLACEMENTS OR EXECUTIONS OF INTERACTIONS. IF ANY PARTICULAR INTERACTION THAT IS
|
||||
PLACED IS NOT EXECUTED BY DEXORDER IN A TIMELY MANNER, YOU MAY CAUSE SUCH INTERACTION TO BE
|
||||
EXECUTED YOURSELF OR BY ENGAGING A THIRD PARTY SERVICE PROVIDER TO DO SO (E.G., BY TRANSMITTING THE
|
||||
APPLICABLE ACTIVATION SIGNAL YOURSELF OR ENGAGING A THIRD PARTY TO DO SO). YOU ACCEPT THE INHERENT
|
||||
RISK THAT ANY PARTICULAR INTERACTION MAY NOT BE EXECUTED, INCLUDING WITHOUT LIMITATION DUE TO BAD
|
||||
ACTORS OR THE MALFUNCTION OF THE UTILITIES, AND DEXORDER HEREBY DISCLAIMS ANY AND ALL LIABILITY AND
|
||||
RESPONSIBILITY IN CONNECTION WITH THE PLACEMENT OR EXECUTION OF INTERACTIONS AND THE VAULT.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
THE UTILITIES MAY NOT BE AVAILABLE DUE TO ANY NUMBER OF FACTORS INCLUDING, BUT NOT LIMITED TO,
|
||||
PERIODIC SYSTEM MAINTENANCE, SCHEDULED OR UNSCHEDULED, ACTS OF GOD, UNAUTHORIZED ACCESS, VIRUSES,
|
||||
DENIAL OF SERVICE OR OTHER ATTACKS, TECHNICAL FAILURE OF THE UTILITIES AND/OR TELECOMMUNICATIONS
|
||||
INFRASTRUCTURE OR DISRUPTION, AND THEREFORE WE EXPRESSLY DISCLAIM ANY EXPRESS OR IMPLIED WARRANTY
|
||||
REGARDING THE USE AND/OR AVAILABILITY, ACCESSIBILITY, SECURITY OR PERFORMANCE OF THE UTILITIES CAUSED
|
||||
BY SUCH FACTORS. WE DO NOT MAKE ANY REPRESENTATIONS OR WARRANTIES AGAINST THE POSSIBILITY OF
|
||||
DELETION, MISDELIVERY OR FAILURE TO STORE COMMUNICATIONS, PERSONALIZED SETTINGS OR OTHER DATA.
|
||||
SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF CERTAIN WARRANTIES. ACCORDINGLY, SOME OF THE
|
||||
ABOVE DISCLAIMERS OF WARRANTIES MAY NOT APPLY TO YOU BUT OTHERS REMAIN IN EFFECT.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
You understand that your use of the Utilities is entirely at your own risk. You assume all risks associated with
|
||||
using the Utilities, and digital assets and decentralized systems generally, including but not limited to, that
|
||||
digital assets are highly volatile; you may not have ready access to assets; and you may lose some or all of your
|
||||
tokens or other assets, including with respect to an Interaction or the Vault. You agree that you will have no
|
||||
recourse against Dexorder for any losses due to your use of the Utilities. For example, these losses may arise
|
||||
from or relate to: (i) lost funds; (ii) server failure or data loss; (iii) corrupted digital wallet files; (iv) unauthorized
|
||||
access; (v) errors, mistakes, or inaccuracies; or (vi) third-party activities.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>12. Assumption of Risk.</v-card-title>
|
||||
<v-card-text>You accept, acknowledge and assume the following risks:</v-card-text>
|
||||
<v-card-text>
|
||||
(a) You are solely responsible for determining what, if any, Taxes apply to your transactions
|
||||
through the Utilities. Neither Dexorder nor any Dexorder affiliates are responsible for determining the Taxes
|
||||
that apply to such transactions.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(b) A lack of use or public interest in the creation and development of distributed
|
||||
ecosystems could negatively impact the development of those ecosystems and related applications, and could
|
||||
therefore also negatively impact the potential utility or value of certain digital assets.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(c) By accessing and using the Utilities, you represent that you understand the inherent
|
||||
risks associated with using cryptographic and blockchain-based systems, and that you have a working knowledge
|
||||
of the usage and intricacies of tokens such as, bitcoin (BTC), ether (ETH), and other digital tokens such as those
|
||||
following the Ethereum Token Standard (ERC-20). You further understand that the markets for tokens can be
|
||||
highly volatile due to factors including (but not limited to) adoption, speculation, technology, security, and
|
||||
regulation. You acknowledge that the cost and speed of transacting with cryptographic and blockchain-based
|
||||
systems are variable and may increase at any time. Accordingly, you understand and agree to assume full
|
||||
responsibility for all of the risks of accessing and using and engaging with the Utilities.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>13. Indemnity</v-card-title>
|
||||
<v-card-text>
|
||||
You will indemnify, defend (at Dexorder’s option) and hold Dexorder and its affiliates and their respective officers,
|
||||
directors, employees and agents, harmless from and against any claims, disputes, demands, liabilities, damages, losses,
|
||||
and costs and expenses, including, without limitation, reasonable legal and accounting fees arising out of or in any way
|
||||
connected with: (a) your access to or use of the Utilities, (b) Interactions and the Vault, (c) your violation of these
|
||||
Terms, or (d) your negligence, willful misconduct, fraud, or violation of Applicable Laws. You may not settle or
|
||||
otherwise compromise any claim subject to this Section without Dexorder’s prior written approval.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>14. Limitation of Liability</v-card-title>
|
||||
<v-card-text>
|
||||
(a) TO THE MAXIMUM EXTENT PERMITTED BY LAW, NEITHER DEXORDER NOR ITS SERVICE
|
||||
PROVIDERS INVOLVED IN CREATING, PRODUCING, OR DELIVERING THE UTILITIES WILL BE LIABLE FOR ANY
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES, OR DAMAGES FOR LOST PROFITS, LOST
|
||||
REVENUES, LOST SAVINGS, LOST BUSINESS OPPORTUNITY, LOSS OF DATA OR GOODWILL, SERVICE
|
||||
INTERRUPTION, COMPUTER DAMAGE OR SYSTEM FAILURE OR THE COST OF SUBSTITUTE SERVICES OF ANY KIND
|
||||
ARISING OUT OF OR IN CONNECTION WITH THESE TERMS OR FROM THE USE OF OR INABILITY TO USE THE
|
||||
UTILITIES, WHETHER BASED ON WARRANTY, CONTRACT, TORT (INCLUDING NEGLIGENCE), PRODUCT LIABILITY
|
||||
OR ANY OTHER LEGAL THEORY, AND WHETHER OR NOT DEXORDER OR ITS SERVICE PROVIDERS HAS BEEN
|
||||
INFORMED OF THE POSSIBILITY OF SUCH DAMAGE, EVEN IF A LIMITED REMEDY SET FORTH HEREIN IS FOUND TO
|
||||
HAVE FAILED OF ITS ESSENTIAL PURPOSE.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(b) TO THE MAXIMUM EXTENT PERMITTED BY THE LAW, IN NO EVENT WILL DEXORDER’S
|
||||
TOTAL LIABILITY ARISING OUT OF OR IN CONNECTION WITH THESE TERMS OR FROM THE USE OF OR INABILITY
|
||||
TO USE THE UTILITIES EXCEED THE TOTAL FEES YOU HAVE PAID OR ARE PAYABLE BY YOU TO DEXORDER FOR USE
|
||||
OF THE UTILITIES (EXCLUDING GAS FEES), OR ONE HUNDRED DOLLARS ($100) IF YOU HAVE NOT HAD ANY
|
||||
PAYMENT OBLIGATIONS TO DEXORDER, AS APPLICABLE.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(c) THE EXCLUSIONS AND LIMITATIONS OF DAMAGES SET FORTH ABOVE ARE
|
||||
FUNDAMENTAL ELEMENTS OF THE BASIS OF THE BARGAIN BETWEEN DEXORDER AND YOU.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>15. Governing Law and Forum Choice</v-card-title>
|
||||
<v-card-text>
|
||||
These Terms will be governed by and construed in accordance with the laws of the British Virgin Islands without regard
|
||||
to its conflict of laws provisions.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>16. Dispute Resolution</v-card-title>
|
||||
<v-card-text>
|
||||
(a) <u>Mandatory Arbitration of Disputes</u>. We each agree that any dispute, claim or
|
||||
controversy arising out of or relating to these Terms or the breach, termination, enforcement, interpretation or
|
||||
validity thereof or the use of the Utilities (collectively, “<b>Disputes</b>”) will be resolved <b>solely by binding, individual
|
||||
arbitration and not in a class, representative or consolidated action or proceeding.</b> You and Dexorder agree
|
||||
that the Cayman Islands Arbitration Law governs the interpretation and enforcement of these Terms, and that
|
||||
you and Dexorder are each waiving the right to a trial by jury or to participate in a class action. This arbitration
|
||||
provision shall survive termination of these Terms.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(b) <u>Exceptions</u>. As limited exceptions to Section 16.(a) above: (i) each party may seek to
|
||||
resolve a Dispute in small claims court if it qualifies; and (ii) each party retains the right to seek injunctive or
|
||||
other equitable relief from a court to prevent (or enjoin) the infringement or misappropriation of our intellectual
|
||||
property rights.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(c) <u>Conducting Arbitration and Arbitration Rules</u>. The arbitration will be conducted by the
|
||||
Cayman International Mediation & Arbitration Centre (CI-MAC) in accordance with its arbitration rules in force
|
||||
at the time of the dispute (“<b>CI-MAC Rules</b>”), except as modified by these Terms. The CI-MAC Rules are available
|
||||
at <a href="https://www.caymanarbitration.com/arbitrationrules2023">https://www.caymanarbitration.com/arbitrationrules2023</a>. A party who wishes to start arbitration must
|
||||
submit a written request for arbitration to CI-MAC and give notice to the other party as specified in the CI-MAC
|
||||
Rules. CI-MAC provides instructions on submitting a request for arbitration under Section 3 (Request for
|
||||
arbitration) of the CI-MAC Rules.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
Any arbitration hearings will take place in the county (or parish) where you live, unless the parties agree to a
|
||||
different location. The parties agree that the arbitrator shall have exclusive authority to decide all issues relating
|
||||
to the interpretation, applicability, enforceability and scope of this arbitration agreement.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(d) <u>Arbitration Costs</u>. Payment of all filing, administration and arbitrator fees will be
|
||||
governed by the JAMS Rules, and we won’t seek to recover the administration and arbitrator fees we are
|
||||
responsible for paying, unless the arbitrator finds your Dispute frivolous. If we prevail in arbitration we’ll pay all
|
||||
of our attorneys’ fees and costs and won’t seek to recover them from you. If you prevail in arbitration you will
|
||||
be entitled to an award of attorneys’ fees and expenses to the extent provided under Applicable Law.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(e) <u>Injunctive and Declaratory Relief</u>. Except as provided in Section 16.(b) above, the
|
||||
arbitrator shall determine all issues of liability on the merits of any claim asserted by either party and may award
|
||||
declaratory or injunctive relief only in favor of the individual party seeking relief and only to the extent
|
||||
necessary to provide relief warranted by that party’s individual claim. To the extent that you or we prevail on a
|
||||
claim and seek public injunctive relief (that is, injunctive relief that has the primary purpose and effect of
|
||||
prohibiting unlawful acts that threaten future injury to the public), the entitlement to and extent of such relief
|
||||
must be litigated in a civil court of competent jurisdiction and not in arbitration. The parties agree that litigation
|
||||
of any issues of public injunctive relief shall be stayed pending the outcome of the merits of any individual
|
||||
claims in arbitration.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(f) <u>Class Action Waiver</u>. <b>YOU AND DEXORDER AGREE THAT EACH MAY BRING CLAIMS
|
||||
AGAINST THE OTHER ONLY IN YOUR OR ITS INDIVIDUAL CAPACITY, AND NOT AS A PLAINTIFF OR CLASS
|
||||
MEMBER IN ANY PURPORTED CLASS OR REPRESENTATIVE PROCEEDING.</b> Further, if the parties’ Dispute is
|
||||
resolved through arbitration, the arbitrator may not consolidate another person’s claims with your claims, and
|
||||
may not otherwise preside over any form of a representative or class proceeding. If this specific provision is
|
||||
found to be unenforceable, then the entirety of this Dispute Resolution section shall be null and void.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(g) <u>Severability</u>. With the exception of any of the provisions in Section 16.(f) of these Terms
|
||||
(“<b>Class Action Waiver</b>”), if an arbitrator or court of competent jurisdiction decides that any part of these Terms
|
||||
is invalid or unenforceable, the other parts of these Terms will still apply.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>17. General Terms</v-card-title>
|
||||
<v-card-text>
|
||||
(a) <u>Reservation of Rights</u>. Dexorder and its licensors exclusively own all right, title and
|
||||
interest in and to the Dexorder Service, including all associated intellectual property rights. You acknowledge
|
||||
that the Dexorder Service is protected by copyright, trademark, and other laws of the United States and foreign
|
||||
countries. You agree not to remove, alter or obscure any copyright, trademark, service mark or other
|
||||
proprietary rights notices incorporated in or accompanying the Dexorder Service.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(b) <u>Entire Agreement</u>. These Terms, including any addendum terms, constitute the entire
|
||||
and exclusive understanding and agreement between Dexorder and you regarding the Dexorder Service, and
|
||||
these Terms supersede and replace all prior oral or written understandings or agreements between Dexorder
|
||||
and you regarding the Dexorder Service. If any provision of these Terms is held invalid or unenforceable by an
|
||||
arbitrator or a court of competent jurisdiction, that provision will be enforced to the maximum extent
|
||||
permissible and the other provisions of these Terms will remain in full force and effect. Except where provided
|
||||
by Applicable Law in your jurisdiction, you may not assign or transfer these Terms, by operation of law or
|
||||
otherwise, without Dexorder’s prior written consent. Any attempt by you to assign or transfer these Terms
|
||||
absent our consent or your statutory right, will be null. Dexorder may freely assign or transfer these Terms
|
||||
without restriction. Subject to the foregoing, these Terms will bind and inure to the benefit of the parties, their
|
||||
successors and permitted assigns.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(c) <u>Notices</u>. Any notices or other communications provided by Dexorder under these Terms
|
||||
will be given: (i) via email; or (ii) by posting to the Dexorder Service. For notices made by email, the date of
|
||||
receipt will be deemed the date on which such notice is transmitted.
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
(d) <u>Waiver of Rights</u>. Dexorder’s failure to enforce any right or provision of these Terms will
|
||||
not be considered a waiver of such right or provision. The waiver of any such right or provision will be effective
|
||||
only if in writing and signed by a duly authorized representative of Dexorder. Except as expressly set forth in
|
||||
these Terms, the exercise by either party of any of its remedies under these Terms will be without prejudice to
|
||||
its other remedies under these Terms or otherwise.
|
||||
</v-card-text>
|
||||
|
||||
<v-card-title>18. Contact Information</v-card-title>
|
||||
<v-card-text>
|
||||
If you have any questions about these Terms or the Dexorder Service, please contact Dexorder
|
||||
at <a href="mailto:legal@dexorder.trade">legal@dexorder.trade</a> or <a href="mailto:support@dexorder.trade">support@dexorder.trade</a>.
|
||||
</v-card-text>
|
||||
|
||||
|
||||
<v-card-actions class="justify-space-around mb-8">
|
||||
<v-btn variant="elevated" @click="decline" :disabled="!acceptable" prepend-icon="mdi-cancel">Decline</v-btn>
|
||||
<v-btn variant="elevated" color="primary" @click="accept" :disabled="!acceptable" prepend-icon="mdi-check">Accept</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// tos = {
|
||||
// version: 1, // Number
|
||||
// date: 12345678, // Unix timestamp
|
||||
// ip: '123.231.132.213', // IP when client accepted
|
||||
// country: 'AD', // https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 Country where the IP is located
|
||||
// }
|
||||
|
||||
import {usePrefStore} from "@/store/store.js";
|
||||
import {computed, ref, watch} from "vue";
|
||||
import {timestamp} from "@/misc.js";
|
||||
|
||||
// INCREMENT THIS WHEN CHANGING THE TOS
|
||||
const CURRENT_VERSION=1
|
||||
|
||||
const prefs = usePrefStore()
|
||||
const ok = computed(()=>{
|
||||
console.log('check ToS', prefs.acceptedTos)
|
||||
return prefs.acceptedTos!==null&&prefs.acceptedTos.version===CURRENT_VERSION
|
||||
})
|
||||
const show = computed(()=>!ok.value)
|
||||
const acceptable = computed(()=>!inFlight.value)
|
||||
const inFlight = ref(false)
|
||||
|
||||
watch(ok, (newVal, oldVal)=> {console.log('check ToS');if(newVal!==oldVal) console.log('ToS accepted', prefs.acceptedTos.version, prefs.acceptedTos.date) })
|
||||
|
||||
function accept() {
|
||||
prefs.acceptedTos = {
|
||||
version: CURRENT_VERSION,
|
||||
date: timestamp(),
|
||||
// todo IP check
|
||||
// ip: '127.0.0.1',
|
||||
// country: 'AD'
|
||||
}
|
||||
inFlight.value = false
|
||||
}
|
||||
|
||||
function decline() {
|
||||
// bounce to top-level non-app domain
|
||||
window.location.href = 'https://dexorder.trade'
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.ii {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
<script setup>
|
||||
// noinspection ES6UnusedImports
|
||||
import {routeInverted, SingletonCoroutine, vAutoSelect} from "@/misc.js";
|
||||
import {SingletonCoroutine, vAutoSelect} from "@/misc.js";
|
||||
import Order from "@/components/Order.vue";
|
||||
import LimitPrice from "@/components/LimitPrice.vue";
|
||||
import {timesliceTranches, applyLimitOld} from "@/orderbuild.js";
|
||||
import {applyLimitOld, timesliceTranches} from "@/orderbuild.js";
|
||||
import Tranches from "@/components/Tranches.vue";
|
||||
import {useOrderStore} from "@/store/store.js";
|
||||
|
||||
|
||||
@@ -81,13 +81,6 @@ function updateValue(v) {
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import {ethers} from "ethers";
|
||||
import {useStore} from "@/store/store.js";
|
||||
const s = useStore()
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "src/styles/vars" as *;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<v-list v-if="token">
|
||||
<v-list-subheader :title="token.s"/>
|
||||
<v-list-item title="Withdraw" key="withdraw" value="withdraw" prepend-icon="mdi-arrow-down-bold"
|
||||
@click="()=>onWithdraw(token.a)"/>
|
||||
@click="()=>onWithdraw(token)"/>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</td>
|
||||
|
||||
@@ -36,10 +36,10 @@ const showDialog = ref(false)
|
||||
const upgradeResult = ref(null)
|
||||
|
||||
detectUpgrade().then((version)=>{
|
||||
if (version===0) {
|
||||
console.log('Vault is the latest version')
|
||||
if (version===null) {
|
||||
console.log('detectUpgrade failed')
|
||||
}
|
||||
else {
|
||||
else if (s.version<version) {
|
||||
upgradeVersion.value = version
|
||||
console.log(`Vault upgrade available to version ${version}`)
|
||||
}
|
||||
|
||||
@@ -34,10 +34,8 @@
|
||||
<v-card-item v-if="!empty">
|
||||
<v-table>
|
||||
<tbody>
|
||||
<suspense>
|
||||
<native-row v-if="nativeBalance" :chain-id="s.chainId" :addr="s.vault" :amount="nativeBalance"
|
||||
:on-withdraw="onWithdrawNative" :on-wrap="()=>wrapShow=true"/>
|
||||
</suspense>
|
||||
<native-row v-if="nativeBalance" :chain-id="s.chainId" :addr="s.vault" :amount="nativeBalance"
|
||||
:on-withdraw="onWithdrawNative" :on-wrap="()=>wrapShow=true"/>
|
||||
<suspense v-for="(amount,addr) of balances">
|
||||
<token-row v-if="BigInt(amount)!==0n" :chain-id="s.chainId" :addr="addr" :amount="amount" :onWithdraw="onWithdraw"/>
|
||||
</suspense>
|
||||
@@ -65,7 +63,6 @@ import {vaultAddress} from "@/blockchain/contract.js";
|
||||
import {ensureVault, provider} from "@/blockchain/wallet.js";
|
||||
import CopyButton from "@/components/CopyButton.vue";
|
||||
import Withdraw from "@/components/Withdraw.vue";
|
||||
import {getToken} from "@/blockchain/token.js";
|
||||
import NativeRow from "@/components/NativeRow.vue";
|
||||
import NativeWrap from "@/components/NativeWrap.vue";
|
||||
import WithdrawNative from "@/components/WithdrawNative.vue";
|
||||
@@ -91,8 +88,7 @@ const hasVault = computed(()=>s.vault!==null)
|
||||
|
||||
const withdrawToken = ref(null)
|
||||
const withdrawShow = ref(false)
|
||||
async function onWithdraw(addr) {
|
||||
const token = await getToken(s.chainId, addr)
|
||||
async function onWithdraw(token) {
|
||||
console.log('withdraw', addr, token)
|
||||
withdrawToken.value = token
|
||||
withdrawShow.value = true
|
||||
|
||||
@@ -30,6 +30,7 @@ import {tokenFloat} from "@/misc.js";
|
||||
import {vaultContract} from "@/blockchain/contract.js"
|
||||
import {pendTransaction} from "@/blockchain/wallet.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {WithdrawTransaction} from "@/blockchain/transaction.js";
|
||||
|
||||
const s = useStore()
|
||||
const props = defineProps(['modelValue', 'vault', 'token'])
|
||||
@@ -50,10 +51,7 @@ function withdraw() {
|
||||
if( amount === 0n )
|
||||
return
|
||||
console.log('pending withdrawal', valueStr, amount, props.token.s)
|
||||
pendTransaction(async (signer)=>{
|
||||
const vault = await vaultContract(vaultAddr, signer)
|
||||
return await vault['withdraw(address,uint256)'](props.token.a, amount)
|
||||
})
|
||||
new WithdrawTransaction(s.chainId, vaultAddr, props.token, amount).submit()
|
||||
floatAmount.value = 0
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
|
||||
@@ -26,9 +26,8 @@
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import {computed, ref} from "vue";
|
||||
import {vaultContract} from "@/blockchain/contract.js"
|
||||
import {pendTransaction} from "@/blockchain/wallet.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {WithdrawNativeTransaction} from "@/blockchain/transaction.js";
|
||||
|
||||
const s = useStore()
|
||||
const props = defineProps(['modelValue', 'vault', 'balance'])
|
||||
@@ -44,11 +43,7 @@ function withdraw() {
|
||||
console.log('pending native withdrawal', valueStr, amount)
|
||||
if( amount === 0n )
|
||||
return
|
||||
pendTransaction(async (signer)=>{
|
||||
const vault = await vaultContract(vaultAddr, signer)
|
||||
console.log('invoking withdraw', vaultAddr, amount)
|
||||
return await vault['withdraw(uint256)'](amount)
|
||||
})
|
||||
new WithdrawNativeTransaction(s.chainId, vaultAddr, amount).submit()
|
||||
floatAmount.value = 0
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
|
||||
@@ -75,8 +75,7 @@ import {useTheme} from "vuetify";
|
||||
import RowBar from "@/components/chart/RowBar.vue";
|
||||
import ColorBand from "@/components/chart/ColorBand.vue";
|
||||
import Color from "color";
|
||||
import {Exchange, newOrder} from "@/blockchain/orderlib.js";
|
||||
import {lookupSymbol} from "@/charts/datafeed.js";
|
||||
import {newOrder} from "@/blockchain/orderlib.js";
|
||||
|
||||
const props = defineProps(['order'])
|
||||
const s = useStore()
|
||||
|
||||
@@ -29,20 +29,21 @@
|
||||
<script setup>
|
||||
import {orderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {addSymbolChangedCallback, removeSymbolChangedCallback} from "@/charts/chart.js";
|
||||
import {computed, onBeforeUnmount, ref} from "vue";
|
||||
import {computed, onBeforeUnmount, ref, toRaw, watchEffect} from "vue";
|
||||
import {useOrderStore, useStore} from "@/store/store.js";
|
||||
|
||||
import {routeFinder} from "@/blockchain/route.js";
|
||||
import ChartOrder from "@/components/chart/ChartOrder.vue";
|
||||
import {useTheme} from "vuetify";
|
||||
import {pendOrder} from "@/blockchain/wallet.js";
|
||||
import {useWalletStore} from "@/blockchain/wallet.js";
|
||||
import ToolbarPane from "@/components/chart/ToolbarPane.vue";
|
||||
import NeedsChart from "@/components/NeedsChart.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
import {PlaceOrderTransaction} from "@/blockchain/transaction.js";
|
||||
|
||||
const s = useStore()
|
||||
const co = useChartOrderStore()
|
||||
const os = useOrderStore()
|
||||
const ws = useWalletStore()
|
||||
|
||||
function changeSymbol(symbol) {
|
||||
console.log('changeSymbol', symbol)
|
||||
@@ -79,6 +80,32 @@ function cancelOrder() {
|
||||
showResetDialog.value = true
|
||||
}
|
||||
|
||||
watchEffect(()=>{
|
||||
const removable = []
|
||||
for (const order of ws.pendingOrders) {
|
||||
console.log('pend state', order.state)
|
||||
switch (order.state) {
|
||||
case PendingOrderState.Sent:
|
||||
break
|
||||
case PendingOrderState.Rejected:
|
||||
removable.push(order)
|
||||
break
|
||||
case PendingOrderState.Signing:
|
||||
break
|
||||
case PendingOrderState.Submitted:
|
||||
removable.push(order)
|
||||
break
|
||||
default:
|
||||
console.error('unknown pend state', order.state)
|
||||
}
|
||||
}
|
||||
if (removable.length>0) {
|
||||
if (ws.pendingOrders.length!==removable.length)
|
||||
console.error('Not all orders were rejected') // todo multiple orders / order group
|
||||
ws.pendingOrders = []
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
async function placeOrder() {
|
||||
const chartOrders = co.orders;
|
||||
@@ -90,13 +117,11 @@ async function placeOrder() {
|
||||
built.push(order)
|
||||
}
|
||||
console.log('place orders', built)
|
||||
if (built.length !== 1) {
|
||||
console.error('Multiple orders not supported')
|
||||
if (ws.transaction!==null) {
|
||||
console.error('Transaction already in progress')
|
||||
}
|
||||
else {
|
||||
await pendOrder(built[0])
|
||||
co.resetOrders()
|
||||
nav('Status')
|
||||
new PlaceOrderTransaction(s.chainId, toRaw(built[0])).submit()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
import {builderDefaults, DEFAULT_SLIPPAGE, MIN_EXECUTION_TIME, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {allocationText, VLine} from "@/charts/shape.js";
|
||||
import {sideColor} from "@/misc.js";
|
||||
import {useTheme} from "vuetify";
|
||||
import {useOrderStore, useStore} from "@/store/store.js";
|
||||
import {DISTANT_FUTURE, MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||
@@ -54,7 +53,6 @@ import {DateTime} from "luxon";
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
const co = useChartOrderStore()
|
||||
const theme = useTheme().current
|
||||
const props = defineProps(['order', 'builder'])
|
||||
const emit = defineEmits(['update:builder'])
|
||||
|
||||
|
||||
@@ -112,7 +112,6 @@ function computeDefaultColor() {
|
||||
}
|
||||
|
||||
const defaultColor = computeDefaultColor()
|
||||
|
||||
const color = computed(()=>props.builder.color ? props.builder.color : defaultColor)
|
||||
|
||||
// Fields must be defined in order to be reactive
|
||||
@@ -399,7 +398,7 @@ function dirtyLine(a, b) {
|
||||
return result
|
||||
}
|
||||
|
||||
const name = computed(()=>(props.builder.breakout?'Breakout':'Limit')+' Diagonal'+(weights.value.length>1?'s':''))
|
||||
const name = computed(()=>props.builder.breakout?'Breakout':'Limit')
|
||||
|
||||
const description = computed(()=>{
|
||||
const buy = props.order.buy
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<rung-builder :name="(builder.breakout?'Breakout':'Limit')+(prices.length>1?' Ladder':'')"
|
||||
<rung-builder :name="(builder.breakout?'Breakout':'Limit')"
|
||||
:description="description"
|
||||
:order="order" :builder="builder"
|
||||
v-model="priceEndpoints" :mode="0" :flip="flipped"
|
||||
|
||||
@@ -4,15 +4,16 @@
|
||||
<div style="min-width: 4em; font-size: larger" :style="colorStyle"
|
||||
class="d-flex flex-column align-self-start ml-2">
|
||||
<div class="flex-row align-items-center">
|
||||
<v-btn variant="outlined" @click="props.builder.breakout=!props.builder.breakout">{{ name }}</v-btn>
|
||||
<div class="description">{{description}}</div>
|
||||
<v-btn variant="outlined" style="width: 8em"
|
||||
@click="props.builder.breakout=!props.builder.breakout">{{ name }}</v-btn>
|
||||
<div class="description w-100 text-center">{{description}}</div>
|
||||
</div>
|
||||
<v-text-field type="number" v-model="rungs"
|
||||
density="compact" hide-details class="mx-1 my-2" variant="outlined"
|
||||
label="Rungs"
|
||||
:color="color" :base-color="color" min="1" :max="MAX_RUNGS"
|
||||
:disabled="rungsDisabled"
|
||||
style="width: 4.5em;"
|
||||
style="width: 6.6em;"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -46,11 +47,13 @@ import {cancelDrawing} from "@/charts/chart.js";
|
||||
import {
|
||||
devectorize,
|
||||
vectorAdd,
|
||||
vectorDiv, vectorEquals,
|
||||
vectorDiv,
|
||||
vectorEquals,
|
||||
vectorIsNull,
|
||||
vectorIsZero,
|
||||
vectorize,
|
||||
vectorMul, vectorNeg,
|
||||
vectorMul,
|
||||
vectorNeg,
|
||||
vectorSub
|
||||
} from "@/vector.js";
|
||||
|
||||
@@ -90,6 +93,13 @@ watchEffect(()=>{
|
||||
// console.log('valid?', prev, props.builder.valid, rungs, valueA.value, valueB.value)
|
||||
})
|
||||
|
||||
let lastBuy = null
|
||||
watchEffect(()=>{
|
||||
if (props.order.buy!==lastBuy) {
|
||||
lastBuy = props.order.buy
|
||||
props.builder.color=computeDefaultColor()
|
||||
}
|
||||
})
|
||||
|
||||
function setEndpoints(a, b) {
|
||||
// console.log('rb setting endpoints', devectorize(a), devectorize(b))
|
||||
@@ -322,9 +332,8 @@ function makeModel(index) {
|
||||
amount: props.order.amount * alloc,
|
||||
amountSymbol: amountSymbol.value,
|
||||
textLocation: above ? 'above' : 'below',
|
||||
extraText: !props.builder.breakout ? ' ' :
|
||||
// (above ? '↑ Breakout ↑' : '↓ Breakout ↓')
|
||||
(above ? '▲ Breakout ▲' : '▼ Breakout ▼')
|
||||
breakout: props.builder.breakout,
|
||||
extraText: null,
|
||||
}
|
||||
setModelValue(result, values.value[index])
|
||||
return result
|
||||
|
||||
@@ -9,27 +9,18 @@
|
||||
<toolbar-button tooltip="Assets" icon="mdi-currency-btc" route="Assets"/>
|
||||
<!-- mdi-format-list-checks mdi-format-list-bulleted-square -->
|
||||
<toolbar-button tooltip="Status" icon="mdi-format-list-checks" route="Status"/>
|
||||
<v-btn variant="text" icon="mdi-help-circle-outline" text="Info" @click="showCorp"></v-btn>
|
||||
<v-btn variant="text" icon="mdi-information-outline" text="Info" @click="showCorp"></v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {useChartOrderStore} from "@/orderbuild.js";
|
||||
import {useTheme} from "vuetify";
|
||||
import ToolbarButton from "@/components/chart/ToolbarButton.vue";
|
||||
import beta from "@/components/Beta.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
|
||||
const props = defineProps(['title', 'icon'])
|
||||
|
||||
const s = useStore()
|
||||
const co = useChartOrderStore()
|
||||
|
||||
const theme = useTheme().current
|
||||
|
||||
function showCorp() {
|
||||
window.open('https://dexorder.trade/', 'dexorder')
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import {useRoute} from "vue-router";
|
||||
import {nav} from "/src/misc.js"
|
||||
|
||||
const props = defineProps(['icon', 'route', 'tooltip'])
|
||||
console.log('toolbar button props', props.route)
|
||||
const router = useRoute();
|
||||
const isCurrent = computed(() => router.name === props.route)
|
||||
</script>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
<logo class="logo-xl"/>
|
||||
</v-card-item>
|
||||
<v-card-subtitle class="pl-8 mx-auto">Advanced DeFi Orders</v-card-subtitle>
|
||||
<social class="ml-12"/>
|
||||
<v-card-text>
|
||||
Dexorder powers up your favorite DeFi exchange with advanced order types!
|
||||
</v-card-text>
|
||||
@@ -15,11 +14,12 @@
|
||||
Supports Uniswap v3 <beta/>
|
||||
</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-clock-outline" class="mr-2"/> DCA and TWAP Orders <beta/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-chart-line" class="mr-2"/> Breakout Orders <beta/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-plus-minus" 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 </v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-cancel" class="mr-2"/> Single-transaction Cancel All <beta/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-alert-outline" class="mr-2"/> Single-transaction Sell Everything <soon/></v-list-item>
|
||||
<v-list-item><v-icon icon="mdi-shimmer" class="mr-2"/> Custom Complex Orders <soon/></v-list-item>
|
||||
</v-list>
|
||||
@@ -28,17 +28,20 @@
|
||||
<app-btn/>
|
||||
<v-btn prepend-icon="mdi-information-outline" variant="flat" text="How It Works" @click="nav('HowItWorks')"/>
|
||||
</div>
|
||||
<div class="w-100 d-flex justify-center my-6 actions">
|
||||
<social class="ml-12"/>
|
||||
</div>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import beta from "@/components/Beta.vue";
|
||||
import Soon from "@/components/Soon.vue";
|
||||
import HowItWorks from "@/corp/HowItWorks.vue";
|
||||
import UniswapLogo from "@/corp/UniswapLogo.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import {nav} from "@/misc.js";
|
||||
import AppBtn from "@/corp/AppBtn.vue";
|
||||
import Social from "@/components/Social.vue";
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,12 +1,95 @@
|
||||
<template>
|
||||
<v-app>
|
||||
<main-view/>
|
||||
<v-dialog v-model="showTransactionDialog" max-width="300">
|
||||
<v-card :title="title">
|
||||
<v-card-text v-if="description!==null">{{description}}</v-card-text>
|
||||
<v-card-text>Confirm this {{noun}} in your wallet.</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import MainView from './MainView.vue'
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {computed} from "vue";
|
||||
import {useWalletStore} from "@/blockchain/wallet.js";
|
||||
import {TransactionType} from "@/blockchain/transaction.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
|
||||
const s = useStore()
|
||||
const ws = useWalletStore()
|
||||
const showTransactionDialog = computed(()=>ws.transaction!==null)
|
||||
const title = computed(()=>{
|
||||
switch (ws.transaction?.type) {
|
||||
case TransactionType.PlaceOrder:
|
||||
return "Placing Order"
|
||||
case TransactionType.CancelOrder:
|
||||
return "Canceling Order"
|
||||
case TransactionType.CancelAll:
|
||||
return "Cancel All Orders"
|
||||
case TransactionType.Wrap:
|
||||
return "Wrap"
|
||||
case TransactionType.Unwrap:
|
||||
return "Unwrap"
|
||||
case TransactionType.WithdrawNative:
|
||||
case TransactionType.Withdraw:
|
||||
return "Withdraw"
|
||||
default:
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
const description = computed(()=>{
|
||||
const tx = ws.transaction
|
||||
switch (tx?.type) {
|
||||
case TransactionType.PlaceOrder:
|
||||
return describeOrder(tx.order)
|
||||
case TransactionType.CancelOrder:
|
||||
return null // todo fetch the order status and describe it
|
||||
case TransactionType.CancelAll:
|
||||
return null
|
||||
case TransactionType.Wrap:
|
||||
return `Wrap ${FixedNumber.fromValue(tx.amount,18)} ETH` // todo native token symbol and decimals
|
||||
case TransactionType.Unwrap:
|
||||
return `Unwrap ${FixedNumber.fromValue(tx.amount,18)} WETH` // todo wrapped token symbol and decimals
|
||||
case TransactionType.WithdrawNative:
|
||||
return `Withdraw ${FixedNumber.fromValue(tx.amount,18)} ETH` // todo native token symbol and decimals
|
||||
case TransactionType.Withdraw:
|
||||
return `Withdraw ${FixedNumber.fromValue(tx.amount,tx.token.d)} ${tx.token.s}`
|
||||
default:
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const noun = computed(()=>{
|
||||
const tx = ws.transaction
|
||||
switch (tx?.type) {
|
||||
case TransactionType.PlaceOrder:
|
||||
return 'order'
|
||||
case TransactionType.CancelOrder:
|
||||
return 'cancelation'
|
||||
case TransactionType.CancelAll:
|
||||
return 'cancelation'
|
||||
case TransactionType.Wrap:
|
||||
return 'wrapping'
|
||||
case TransactionType.Unwrap:
|
||||
return 'unwrapping'
|
||||
case TransactionType.WithdrawNative:
|
||||
return 'withdrawal'
|
||||
case TransactionType.Withdraw:
|
||||
return 'withdrawal'
|
||||
default:
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
function describeOrder(order) {
|
||||
return null // todo
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
14
src/misc.js
14
src/misc.js
@@ -144,7 +144,7 @@ export function inversionPreference(chainId, base, quote) {
|
||||
const inputInverted = base.a > quote.a
|
||||
const token0 = !inputInverted ? base.a : quote.a
|
||||
const token1 = inputInverted ? base.a : quote.a
|
||||
const key = [chainId, token0, token1];
|
||||
const key = [chainId, token0, token1]; // todo chainId shouldn't matter
|
||||
const prefs = usePrefStore()
|
||||
if (!(key in prefs.inverted)) {
|
||||
// todo prefer stablecoins as the quote asset
|
||||
@@ -157,6 +157,7 @@ export function inversionPreference(chainId, base, quote) {
|
||||
break // definitely inverted
|
||||
}
|
||||
}
|
||||
console.log('inverted?', base, quote, preferInverted)
|
||||
prefs.inverted[key] = preferInverted
|
||||
}
|
||||
// console.log('inversion preference', base, quote, prefs.inverted[key], inputInverted)
|
||||
@@ -187,7 +188,7 @@ const colorRanges = {
|
||||
sell: ['#CC0033', '#CCCC33'],
|
||||
}
|
||||
|
||||
export function sideColor(buy, index) {
|
||||
export function sideColor(buy, index=0) {
|
||||
const range = buy ? colorRanges.buy : colorRanges.sell
|
||||
const a = new Color(range[0]).rgb()
|
||||
const b = new Color(range[1]).rgb()
|
||||
@@ -232,7 +233,7 @@ export function intervalToSeconds(interval) {
|
||||
: interval.endsWith('S') ? 1
|
||||
: 60 // if no unit char, then it's minutes
|
||||
const result = parseInt(/\d+/.exec(interval)[0]) * unit
|
||||
console.log('intervalToSeconds', interval, result)
|
||||
// console.log('intervalToSeconds', interval, result)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -252,4 +253,9 @@ export function computeInterceptSlope(time0, price0, time1, price1) {
|
||||
const slope = (price1 - price0) / (t1 - t0)
|
||||
const intercept = price1 - slope * t1
|
||||
return [intercept, slope]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function defined(v) {
|
||||
return v !== undefined && v !== null
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ export async function notifyFillEvent(chainId, status, trancheIndex, fill) {
|
||||
const quoteAddr = status.order.inverted ? low : high
|
||||
const buy = status.order.tokenIn === quoteAddr
|
||||
const [base, quote] = await Promise.all([getToken(chainId, baseAddr), getToken(chainId, quoteAddr)]);
|
||||
const baseAmount = (buy ? fill.filledOut : fill.filledIn) * 10**-base.d
|
||||
const quoteAmount = (buy ? fill.filledIn : fill.filledOut) * 10**-quote.d
|
||||
const baseAmount = Number(buy ? fill.filledOut : fill.filledIn) * 10**-base.d
|
||||
const quoteAmount = Number(buy ? fill.filledIn : fill.filledOut) * 10**-quote.d
|
||||
const average = quoteAmount / baseAmount
|
||||
const title = `${buy?"Bought":"Sold"} ${baseAmount.toPrecision(5)} ${base.s}`;
|
||||
const msg = title +
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
// Plugins
|
||||
import { loadFonts } from './webfontloader'
|
||||
import vuetify from './vuetify'
|
||||
import pinia from '../store/pinia.js'
|
||||
import {pinia} from '../store/pinia.js'
|
||||
import router from '../router'
|
||||
import vsp from "vue-scroll-picker";
|
||||
|
||||
import "vue-scroll-picker/lib/style.css";
|
||||
|
||||
export function registerPlugins (app) {
|
||||
loadFonts()
|
||||
loadFonts().catch((e)=>console.error('Could not load fonts!',e))
|
||||
app
|
||||
.use(vuetify)
|
||||
.use(router)
|
||||
|
||||
@@ -17,6 +17,16 @@ socket.on('disconnect', () => {
|
||||
useStore().connected = false
|
||||
})
|
||||
|
||||
socket.on('approvedRegion', (approved) => {
|
||||
console.log('approved region', approved)
|
||||
useStore().regionApproved = approved
|
||||
})
|
||||
|
||||
socket.on('approvedWallet', (approved) => {
|
||||
console.log('approved wallet', approved)
|
||||
useStore().walletApproved = approved
|
||||
})
|
||||
|
||||
socket.on('p', async (chainId, pool, price) => {
|
||||
console.log('pool price from message', chainId, pool, price)
|
||||
const s = useStore()
|
||||
@@ -53,7 +63,7 @@ socket.on('vaults', (chainId, owner, vaults)=>{
|
||||
s.vaults = vaults
|
||||
if( vaults.length ) {
|
||||
const vault = vaults[0]
|
||||
flushOrders(vault)
|
||||
flushOrders(chainId, owner, 0, vault)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -95,7 +105,7 @@ socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
|
||||
}
|
||||
|
||||
const status = s.orders[vault][orderIndex]
|
||||
console.log('apply fills', status, filled)
|
||||
// console.log('apply fills', status, filled)
|
||||
|
||||
let orderIn = 0n
|
||||
let orderOut = 0n
|
||||
@@ -107,7 +117,10 @@ socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
|
||||
const numOld = ts.fills.length;
|
||||
for (let i=0; i<fills.length; i++) {
|
||||
const fill = fills[i]
|
||||
const [tx, time, fi, fo, fee] = fill
|
||||
let [tx, time, fi, fo, fee] = fill
|
||||
fi = BigInt(fi)
|
||||
fo = BigInt(fo)
|
||||
fee = BigInt(fee)
|
||||
filledIn += fi
|
||||
filledOut += fo
|
||||
if (i<=numOld) {
|
||||
@@ -124,8 +137,9 @@ socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
|
||||
orderIn += filledIn
|
||||
orderOut += filledOut
|
||||
}
|
||||
status[7] = orderIn.toString()
|
||||
status[8] = orderOut.toString()
|
||||
status.filledIn = orderIn
|
||||
status.filledOut = orderOut
|
||||
status.filled = status.order.amountIsInput ? orderIn : orderOut
|
||||
|
||||
console.log('apply fills completed', status)
|
||||
// console.log('apply fills completed', status)
|
||||
})
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// Utilities
|
||||
import { createPinia } from 'pinia'
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
|
||||
export default createPinia()
|
||||
export const pinia = createPinia()
|
||||
pinia.use(piniaPluginPersistedstate)
|
||||
|
||||
@@ -33,7 +33,7 @@ function timestamp() {
|
||||
|
||||
const UNKNOWN_PROVIDER = {}
|
||||
|
||||
const REQUIRE_AUTH = import.meta.env.VITE_REQUIRE_AUTH !== 'NOAUTH';
|
||||
const REQUIRE_APPROVAL = import.meta.env.VITE_REQUIRE_APPROVAL !== 'NO';
|
||||
|
||||
export const useStore = defineStore('app', ()=> {
|
||||
const clock = ref(timestamp()) // the clock ticks infrequently enough to be mostly stable for user display
|
||||
@@ -44,7 +44,8 @@ export const useStore = defineStore('app', ()=> {
|
||||
const theme = ref('light') // todo 'dark'
|
||||
|
||||
const connected = ref(true) // we assume a connection will succeed until socket.io complains otherwise
|
||||
const allowed = ref(!REQUIRE_AUTH)
|
||||
const regionApproved = ref(REQUIRE_APPROVAL?null:true)
|
||||
const walletApproved = ref(REQUIRE_APPROVAL?null:true)
|
||||
|
||||
const _chainId = ref(Number(Object.keys(versionMeta.chainInfo)[0]))
|
||||
const _chainInfo = ref(versionMeta.chainInfo)
|
||||
@@ -133,11 +134,12 @@ export const useStore = defineStore('app', ()=> {
|
||||
|
||||
return {
|
||||
connected,
|
||||
allowed, nav, chainId, chainInfo, chain, provider, providerRef, vaultInitCodeHash, account, vaults, vaultVersions,
|
||||
nav, chainId, chainInfo, chain, provider, providerRef, vaultInitCodeHash, account, vaults, vaultVersions,
|
||||
transactionSenders, errors, extraTokens, poolPrices, vaultBalances, orders, vault, version, upgrade, vaultOrders,
|
||||
tokens, factory, helper, theme,
|
||||
mockenv, mockCoins,
|
||||
removeTransactionSender, error, closeError, addToken, clock, timeZone, balances,
|
||||
regionApproved, walletApproved,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -197,10 +199,14 @@ export const useOrderStore = defineStore('order', ()=> {
|
||||
})
|
||||
|
||||
|
||||
export const usePrefStore = defineStore('prefs', ()=> {
|
||||
// user preferences
|
||||
const inverted = ref({})
|
||||
|
||||
return {inverted,}
|
||||
export const usePrefStore = defineStore({
|
||||
id: 'pref',
|
||||
persist: true,
|
||||
state: ()=> {
|
||||
// user preferences
|
||||
const inverted = ref({})
|
||||
const acceptedTos = ref(null)
|
||||
return {inverted, acceptedTos,}
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user