@meshconnect/uwc-core 0.2.13 → 0.2.14
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/package.json +4 -4
- package/src/managers/event-manager.test.ts +74 -0
- package/src/managers/session-manager.test.ts +119 -0
- package/src/services/connection-service.test.ts +151 -0
- package/src/services/network-switch-service.test.ts +187 -0
- package/src/services/signature-service.test.ts +108 -0
- package/src/services/transaction-service.test.ts +163 -0
- package/src/universal-wallet-connector.test.ts +428 -0
- package/src/utils/network-rpc-utils.test.ts +329 -0
- package/dist/connection-manager.d.ts +0 -18
- package/dist/connection-manager.d.ts.map +0 -1
- package/dist/connection-manager.js +0 -54
- package/dist/connection-manager.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meshconnect/uwc-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.14",
|
|
4
4
|
"description": "Core functionality for Universal Wallet Connector",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
"src"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
+
"@meshconnect/uwc-injected-connector": "0.2.9",
|
|
20
|
+
"@meshconnect/uwc-types": "0.2.6",
|
|
19
21
|
"@meshconnect/uwc-bridge-child": "0.0.3",
|
|
20
|
-
"@meshconnect/uwc-
|
|
21
|
-
"@meshconnect/uwc-injected-connector": "0.2.8",
|
|
22
|
-
"@meshconnect/uwc-wallet-connect-connector": "0.2.8"
|
|
22
|
+
"@meshconnect/uwc-wallet-connect-connector": "0.2.9"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"typescript": "^5.9.2"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest'
|
|
2
|
+
import { EventManager } from './event-manager'
|
|
3
|
+
|
|
4
|
+
describe('EventManager', () => {
|
|
5
|
+
let eventManager: EventManager
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
eventManager = new EventManager()
|
|
9
|
+
})
|
|
10
|
+
it('should subscribe and notify listeners', () => {
|
|
11
|
+
let eventReceived = false
|
|
12
|
+
|
|
13
|
+
const unsubscribe = eventManager.subscribe(() => {
|
|
14
|
+
eventReceived = true
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
eventManager.notify()
|
|
18
|
+
|
|
19
|
+
expect(eventReceived).toBe(true)
|
|
20
|
+
|
|
21
|
+
unsubscribe()
|
|
22
|
+
eventReceived = false
|
|
23
|
+
|
|
24
|
+
eventManager.notify()
|
|
25
|
+
|
|
26
|
+
expect(eventReceived).toBe(false)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should handle multiple subscribers', () => {
|
|
30
|
+
let subscriber1Called = false
|
|
31
|
+
let subscriber2Called = false
|
|
32
|
+
|
|
33
|
+
const unsubscribe1 = eventManager.subscribe(() => {
|
|
34
|
+
subscriber1Called = true
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const unsubscribe2 = eventManager.subscribe(() => {
|
|
38
|
+
subscriber2Called = true
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
eventManager.notify()
|
|
42
|
+
|
|
43
|
+
expect(subscriber1Called).toBe(true)
|
|
44
|
+
expect(subscriber2Called).toBe(true)
|
|
45
|
+
|
|
46
|
+
unsubscribe1()
|
|
47
|
+
unsubscribe2()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('should track listener count', () => {
|
|
51
|
+
expect(eventManager.getListenerCount()).toBe(0)
|
|
52
|
+
|
|
53
|
+
const unsubscribe1 = eventManager.subscribe(() => {})
|
|
54
|
+
expect(eventManager.getListenerCount()).toBe(1)
|
|
55
|
+
|
|
56
|
+
const unsubscribe2 = eventManager.subscribe(() => {})
|
|
57
|
+
expect(eventManager.getListenerCount()).toBe(2)
|
|
58
|
+
|
|
59
|
+
unsubscribe1()
|
|
60
|
+
expect(eventManager.getListenerCount()).toBe(1)
|
|
61
|
+
|
|
62
|
+
unsubscribe2()
|
|
63
|
+
expect(eventManager.getListenerCount()).toBe(0)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('should clear all listeners', () => {
|
|
67
|
+
eventManager.subscribe(() => {})
|
|
68
|
+
eventManager.subscribe(() => {})
|
|
69
|
+
expect(eventManager.getListenerCount()).toBe(2)
|
|
70
|
+
|
|
71
|
+
eventManager.clearAllListeners()
|
|
72
|
+
expect(eventManager.getListenerCount()).toBe(0)
|
|
73
|
+
})
|
|
74
|
+
})
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest'
|
|
2
|
+
import { SessionManager } from './session-manager'
|
|
3
|
+
import type { Network } from '../../../types/src'
|
|
4
|
+
|
|
5
|
+
describe('SessionManager', () => {
|
|
6
|
+
let sessionManager: SessionManager
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
sessionManager = new SessionManager()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it('should initialize with empty session', () => {
|
|
13
|
+
const session = sessionManager.getSession()
|
|
14
|
+
expect(session.connectionMode).toBeNull()
|
|
15
|
+
expect(session.activeWallet).toBeNull()
|
|
16
|
+
expect(session.activeNetwork).toBeNull()
|
|
17
|
+
expect(session.activeAddress).toBeNull()
|
|
18
|
+
expect(session.availableNetworks).toEqual([])
|
|
19
|
+
expect(session.availableAddresses).toEqual([])
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('should update session correctly', () => {
|
|
23
|
+
const updates = {
|
|
24
|
+
connectionMode: 'injected' as const,
|
|
25
|
+
activeAddress: '0x1234567890abcdef',
|
|
26
|
+
availableNetworks: [
|
|
27
|
+
{
|
|
28
|
+
id: 'eip155:1',
|
|
29
|
+
internalId: 1,
|
|
30
|
+
name: 'Ethereum Mainnet',
|
|
31
|
+
namespace: 'eip155',
|
|
32
|
+
logoUrl:
|
|
33
|
+
'https://ethereum.org/static/6b935ac0e619424734bc5a3b11026273/6ed5f/eth-diamond-black.png',
|
|
34
|
+
rpcUrls: {
|
|
35
|
+
default: {
|
|
36
|
+
http: ['https://mainnet.infura.io/v3/test']
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
blockExplorers: {
|
|
40
|
+
default: {
|
|
41
|
+
name: 'Etherscan',
|
|
42
|
+
url: 'https://etherscan.io'
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
networkType: 'evm',
|
|
46
|
+
nativeCurrency: {
|
|
47
|
+
name: 'Ether',
|
|
48
|
+
symbol: 'ETH',
|
|
49
|
+
decimals: 18
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
sessionManager.updateSession(updates)
|
|
56
|
+
const session = sessionManager.getSession()
|
|
57
|
+
|
|
58
|
+
expect(session.connectionMode).toBe('injected')
|
|
59
|
+
expect(session.activeAddress).toBe('0x1234567890abcdef')
|
|
60
|
+
expect(session.availableNetworks).toHaveLength(1)
|
|
61
|
+
expect(session.availableNetworks[0].name).toBe('Ethereum Mainnet')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('should clear session correctly', () => {
|
|
65
|
+
// First update the session
|
|
66
|
+
sessionManager.updateSession({
|
|
67
|
+
connectionMode: 'injected',
|
|
68
|
+
activeAddress: '0x1234567890abcdef'
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// Then clear it
|
|
72
|
+
sessionManager.clearSession()
|
|
73
|
+
const session = sessionManager.getSession()
|
|
74
|
+
|
|
75
|
+
expect(session.connectionMode).toBeNull()
|
|
76
|
+
expect(session.activeWallet).toBeNull()
|
|
77
|
+
expect(session.activeNetwork).toBeNull()
|
|
78
|
+
expect(session.activeAddress).toBeNull()
|
|
79
|
+
expect(session.availableNetworks).toEqual([])
|
|
80
|
+
expect(session.availableAddresses).toEqual([])
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('should set individual properties', () => {
|
|
84
|
+
const network: Network = {
|
|
85
|
+
id: 'eip155:1',
|
|
86
|
+
internalId: 1,
|
|
87
|
+
name: 'Ethereum Mainnet',
|
|
88
|
+
namespace: 'eip155',
|
|
89
|
+
logoUrl:
|
|
90
|
+
'https://ethereum.org/static/6b935ac0e619424734bc5a3b11026273/6ed5f/eth-diamond-black.png',
|
|
91
|
+
rpcUrls: {
|
|
92
|
+
default: {
|
|
93
|
+
http: ['https://mainnet.infura.io/v3/test']
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
blockExplorers: {
|
|
97
|
+
default: {
|
|
98
|
+
name: 'Etherscan',
|
|
99
|
+
url: 'https://etherscan.io'
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
networkType: 'evm',
|
|
103
|
+
nativeCurrency: {
|
|
104
|
+
name: 'Ether',
|
|
105
|
+
symbol: 'ETH',
|
|
106
|
+
decimals: 18
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
sessionManager.setActiveNetwork(network)
|
|
111
|
+
sessionManager.setActiveAddress('0xabcdef1234567890')
|
|
112
|
+
sessionManager.setAvailableNetworks([network])
|
|
113
|
+
|
|
114
|
+
const session = sessionManager.getSession()
|
|
115
|
+
expect(session.activeNetwork).toEqual(network)
|
|
116
|
+
expect(session.activeAddress).toBe('0xabcdef1234567890')
|
|
117
|
+
expect(session.availableNetworks).toEqual([network])
|
|
118
|
+
})
|
|
119
|
+
})
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
2
|
+
import { ConnectionService } from './connection-service'
|
|
3
|
+
import { SessionManager } from '../managers/session-manager'
|
|
4
|
+
import { EventManager } from '../managers/event-manager'
|
|
5
|
+
import type {
|
|
6
|
+
Network,
|
|
7
|
+
WalletMetadata,
|
|
8
|
+
ConnectionMode,
|
|
9
|
+
Connector
|
|
10
|
+
} from '../../../types/src'
|
|
11
|
+
|
|
12
|
+
describe('ConnectionService', () => {
|
|
13
|
+
let connectionService: ConnectionService
|
|
14
|
+
let sessionManager: SessionManager
|
|
15
|
+
let eventManager: EventManager
|
|
16
|
+
let mockConnector: Connector
|
|
17
|
+
let networks: Network[]
|
|
18
|
+
let wallets: WalletMetadata[]
|
|
19
|
+
let connectors: Map<ConnectionMode, Connector>
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
sessionManager = new SessionManager()
|
|
23
|
+
eventManager = new EventManager()
|
|
24
|
+
|
|
25
|
+
networks = [
|
|
26
|
+
{
|
|
27
|
+
id: 'eip155:1',
|
|
28
|
+
internalId: 1,
|
|
29
|
+
name: 'Ethereum Mainnet',
|
|
30
|
+
namespace: 'eip155',
|
|
31
|
+
logoUrl:
|
|
32
|
+
'https://ethereum.org/static/6b935ac0e619424734bc5a3b11026273/6ed5f/eth-diamond-black.png',
|
|
33
|
+
rpcUrls: {
|
|
34
|
+
default: {
|
|
35
|
+
http: ['https://mainnet.infura.io/v3/test']
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
blockExplorers: {
|
|
39
|
+
default: {
|
|
40
|
+
name: 'Etherscan',
|
|
41
|
+
url: 'https://etherscan.io'
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
networkType: 'evm',
|
|
45
|
+
nativeCurrency: {
|
|
46
|
+
name: 'Ether',
|
|
47
|
+
symbol: 'ETH',
|
|
48
|
+
decimals: 18
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
wallets = [
|
|
54
|
+
{
|
|
55
|
+
id: 'metamask',
|
|
56
|
+
name: 'MetaMask',
|
|
57
|
+
metadata: {
|
|
58
|
+
icon: 'data:image/svg+xml;base64,test',
|
|
59
|
+
downloadUrl: 'https://metamask.io',
|
|
60
|
+
supportedChains: ['eip155:1']
|
|
61
|
+
},
|
|
62
|
+
extensionInjectedProvider: {} as any,
|
|
63
|
+
walletConnectProvider: {} as any
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
mockConnector = {
|
|
68
|
+
connect: vi.fn(),
|
|
69
|
+
disconnect: vi.fn(),
|
|
70
|
+
signMessage: vi.fn(),
|
|
71
|
+
sendTransaction: vi.fn(),
|
|
72
|
+
switchNetwork: vi.fn()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
connectors = new Map()
|
|
76
|
+
connectors.set('injected', mockConnector)
|
|
77
|
+
|
|
78
|
+
connectionService = new ConnectionService(
|
|
79
|
+
networks,
|
|
80
|
+
wallets,
|
|
81
|
+
sessionManager,
|
|
82
|
+
connectors,
|
|
83
|
+
false,
|
|
84
|
+
eventManager
|
|
85
|
+
)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('should initialize with provided parameters', () => {
|
|
89
|
+
expect(connectionService).toBeDefined()
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('should find wallet by id', () => {
|
|
93
|
+
const wallet = connectionService['findWallet']('metamask')
|
|
94
|
+
expect(wallet).toEqual(wallets[0])
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('should throw error for unknown wallet', () => {
|
|
98
|
+
expect(() => {
|
|
99
|
+
connectionService['findWallet']('unknown')
|
|
100
|
+
}).toThrow("Wallet with id 'unknown' not found")
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('should validate network exists', () => {
|
|
104
|
+
const mockProvider = {
|
|
105
|
+
supportedNetworkIds: ['eip155:1']
|
|
106
|
+
}
|
|
107
|
+
const network = connectionService['validateAndDetermineNetwork'](
|
|
108
|
+
'eip155:1',
|
|
109
|
+
mockProvider as any
|
|
110
|
+
)
|
|
111
|
+
expect(network).toEqual(networks[0])
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('should throw error for unknown network', () => {
|
|
115
|
+
const mockProvider = {
|
|
116
|
+
supportedNetworkIds: ['eip155:1']
|
|
117
|
+
}
|
|
118
|
+
expect(() => {
|
|
119
|
+
connectionService['validateAndDetermineNetwork'](
|
|
120
|
+
'eip155:999',
|
|
121
|
+
mockProvider as any
|
|
122
|
+
)
|
|
123
|
+
}).toThrow('Network eip155:999 is not in the configured networks')
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('should get connector by mode', () => {
|
|
127
|
+
const connector = connectionService['getConnector']('injected')
|
|
128
|
+
expect(connector).toBe(mockConnector)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('should throw error for unknown connector mode', () => {
|
|
132
|
+
expect(() => {
|
|
133
|
+
connectionService['getConnector']('unknown' as ConnectionMode)
|
|
134
|
+
}).toThrow('No connector found for connection mode: unknown')
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('should get provider for injected mode', () => {
|
|
138
|
+
const wallet = wallets[0]
|
|
139
|
+
const provider = connectionService['getProviderForMode'](wallet, 'injected')
|
|
140
|
+
expect(provider).toBeDefined()
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
it('should get provider for walletConnect mode', () => {
|
|
144
|
+
const wallet = wallets[0]
|
|
145
|
+
const provider = connectionService['getProviderForMode'](
|
|
146
|
+
wallet,
|
|
147
|
+
'walletConnect'
|
|
148
|
+
)
|
|
149
|
+
expect(provider).toBeDefined()
|
|
150
|
+
})
|
|
151
|
+
})
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
2
|
+
import { NetworkSwitchService } from './network-switch-service'
|
|
3
|
+
import { SessionManager } from '../managers/session-manager'
|
|
4
|
+
import { EventManager } from '../managers/event-manager'
|
|
5
|
+
import type { Network, ConnectionMode, Connector } from '../../../types/src'
|
|
6
|
+
|
|
7
|
+
describe('NetworkSwitchService', () => {
|
|
8
|
+
let networkSwitchService: NetworkSwitchService
|
|
9
|
+
let sessionManager: SessionManager
|
|
10
|
+
let eventManager: EventManager
|
|
11
|
+
let mockConnector: Connector
|
|
12
|
+
let networks: Network[]
|
|
13
|
+
let connectors: Map<ConnectionMode, Connector>
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
sessionManager = new SessionManager()
|
|
17
|
+
eventManager = new EventManager()
|
|
18
|
+
|
|
19
|
+
networks = [
|
|
20
|
+
{
|
|
21
|
+
id: 'eip155:1',
|
|
22
|
+
internalId: 1,
|
|
23
|
+
name: 'Ethereum Mainnet',
|
|
24
|
+
namespace: 'eip155',
|
|
25
|
+
logoUrl:
|
|
26
|
+
'https://ethereum.org/static/6b935ac0e619424734bc5a3b11026273/6ed5f/eth-diamond-black.png',
|
|
27
|
+
rpcUrls: {
|
|
28
|
+
default: {
|
|
29
|
+
http: ['https://mainnet.infura.io/v3/test']
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
blockExplorers: {
|
|
33
|
+
default: {
|
|
34
|
+
name: 'Etherscan',
|
|
35
|
+
url: 'https://etherscan.io'
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
networkType: 'evm',
|
|
39
|
+
nativeCurrency: {
|
|
40
|
+
name: 'Ether',
|
|
41
|
+
symbol: 'ETH',
|
|
42
|
+
decimals: 18
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'eip155:137',
|
|
47
|
+
internalId: 137,
|
|
48
|
+
name: 'Polygon',
|
|
49
|
+
namespace: 'eip155',
|
|
50
|
+
logoUrl: 'https://polygon.technology/static/polygon-logo.png',
|
|
51
|
+
rpcUrls: {
|
|
52
|
+
default: {
|
|
53
|
+
http: ['https://polygon-rpc.com']
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
blockExplorers: {
|
|
57
|
+
default: {
|
|
58
|
+
name: 'Polygonscan',
|
|
59
|
+
url: 'https://polygonscan.com'
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
networkType: 'evm',
|
|
63
|
+
nativeCurrency: {
|
|
64
|
+
name: 'MATIC',
|
|
65
|
+
symbol: 'MATIC',
|
|
66
|
+
decimals: 18
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
mockConnector = {
|
|
72
|
+
connect: vi.fn(),
|
|
73
|
+
disconnect: vi.fn(),
|
|
74
|
+
signMessage: vi.fn(),
|
|
75
|
+
sendTransaction: vi.fn(),
|
|
76
|
+
switchNetwork: vi.fn()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
connectors = new Map()
|
|
80
|
+
connectors.set('injected', mockConnector)
|
|
81
|
+
|
|
82
|
+
networkSwitchService = new NetworkSwitchService(
|
|
83
|
+
networks,
|
|
84
|
+
sessionManager,
|
|
85
|
+
connectors,
|
|
86
|
+
false,
|
|
87
|
+
eventManager
|
|
88
|
+
)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('should initialize with provided parameters', () => {
|
|
92
|
+
expect(networkSwitchService).toBeDefined()
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('should return loading state', () => {
|
|
96
|
+
const state = networkSwitchService.getLoadingState()
|
|
97
|
+
expect(state).toEqual({
|
|
98
|
+
isLoading: false,
|
|
99
|
+
isWaitingForUserApproval: false
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('should throw error when no active connection', async () => {
|
|
104
|
+
await expect(
|
|
105
|
+
networkSwitchService.switchNetwork('eip155:1')
|
|
106
|
+
).rejects.toThrow('No active wallet found in session')
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('should throw error for unknown network', async () => {
|
|
110
|
+
sessionManager.updateSession({
|
|
111
|
+
connectionMode: 'injected',
|
|
112
|
+
activeWallet: {
|
|
113
|
+
id: 'metamask',
|
|
114
|
+
name: 'MetaMask',
|
|
115
|
+
metadata: {
|
|
116
|
+
icon: 'test',
|
|
117
|
+
downloadUrl: 'test',
|
|
118
|
+
supportedChains: ['eip155:1']
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
await expect(
|
|
124
|
+
networkSwitchService.switchNetwork('eip155:999')
|
|
125
|
+
).rejects.toThrow("Network with id 'eip155:999' not found")
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('should throw error when no active wallet', async () => {
|
|
129
|
+
sessionManager.updateSession({
|
|
130
|
+
connectionMode: 'injected'
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
await expect(
|
|
134
|
+
networkSwitchService.switchNetwork('eip155:1')
|
|
135
|
+
).rejects.toThrow('No active wallet found in session')
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('should throw error when wallet does not support network', async () => {
|
|
139
|
+
sessionManager.updateSession({
|
|
140
|
+
connectionMode: 'injected',
|
|
141
|
+
activeWallet: {
|
|
142
|
+
id: 'metamask',
|
|
143
|
+
name: 'MetaMask',
|
|
144
|
+
metadata: {
|
|
145
|
+
icon: 'test',
|
|
146
|
+
downloadUrl: 'test',
|
|
147
|
+
supportedChains: ['eip155:1']
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
await expect(
|
|
153
|
+
networkSwitchService.switchNetwork('eip155:137')
|
|
154
|
+
).rejects.toThrow(
|
|
155
|
+
"Wallet 'metamask' does not have a provider for injected mode"
|
|
156
|
+
)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('should throw error when connector does not support network switching', async () => {
|
|
160
|
+
const connectorWithoutSwitch = {
|
|
161
|
+
connect: vi.fn(),
|
|
162
|
+
disconnect: vi.fn(),
|
|
163
|
+
signMessage: vi.fn(),
|
|
164
|
+
sendTransaction: vi.fn()
|
|
165
|
+
}
|
|
166
|
+
connectors.set('injected', connectorWithoutSwitch)
|
|
167
|
+
|
|
168
|
+
sessionManager.updateSession({
|
|
169
|
+
connectionMode: 'injected',
|
|
170
|
+
activeWallet: {
|
|
171
|
+
id: 'metamask',
|
|
172
|
+
name: 'MetaMask',
|
|
173
|
+
metadata: {
|
|
174
|
+
icon: 'test',
|
|
175
|
+
downloadUrl: 'test',
|
|
176
|
+
supportedChains: ['eip155:1']
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
await expect(
|
|
182
|
+
networkSwitchService.switchNetwork('eip155:1')
|
|
183
|
+
).rejects.toThrow(
|
|
184
|
+
"Wallet 'metamask' does not have a provider for injected mode"
|
|
185
|
+
)
|
|
186
|
+
})
|
|
187
|
+
})
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
2
|
+
import { SignatureService } from './signature-service'
|
|
3
|
+
import { SessionManager } from '../managers/session-manager'
|
|
4
|
+
import type { ConnectionMode, Connector } from '../../../types/src'
|
|
5
|
+
|
|
6
|
+
describe('SignatureService', () => {
|
|
7
|
+
let signatureService: SignatureService
|
|
8
|
+
let sessionManager: SessionManager
|
|
9
|
+
let mockConnector: Connector
|
|
10
|
+
let connectors: Map<ConnectionMode, Connector>
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
sessionManager = new SessionManager()
|
|
14
|
+
|
|
15
|
+
mockConnector = {
|
|
16
|
+
connect: vi.fn(),
|
|
17
|
+
disconnect: vi.fn(),
|
|
18
|
+
signMessage: vi.fn().mockResolvedValue('0xsignature'),
|
|
19
|
+
sendTransaction: vi.fn(),
|
|
20
|
+
switchNetwork: vi.fn()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
connectors = new Map()
|
|
24
|
+
connectors.set('injected', mockConnector)
|
|
25
|
+
|
|
26
|
+
signatureService = new SignatureService(sessionManager, connectors)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should initialize with provided parameters', () => {
|
|
30
|
+
expect(signatureService).toBeDefined()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('should throw error when no active connection', async () => {
|
|
34
|
+
await expect(signatureService.signMessage('test message')).rejects.toThrow(
|
|
35
|
+
'No active connection'
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('should throw error when no active address', async () => {
|
|
40
|
+
sessionManager.updateSession({
|
|
41
|
+
connectionMode: 'injected'
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
await expect(signatureService.signMessage('test message')).rejects.toThrow(
|
|
45
|
+
'No active wallet address'
|
|
46
|
+
)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('should throw error when connector not found', async () => {
|
|
50
|
+
sessionManager.updateSession({
|
|
51
|
+
connectionMode: 'unknown' as ConnectionMode,
|
|
52
|
+
activeAddress: '0x123'
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
await expect(signatureService.signMessage('test message')).rejects.toThrow(
|
|
56
|
+
'No connector found for connection mode: unknown'
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should throw error when connector does not support signing', async () => {
|
|
61
|
+
const connectorWithoutSign = {
|
|
62
|
+
connect: vi.fn(),
|
|
63
|
+
disconnect: vi.fn(),
|
|
64
|
+
sendTransaction: vi.fn(),
|
|
65
|
+
switchNetwork: vi.fn()
|
|
66
|
+
}
|
|
67
|
+
connectors.set('injected', connectorWithoutSign)
|
|
68
|
+
|
|
69
|
+
sessionManager.updateSession({
|
|
70
|
+
connectionMode: 'injected',
|
|
71
|
+
activeAddress: '0x123'
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
await expect(signatureService.signMessage('test message')).rejects.toThrow(
|
|
75
|
+
'Connector does not support message signing'
|
|
76
|
+
)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('should sign message successfully', async () => {
|
|
80
|
+
sessionManager.updateSession({
|
|
81
|
+
connectionMode: 'injected',
|
|
82
|
+
activeAddress: '0x123'
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
const provider = {} as any
|
|
86
|
+
const result = await signatureService.signMessage('test message', provider)
|
|
87
|
+
expect(result).toBe('0xsignature')
|
|
88
|
+
expect(mockConnector.signMessage).toHaveBeenCalledWith(
|
|
89
|
+
'test message',
|
|
90
|
+
provider
|
|
91
|
+
)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('should sign message with provider', async () => {
|
|
95
|
+
sessionManager.updateSession({
|
|
96
|
+
connectionMode: 'injected',
|
|
97
|
+
activeAddress: '0x123'
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const provider = {} as any
|
|
101
|
+
const result = await signatureService.signMessage('test message', provider)
|
|
102
|
+
expect(result).toBe('0xsignature')
|
|
103
|
+
expect(mockConnector.signMessage).toHaveBeenCalledWith(
|
|
104
|
+
'test message',
|
|
105
|
+
provider
|
|
106
|
+
)
|
|
107
|
+
})
|
|
108
|
+
})
|