From db2feb88424d071a61f2c70caf090702bbe17e41 Mon Sep 17 00:00:00 2001
From: Tim
Date: Thu, 11 Apr 2024 19:50:28 -0400
Subject: [PATCH] wallet connection fixes
---
src/blockchain/prices.js | 2 +-
src/blockchain/route.js | 3 +-
src/blockchain/token.js | 5 +-
src/blockchain/wallet.js | 100 +++++++++++++++++++------------
src/components/CopyButton.vue | 2 +-
src/components/NeedsProvider.vue | 72 ++++++++++------------
src/components/NeedsSigner.vue | 89 ++++++++++++++++++++++++---
src/components/Status.vue | 1 +
src/store/store.js | 28 ++-------
9 files changed, 188 insertions(+), 114 deletions(-)
diff --git a/src/blockchain/prices.js b/src/blockchain/prices.js
index 8273d07..bb76c25 100644
--- a/src/blockchain/prices.js
+++ b/src/blockchain/prices.js
@@ -5,6 +5,7 @@ import {uniswapV3PoolAddress} from "@/blockchain/uniswap.js";
import {ethers, FixedNumber} from "ethers";
import {uniswapV3PoolAbi} from "@/blockchain/abi.js";
import {subOHLCs} from "@/blockchain/ohlcs.js";
+import {provider} from "@/blockchain/wallet.js";
const subscriptionCounts = {} // key is route and value is a subscription counter
export const WIDE_PRICE_FORMAT = {decimals:38, width:512, signed:false}; // 38 decimals is 127 bits
@@ -79,7 +80,6 @@ async function getPriceForRoute(route) {
if( route.exchange === Exchange.UniswapV3 ) {
const addr = uniswapV3PoolAddress(route.chainId, route.token0.address, route.token1.address, route.fee)
const store = useStore();
- const provider = store.provider;
if( provider === null ) {
console.error('provider was null during getPriceForRoute')
return null
diff --git a/src/blockchain/route.js b/src/blockchain/route.js
index 21d127f..0f1a36f 100644
--- a/src/blockchain/route.js
+++ b/src/blockchain/route.js
@@ -2,6 +2,7 @@ import {Exchange} from "@/blockchain/orderlib.js";
import {useOrderStore, useStore} from "@/store/store.js";
import {queryHelperContract} from "@/blockchain/contract.js";
import {SingletonCoroutine} from "@/misc.js";
+import {provider} from "@/blockchain/wallet.js";
export async function findRoute(helper, chainId, tokenA, tokenB) {
@@ -40,7 +41,7 @@ async function componentFindRoute() {
os.routesPending = true
try {
console.log('getting query helper')
- const helper = await queryHelperContract(s.helper, s.provider)
+ const helper = await queryHelperContract(s.helper, provider)
if (!helper) {
console.log('no helper')
} else {
diff --git a/src/blockchain/token.js b/src/blockchain/token.js
index ac3370e..702205d 100644
--- a/src/blockchain/token.js
+++ b/src/blockchain/token.js
@@ -3,6 +3,7 @@ import {useStore} from "@/store/store.js";
import {erc20Abi} from "@/blockchain/abi.js";
import {ethers} from "ethers";
import {metadata, metadataMap} from "@/version.js";
+import {provider} from "@/blockchain/wallet.js";
// synchronous version may return null but will trigger a lookup
@@ -58,12 +59,12 @@ export async function addExtraToken(chainId, addr) {
resolve(info)
}
else {
- if( s.provider===null ) {
+ if( provider===null ) {
console.log('warning: token lookup cancelled due to null provider', addr)
resolve(null)
}
else {
- const token = new ethers.Contract(addr, erc20Abi, s.provider)
+ const token = new ethers.Contract(addr, erc20Abi, provider)
Promise.all( [token.name(), token.symbol(), token.decimals()] ).then((name,symbol,decimals)=>{
info = {
a: addr,
diff --git a/src/blockchain/wallet.js b/src/blockchain/wallet.js
index 0eedf98..3da7735 100644
--- a/src/blockchain/wallet.js
+++ b/src/blockchain/wallet.js
@@ -1,4 +1,4 @@
-import {ethers} from "ethers";
+import {BrowserProvider, ethers} from "ethers";
import {useStore} from "@/store/store";
import {socket} from "@/socket.js";
import {contractOrNull, vaultAddress} from "@/blockchain/contract.js";
@@ -9,6 +9,9 @@ import {ref} from "vue";
import {metadataMap} from "@/version.js";
+export let provider = null
+
+
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)
@@ -31,6 +34,7 @@ export const useWalletStore = defineStore('wallet', ()=>{
export function onChainChanged(chainId) {
+ console.log('onChainChanged', chainId)
chainId = Number(chainId)
const store = useStore()
const ws = useWalletStore()
@@ -41,6 +45,8 @@ export function onChainChanged(chainId) {
console.log('app chain changed', chainId)
store.chainId = chainId
store.account = null
+ provider = new BrowserProvider(window.ethereum, chainId)
+ updateAccounts(chainId, provider)
}
else {
console.log('app chain NOT changed')
@@ -77,6 +83,7 @@ function changeAccounts(chainId, accounts) {
}
function onAccountsChanged(accounts) {
+ console.log('onAccountsChanged', accounts)
const store = useStore()
const ws = useWalletStore()
if (accounts.length === 0 || accounts[0] !== store.account)
@@ -84,11 +91,17 @@ function onAccountsChanged(accounts) {
}
export function detectChain() {
+ try {
+ window.ethereum.on('chainChanged', onChainChanged);
+ window.ethereum.on('accountsChanged', onAccountsChanged);
+ }
+ catch (e) {
+ console.log('Could not connect change hooks to wallet', e)
+ return
+ }
new ethers.BrowserProvider(window.ethereum).getNetwork().then((network)=>{
const chainId = network.chainId
onChainChanged(chainId)
- window.ethereum.on('chainChanged', onChainChanged);
- window.ethereum.on('accountsChanged', onAccountsChanged);
})
}
@@ -125,50 +138,50 @@ const errorHandlingProxy = {
}
-export async function connectProvider(chainId) {
- console.log('connectProvider', chainId)
- try {
- return new ethers.BrowserProvider(window.ethereum, chainId)
- }
- catch (e) {
- console.log('provider error', e)
- }
- return null
-}
-
-
export async function connectWallet(chainId) {
console.log('connectWallet', chainId)
- const ws = useWalletStore()
- if (ws.chainId !== chainId && !await switchChain(chainId))
- return null
- const p = await connectProvider(chainId)
- if (p!==null) {
+ await switchChain(chainId)
+ if (provider!==null) {
try {
console.log('getSigner')
- return await p.getSigner();
+ await provider.getSigner()
+ await updateAccounts(chainId, provider)
}
catch (e) {
if (e.reason!=='rejected')
console.error(e, e.reason)
- return null
}
}
+ else
+ console.error('provider was null after chain switch')
}
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
- }
+ return
+ await window.ethereum.request({
+ "method": "wallet_switchEthereumChain",
+ "params": [{"chainId": '0x' + chainId.toString(16)}]
+ })
+}
+
+
+export async function addTestnet() {
+ const info = {
+ "chainId": "0x539",
+ "chainName": "Dexorder Alpha Testnet",
+ "rpcUrls": ["https://rpc.alpha.dexorder.trade"],
+ "nativeCurrency": {
+ "name": "Test Ethereum",
+ "symbol": "TETH",
+ "decimals": 18
+ }
+ };
+ await window.ethereum.request({
+ "method": "wallet_addEthereumChain",
+ "params": [info]
+ });
}
@@ -198,7 +211,7 @@ async function _discoverVaults(owner) {
s.vaults = []
return
}
- const provider = s.provider;
+ console.log('provider', provider)
if (!provider) {
console.log('No provider')
return // do not change whatever was already found
@@ -350,10 +363,19 @@ function pendOrderAsTransaction(pend) {
console.error('vault contract was null while sending order transaction', pend.vault)
return null
}
- if (!await switchChain(pend.chainId)) {
- console.log('user refused chain switch')
- pend.state = PendingOrderState.Rejected
- return null
+ try {
+ await switchChain(pend.chainId)
+ }
+ catch (e) {
+ if(e.code===4001) {
+ console.log('user refused chain switch')
+ pend.state = PendingOrderState.Rejected
+ return null
+ }
+ else {
+ console.error('Unknown error while switching chain to pend order', e)
+ return null
+ }
}
console.log('placing order', pend.id)
const tx = await contract.placeDexorder(pend.order) // todo update status
@@ -393,7 +415,7 @@ export function flushTransactions() {
async function asyncFlushTransactions() {
const s = useStore()
- if( s.provider === null ) {
+ if( provider === null ) {
console.log('warning: asyncFlushOrders() cancelled due to null provider')
return
}
@@ -403,7 +425,7 @@ async function asyncFlushTransactions() {
console.log(`flushing ${senders.length} transactions`)
let signer
try {
- signer = await s.provider.getSigner();
+ signer = await provider.getSigner();
} catch (e) {
// {
// "code": -32002,
diff --git a/src/components/CopyButton.vue b/src/components/CopyButton.vue
index 7ea4c6b..4b9345e 100644
--- a/src/components/CopyButton.vue
+++ b/src/components/CopyButton.vue
@@ -7,7 +7,7 @@
:icon="error?'mdi-close-box-outline':copied?'mdi-check-circle-outline':'mdi-content-copy'"
:text="showText?text:''"
/>
-
+ {{text}}
Copied!
diff --git a/src/components/NeedsProvider.vue b/src/components/NeedsProvider.vue
index 7720ce2..eee2cc1 100644
--- a/src/components/NeedsProvider.vue
+++ b/src/components/NeedsProvider.vue
@@ -10,20 +10,24 @@
+
+
+ TODO
+
+–>
Welcome to Dexorder Alpha!
This alpha test runs on the Dexorder Testnet blockchain, which gives you free testnet tokens to trade.
@@ -52,54 +56,42 @@
Open Metamask again and select the "Dexorder Alpha" blockchain for use with this website.
+-->
diff --git a/src/components/Status.vue b/src/components/Status.vue
index 18da8ee..9988965 100644
--- a/src/components/Status.vue
+++ b/src/components/Status.vue
@@ -266,6 +266,7 @@ const orders = computed(()=>{
st.token1 = o.tokenIn < o.tokenOut ? o.tokenOut : o.tokenIn
}
}
+ result.sort((a,b)=>b.start-a.start)
console.log('orders', result)
return result
})
diff --git a/src/store/store.js b/src/store/store.js
index 5b9af52..69fe64f 100644
--- a/src/store/store.js
+++ b/src/store/store.js
@@ -3,8 +3,6 @@ import {defineStore} from 'pinia'
import {knownTokens} from "@/knownTokens.js";
import {computed, ref} from "vue";
import {version} from "@/version.js";
-import {ethers} from "ethers";
-import {updateAccounts} from "@/blockchain/wallet.js";
// USING THE STORE:
//
@@ -70,9 +68,9 @@ export const useStore = defineStore('app', ()=> {
_chainId.value = v
account.value = null
}
- if (changed || _provider.value === null) {
+ if (changed || providerRef.value === null) {
console.log('invalidating provider')
- _provider.value = UNKNOWN_PROVIDER
+ providerRef.value = UNKNOWN_PROVIDER
}
}
})
@@ -82,22 +80,8 @@ export const useStore = defineStore('app', ()=> {
})
const chain = computed(() => !_chainId.value ? null : (_chainInfo.value[_chainId.value] || null))
// this provider is for the app's chainId not the wallet's chainId.
- let _provider = UNKNOWN_PROVIDER // null indicates a known-unavailable provider whereas undefined means provider status is unknown
- const provider = computed(()=>{
- if (_provider===UNKNOWN_PROVIDER) {
- // unknown provider status
- try {
- _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 providerRef = ref(null)
+ const provider = computed(()=>providerRef.value)
const vaultInitCodeHash = computed(() => !chain.value ? null : chain.value.vaultInitCodeHash)
const account = ref(null)
const vaults = ref([])
@@ -140,8 +124,8 @@ export const useStore = defineStore('app', ()=> {
setInterval(()=>clock.value=timestamp(), 10*1000)
return {
- nav, chainId, chainInfo, chain, provider, vaultInitCodeHash, account, vaults, transactionSenders, errors,
- extraTokens, poolPrices, vaultBalances, orders, vault, tokens, factory, helper, mockenv, mockCoins,
+ nav, chainId, chainInfo, chain, provider, providerRef, vaultInitCodeHash, account, vaults, transactionSenders,
+ errors, extraTokens, poolPrices, vaultBalances, orders, vault, tokens, factory, helper, mockenv, mockCoins,
removeTransactionSender, error, closeError, addToken, clock, balances,
}
})