@meshconnect/web-link-sdk 3.2.15 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Link.d.ts +2 -0
- package/Link.js +535 -0
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +9 -20
- package/utils/connectors/evm/chainConfigs.d.ts +2 -0
- package/utils/connectors/evm/chainConfigs.js +115 -0
- package/utils/connectors/evm/chainSwitching.d.ts +15 -0
- package/utils/connectors/evm/chainSwitching.js +242 -0
- package/utils/connectors/evm/index.d.ts +8 -0
- package/utils/connectors/evm/index.js +8 -0
- package/utils/connectors/evm/provider.d.ts +6 -0
- package/utils/connectors/evm/provider.js +13 -0
- package/utils/connectors/evm/signing.d.ts +1 -0
- package/utils/connectors/evm/signing.js +78 -0
- package/utils/connectors/evm/transactions.d.ts +28 -0
- package/utils/connectors/evm/transactions.js +381 -0
- package/utils/connectors/evm/types.d.ts +57 -0
- package/utils/connectors/evm/types.js +1 -0
- package/utils/connectors/evm/walletConnection.d.ts +20 -0
- package/utils/connectors/evm/walletConnection.js +160 -0
- package/utils/connectors/evm/walletDiscovery.d.ts +10 -0
- package/utils/connectors/evm/walletDiscovery.js +55 -0
- package/utils/connectors/solana/connection.d.ts +4 -0
- package/utils/connectors/solana/connection.js +108 -0
- package/utils/connectors/solana/index.d.ts +5 -0
- package/utils/connectors/solana/index.js +5 -0
- package/utils/connectors/solana/providerDiscovery.d.ts +3 -0
- package/utils/connectors/solana/providerDiscovery.js +127 -0
- package/utils/connectors/solana/signing.d.ts +1 -0
- package/utils/connectors/solana/signing.js +59 -0
- package/utils/connectors/solana/transaction.d.ts +17 -0
- package/utils/connectors/solana/transaction.js +362 -0
- package/utils/connectors/solana/types.d.ts +71 -0
- package/utils/connectors/solana/types.js +8 -0
- package/utils/event-types.d.ts +233 -0
- package/{src/utils/event-types.test.ts → utils/event-types.js} +5 -15
- package/utils/popup.d.ts +3 -0
- package/utils/popup.js +36 -0
- package/utils/sdk-specs.d.ts +5 -0
- package/utils/sdk-specs.js +6 -0
- package/utils/style.d.ts +3 -0
- package/utils/style.js +13 -0
- package/utils/types.d.ts +234 -0
- package/utils/types.js +1 -0
- package/utils/version.d.ts +1 -0
- package/utils/version.js +1 -0
- package/utils/wallet/EVMWalletStrategy.d.ts +31 -0
- package/utils/wallet/EVMWalletStrategy.js +265 -0
- package/utils/wallet/SolanaWalletStrategy.d.ts +33 -0
- package/utils/wallet/SolanaWalletStrategy.js +300 -0
- package/utils/wallet/WalletStrategy.d.ts +61 -0
- package/utils/wallet/WalletStrategy.js +25 -0
- package/utils/wallet/WalletStrategyFactory.d.ts +15 -0
- package/utils/wallet/WalletStrategyFactory.js +31 -0
- package/utils/wallet/index.d.ts +4 -0
- package/utils/wallet/index.js +4 -0
- package/utils/wallet-browser-event-types.d.ts +116 -0
- package/utils/wallet-browser-event-types.js +17 -0
- package/jest.setup.ts +0 -4
- package/src/Link.test.ts +0 -434
- package/src/Link.ts +0 -491
- package/src/index.ts +0 -3
- package/src/utils/__snapshots__/popup.test.ts.snap +0 -89
- package/src/utils/connectors/evm/chainConfigs.ts +0 -120
- package/src/utils/connectors/evm/chainSwitching.ts +0 -165
- package/src/utils/connectors/evm/index.ts +0 -8
- package/src/utils/connectors/evm/provider.ts +0 -22
- package/src/utils/connectors/evm/signing.ts +0 -39
- package/src/utils/connectors/evm/transactions.ts +0 -356
- package/src/utils/connectors/evm/types.ts +0 -63
- package/src/utils/connectors/evm/walletConnection.ts +0 -140
- package/src/utils/connectors/evm/walletDiscovery.ts +0 -67
- package/src/utils/connectors/solana/connection.ts +0 -69
- package/src/utils/connectors/solana/index.ts +0 -5
- package/src/utils/connectors/solana/providerDiscovery.ts +0 -153
- package/src/utils/connectors/solana/signing.ts +0 -18
- package/src/utils/connectors/solana/transaction.ts +0 -382
- package/src/utils/connectors/solana/types.ts +0 -66
- package/src/utils/event-types.ts +0 -350
- package/src/utils/popup.test.ts +0 -50
- package/src/utils/popup.ts +0 -123
- package/src/utils/sdk-specs.test.ts +0 -18
- package/src/utils/sdk-specs.ts +0 -7
- package/src/utils/style.test.ts +0 -33
- package/src/utils/style.ts +0 -15
- package/src/utils/types.ts +0 -270
- package/src/utils/version.ts +0 -1
- package/src/utils/wallet/EVMWalletStrategy.ts +0 -176
- package/src/utils/wallet/SolanaWalletStrategy.ts +0 -207
- package/src/utils/wallet/WalletStrategy.ts +0 -99
- package/src/utils/wallet/WalletStrategyFactory.ts +0 -46
- package/src/utils/wallet/__tests__/EVMWalletStrategy.test.ts +0 -233
- package/src/utils/wallet/__tests__/SolanaWalletStrategy.test.ts +0 -253
- package/src/utils/wallet/__tests__/WalletStrategy.test.ts +0 -77
- package/src/utils/wallet/__tests__/WalletStrategyFactory.test.ts +0 -65
- package/src/utils/wallet/index.ts +0 -4
- package/src/utils/wallet-browser-event-types.ts +0 -190
- package/tools/copy.js +0 -26
- package/tools/update-version.js +0 -10
- package/tsconfig.json +0 -14
@@ -1,165 +0,0 @@
|
|
1
|
-
import { EVMProvider } from './types'
|
2
|
-
import { getChainConfiguration } from './chainConfigs'
|
3
|
-
import { getActiveRawProvider } from './provider'
|
4
|
-
|
5
|
-
// Chain switch status tracking
|
6
|
-
const isChainSwitching = false
|
7
|
-
const chainSwitchError: Error | null = null
|
8
|
-
|
9
|
-
const MAX_RETRY_ATTEMPTS = 3
|
10
|
-
const RETRY_DELAY = 1000
|
11
|
-
|
12
|
-
/**
|
13
|
-
* Waits for a pending chain switch to complete
|
14
|
-
*/
|
15
|
-
const waitForPendingSwitch = async (
|
16
|
-
provider: EVMProvider,
|
17
|
-
chainIdHex: string,
|
18
|
-
attempt: number = 0
|
19
|
-
): Promise<void> => {
|
20
|
-
try {
|
21
|
-
// Get current chain
|
22
|
-
const currentChainHex = await provider.request({ method: 'eth_chainId' })
|
23
|
-
if (currentChainHex === chainIdHex) {
|
24
|
-
return // Switch completed
|
25
|
-
}
|
26
|
-
|
27
|
-
if (attempt >= MAX_RETRY_ATTEMPTS) {
|
28
|
-
throw new Error('Chain switch timeout')
|
29
|
-
}
|
30
|
-
|
31
|
-
// Wait and retry
|
32
|
-
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY))
|
33
|
-
return waitForPendingSwitch(provider, chainIdHex, attempt + 1)
|
34
|
-
} catch (error: any) {
|
35
|
-
if (error.code === -32002) {
|
36
|
-
// Still pending, wait and retry
|
37
|
-
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY))
|
38
|
-
return waitForPendingSwitch(provider, chainIdHex, attempt + 1)
|
39
|
-
}
|
40
|
-
throw error
|
41
|
-
}
|
42
|
-
}
|
43
|
-
|
44
|
-
/**
|
45
|
-
* Switches the current EVM chain
|
46
|
-
*/
|
47
|
-
export const switchEVMChain = async (
|
48
|
-
chainId: number,
|
49
|
-
provider?: EVMProvider
|
50
|
-
): Promise<{ chainId: number; accounts: string[] } | Error> => {
|
51
|
-
try {
|
52
|
-
const targetProvider = provider || getActiveRawProvider()
|
53
|
-
if (!targetProvider) {
|
54
|
-
throw new Error('No active EVM provider')
|
55
|
-
}
|
56
|
-
|
57
|
-
const chainIdHex = `0x${chainId.toString(16)}`
|
58
|
-
|
59
|
-
try {
|
60
|
-
await switchChain(targetProvider, chainIdHex)
|
61
|
-
} catch (switchError: any) {
|
62
|
-
await handleSwitchError(switchError, targetProvider, chainId, chainIdHex)
|
63
|
-
}
|
64
|
-
|
65
|
-
const accounts = await targetProvider.request({ method: 'eth_accounts' })
|
66
|
-
return { chainId, accounts }
|
67
|
-
} catch (error) {
|
68
|
-
if (isUserRejection(error)) {
|
69
|
-
return new Error('User rejected chain switch')
|
70
|
-
}
|
71
|
-
await new Promise(resolve => setTimeout(resolve, 1000))
|
72
|
-
console.error('Chain switch error:', error)
|
73
|
-
return error instanceof Error ? error : new Error('Failed to switch chain')
|
74
|
-
}
|
75
|
-
}
|
76
|
-
|
77
|
-
/**
|
78
|
-
* Attempts to switch to a specific chain
|
79
|
-
*/
|
80
|
-
const switchChain = async (
|
81
|
-
provider: EVMProvider,
|
82
|
-
chainIdHex: string
|
83
|
-
): Promise<void> => {
|
84
|
-
await provider.request({
|
85
|
-
method: 'wallet_switchEthereumChain',
|
86
|
-
params: [{ chainId: chainIdHex }]
|
87
|
-
})
|
88
|
-
}
|
89
|
-
|
90
|
-
/**
|
91
|
-
* Handles chain switch errors
|
92
|
-
*/
|
93
|
-
const handleSwitchError = async (
|
94
|
-
error: any,
|
95
|
-
provider: EVMProvider,
|
96
|
-
chainId: number,
|
97
|
-
chainIdHex: string
|
98
|
-
): Promise<void> => {
|
99
|
-
if (error.code === 4001) {
|
100
|
-
throw new Error('User rejected chain switch')
|
101
|
-
}
|
102
|
-
|
103
|
-
if (error.code === -32002) {
|
104
|
-
// Request already pending, wait for it
|
105
|
-
await waitForPendingSwitch(provider, chainIdHex)
|
106
|
-
return
|
107
|
-
}
|
108
|
-
|
109
|
-
if (error.code === 4902 || error.code === -32603) {
|
110
|
-
await addChain(provider, chainId, chainIdHex)
|
111
|
-
await switchChain(provider, chainIdHex)
|
112
|
-
} else {
|
113
|
-
throw error
|
114
|
-
}
|
115
|
-
}
|
116
|
-
|
117
|
-
/**
|
118
|
-
* Adds a new chain to the wallet
|
119
|
-
*/
|
120
|
-
const addChain = async (
|
121
|
-
provider: EVMProvider,
|
122
|
-
chainId: number,
|
123
|
-
chainIdHex: string
|
124
|
-
): Promise<void> => {
|
125
|
-
const chainConfig = getChainConfiguration(chainId)
|
126
|
-
|
127
|
-
if (!chainConfig) {
|
128
|
-
throw new Error(`No configuration found for chain ${chainId}`)
|
129
|
-
}
|
130
|
-
|
131
|
-
try {
|
132
|
-
await provider.request({
|
133
|
-
method: 'wallet_addEthereumChain',
|
134
|
-
params: [
|
135
|
-
{
|
136
|
-
chainId: chainIdHex,
|
137
|
-
chainName: chainConfig.name,
|
138
|
-
nativeCurrency: chainConfig.nativeCurrency,
|
139
|
-
rpcUrls: chainConfig.rpcUrls.default.http,
|
140
|
-
blockExplorerUrls: [chainConfig.blockExplorers.default.url]
|
141
|
-
}
|
142
|
-
]
|
143
|
-
})
|
144
|
-
} catch (addError: any) {
|
145
|
-
if (addError.code === 4001) {
|
146
|
-
throw new Error('User rejected chain add')
|
147
|
-
}
|
148
|
-
throw addError
|
149
|
-
}
|
150
|
-
}
|
151
|
-
|
152
|
-
/**
|
153
|
-
* Checks if an error is a user rejection
|
154
|
-
*/
|
155
|
-
const isUserRejection = (error: any): boolean => {
|
156
|
-
return error instanceof Error && error.message.includes('rejected')
|
157
|
-
}
|
158
|
-
|
159
|
-
/**
|
160
|
-
* Gets the current chain switch status
|
161
|
-
*/
|
162
|
-
export const getChainSwitchStatus = () => ({
|
163
|
-
isChainSwitching,
|
164
|
-
chainSwitchError
|
165
|
-
})
|
@@ -1,22 +0,0 @@
|
|
1
|
-
import { ethers } from 'ethers'
|
2
|
-
import { EVMProvider } from './types'
|
3
|
-
|
4
|
-
// Keep track of the active provider
|
5
|
-
let activeEVMProvider: ethers.BrowserProvider | null = null
|
6
|
-
let activeRawProvider: EVMProvider | null = null
|
7
|
-
|
8
|
-
export const setActiveEVMProvider = (
|
9
|
-
provider: ethers.BrowserProvider,
|
10
|
-
rawProvider: EVMProvider
|
11
|
-
) => {
|
12
|
-
activeEVMProvider = provider
|
13
|
-
activeRawProvider = rawProvider
|
14
|
-
}
|
15
|
-
|
16
|
-
export const getActiveEVMProvider = () => activeEVMProvider
|
17
|
-
export const getActiveRawProvider = () => activeRawProvider
|
18
|
-
|
19
|
-
export const clearActiveProviders = () => {
|
20
|
-
activeEVMProvider = null
|
21
|
-
activeRawProvider = null
|
22
|
-
}
|
@@ -1,39 +0,0 @@
|
|
1
|
-
import { ethers } from 'ethers'
|
2
|
-
import { getActiveEVMProvider, getActiveRawProvider } from './provider'
|
3
|
-
|
4
|
-
export const signEVMMessage = async (
|
5
|
-
walletName: string,
|
6
|
-
address: string,
|
7
|
-
message: string
|
8
|
-
): Promise<string | Error> => {
|
9
|
-
try {
|
10
|
-
const activeProvider = getActiveEVMProvider()
|
11
|
-
const activeRawProvider = getActiveRawProvider()
|
12
|
-
|
13
|
-
if (!activeProvider || !activeRawProvider) {
|
14
|
-
throw new Error('No active EVM provider')
|
15
|
-
}
|
16
|
-
|
17
|
-
// Special handling for Rainbow wallet using personal_sign
|
18
|
-
if (walletName.toLowerCase() === 'rainbow') {
|
19
|
-
const messageHex = ethers.hexlify(ethers.toUtf8Bytes(message))
|
20
|
-
const signature = await activeRawProvider.request({
|
21
|
-
method: 'personal_sign',
|
22
|
-
// EIP-191 standard order: address first, then message
|
23
|
-
params: [address.toLowerCase(), messageHex]
|
24
|
-
})
|
25
|
-
return signature
|
26
|
-
}
|
27
|
-
|
28
|
-
// For other wallets, use ethers.js signing
|
29
|
-
const provider = new ethers.BrowserProvider(activeRawProvider)
|
30
|
-
const signer = await provider.getSigner(address)
|
31
|
-
const signature = await signer.signMessage(message)
|
32
|
-
return signature
|
33
|
-
} catch (error) {
|
34
|
-
console.error('EVM message signing error:', error)
|
35
|
-
return error instanceof Error
|
36
|
-
? error
|
37
|
-
: new Error(`Failed to sign message with ${walletName} wallet`)
|
38
|
-
}
|
39
|
-
}
|
@@ -1,356 +0,0 @@
|
|
1
|
-
import { ethers } from 'ethers'
|
2
|
-
import { getActiveRawProvider } from './provider'
|
3
|
-
|
4
|
-
const isUserRejection = (error: any): boolean => {
|
5
|
-
if (!error) return false
|
6
|
-
|
7
|
-
// Check for various wallet rejection patterns
|
8
|
-
const message = error.message?.toLowerCase() || ''
|
9
|
-
return (
|
10
|
-
error.code === 4001 || // Standard EIP-1193 user rejection code
|
11
|
-
message.includes('user rejected') ||
|
12
|
-
message.includes('user denied') ||
|
13
|
-
message.includes('user cancelled') ||
|
14
|
-
message.includes('declined')
|
15
|
-
)
|
16
|
-
}
|
17
|
-
|
18
|
-
/**
|
19
|
-
* Sends a native EVM transaction
|
20
|
-
*/
|
21
|
-
export const sendEVMTransaction = async (
|
22
|
-
toAddress: string,
|
23
|
-
amount: bigint,
|
24
|
-
fromAddress: string,
|
25
|
-
gasLimit?: number | null,
|
26
|
-
maxFeePerGas?: number | null,
|
27
|
-
maxPriorityFeePerGas?: number | null
|
28
|
-
): Promise<string | Error> => {
|
29
|
-
try {
|
30
|
-
const activeRawProvider = getActiveRawProvider()
|
31
|
-
if (!activeRawProvider) {
|
32
|
-
throw new Error('No active EVM provider')
|
33
|
-
}
|
34
|
-
|
35
|
-
// Get current chain ID before transaction
|
36
|
-
const chainIdHex = await activeRawProvider.request({
|
37
|
-
method: 'eth_chainId'
|
38
|
-
})
|
39
|
-
const chainId = parseInt(chainIdHex, 16)
|
40
|
-
|
41
|
-
// Create a new provider instance for this transaction
|
42
|
-
const provider = new ethers.BrowserProvider(activeRawProvider)
|
43
|
-
const signer = await provider.getSigner(fromAddress)
|
44
|
-
|
45
|
-
// Verify we're still on the same network before proceeding
|
46
|
-
const network = await provider.getNetwork()
|
47
|
-
if (Number(network.chainId) !== chainId) {
|
48
|
-
throw new Error('Network changed during transaction setup')
|
49
|
-
}
|
50
|
-
|
51
|
-
try {
|
52
|
-
const tx = await signer.sendTransaction({
|
53
|
-
to: toAddress,
|
54
|
-
value: amount,
|
55
|
-
gasLimit: gasLimit ? BigInt(Math.floor(gasLimit)) : undefined,
|
56
|
-
maxFeePerGas: maxFeePerGas
|
57
|
-
? BigInt(Math.floor(maxFeePerGas))
|
58
|
-
: undefined,
|
59
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas
|
60
|
-
? BigInt(Math.floor(maxPriorityFeePerGas))
|
61
|
-
: undefined
|
62
|
-
})
|
63
|
-
|
64
|
-
const receipt = await tx.wait()
|
65
|
-
return receipt ? receipt.hash : ''
|
66
|
-
} catch (txError: any) {
|
67
|
-
if (isUserRejection(txError)) {
|
68
|
-
return new Error('Transaction was rejected by user')
|
69
|
-
}
|
70
|
-
throw txError
|
71
|
-
}
|
72
|
-
} catch (error: any) {
|
73
|
-
console.error('Transaction error:', error)
|
74
|
-
|
75
|
-
if (isUserRejection(error)) {
|
76
|
-
return new Error('Transaction was rejected by user')
|
77
|
-
}
|
78
|
-
|
79
|
-
if (error.code === 'NETWORK_ERROR') {
|
80
|
-
return new Error('Network changed during transaction. Please try again.')
|
81
|
-
}
|
82
|
-
|
83
|
-
return error instanceof Error
|
84
|
-
? error
|
85
|
-
: new Error('Failed to send transaction')
|
86
|
-
}
|
87
|
-
}
|
88
|
-
|
89
|
-
/**
|
90
|
-
* Sends an EVM token transaction
|
91
|
-
*/
|
92
|
-
export const sendEVMTokenTransaction = async (
|
93
|
-
contractAddress: string,
|
94
|
-
abi: ethers.InterfaceAbi,
|
95
|
-
functionName: string,
|
96
|
-
args: unknown[],
|
97
|
-
fromAddress: string
|
98
|
-
): Promise<string | Error> => {
|
99
|
-
try {
|
100
|
-
const activeRawProvider = getActiveRawProvider()
|
101
|
-
if (!activeRawProvider) {
|
102
|
-
throw new Error('No active EVM provider')
|
103
|
-
}
|
104
|
-
|
105
|
-
const chainIdHex = await activeRawProvider.request({
|
106
|
-
method: 'eth_chainId'
|
107
|
-
})
|
108
|
-
const chainId = parseInt(chainIdHex, 16)
|
109
|
-
|
110
|
-
const provider = new ethers.BrowserProvider(activeRawProvider)
|
111
|
-
const signer = await provider.getSigner(fromAddress)
|
112
|
-
|
113
|
-
// Verify we're still on the same network before proceeding
|
114
|
-
const network = await provider.getNetwork()
|
115
|
-
if (Number(network.chainId) !== chainId) {
|
116
|
-
throw new Error('Network changed during transaction setup')
|
117
|
-
}
|
118
|
-
|
119
|
-
const contract = new ethers.Contract(contractAddress, abi, signer)
|
120
|
-
const txOptions: ethers.Overrides = {}
|
121
|
-
|
122
|
-
const gasLimit =
|
123
|
-
args?.[2] !== undefined ? toSafeNumber(args[2], 'gasLimit') : undefined
|
124
|
-
const maxFeePerGas =
|
125
|
-
args?.[3] !== undefined
|
126
|
-
? toSafeNumber(args[3], 'maxFeePerGas')
|
127
|
-
: undefined
|
128
|
-
const maxPriorityFeePerGas =
|
129
|
-
args?.[4] !== undefined
|
130
|
-
? toSafeNumber(args[4], 'maxPriorityFeePerGas')
|
131
|
-
: undefined
|
132
|
-
|
133
|
-
txOptions.gasLimit = gasLimit ? BigInt(Math.floor(gasLimit)) : undefined
|
134
|
-
txOptions.maxFeePerGas = maxFeePerGas
|
135
|
-
? BigInt(Math.floor(maxFeePerGas))
|
136
|
-
: undefined
|
137
|
-
txOptions.maxPriorityFeePerGas = maxPriorityFeePerGas
|
138
|
-
? BigInt(Math.floor(maxPriorityFeePerGas))
|
139
|
-
: undefined
|
140
|
-
|
141
|
-
try {
|
142
|
-
// Send the transaction
|
143
|
-
const tx = await contract[functionName](args[0], args[1], txOptions)
|
144
|
-
|
145
|
-
// Wait for transaction confirmation
|
146
|
-
const receipt = await tx.wait()
|
147
|
-
return receipt ? receipt.hash : ''
|
148
|
-
} catch (txError: any) {
|
149
|
-
if (isUserRejection(txError)) {
|
150
|
-
return new Error('Transaction was rejected by user')
|
151
|
-
}
|
152
|
-
throw txError
|
153
|
-
}
|
154
|
-
} catch (error: any) {
|
155
|
-
console.error('Token transaction error:', error)
|
156
|
-
|
157
|
-
if (isUserRejection(error)) {
|
158
|
-
return new Error('Transaction was rejected by user')
|
159
|
-
}
|
160
|
-
|
161
|
-
if (error.code === 'NETWORK_ERROR') {
|
162
|
-
return new Error('Network changed during transaction. Please try again.')
|
163
|
-
}
|
164
|
-
|
165
|
-
return error instanceof Error
|
166
|
-
? error
|
167
|
-
: new Error('Failed to send token transaction')
|
168
|
-
}
|
169
|
-
}
|
170
|
-
|
171
|
-
/**
|
172
|
-
* Sends an native smart contract transaction
|
173
|
-
*/
|
174
|
-
export const sendNativeSmartContractTransaction = async (
|
175
|
-
contractAddress: string,
|
176
|
-
abi: ethers.InterfaceAbi,
|
177
|
-
functionName: string,
|
178
|
-
args: unknown[],
|
179
|
-
fromAddress: string,
|
180
|
-
value?: string
|
181
|
-
): Promise<string | Error> => {
|
182
|
-
try {
|
183
|
-
const activeRawProvider = getActiveRawProvider()
|
184
|
-
if (!activeRawProvider) {
|
185
|
-
throw new Error('No active EVM provider')
|
186
|
-
}
|
187
|
-
|
188
|
-
const chainIdHex = await activeRawProvider.request({
|
189
|
-
method: 'eth_chainId'
|
190
|
-
})
|
191
|
-
const chainId = parseInt(chainIdHex, 16)
|
192
|
-
|
193
|
-
const provider = new ethers.BrowserProvider(activeRawProvider)
|
194
|
-
const signer = await provider.getSigner(fromAddress)
|
195
|
-
|
196
|
-
// Verify we're still on the same network before proceeding
|
197
|
-
const network = await provider.getNetwork()
|
198
|
-
if (Number(network.chainId) !== chainId) {
|
199
|
-
throw new Error('Network changed during transaction setup')
|
200
|
-
}
|
201
|
-
|
202
|
-
const contract = new ethers.Contract(contractAddress, abi, signer)
|
203
|
-
const txOptions: ethers.Overrides = {}
|
204
|
-
|
205
|
-
const gasLimit =
|
206
|
-
args?.[1] !== undefined ? toSafeNumber(args[1], 'gasLimit') : undefined
|
207
|
-
const maxFeePerGas =
|
208
|
-
args?.[2] !== undefined
|
209
|
-
? toSafeNumber(args[2], 'maxFeePerGas')
|
210
|
-
: undefined
|
211
|
-
const maxPriorityFeePerGas =
|
212
|
-
args?.[3] !== undefined
|
213
|
-
? toSafeNumber(args[3], 'maxPriorityFeePerGas')
|
214
|
-
: undefined
|
215
|
-
|
216
|
-
txOptions.gasLimit = gasLimit ? BigInt(Math.floor(gasLimit)) : undefined
|
217
|
-
txOptions.maxFeePerGas = maxFeePerGas
|
218
|
-
? BigInt(Math.floor(maxFeePerGas))
|
219
|
-
: undefined
|
220
|
-
txOptions.maxPriorityFeePerGas = maxPriorityFeePerGas
|
221
|
-
? BigInt(Math.floor(maxPriorityFeePerGas))
|
222
|
-
: undefined
|
223
|
-
|
224
|
-
if (value) {
|
225
|
-
txOptions.value = value
|
226
|
-
}
|
227
|
-
|
228
|
-
try {
|
229
|
-
// Send the transaction
|
230
|
-
const tx = await contract[functionName](args[0], txOptions)
|
231
|
-
|
232
|
-
// Wait for transaction confirmation
|
233
|
-
const receipt = await tx.wait()
|
234
|
-
return receipt ? receipt.hash : ''
|
235
|
-
} catch (txError: any) {
|
236
|
-
if (isUserRejection(txError)) {
|
237
|
-
return new Error('Transaction was rejected by user')
|
238
|
-
}
|
239
|
-
throw txError
|
240
|
-
}
|
241
|
-
} catch (error: any) {
|
242
|
-
console.error('Token transaction error:', error)
|
243
|
-
|
244
|
-
if (isUserRejection(error)) {
|
245
|
-
return new Error('Transaction was rejected by user')
|
246
|
-
}
|
247
|
-
|
248
|
-
if (error.code === 'NETWORK_ERROR') {
|
249
|
-
return new Error('Network changed during transaction. Please try again.')
|
250
|
-
}
|
251
|
-
|
252
|
-
return error instanceof Error
|
253
|
-
? error
|
254
|
-
: new Error('Failed to send token transaction')
|
255
|
-
}
|
256
|
-
}
|
257
|
-
|
258
|
-
function toSafeNumber(value: unknown, name: string): number {
|
259
|
-
if (typeof value !== 'number' || Number.isNaN(value)) {
|
260
|
-
throw new TypeError(
|
261
|
-
`Invalid ${name}: expected a number, got ${typeof value} (${value})`
|
262
|
-
)
|
263
|
-
}
|
264
|
-
return value
|
265
|
-
}
|
266
|
-
|
267
|
-
/**
|
268
|
-
* Sends a batch of EVM transactions
|
269
|
-
*/
|
270
|
-
export const sendEVMTransactionBatch = async (params: {
|
271
|
-
version: string
|
272
|
-
from: string
|
273
|
-
chainId: string
|
274
|
-
atomicRequired: boolean
|
275
|
-
calls: {
|
276
|
-
to: string
|
277
|
-
value: string
|
278
|
-
data?: string
|
279
|
-
}[]
|
280
|
-
}): Promise<string | Error> => {
|
281
|
-
try {
|
282
|
-
const activeRawProvider = getActiveRawProvider()
|
283
|
-
if (!activeRawProvider) {
|
284
|
-
throw new Error('No active EVM provider')
|
285
|
-
}
|
286
|
-
|
287
|
-
const provider = new ethers.BrowserProvider(activeRawProvider)
|
288
|
-
|
289
|
-
try {
|
290
|
-
// Send the transaction batch
|
291
|
-
const response: { id: `0x${string}` } = await provider.send(
|
292
|
-
'wallet_sendCalls',
|
293
|
-
[params]
|
294
|
-
)
|
295
|
-
|
296
|
-
// Wait for transaction confirmation
|
297
|
-
let result: {
|
298
|
-
chainId: `0x${string}`
|
299
|
-
id: `0x${string}`
|
300
|
-
status: number
|
301
|
-
atomic: boolean
|
302
|
-
receipts: [
|
303
|
-
{
|
304
|
-
transactionHash: `0x${string}`
|
305
|
-
}
|
306
|
-
]
|
307
|
-
}
|
308
|
-
do {
|
309
|
-
result = await provider.send('wallet_getCallsStatus', [response.id])
|
310
|
-
|
311
|
-
// wait 1 second if receipt is not yet available
|
312
|
-
if (result.status == 100) {
|
313
|
-
await new Promise(resolve => setTimeout(resolve, 1000))
|
314
|
-
}
|
315
|
-
} while (result.status == 100)
|
316
|
-
|
317
|
-
return result?.status != 200
|
318
|
-
? new Error('Failed to send batched transactions')
|
319
|
-
: result.receipts.find(x => x)?.transactionHash ??
|
320
|
-
new Error('Failed to get batched transactions receipt')
|
321
|
-
} catch (txError: any) {
|
322
|
-
if (isUserRejection(txError)) {
|
323
|
-
return new Error('Transaction was rejected by user')
|
324
|
-
}
|
325
|
-
throw txError
|
326
|
-
}
|
327
|
-
} catch (error: any) {
|
328
|
-
console.error('Token transaction error:', error)
|
329
|
-
|
330
|
-
if (isUserRejection(error)) {
|
331
|
-
return new Error('Transaction was rejected by user')
|
332
|
-
}
|
333
|
-
|
334
|
-
if (error.code === 'NETWORK_ERROR') {
|
335
|
-
return new Error('Network changed during transaction. Please try again.')
|
336
|
-
}
|
337
|
-
|
338
|
-
return error instanceof Error
|
339
|
-
? error
|
340
|
-
: new Error('Failed to send token transaction')
|
341
|
-
}
|
342
|
-
}
|
343
|
-
|
344
|
-
export const getWalletCapabilities = async (from: string, chainId: string) => {
|
345
|
-
const activeRawProvider = getActiveRawProvider()
|
346
|
-
if (!activeRawProvider) {
|
347
|
-
throw new Error('No active EVM provider')
|
348
|
-
}
|
349
|
-
const provider = new ethers.BrowserProvider(activeRawProvider)
|
350
|
-
|
351
|
-
const capabilities = await provider.send('wallet_getCapabilities', [
|
352
|
-
from,
|
353
|
-
[chainId]
|
354
|
-
])
|
355
|
-
return capabilities[chainId]
|
356
|
-
}
|
@@ -1,63 +0,0 @@
|
|
1
|
-
import { ethers, Eip1193Provider } from 'ethers'
|
2
|
-
|
3
|
-
export interface EVMConnectResult {
|
4
|
-
accounts: string[]
|
5
|
-
chainId: number
|
6
|
-
isConnected: boolean
|
7
|
-
}
|
8
|
-
|
9
|
-
export interface EVMProvider extends ethers.Eip1193Provider {
|
10
|
-
on(event: string, listener: (...args: any[]) => void): void
|
11
|
-
removeListener(event: string, listener: (...args: any[]) => void): void
|
12
|
-
removeAllListeners(): void
|
13
|
-
[key: string]: any
|
14
|
-
}
|
15
|
-
|
16
|
-
export interface InjectedProviderInfo {
|
17
|
-
name: string
|
18
|
-
id: string
|
19
|
-
icon?: string
|
20
|
-
injectedData: {
|
21
|
-
provider: EVMProvider
|
22
|
-
[key: string]: any
|
23
|
-
}
|
24
|
-
}
|
25
|
-
|
26
|
-
export interface ChainConfig {
|
27
|
-
name: string
|
28
|
-
nativeCurrency: {
|
29
|
-
decimals: number
|
30
|
-
name: string
|
31
|
-
symbol: string
|
32
|
-
}
|
33
|
-
rpcUrls: {
|
34
|
-
default: { http: string[] }
|
35
|
-
}
|
36
|
-
blockExplorers: {
|
37
|
-
default: {
|
38
|
-
name: string
|
39
|
-
url: string
|
40
|
-
}
|
41
|
-
}
|
42
|
-
}
|
43
|
-
|
44
|
-
export interface EIP6963ProviderInfo {
|
45
|
-
uuid: string
|
46
|
-
name: string
|
47
|
-
icon?: string
|
48
|
-
rdns?: string
|
49
|
-
}
|
50
|
-
|
51
|
-
export interface EIP6963ProviderDetail {
|
52
|
-
info: EIP6963ProviderInfo
|
53
|
-
provider: Eip1193Provider
|
54
|
-
}
|
55
|
-
|
56
|
-
export interface EIP6963AnnounceProviderEvent extends CustomEvent {
|
57
|
-
type: 'eip6963:announceProvider'
|
58
|
-
detail: EIP6963ProviderDetail
|
59
|
-
}
|
60
|
-
|
61
|
-
export interface EIP6963RequestProviderEvent extends Event {
|
62
|
-
type: 'eip6963:requestProvider'
|
63
|
-
}
|