Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bda184bba | |||
| 069fb31f82 | |||
| 7965eab85b | |||
| 321b250de0 |
5731
package-lock.json
generated
Normal file
5731
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@isaacs/ttlcache": "^1.4.1",
|
"@isaacs/ttlcache": "^1.4.1",
|
||||||
"@mdi/font": "6.9.96",
|
"@mdi/font": "6.9.96",
|
||||||
|
"@web3modal/ethers": "^5.1.11",
|
||||||
"color": "^4.2.3",
|
"color": "^4.2.3",
|
||||||
"core-js": "^3.29.0",
|
"core-js": "^3.29.0",
|
||||||
"ethers": "^6.7.1",
|
"ethers": "^6.16.0",
|
||||||
"flexsearch": "^0.7.43",
|
"flexsearch": "^0.7.43",
|
||||||
"lru-cache": "^11.0.2",
|
"lru-cache": "^11.0.2",
|
||||||
"luxon": "^3.4.4",
|
"luxon": "^3.4.4",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {metadataMap, version} from "@/version.js";
|
|||||||
import {TransactionState, TransactionType} from "@/blockchain/transactionDecl.js";
|
import {TransactionState, TransactionType} from "@/blockchain/transactionDecl.js";
|
||||||
import {track} from "@/track.js";
|
import {track} from "@/track.js";
|
||||||
import {socket} from "@/socket.js";
|
import {socket} from "@/socket.js";
|
||||||
|
import {web3modal} from "@/blockchain/web3modal.js";
|
||||||
|
|
||||||
|
|
||||||
export const useWalletStore = defineStore('wallet', ()=>{
|
export const useWalletStore = defineStore('wallet', ()=>{
|
||||||
@@ -131,7 +132,8 @@ export function detectChain() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
detectChain()
|
// Commented out - Web3Modal handles wallet detection now
|
||||||
|
// detectChain()
|
||||||
|
|
||||||
const errorHandlingProxy = {
|
const errorHandlingProxy = {
|
||||||
get(target, prop, proxy) {
|
get(target, prop, proxy) {
|
||||||
@@ -166,29 +168,123 @@ const errorHandlingProxy = {
|
|||||||
|
|
||||||
|
|
||||||
export async function connectWallet(chainId) {
|
export async function connectWallet(chainId) {
|
||||||
console.log('connectWallet', chainId)
|
console.log('connectWallet via Web3Modal', chainId)
|
||||||
|
|
||||||
|
// Return a promise that resolves when connection is complete
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let resolved = false
|
||||||
|
let unsubscribeProvider = null
|
||||||
|
let unsubscribeState = null
|
||||||
|
|
||||||
|
// Subscribe to provider changes (fires when wallet connects)
|
||||||
|
unsubscribeProvider = web3modal.subscribeProvider(async (newState) => {
|
||||||
|
console.log('Provider state changed:', newState)
|
||||||
|
|
||||||
|
if (newState.provider && !resolved) {
|
||||||
|
resolved = true
|
||||||
|
unsubscribeProvider?.()
|
||||||
|
unsubscribeState?.()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await switchChain(chainId)
|
const walletProvider = newState.provider
|
||||||
console.log('getSigner')
|
|
||||||
const p = new BrowserProvider(window.ethereum, chainId)
|
// Create ethers provider from Web3Modal provider
|
||||||
await p.getSigner()
|
const p = new BrowserProvider(walletProvider)
|
||||||
await updateAccounts(chainId, p)
|
setProvider(p)
|
||||||
|
|
||||||
|
// Get network info from the provider
|
||||||
|
const network = await p.getNetwork()
|
||||||
|
const connectedChainId = Number(network.chainId)
|
||||||
|
|
||||||
|
console.log('Connected to chain', connectedChainId)
|
||||||
|
|
||||||
|
// Update wallet store
|
||||||
|
const ws = useWalletStore()
|
||||||
|
ws.chainId = connectedChainId
|
||||||
|
|
||||||
|
// Get accounts
|
||||||
|
await updateAccounts(connectedChainId, p)
|
||||||
|
|
||||||
|
// Subscribe to Web3Modal provider events
|
||||||
|
subscribeToProviderEvents(walletProvider)
|
||||||
|
|
||||||
|
resolve()
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error after connection', e)
|
||||||
|
reject(e)
|
||||||
}
|
}
|
||||||
catch (e) {
|
}
|
||||||
console.log('connectWallet error', e.reason, e)
|
})
|
||||||
if (e.reason==='rejected') {
|
|
||||||
|
// Subscribe to modal state (fires when modal opens/closes)
|
||||||
|
unsubscribeState = web3modal.subscribeState((state) => {
|
||||||
|
// If modal closes without connection, resolve the promise
|
||||||
|
if (state.open === false && !resolved) {
|
||||||
|
console.log('Modal closed without connection')
|
||||||
|
resolved = true
|
||||||
|
unsubscribeProvider?.()
|
||||||
|
unsubscribeState?.()
|
||||||
|
resolve() // Resolve (not reject) so the button re-enables
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Open the modal
|
||||||
|
web3modal.open().catch((e) => {
|
||||||
|
if (!resolved) {
|
||||||
|
resolved = true
|
||||||
|
unsubscribeProvider?.()
|
||||||
|
unsubscribeState?.()
|
||||||
|
|
||||||
|
if (e.reason === 'rejected' || e.message?.includes('rejected')) {
|
||||||
const ws = useWalletStore();
|
const ws = useWalletStore();
|
||||||
const tx = ws.transaction
|
const tx = ws.transaction
|
||||||
if (tx) {
|
if (tx) {
|
||||||
tx.state = TransactionState.Rejected
|
tx.state = TransactionState.Rejected
|
||||||
ws.transaction = null
|
ws.transaction = null
|
||||||
}
|
}
|
||||||
}
|
resolve() // Don't reject on user cancellation
|
||||||
else {
|
} else {
|
||||||
console.error(e, e.reason)
|
reject(e)
|
||||||
throw e
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Timeout after 60 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!resolved) {
|
||||||
|
resolved = true
|
||||||
|
unsubscribeProvider?.()
|
||||||
|
unsubscribeState?.()
|
||||||
|
console.log('Connection timeout')
|
||||||
|
resolve() // Resolve instead of reject so button re-enables
|
||||||
|
}
|
||||||
|
}, 60000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe to provider events from Web3Modal
|
||||||
|
function subscribeToProviderEvents(walletProvider) {
|
||||||
|
// Handle account changes
|
||||||
|
walletProvider.on('accountsChanged', (accounts) => {
|
||||||
|
console.log('accountsChanged from Web3Modal', accounts)
|
||||||
|
if (accounts.length === 0) {
|
||||||
|
disconnectWallet()
|
||||||
|
} else {
|
||||||
|
onAccountsChanged(accounts)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Handle chain changes
|
||||||
|
walletProvider.on('chainChanged', (chainId) => {
|
||||||
|
console.log('chainChanged from Web3Modal', chainId)
|
||||||
|
onChainChanged(chainId)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Handle disconnect
|
||||||
|
walletProvider.on('disconnect', () => {
|
||||||
|
console.log('Provider disconnected from Web3Modal')
|
||||||
|
disconnectWallet()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -637,21 +733,7 @@ export async function addNetwork(chainId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function addNetworkAndConnectWallet(chainId) {
|
export async function addNetworkAndConnectWallet(chainId) {
|
||||||
try {
|
|
||||||
await switchChain(chainId)
|
|
||||||
} catch (e) {
|
|
||||||
if (e.code === 4001) {
|
|
||||||
// explicit user rejection
|
|
||||||
return
|
|
||||||
} else if (e.code === 4902) {
|
|
||||||
try {
|
|
||||||
await addNetwork(chainId)
|
|
||||||
} catch (e) {
|
|
||||||
console.log(`Could not add network ${chainId}`)
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
console.log('switchChain() failure', e)
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
await connectWallet(chainId)
|
await connectWallet(chainId)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -659,3 +741,44 @@ export async function addNetworkAndConnectWallet(chainId) {
|
|||||||
console.log('connectWallet() failed', e)
|
console.log('connectWallet() failed', e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function disconnectWallet() {
|
||||||
|
console.log('disconnectWallet')
|
||||||
|
const store = useStore()
|
||||||
|
const ws = useWalletStore()
|
||||||
|
|
||||||
|
// Disconnect from Web3Modal
|
||||||
|
try {
|
||||||
|
await web3modal.disconnect()
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Web3Modal disconnect error (ignoring)', e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear provider
|
||||||
|
setProvider(null)
|
||||||
|
|
||||||
|
// Clear account and vaults
|
||||||
|
store.account = null
|
||||||
|
store.vaults = []
|
||||||
|
store.vaultVersions = []
|
||||||
|
|
||||||
|
// Clear any pending transactions
|
||||||
|
if (ws.transaction !== null) {
|
||||||
|
ws.transaction = null
|
||||||
|
}
|
||||||
|
ws.pendingOrders = []
|
||||||
|
|
||||||
|
// Clear transaction senders
|
||||||
|
store.transactionSenders = []
|
||||||
|
|
||||||
|
// Emit socket disconnect
|
||||||
|
socket.emit('address', ws.chainId, null)
|
||||||
|
|
||||||
|
track('logout', {chainId: ws.chainId})
|
||||||
|
console.log('Wallet disconnected')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make it globally accessible from console
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.disconnectWallet = disconnectWallet
|
||||||
|
}
|
||||||
|
|||||||
53
src/blockchain/web3modal.js
Normal file
53
src/blockchain/web3modal.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
// src/blockchain/web3modal.js
|
||||||
|
import { createWeb3Modal, defaultConfig } from '@web3modal/ethers'
|
||||||
|
|
||||||
|
const projectId = 'a2302c95fedb32f4c64672a41159df37' // Get from https://cloud.walletconnect.com
|
||||||
|
|
||||||
|
const chains = [
|
||||||
|
{
|
||||||
|
chainId: 42161,
|
||||||
|
name: 'Arbitrum One',
|
||||||
|
currency: 'ETH',
|
||||||
|
explorerUrl: 'https://arbiscan.io',
|
||||||
|
rpcUrl: 'https://arbitrum-mainnet.infura.io'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chainId: 1337,
|
||||||
|
name: 'Dexorder Alpha Testnet',
|
||||||
|
currency: 'TETH',
|
||||||
|
explorerUrl: '',
|
||||||
|
rpcUrl: 'https://rpc.alpha.dexorder.com'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chainId: 31337,
|
||||||
|
name: 'Mockchain',
|
||||||
|
currency: 'TETH',
|
||||||
|
explorerUrl: '',
|
||||||
|
rpcUrl: 'http://localhost:8545'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const ethersConfig = defaultConfig({
|
||||||
|
metadata: {
|
||||||
|
name: 'Dexorder',
|
||||||
|
description: 'Dexorder Trading Platform',
|
||||||
|
url: window.location.origin,
|
||||||
|
icons: ['https://your-icon-url.com']
|
||||||
|
},
|
||||||
|
defaultChainId: 42161,
|
||||||
|
enableEIP6963: false, // Disable to prevent wallets from auto-announcing
|
||||||
|
enableInjected: true,
|
||||||
|
enableCoinbase: true,
|
||||||
|
rpcUrl: 'https://arbitrum-mainnet.infura.io'
|
||||||
|
})
|
||||||
|
|
||||||
|
export const web3modal = createWeb3Modal({
|
||||||
|
ethersConfig,
|
||||||
|
chains,
|
||||||
|
projectId,
|
||||||
|
enableAnalytics: false,
|
||||||
|
themeMode: 'dark',
|
||||||
|
featuredWalletIds: [
|
||||||
|
'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96' // MetaMask
|
||||||
|
],
|
||||||
|
})
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<v-card-actions v-if="status>Status.NEEDS_PLUGIN">
|
<v-card-actions v-if="status>Status.NEEDS_PLUGIN">
|
||||||
<btn v-if="pluginOk" icon="mdi-wallet-outline" color="warning" variant="outlined"
|
<btn v-if="pluginOk" icon="mdi-wallet-outline" color="green-accent-4" variant="flat"
|
||||||
@click="connect" :disabled="disabled" text="Connect Wallet"/>
|
@click="connect" :disabled="disabled" text="Connect Wallet" class="connect-wallet-btn"/>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
|
|
||||||
</v-card>
|
</v-card>
|
||||||
@@ -87,4 +87,16 @@ async function connect() {
|
|||||||
#manualsetup tr td:last-child {
|
#manualsetup tr td:last-child {
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.connect-wallet-btn) {
|
||||||
|
background-color: #00ff41 !important;
|
||||||
|
color: #000 !important;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: 0 0 8px rgba(0, 255, 65, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.connect-wallet-btn:hover) {
|
||||||
|
background-color: #00cc34 !important;
|
||||||
|
box-shadow: 0 0 12px rgba(0, 255, 65, 0.4) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
26
src/main.js
26
src/main.js
@@ -15,6 +15,11 @@ import { registerPlugins } from '@/plugins'
|
|||||||
import '@/styles/style.scss'
|
import '@/styles/style.scss'
|
||||||
import "./socketInit.js"
|
import "./socketInit.js"
|
||||||
import "./version.js"
|
import "./version.js"
|
||||||
|
import { web3modal } from '@/blockchain/web3modal.js'
|
||||||
|
import { BrowserProvider } from 'ethers'
|
||||||
|
import { setProvider } from '@/blockchain/provider.js'
|
||||||
|
import { updateAccounts } from '@/blockchain/wallet.js'
|
||||||
|
import { useWalletStore } from '@/blockchain/wallet.js'
|
||||||
|
|
||||||
BigInt.prototype.toJSON = function() { return this.toString() }
|
BigInt.prototype.toJSON = function() { return this.toString() }
|
||||||
|
|
||||||
@@ -22,3 +27,24 @@ const app = createApp(App)
|
|||||||
registerPlugins(app)
|
registerPlugins(app)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
window.$vuetify = app
|
window.$vuetify = app
|
||||||
|
|
||||||
|
// Check if Web3Modal has an existing connection on app start
|
||||||
|
web3modal.subscribeProvider(async (state) => {
|
||||||
|
if (state.isConnected && state.provider) {
|
||||||
|
try {
|
||||||
|
console.log('Restoring existing Web3Modal connection')
|
||||||
|
const p = new BrowserProvider(state.provider)
|
||||||
|
setProvider(p)
|
||||||
|
|
||||||
|
const network = await p.getNetwork()
|
||||||
|
const chainId = Number(network.chainId)
|
||||||
|
|
||||||
|
const ws = useWalletStore()
|
||||||
|
ws.chainId = chainId
|
||||||
|
|
||||||
|
await updateAccounts(chainId, p)
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error restoring connection', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user