wallet flow; new faucet; placing chart orders works!
This commit is contained in:
@@ -36,7 +36,7 @@ async function componentFindRoute() {
|
|||||||
os.routes = []
|
os.routes = []
|
||||||
if (!tokenA || !tokenB)
|
if (!tokenA || !tokenB)
|
||||||
return
|
return
|
||||||
console.log('finding route', s.chainId.value, tokenA, tokenB)
|
console.log('finding route', s.chainId, tokenA, tokenB)
|
||||||
os.routesPending = true
|
os.routesPending = true
|
||||||
try {
|
try {
|
||||||
console.log('getting query helper')
|
console.log('getting query helper')
|
||||||
@@ -44,7 +44,7 @@ async function componentFindRoute() {
|
|||||||
if (!helper) {
|
if (!helper) {
|
||||||
console.log('no helper')
|
console.log('no helper')
|
||||||
} else {
|
} else {
|
||||||
const result = await findRoute(helper, s.chainId.value, tokenA, tokenB)
|
const result = await findRoute(helper, s.chainId, tokenA, tokenB)
|
||||||
console.log('found route', result)
|
console.log('found route', result)
|
||||||
os.routes = result
|
os.routes = result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import {ethers} from "ethers";
|
|||||||
|
|
||||||
// synchronous version may return null but will trigger a lookup
|
// synchronous version may return null but will trigger a lookup
|
||||||
export function token(addr) {
|
export function token(addr) {
|
||||||
|
// todo deprecated. use metadataMap[chainId][addr]
|
||||||
|
console.warn('token() is deprecated')
|
||||||
console.log('token', addr)
|
console.log('token', addr)
|
||||||
if( !addr ) {
|
if( !addr ) {
|
||||||
// console.log('ignoring call to token', addr)
|
// console.log('ignoring call to token', addr)
|
||||||
@@ -23,6 +25,8 @@ export function token(addr) {
|
|||||||
|
|
||||||
// async version doesnt return until it has a token value
|
// async version doesnt return until it has a token value
|
||||||
export async function getToken(addr) {
|
export async function getToken(addr) {
|
||||||
|
// todo deprecated. use metadataMap[chainId][addr]
|
||||||
|
console.warn('getToken() is deprecated')
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if (!(addr in s.tokens))
|
if (!(addr in s.tokens))
|
||||||
await addExtraToken(addr)
|
await addExtraToken(addr)
|
||||||
|
|||||||
@@ -6,20 +6,26 @@ import {vaultAbi} from "@/blockchain/abi.js";
|
|||||||
import {SingletonCoroutine} from "@/misc.js";
|
import {SingletonCoroutine} from "@/misc.js";
|
||||||
import {defineStore} from "pinia";
|
import {defineStore} from "pinia";
|
||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
|
import {metadata, metadataMap} from "@/version.js";
|
||||||
|
|
||||||
|
|
||||||
export const useWalletStore = defineStore('wallet', ()=>{
|
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
|
// Pending Order Format
|
||||||
// {
|
// {
|
||||||
// chainId: 31337, // must never be null, even if no wallet plugin exists. chosen by app, not wallet.
|
// chainId: 31337, // must never be null, even if no wallet plugin exists. chosen by app, not wallet.
|
||||||
// placementTime: Date.now(),
|
// placementTime: Date.now(),
|
||||||
|
// submitted: false // true after the order has started to be sent to the wallet
|
||||||
|
// tx: null // transaction ID
|
||||||
// vault: '0x...', // or null if account not logged in yet
|
// vault: '0x...', // or null if account not logged in yet
|
||||||
// order: {tokenIn:..., tokenOut:..., ...} // blockchain binary order object
|
// order: {tokenIn:..., tokenOut:..., ...} // blockchain binary order object
|
||||||
// }
|
// }
|
||||||
const pendingOrders = ref([])
|
const pendingOrders = ref([])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pendingOrders,
|
chainId, pendingOrders,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -27,27 +33,31 @@ export const useWalletStore = defineStore('wallet', ()=>{
|
|||||||
export function onChainChanged(chainId) {
|
export function onChainChanged(chainId) {
|
||||||
chainId = Number(chainId)
|
chainId = Number(chainId)
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
if( chainId !== store.chainId.value ) {
|
const ws = useWalletStore()
|
||||||
// todo check pending orders and confirm cancellation
|
if( chainId !== ws.chainId ) {
|
||||||
console.log('chain changed', chainId)
|
console.log('chain changed', chainId)
|
||||||
store.chainId.value = chainId
|
ws.chainId = chainId
|
||||||
|
if (chainId.toString() in metadataMap) {
|
||||||
|
console.log('app chain changed', chainId)
|
||||||
|
store.chainId = chainId
|
||||||
store.account = null
|
store.account = null
|
||||||
const provider = new ethers.BrowserProvider(window.ethereum, chainId);
|
}
|
||||||
store.provider = provider
|
|
||||||
provider.listAccounts().then((accounts)=>changeAccounts(chainId, accounts.map((a)=>a.address)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function updateAccounts(chainId, provider) {
|
||||||
|
provider.listAccounts().then((accounts) => changeAccounts(chainId, accounts.map((a) => a.address)))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function changeAccounts(chainId, accounts) {
|
function changeAccounts(chainId, accounts) {
|
||||||
// console.log('changeAccounts', chainId, accounts)
|
// this is a notification from the wallet that the user selected a different blockchain. that chain may or may not
|
||||||
|
// be supported. we store this value in walletStore.chainId, which may or may not be the same as
|
||||||
|
// the application's useStore().chainId
|
||||||
|
console.log('changeAccounts', chainId, accounts)
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
if( accounts.length === 0 ) {
|
if (chainId === store.chainId && accounts.length) {
|
||||||
console.log('account logged out')
|
|
||||||
store.account = null
|
|
||||||
store.vaults = []
|
|
||||||
store.vaultBalances = {}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const addr = accounts[0]
|
const addr = accounts[0]
|
||||||
console.log('account logged in', addr)
|
console.log('account logged in', addr)
|
||||||
store.account = addr
|
store.account = addr
|
||||||
@@ -55,12 +65,19 @@ function changeAccounts(chainId, accounts) {
|
|||||||
flushTransactions()
|
flushTransactions()
|
||||||
socket.emit('address', chainId, addr)
|
socket.emit('address', chainId, addr)
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
console.log('account logged out')
|
||||||
|
store.account = null
|
||||||
|
store.vaults = []
|
||||||
|
store.vaultBalances = {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAccountsChanged(accounts) {
|
function onAccountsChanged(accounts) {
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
const ws = useWalletStore()
|
||||||
if (accounts.length === 0 || accounts[0] !== store.account)
|
if (accounts.length === 0 || accounts[0] !== store.account)
|
||||||
changeAccounts(store.chainId.value, accounts);
|
changeAccounts(ws.chainId, accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function detectChain() {
|
export function detectChain() {
|
||||||
@@ -105,8 +122,49 @@ const errorHandlingProxy = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function connectProvider(chainId) {
|
||||||
|
console.log('connecting provider to chainId', chainId)
|
||||||
|
try {
|
||||||
|
return new ethers.BrowserProvider(window.ethereum, chainId)
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log('provider error', e)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function connectWallet(chainId) {
|
export async function connectWallet(chainId) {
|
||||||
await new ethers.BrowserProvider(window.ethereum, chainId).getSigner();
|
console.log('connectWallet', chainId)
|
||||||
|
const ws = useWalletStore()
|
||||||
|
if (ws.chainId !== chainId && !await switchChain(chainId))
|
||||||
|
return null
|
||||||
|
const p = await connectProvider(chainId)
|
||||||
|
if (p!==null) {
|
||||||
|
try {
|
||||||
|
return await p.getSigner();
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (e.reason!=='rejected')
|
||||||
|
console.error(e, e.reason)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function switchChain(chainId) {
|
||||||
|
if (useWalletStore().chainId === chainId)
|
||||||
|
return true
|
||||||
|
try {
|
||||||
|
await window.ethereum.request({
|
||||||
|
"method": "wallet_switchEthereumChain",
|
||||||
|
"params": [{"chainId": '0x' + chainId.toString(16)}]
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -123,7 +181,7 @@ const doDiscoverVaults = new SingletonCoroutine(_discoverVaults, 50, false)
|
|||||||
async function _discoverVaults(owner) {
|
async function _discoverVaults(owner) {
|
||||||
const result = []
|
const result = []
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( !owner || !s.chainId.value || !s.account) {
|
if( !owner || !s.chainId || !s.account) {
|
||||||
s.vaults = []
|
s.vaults = []
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -159,7 +217,7 @@ async function _discoverVaults(owner) {
|
|||||||
if( result.length )
|
if( result.length )
|
||||||
flushOrders(result[0])
|
flushOrders(result[0])
|
||||||
else
|
else
|
||||||
ensureVault2(s.chainId.value, owner, 0)
|
ensureVault2(s.chainId, owner, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,8 +234,8 @@ async function ensureVault1() {
|
|||||||
const s = useStore()
|
const s = useStore()
|
||||||
const owner = s.account;
|
const owner = s.account;
|
||||||
if (owner===null)
|
if (owner===null)
|
||||||
await connectWallet(s.chainId.value)
|
await connectWallet(s.chainId)
|
||||||
ensureVault2(s.chainId.value, owner, 0)
|
ensureVault2(s.chainId, owner, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ensureVault2(chainId, owner, num) {
|
export function ensureVault2(chainId, owner, num) {
|
||||||
@@ -209,9 +267,10 @@ export async function pendOrder(order) {
|
|||||||
console.log('order', JSON.stringify(order))
|
console.log('order', JSON.stringify(order))
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
useWalletStore().pendingOrders.push({
|
useWalletStore().pendingOrders.push({
|
||||||
chainId: s.chainId.value,
|
chainId: s.chainId,
|
||||||
placementTime: new Date(),
|
placementTime: new Date(),
|
||||||
vault: s.vaults.length ? s.vaults[0] : null,
|
vault: s.vaults.length ? s.vaults[0] : null,
|
||||||
|
submitted: false,
|
||||||
order
|
order
|
||||||
})
|
})
|
||||||
ensureVault()
|
ensureVault()
|
||||||
@@ -243,12 +302,17 @@ export async function cancelAll(vault) {
|
|||||||
|
|
||||||
export function flushOrders(vault) {
|
export function flushOrders(vault) {
|
||||||
const ws = useWalletStore();
|
const ws = useWalletStore();
|
||||||
|
let needsFlush = false
|
||||||
for( const order of ws.pendingOrders ) {
|
for( const order of ws.pendingOrders ) {
|
||||||
if (order.vault === null)
|
if (order.vault === null)
|
||||||
order.vault = vault
|
order.vault = vault
|
||||||
|
if (!order.submitted) {
|
||||||
pendOrderAsTransaction(order)
|
pendOrderAsTransaction(order)
|
||||||
|
order.submitted = true
|
||||||
|
needsFlush = true
|
||||||
}
|
}
|
||||||
ws.pendingOrders = []
|
}
|
||||||
|
if (needsFlush)
|
||||||
flushTransactions()
|
flushTransactions()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,8 +324,18 @@ function pendOrderAsTransaction(order) {
|
|||||||
console.error('vault contract was null while sending order transaction', order.vault)
|
console.error('vault contract was null while sending order transaction', order.vault)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
if (!await switchChain(order.chainId)) {
|
||||||
|
console.log('user refused chain switch')
|
||||||
|
return null
|
||||||
|
}
|
||||||
console.log('placing order', order)
|
console.log('placing order', order)
|
||||||
return await contract.placeOrder(order.order) // todo update status
|
const tx = await contract.placeOrder(order.order) // todo update status
|
||||||
|
order.tx = tx
|
||||||
|
tx.wait().then((txReceipt)=>{
|
||||||
|
const ws = useWalletStore();
|
||||||
|
ws.pendingOrders = ws.pendingOrders.filter((o)=>o!==order)
|
||||||
|
})
|
||||||
|
return tx
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,26 +347,15 @@ export function pendTransaction(sender) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const flushTransactionsRoutine = new SingletonCoroutine(asyncFlushTransactions,1)
|
||||||
|
|
||||||
let flushing = 0 // semaphore
|
let flushing = 0 // semaphore
|
||||||
|
|
||||||
export function flushTransactions() {
|
export function flushTransactions() {
|
||||||
flushing++
|
flushTransactionsRoutine.invoke()
|
||||||
if( flushing === 1 )
|
|
||||||
// noinspection JSIgnoredPromiseFromCall
|
|
||||||
asyncFlushTransactions()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function asyncFlushTransactions() {
|
async function asyncFlushTransactions() {
|
||||||
let counter
|
|
||||||
do {
|
|
||||||
counter = flushing
|
|
||||||
await asyncFlushTransactions2()
|
|
||||||
} while( flushing > counter)
|
|
||||||
flushing = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function asyncFlushTransactions2() {
|
|
||||||
// todo rework into flushTransactions()
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( s.provider === null ) {
|
if( s.provider === null ) {
|
||||||
console.log('warning: asyncFlushOrders() cancelled due to null provider')
|
console.log('warning: asyncFlushOrders() cancelled due to null provider')
|
||||||
@@ -319,22 +382,21 @@ export async function asyncFlushTransactions2() {
|
|||||||
|
|
||||||
function doSendTransaction(sender, signer) {
|
function doSendTransaction(sender, signer) {
|
||||||
const s = useStore();
|
const s = useStore();
|
||||||
sender(signer).then((tx)=>{
|
|
||||||
console.log('sent transaction', tx)
|
|
||||||
s.removeTransactionSender(sender)
|
s.removeTransactionSender(sender)
|
||||||
|
sender(signer).then((tx)=>{
|
||||||
|
if (tx!==null) {
|
||||||
|
console.log('sent transaction', tx)
|
||||||
tx.wait().then((tr)=>console.log('tx receipt',tr))
|
tx.wait().then((tr)=>console.log('tx receipt',tr))
|
||||||
|
}
|
||||||
}).catch((e)=>{
|
}).catch((e)=>{
|
||||||
if( e.info?.error?.code === 4001 ) {
|
if( e.info?.error?.code === 4001 ) {
|
||||||
console.log(`user rejected transaction`)
|
console.log(`user rejected transaction`)
|
||||||
s.removeTransactionSender(sender)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( e.reason && e.info )
|
if( e.reason && e.info )
|
||||||
console.error('error sending transaction', e.reason, e.info)
|
console.error('error sending transaction', e.reason, e.info)
|
||||||
else
|
else
|
||||||
console.error('error sending transaction', e)
|
console.error('error sending transaction', e)
|
||||||
s.removeTransactionSender(sender)
|
|
||||||
// todo retry?
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ function addSymbol(p, base, quote, inverted) {
|
|||||||
|
|
||||||
async function getAllSymbols() {
|
async function getAllSymbols() {
|
||||||
if (_symbols===null) {
|
if (_symbols===null) {
|
||||||
const chainId = useStore().chainId.value;
|
const chainId = useStore().chainId;
|
||||||
const md = metadata[chainId]
|
const md = metadata[chainId]
|
||||||
if(!md) {
|
if(!md) {
|
||||||
console.log('could not get metadata for chain', chainId)
|
console.log('could not get metadata for chain', chainId)
|
||||||
@@ -340,7 +340,7 @@ export const DataFeed = {
|
|||||||
onResetCacheNeededCallback,
|
onResetCacheNeededCallback,
|
||||||
) => {
|
) => {
|
||||||
console.log('[subscribeBars]', symbolInfo, resolution, subscriberUID);
|
console.log('[subscribeBars]', symbolInfo, resolution, subscriberUID);
|
||||||
const chainId = useStore().chainId.value;
|
const chainId = useStore().chainId;
|
||||||
const poolAddr = useChartOrderStore().selectedPool[0];
|
const poolAddr = useChartOrderStore().selectedPool[0];
|
||||||
const period = tvResolutionToPeriodString(resolution);
|
const period = tvResolutionToPeriodString(resolution);
|
||||||
subscriptions[subscriberUID] = [chainId, poolAddr, period, onRealtimeCallback, onResetCacheNeededCallback]
|
subscriptions[subscriberUID] = [chainId, poolAddr, period, onRealtimeCallback, onResetCacheNeededCallback]
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-btn :prepend-icon="icon" variant="plain" class="mx-2">
|
<v-btn :prepend-icon="icon" :variant="variant===undefined?'text':variant" class="mx-2">
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<v-icon :color="color"></v-icon>
|
<v-icon :color="color"></v-icon>
|
||||||
</template>
|
</template>
|
||||||
<slot name="text">{{text}}</slot>
|
<template v-slot>{{text}}<slot/></template>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -12,7 +12,12 @@ import {useStore} from "@/store/store";
|
|||||||
import {useAttrs} from "vue";
|
import {useAttrs} from "vue";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const props = defineProps(['icon', 'color', 'text'])
|
const props = defineProps({
|
||||||
|
icon: {default:null},
|
||||||
|
color: {default:null},
|
||||||
|
text: {default:null},
|
||||||
|
variant: {default:'text'},
|
||||||
|
})
|
||||||
const attrs = useAttrs()
|
const attrs = useAttrs()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<phone-card v-if="s.mockenv && s.vault" class="maxw">
|
<!-- <div>-->
|
||||||
|
<!--
|
||||||
<v-card-title><v-icon icon="mdi-faucet"/> Testnet Faucet</v-card-title>
|
<v-card-title><v-icon icon="mdi-faucet"/> Testnet Faucet</v-card-title>
|
||||||
<v-card-text>The Dexorder testnet faucet will send 1 TETH (Testnet ETH) to your account, plus 10 MEH (Mock Ethernet Hardfork) and 10,000 USXD (Joke Currency XD) to your vault.</v-card-text>
|
<v-card-text>The Dexorder testnet faucet will send 1 TETH (Testnet ETH) to your account, plus 10 MEH (Mock Ethernet Hardfork) and 10,000 USXD (Joke Currency XD) to your vault.</v-card-text>
|
||||||
<v-card-text>Click below to get free test tokens: </v-card-text>
|
<v-card-text>Click below to get free test tokens: </v-card-text>
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
|
-->
|
||||||
<!--
|
<!--
|
||||||
<v-table plain>
|
<v-table plain>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -14,9 +16,9 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</v-table>
|
</v-table>
|
||||||
-->
|
-->
|
||||||
<btn icon='mdi-plus' color="green" :disabled="disabled" @click="gib">GIB!</btn>
|
<btn icon='mdi-plus' color="green" :disabled="disabled" @click="gib" :text="text"/>
|
||||||
</v-card-item>
|
<!-- </v-card-item>-->
|
||||||
</phone-card>
|
<!-- </div>-->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -28,7 +30,11 @@ import {pendTransaction} from "@/blockchain/wallet.js";
|
|||||||
import {mockErc20Abi} from "@/blockchain/abi.js";
|
import {mockErc20Abi} from "@/blockchain/abi.js";
|
||||||
import Btn from "@/components/Btn.vue";
|
import Btn from "@/components/Btn.vue";
|
||||||
import {socket} from "@/socket.js";
|
import {socket} from "@/socket.js";
|
||||||
|
import {metadata} from "@/version.js";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
text: {default:'GIB!'},
|
||||||
|
})
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -45,12 +51,37 @@ function gib(token) {
|
|||||||
|
|
||||||
const disabled = ref(false)
|
const disabled = ref(false)
|
||||||
|
|
||||||
|
const FAUCET_CONFIG = {
|
||||||
|
'': 1, // native coin
|
||||||
|
MEH: 1,
|
||||||
|
USXD: 1000,
|
||||||
|
WETH: 1,
|
||||||
|
ARB: 1000,
|
||||||
|
USDC: 1000,
|
||||||
|
}
|
||||||
|
|
||||||
function gib() {
|
function gib() {
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( s.account ) {
|
if( s.account ) {
|
||||||
|
const chainId = s.chainId
|
||||||
|
const tokenAmounts = {}
|
||||||
|
const tmd = metadata[chainId].t // token metadata
|
||||||
|
for (const [symbol, amount] of Object.entries(FAUCET_CONFIG)) {
|
||||||
|
for (const t of tmd) {
|
||||||
|
if (t.s===symbol) {
|
||||||
|
if (t.x?.mock===true) {
|
||||||
|
tokenAmounts[t.a] = BigInt(Math.trunc(10 ** t.d * amount))
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('gib', s.chainId, s.account, s.vault, tokenAmounts )
|
||||||
|
if (Object.keys(tokenAmounts).length>0) {
|
||||||
disabled.value = true
|
disabled.value = true
|
||||||
socket.emit('faucet', s.chainId.value, s.account)
|
socket.emit('gib', s.chainId, s.account, s.vault, tokenAmounts )
|
||||||
setTimeout(()=>disabled.value=false, 60*1000)
|
setTimeout(()=>disabled.value=false, 1*1000) // todo disable longer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<slot v-if="ok"/>
|
<slot v-if="ok"/>
|
||||||
<phone-card v-if="!walletOk">
|
<div v-if="!walletOk">
|
||||||
<v-card-title>Install Wallet</v-card-title>
|
<h2>Install Wallet</h2>
|
||||||
<v-card-text>
|
<p>
|
||||||
A cryptocurrency wallet such as <a href="https://metamask.io/download/" target="MetaMask">MetaMask</a> is
|
A cryptocurrency wallet such as <a href="https://metamask.io/download/" target="MetaMask">MetaMask</a> is
|
||||||
required to use Dexorder. Please install a crypto wallet into your browser to experience the power of Dexorder.
|
required to use Dexorder. Please install a crypto wallet into your browser to experience the power of Dexorder.
|
||||||
</v-card-text>
|
</p>
|
||||||
<v-card-actions>
|
<p>
|
||||||
<v-btn prepend-icon="mdi-reload" text="Reload After Installing Wallet" @click="reload"/>
|
<v-btn prepend-icon="mdi-reload" text="Reload After Installing Wallet" @click="reload"/>
|
||||||
</v-card-actions>
|
</p>
|
||||||
</phone-card>
|
</div>
|
||||||
<phone-card v-if="walletOk && !providerOk">
|
<div v-if="walletOk && !providerOk">
|
||||||
<v-card-text>
|
<p>
|
||||||
Please log in to your crypto wallet.
|
Please log in to your crypto wallet.
|
||||||
</v-card-text>
|
</p>
|
||||||
<v-card-actions v-if="walletOk && !providerOk">
|
|
||||||
<v-btn prepend-icon="mdi-power" text="Connect Wallet" @click="connectWallet"/>
|
<v-btn prepend-icon="mdi-power" text="Connect Wallet" @click="connectWallet"/>
|
||||||
</v-card-actions>
|
</div>
|
||||||
</phone-card>
|
<div v-if="walletOk && chainOk && !providerOk">
|
||||||
<phone-card v-if="walletOk && providerOk && !chainOk">
|
|
||||||
<!-- todo Alpha Live
|
<!-- todo Alpha Live
|
||||||
<v-card-title><v-icon icon="mdi-reload-alert" color="warning"/> Change Blockchain</v-card-title>
|
<v-card-title><v-icon icon="mdi-reload-alert" color="warning"/> Change Blockchain</v-card-title>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
@@ -26,11 +24,14 @@
|
|||||||
<blockchain chain-id="42161"/> blockchain in your wallet.
|
<blockchain chain-id="42161"/> blockchain in your wallet.
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
-->
|
-->
|
||||||
<v-card-title><v-icon icon="mdi-hand-wave" color="warning"/> Welcome to Dexorder Alpha!</v-card-title>
|
<h2><v-icon icon="mdi-hand-wave" color="warning"/> Welcome to Dexorder Alpha!</h2>
|
||||||
<v-card-text>
|
<p>
|
||||||
This alpha test runs on a private blockchain, which you need to set up.
|
This alpha test runs on the Dexorder Testnet blockchain, which gives you free testnet tokens to trade.
|
||||||
</v-card-text>
|
</p>
|
||||||
<v-card-item>
|
<p>
|
||||||
|
<v-btn variant="tonal" @click="addChain">Setup Dexorder Testnet</v-btn>
|
||||||
|
</p>
|
||||||
|
<p>Manual Setup:</p>
|
||||||
<ol class="ml-6">
|
<ol class="ml-6">
|
||||||
<li>Open Metamask</li>
|
<li>Open Metamask</li>
|
||||||
<li>Click in the upper-left to choose a Network</li>
|
<li>Click in the upper-left to choose a Network</li>
|
||||||
@@ -38,7 +39,7 @@
|
|||||||
<li>Choose "Add a Network Manually"</li>
|
<li>Choose "Add a Network Manually"</li>
|
||||||
<li>Enter the following information:
|
<li>Enter the following information:
|
||||||
<ul>
|
<ul>
|
||||||
<li>Name: Dexorder Alpha</li>
|
<li>Name: Dexorder Alpha Testnet</li>
|
||||||
<li>New RPC URL: https://rpc.alpha.dexorder.trade</li>
|
<li>New RPC URL: https://rpc.alpha.dexorder.trade</li>
|
||||||
<li>Chain ID: 1337</li>
|
<li>Chain ID: 1337</li>
|
||||||
<li>Currency Symbol: TETH</li>
|
<li>Currency Symbol: TETH</li>
|
||||||
@@ -51,15 +52,14 @@
|
|||||||
Open Metamask again and select the "Dexorder Alpha" blockchain for use with this website.
|
Open Metamask again and select the "Dexorder Alpha" blockchain for use with this website.
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</v-card-item>
|
</div>
|
||||||
</phone-card>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {useStore} from "@/store/store";
|
import {useStore} from "@/store/store";
|
||||||
import PhoneCard from "@/components/PhoneCard.vue";
|
import PhoneCard from "@/components/PhoneCard.vue";
|
||||||
import {connectWallet} from "@/blockchain/wallet.js";
|
import {connectWallet} from "@/blockchain/wallet.js";
|
||||||
import {computed} from "vue";
|
import {computed, watch} from "vue";
|
||||||
import Blockchain from "@/components/Blockchain.vue";
|
import Blockchain from "@/components/Blockchain.vue";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
@@ -67,11 +67,42 @@ const walletOk = typeof window.ethereum !== 'undefined'
|
|||||||
const providerOk = computed(()=>s.provider!==null)
|
const providerOk = computed(()=>s.provider!==null)
|
||||||
const chainOk = computed(()=>providerOk.value && s.helper!==null)
|
const chainOk = computed(()=>providerOk.value && s.helper!==null)
|
||||||
const ok = computed(()=>{
|
const ok = computed(()=>{
|
||||||
|
console.log('recompute provider ok')
|
||||||
return walletOk && providerOk.value && chainOk.value
|
return walletOk && providerOk.value && chainOk.value
|
||||||
})
|
})
|
||||||
function reload() {
|
function reload() {
|
||||||
window.location.reload()
|
window.location.reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function addChain() {
|
||||||
|
await window.ethereum.request({
|
||||||
|
"method": "wallet_addEthereumChain",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"chainId": "0x539",
|
||||||
|
"chainName": "Dexorder Alpha Testnet",
|
||||||
|
"rpcUrls": ["https://rpc.alpha.dexorder.trade"],
|
||||||
|
"nativeCurrency": {
|
||||||
|
"name": "Test Ethereum",
|
||||||
|
"symbol": "TETH",
|
||||||
|
"decimals": 18
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([providerOk, chainOk], async () => {
|
||||||
|
console.log('checking chain')
|
||||||
|
if (walletOk && providerOk.value && !chainOk.value) {
|
||||||
|
console.log('switching chain')
|
||||||
|
const result = await window.ethereum.request({
|
||||||
|
"method": "wallet_switchEthereumChain",
|
||||||
|
"params": [{"chainId": '0x' + Object.keys(metadata)[0].toString(16)}]
|
||||||
|
});
|
||||||
|
console.log('chain switch result', result)
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -1,29 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<NeedsProvider>
|
<needs-provider>
|
||||||
<slot v-if="ok"/>
|
<slot v-if="ok" v-bind="$props"/>
|
||||||
<phone-card v-if="!ok">
|
<div v-if="!ok">
|
||||||
<v-card-title><v-icon icon="mdi-reload-alert" color="warning"/> Connect Wallet</v-card-title>
|
<btn icon="mdi-wallet-outline" color="warning" variant="outlined" @click="connect" :disabled="disabled" text="Connect Wallet"/>
|
||||||
<v-card-text>
|
</div>
|
||||||
Please select an account to use from your wallet.
|
</needs-provider>
|
||||||
</v-card-text>
|
|
||||||
<v-card-actions>
|
|
||||||
<btn icon="mdi-wallet-outline" color="warning" @click="connectWallet">Connect Wallet</btn>
|
|
||||||
</v-card-actions>
|
|
||||||
</phone-card>
|
|
||||||
</NeedsProvider>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {useStore} from "@/store/store";
|
import {useStore} from "@/store/store";
|
||||||
import NeedsProvider from "@/components/NeedsProvider.vue";
|
import NeedsProvider from "@/components/NeedsProvider.vue";
|
||||||
import {computed} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import PhoneCard from "@/components/PhoneCard.vue";
|
|
||||||
import {connectWallet} from "@/blockchain/wallet.js";
|
import {connectWallet} from "@/blockchain/wallet.js";
|
||||||
import Btn from "@/components/Btn.vue";
|
import Btn from "@/components/Btn.vue";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
|
|
||||||
const ok = computed(()=>s.account!==null)
|
const ok = computed(()=>s.account!==null)
|
||||||
|
const disabled = ref(false)
|
||||||
|
|
||||||
|
async function connect() {
|
||||||
|
disabled.value = true
|
||||||
|
try {
|
||||||
|
await connectWallet(s.chainId)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
disabled.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ const price = computed(()=>{
|
|||||||
|
|
||||||
if( route.value ) {
|
if( route.value ) {
|
||||||
subPrices([route.value])
|
subPrices([route.value])
|
||||||
subOHLCs( s.chainId.value, [[route.value.pool,'1D']])
|
subOHLCs( s.chainId, [[route.value.pool,'1D']])
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
console.log('route is empty: no price')
|
console.log('route is empty: no price')
|
||||||
|
|||||||
@@ -22,14 +22,18 @@
|
|||||||
</v-card-text>
|
</v-card-text>
|
||||||
</PhoneCard>
|
</PhoneCard>
|
||||||
-->
|
-->
|
||||||
<phone-card v-if="s.vaults.length<=num" class="maxw">
|
<div>
|
||||||
<v-card-title><v-icon icon="mdi-safe-square" size="small" color="grey-darken-1"/> Create a Dexorder Vault</v-card-title>
|
<div v-if="s.vaults.length<=num">
|
||||||
|
<v-card-title>
|
||||||
|
<v-icon icon="mdi-safe-square" size="small" color="grey-darken-1"/>
|
||||||
|
Create a Dexorder Vault
|
||||||
|
</v-card-title>
|
||||||
<v-card-text v-if="num!==0"><!--todo-->Multiple vaults are not yet supported</v-card-text>
|
<v-card-text v-if="num!==0"><!--todo-->Multiple vaults are not yet supported</v-card-text>
|
||||||
<!-- todo restore the vault-on-order approach for public beta
|
<!-- todo restore the vault-on-order approach for public beta
|
||||||
<v-card-text v-if="num===0">Create an order first, then your vault account will appear here to accept a deposit of trading funds.</v-card-text>
|
<v-card-text v-if="num===0">Create an order first, then your vault account will appear here to accept a deposit of trading funds.</v-card-text>
|
||||||
<v-card-actions><v-btn prepend-icon="mdi-plus" text="Create Order" @click="$router.push('/twap')"/></v-card-actions>
|
<v-card-actions><v-btn prepend-icon="mdi-plus" text="Create Order" @click="$router.push('/twap')"/></v-card-actions>
|
||||||
-->
|
-->
|
||||||
<!-- User-actioned but dexorder executed
|
<!-- User-actioned but dexorder executed
|
||||||
<v-card-text v-if="num===0">
|
<v-card-text v-if="num===0">
|
||||||
Your vault is a smart contract that securely holds your funds plus any orders you place. When your order
|
Your vault is a smart contract that securely holds your funds plus any orders you place. When your order
|
||||||
conditions are met, Dexorder creates a blockchain transaction for <code>vault.execute()</code>,
|
conditions are met, Dexorder creates a blockchain transaction for <code>vault.execute()</code>,
|
||||||
@@ -39,25 +43,32 @@
|
|||||||
Start placing dexorders by clicking the button below to create your own personal Vault!
|
Start placing dexorders by clicking the button below to create your own personal Vault!
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions><btn icon="mdi-safe-square" color="grey-darken-1" text="Create Vault" @click="ensureVault"/></v-card-actions>
|
<v-card-actions><btn icon="mdi-safe-square" color="grey-darken-1" text="Create Vault" @click="ensureVault"/></v-card-actions>
|
||||||
-->
|
-->
|
||||||
<v-card-text v-if="num===0">
|
<v-card-text v-if="num===0">
|
||||||
Please wait while your vault is being created. This should only take a few seconds.
|
Please wait while your vault is being created. This should only take a few seconds.
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</phone-card>
|
</div>
|
||||||
<v-card v-if="s.vaults.length>num" :class="empty?'maxw':''">
|
<div v-if="s.vaults.length>num" :class="empty?'maxw':''">
|
||||||
<v-card-title><v-icon icon="mdi-safe-square" color="grey-darken-2" size="small"/> Vault Assets {{s.vaults.length>1?'#'+(num+1):''}}</v-card-title> <!-- todo vault nicknames -->
|
<v-card-title>
|
||||||
<v-card-subtitle v-if="exists" class="overflow-x-hidden"><copy-button :text="addr"/>{{addr}}</v-card-subtitle>
|
Your Deposit Address {{ s.vaults.length > 1 ? '#' + (num + 1) : '' }}
|
||||||
|
</v-card-title> <!-- todo vault nicknames -->
|
||||||
|
<v-card-subtitle v-if="exists" class="overflow-x-hidden">
|
||||||
|
<copy-button :text="addr"/>
|
||||||
|
{{ addr }}
|
||||||
|
</v-card-subtitle>
|
||||||
<v-card-text v-if="empty">
|
<v-card-text v-if="empty">
|
||||||
<!--
|
<!--
|
||||||
<p>
|
<p>
|
||||||
Your vault is a smart contract that securely holds your funds plus any orders you place. When your order
|
Your vault is a smart contract that securely holds your funds plus any orders you place. When your order
|
||||||
conditions are met, Dexorder creates a blockchain transaction asking your vault to execute the order. Your
|
conditions are met, Dexorder creates a blockchain transaction asking your vault to execute the order. Your
|
||||||
vault then checks that order against the current blockchain time and pool price, and only trades if
|
vault then checks that order against the current blockchain time and pool price, and only trades if
|
||||||
everything looks good.
|
everything looks good.
|
||||||
</p>
|
</p>
|
||||||
-->
|
-->
|
||||||
<p v-if="!s.mockenv">There are no funds currently in your vault. Send tokens to the address above to fund your vault.</p>
|
<p v-if="!s.mockenv">There are no funds currently in your vault. Send tokens to the address above to fund your
|
||||||
<p v-if="s.mockenv">There are no funds currently in your vault. Use the faucet below to mint some testnet coins into your vault.</p>
|
vault.</p>
|
||||||
|
<p v-if="s.mockenv">There are no funds currently in your vault. Use the faucet below to mint some testnet coins
|
||||||
|
into your vault.</p>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-item v-if="!empty">
|
<v-card-item v-if="!empty">
|
||||||
<v-table>
|
<v-table>
|
||||||
@@ -68,8 +79,9 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</v-table>
|
</v-table>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
</v-card>
|
</div>
|
||||||
<withdraw :vault="addr" :token="withdrawToken" v-model="withdrawShow"/>
|
<withdraw :vault="addr" :token="withdrawToken" v-model="withdrawShow"/>
|
||||||
|
</div>
|
||||||
<!--
|
<!--
|
||||||
<div>
|
<div>
|
||||||
addr {{ addr }}<br/>
|
addr {{ addr }}<br/>
|
||||||
|
|||||||
17
src/components/chart/ChartOrders.vue
Normal file
17
src/components/chart/ChartOrders.vue
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<div class="d-flex flex-column h-100">
|
||||||
|
<toolbar title="Orders" icon="mdi-format-list-bulleted-square">
|
||||||
|
</toolbar>
|
||||||
|
<orders-view/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
import Toolbar from "@/components/chart/Toolbar.vue";
|
||||||
|
import OrdersView from "@/views/OrdersView.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
25
src/components/chart/ChartVault.vue
Normal file
25
src/components/chart/ChartVault.vue
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<div class="d-flex flex-column h-100">
|
||||||
|
<toolbar title="Assets" icon="mdi-currency-btc"></toolbar>
|
||||||
|
<needs-signer>
|
||||||
|
<vault :owner="s.account" :num="0"/>
|
||||||
|
<faucet variant="outlined" text="Get Free Testnet Coins!" style="width: 15em"/>
|
||||||
|
</needs-signer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
import Toolbar from "@/components/chart/Toolbar.vue";
|
||||||
|
import Vault from "@/components/Vault.vue";
|
||||||
|
import NeedsSigner from "@/components/NeedsSigner.vue";
|
||||||
|
import Faucet from "@/components/Faucet.vue";
|
||||||
|
import {useStore} from "@/store/store.js";
|
||||||
|
|
||||||
|
const s = useStore()
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,12 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="d-flex mb-1">
|
<div class="d-flex mb-1 align-center w-100">
|
||||||
|
<div class="d-flex align-end clickable" @click="$router.push('/place')">
|
||||||
<span class="arrow align-self-start"><v-icon icon="mdi-arrow-up-bold" :color="theme.colors.success"/></span>
|
<span class="arrow align-self-start"><v-icon icon="mdi-arrow-up-bold" :color="theme.colors.success"/></span>
|
||||||
<span class="logo">dexorder</span>
|
<span class="logo">dexorder</span>
|
||||||
<v-chip text="ALPHA" size='x-small' color="red" class="align-self-start pr-6" variant="text"/>
|
<v-chip text="ALPHA" size='x-small' color="red" class="align-self-start pr-6" variant="text"/>
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
<div class="d-flex align-center">
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
<slot/>
|
<slot/>
|
||||||
<div class="w-100 d-flex justify-end">
|
<div class="ml-auto d-flex align-center">
|
||||||
<v-btn variant="text" icon="mdi-safe-square" color="grey-darken-2" text="Vault" @click="$router.push('/vault')"></v-btn>
|
<!-- <v-icon :icon="icon" size="small"/> -->
|
||||||
<v-btn variant="text" icon="mdi-information-outline" text="Order Status" @click="$router.push('/orders')"></v-btn>
|
<span class="title">{{title}}</span>
|
||||||
|
<toolbar-button icon="mdi-currency-btc" path="/vault"/>
|
||||||
|
<toolbar-button icon="mdi-format-list-bulleted-square" path="/orders"/>
|
||||||
|
<v-btn variant="text" icon="mdi-help-circle-outline" text="Info" @click="showCorp" disabled></v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -19,21 +28,17 @@ import {timestamp} from "@/misc.js";
|
|||||||
import {ShapeType} from "@/charts/shape.js";
|
import {ShapeType} from "@/charts/shape.js";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import {useTheme} from "vuetify";
|
import {useTheme} from "vuetify";
|
||||||
|
import ToolbarButton from "@/components/chart/ToolbarButton.vue";
|
||||||
|
|
||||||
|
const props = defineProps(['title', 'icon'])
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const co = useChartOrderStore()
|
const co = useChartOrderStore()
|
||||||
|
|
||||||
const showCancel = ref(false)
|
|
||||||
|
|
||||||
const theme = useTheme().current
|
const theme = useTheme().current
|
||||||
|
|
||||||
function cancelOrder() {
|
function showCorp() {
|
||||||
showCancel.value = true
|
window.open('https://dexorder.trade', 'dexorder')
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function placeOrder() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
15
src/components/chart/ToolbarButton.vue
Normal file
15
src/components/chart/ToolbarButton.vue
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<v-btn :color="isCurrent?'primary':undefined" variant="text" :icon="icon" @click="$router.push(path)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {computed} from "vue";
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
|
||||||
|
const props = defineProps(['icon', 'path'])
|
||||||
|
const isCurrent = computed(() => useRoute().path === props.path)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -11,7 +11,7 @@ const routes = [
|
|||||||
// route level code-splitting
|
// route level code-splitting
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
// which is lazy-loaded when the route is visited.
|
// which is lazy-loaded when the route is visited.
|
||||||
component: () => import(/* webpackChunkName: "chartorder" */ '@/components/chart/ChartOrderPane.vue'),
|
component: () => import(/* webpackChunkName: "chartorder" */ '@/components/chart/ChartPlaceOrder.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/place',
|
path: '/place',
|
||||||
@@ -19,7 +19,7 @@ const routes = [
|
|||||||
// route level code-splitting
|
// route level code-splitting
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
// which is lazy-loaded when the route is visited.
|
// which is lazy-loaded when the route is visited.
|
||||||
component: () => import(/* webpackChunkName: "chartorder" */ '@/components/chart/ChartOrderPane.vue'),
|
component: () => import(/* webpackChunkName: "chartorder" */ '@/components/chart/ChartPlaceOrder.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/vault',
|
path: '/vault',
|
||||||
@@ -27,7 +27,7 @@ const routes = [
|
|||||||
// route level code-splitting
|
// route level code-splitting
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
// which is lazy-loaded when the route is visited.
|
// which is lazy-loaded when the route is visited.
|
||||||
component: () => import(/* webpackChunkName: "vaultview" */ '@/views/VaultView.vue'),
|
component: () => import(/* webpackChunkName: "vaultview" */ '@/components/chart/ChartVault.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/orders',
|
path: '/orders',
|
||||||
@@ -35,13 +35,13 @@ const routes = [
|
|||||||
// route level code-splitting
|
// route level code-splitting
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
// which is lazy-loaded when the route is visited.
|
// which is lazy-loaded when the route is visited.
|
||||||
component: () => import(/* webpackChunkName: "ordersview" */ '@/views/OrdersView.vue'),
|
component: () => import(/* webpackChunkName: "ordersview" */ '@/components/chart/ChartOrders.vue'),
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
path: '/create',
|
path: '/create',
|
||||||
name: 'Create',
|
name: 'Create',
|
||||||
component: () => import(/!* webpackChunkName: "chartorder" *!/ '@/components/chart/ChartOrderPane.vue'),
|
component: () => import(/!* webpackChunkName: "chartorder" *!/ '@/components/chart/ChartPlaceOrder.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/twap',
|
path: '/twap',
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ socket.on('disconnect', () => {
|
|||||||
socket.on('p', async (chainId, pool, price) => {
|
socket.on('p', async (chainId, pool, price) => {
|
||||||
console.log('pool price from message', chainId, pool, price)
|
console.log('pool price from message', chainId, pool, price)
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( s.chainId.value !== chainId )
|
if( s.chainId !== chainId )
|
||||||
return
|
return
|
||||||
s.poolPrices[[chainId,pool]] = price
|
s.poolPrices[[chainId,pool]] = price
|
||||||
})
|
})
|
||||||
@@ -29,7 +29,7 @@ socket.on('ohlc', async (chainId, pool, ohlcs) => {
|
|||||||
|
|
||||||
socket.on('vb', async (chainId, vault, balances) => {
|
socket.on('vb', async (chainId, vault, balances) => {
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( s.chainId.value !== chainId )
|
if( s.chainId !== chainId )
|
||||||
return
|
return
|
||||||
console.log('vb', vault, balances)
|
console.log('vb', vault, balances)
|
||||||
s.vaultBalances[vault] = JSON.parse(balances)
|
s.vaultBalances[vault] = JSON.parse(balances)
|
||||||
@@ -39,7 +39,7 @@ socket.on('vb', async (chainId, vault, balances) => {
|
|||||||
socket.on('vaults', (chainId, owner, vaults)=>{
|
socket.on('vaults', (chainId, owner, vaults)=>{
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
console.log('vaults', vaults)
|
console.log('vaults', vaults)
|
||||||
if( s.chainId.value !== chainId || s.account !== owner )
|
if( s.chainId !== chainId || s.account !== owner )
|
||||||
return
|
return
|
||||||
if( vaults.length > s.vaults.length ) {
|
if( vaults.length > s.vaults.length ) {
|
||||||
s.vaults = vaults
|
s.vaults = vaults
|
||||||
@@ -53,7 +53,7 @@ socket.on('vaults', (chainId, owner, vaults)=>{
|
|||||||
|
|
||||||
function handleOrderStatus(chainId, vault, orderIndex, status) {
|
function handleOrderStatus(chainId, vault, orderIndex, status) {
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( s.chainId.value !== chainId )
|
if( s.chainId !== chainId )
|
||||||
return
|
return
|
||||||
// message 'o' is a single order status
|
// message 'o' is a single order status
|
||||||
const parsed = parseOrderStatus(status);
|
const parsed = parseOrderStatus(status);
|
||||||
@@ -74,7 +74,7 @@ socket.on( 'o', handleOrderStatus)
|
|||||||
|
|
||||||
socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
|
socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( s.chainId.value !== chainId )
|
if( s.chainId !== chainId )
|
||||||
return
|
return
|
||||||
console.log('of', chainId, vault, orderIndex, filled)
|
console.log('of', chainId, vault, orderIndex, filled)
|
||||||
if( !(vault in s.orders) ) {
|
if( !(vault in s.orders) ) {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import {defineStore} from 'pinia'
|
|||||||
import {knownTokens} from "@/knownTokens.js";
|
import {knownTokens} from "@/knownTokens.js";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import {version} from "@/version.js";
|
import {version} from "@/version.js";
|
||||||
|
import {ethers} from "ethers";
|
||||||
|
import {updateAccounts} from "@/blockchain/wallet.js";
|
||||||
|
|
||||||
// USING THE STORE:
|
// USING THE STORE:
|
||||||
//
|
//
|
||||||
@@ -31,11 +33,15 @@ function timestamp() {
|
|||||||
return Math.round(new Date().getTime() / 1000)
|
return Math.round(new Date().getTime() / 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const UNKNOWN_PROVIDER = {}
|
||||||
|
|
||||||
|
|
||||||
export const useStore = defineStore('app', ()=> {
|
export const useStore = defineStore('app', ()=> {
|
||||||
const clock = ref(timestamp())
|
const clock = ref(timestamp())
|
||||||
const nav = ref(false) // controls opening navigation drawer
|
const nav = ref(false) // controls opening navigation drawer
|
||||||
|
|
||||||
const _chainId = ref(Object.keys(version.chainInfo)[0])
|
const _chainId = ref(Number(Object.keys(version.chainInfo)[0]))
|
||||||
const _chainInfo = ref(version.chainInfo)
|
const _chainInfo = ref(version.chainInfo)
|
||||||
|
|
||||||
function getTokenList() {
|
function getTokenList() {
|
||||||
@@ -54,25 +60,42 @@ export const useStore = defineStore('app', ()=> {
|
|||||||
result[token.address] = token
|
result[token.address] = token
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
function refreshChain() {
|
|
||||||
useOrderStore().setDefaultTokens(getTokenList())
|
|
||||||
}
|
|
||||||
const chainId = computed({
|
const chainId = computed({
|
||||||
get() {return _chainId},
|
get() {return _chainId.value},
|
||||||
set(v) {_chainId.value=v; refreshChain()}
|
set(v) {
|
||||||
|
console.log('setting chainid',_chainId.value, v)
|
||||||
|
if (_chainId.value!==v) {
|
||||||
|
console.log('do set')
|
||||||
|
_chainId.value = v
|
||||||
|
account.value = null
|
||||||
|
}
|
||||||
|
if (_chainId.value!==v || _provider.value === null) {
|
||||||
|
console.log('update provider')
|
||||||
|
_provider.value = UNKNOWN_PROVIDER
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
const chainInfo = computed({
|
const chainInfo = computed({
|
||||||
get() {return _chainInfo},
|
get() {return _chainInfo.value},
|
||||||
set(v) {_chainInfo.value=v; refreshChain()}
|
set(v) {_chainInfo.value=v}
|
||||||
})
|
})
|
||||||
const chain = computed(() => !_chainId.value ? null : (_chainInfo.value[_chainId.value] || null))
|
const chain = computed(() => !_chainId.value ? null : (_chainInfo.value[_chainId.value] || null))
|
||||||
// making the provider directly reactive causes exceptions (calling private method...) when calling provider
|
// this provider is for the app's chainId not the wallet's chainId.
|
||||||
// functions, so we use a separate ref to signal changes
|
let _provider = UNKNOWN_PROVIDER // null indicates a known-unavailable provider whereas undefined means provider status is unknown
|
||||||
let _provider = null
|
const provider = computed(()=>{
|
||||||
const _providerTouch = ref(false)
|
if (_provider===UNKNOWN_PROVIDER) {
|
||||||
const provider = computed({
|
// unknown provider status
|
||||||
get() {_providerTouch.value; return _provider},
|
try {
|
||||||
set(v) {_provider=v; _providerTouch.value = !_providerTouch.value}
|
_provider = new ethers.BrowserProvider(window.ethereum, _chainId.value);
|
||||||
|
updateAccounts(_chainId.value, _provider)
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error('could not get provider', _chainId.value, e)
|
||||||
|
_provider = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if _provider is null then it is known to be an unavailable chain
|
||||||
|
return _provider
|
||||||
})
|
})
|
||||||
const vaultInitCodeHash = computed(() => !chain.value ? null : chain.value.vaultInitCodeHash)
|
const vaultInitCodeHash = computed(() => !chain.value ? null : chain.value.vaultInitCodeHash)
|
||||||
const account = ref(null)
|
const account = ref(null)
|
||||||
|
|||||||
@@ -7,6 +7,12 @@
|
|||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-family: v.$heading-font-family;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
.clickable {
|
.clickable {
|
||||||
:hover {
|
:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ for (const [chain, info] of Object.entries(metadata)) {
|
|||||||
map[poolMeta.a] = poolMeta
|
map[poolMeta.a] = poolMeta
|
||||||
for (const tokenMeta of info.t)
|
for (const tokenMeta of info.t)
|
||||||
map[tokenMeta.a] = tokenMeta
|
map[tokenMeta.a] = tokenMeta
|
||||||
metadataMap[chain] = map
|
metadataMap[Number(chain)] = map
|
||||||
}
|
}
|
||||||
console.log('metadataMap', metadataMap)
|
console.log('metadataMap', metadataMap)
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- todo needs account -->
|
|
||||||
<needs-signer>
|
<needs-signer>
|
||||||
|
<phone-card class="maxw">
|
||||||
<vault :owner="s.account" :num="0"/>
|
<vault :owner="s.account" :num="0"/>
|
||||||
|
</phone-card>
|
||||||
|
<phone-card v-if="s.mockenv && s.vault" class="maxw">
|
||||||
<faucet class="mt-3"/>
|
<faucet class="mt-3"/>
|
||||||
|
</phone-card>
|
||||||
<new-order class="my-6"/>
|
<new-order class="my-6"/>
|
||||||
</needs-signer>
|
</needs-signer>
|
||||||
</template>
|
</template>
|
||||||
@@ -14,6 +17,7 @@ import NeedsSigner from "@/components/NeedsSigner.vue";
|
|||||||
import Faucet from "@/components/Faucet.vue";
|
import Faucet from "@/components/Faucet.vue";
|
||||||
import NeedsProvider from "@/components/NeedsProvider.vue";
|
import NeedsProvider from "@/components/NeedsProvider.vue";
|
||||||
import NewOrder from "@/components/NewOrder.vue";
|
import NewOrder from "@/components/NewOrder.vue";
|
||||||
|
import PhoneCard from "@/components/PhoneCard.vue";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user