forked from Echo-Mirror-Butler/echomirror-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwallets.test.ts
More file actions
149 lines (127 loc) · 5.31 KB
/
Copy pathwallets.test.ts
File metadata and controls
149 lines (127 loc) · 5.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import {
WalletNotFoundError,
WalletUserRejectedError,
} from '../src/errors'
import { connectWallet, detectWallets, getWalletAdapter } from '../src/wallets'
import { FreighterAdapter } from '../src/wallets/freighter'
import { XBullAdapter } from '../src/wallets/xbull'
const TESTNET_PASSPHRASE = 'Test SDF Network ; September 2015'
const PUBKEY = 'GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6'
const globals = globalThis as Record<string, unknown>
function installFreighter(overrides: Record<string, unknown> = {}) {
globals.freighterApi = {
isConnected: async () => true,
requestAccess: async () => ({ address: PUBKEY }),
getNetworkDetails: async () => ({ networkPassphrase: TESTNET_PASSPHRASE }),
signTransaction: async () => ({ signedTxXdr: 'SIGNED_XDR' }),
...overrides,
}
}
function installXBull(overrides: Record<string, unknown> = {}) {
globals.xBullSDK = {
connect: async () => true,
getPublicKey: async () => PUBKEY,
signXDR: async (xdr: string) => `signed:${xdr}`,
...overrides,
}
}
beforeEach(() => {
delete globals.freighterApi
delete globals.xBullSDK
})
afterEach(() => {
delete globals.freighterApi
delete globals.xBullSDK
vi.restoreAllMocks()
})
describe('FreighterAdapter', () => {
it('connects via the modern requestAccess flow', async () => {
installFreighter()
const connection = await new FreighterAdapter().connect()
expect(connection).toEqual({ walletId: 'freighter', publicKey: PUBKEY, network: 'testnet' })
})
it('connects via the legacy isAllowed/getPublicKey flow', async () => {
installFreighter({
requestAccess: undefined,
isAllowed: async () => false,
setAllowed: async () => true,
getPublicKey: async () => PUBKEY,
getNetworkDetails: async () => ({ networkPassphrase: 'Public Global Stellar Network ; September 2015' }),
})
const connection = await new FreighterAdapter().connect()
expect(connection.publicKey).toBe(PUBKEY)
expect(connection.network).toBe('mainnet')
})
it('unwraps every known signTransaction result shape', async () => {
const adapter = new FreighterAdapter()
const opts = { networkPassphrase: TESTNET_PASSPHRASE }
installFreighter({ signTransaction: async () => 'RAW_STRING_XDR' })
expect(await adapter.signTransaction('XDR', opts)).toBe('RAW_STRING_XDR')
installFreighter({ signTransaction: async () => ({ signedTransaction: 'V1_SHAPE' }) })
expect(await adapter.signTransaction('XDR', opts)).toBe('V1_SHAPE')
installFreighter({ signTransaction: async () => ({ signedTxXdr: 'V2_SHAPE' }) })
expect(await adapter.signTransaction('XDR', opts)).toBe('V2_SHAPE')
})
it('maps user rejection during signing', async () => {
installFreighter({
signTransaction: async () => ({ error: 'User declined access' }),
})
await expect(
new FreighterAdapter().signTransaction('XDR', { networkPassphrase: TESTNET_PASSPHRASE }),
).rejects.toBeInstanceOf(WalletUserRejectedError)
})
it('throws WalletNotFoundError with install link when missing', async () => {
await expect(new FreighterAdapter().connect()).rejects.toMatchObject({
name: 'WalletNotFoundError',
message: expect.stringContaining('freighter.app'),
})
})
})
describe('XBullAdapter', () => {
it('connects and reports the configured network', async () => {
installXBull()
const connection = await new XBullAdapter('testnet').connect()
expect(connection).toEqual({ walletId: 'xbull', publicKey: PUBKEY, network: 'testnet' })
})
it('maps rejection thrown as a bare string', async () => {
installXBull({ connect: async () => Promise.reject('Connection denied') })
await expect(new XBullAdapter().connect()).rejects.toBeInstanceOf(WalletUserRejectedError)
})
})
describe('detection & fallback', () => {
it('detects only the wallets that are present (none in Node)', async () => {
expect(await detectWallets()).toEqual([])
})
it('detects installed extensions', async () => {
installFreighter()
installXBull()
const ids = (await detectWallets()).map((w) => w.id)
expect(ids).toContain('freighter')
expect(ids).toContain('xbull')
expect(ids).not.toContain('albedo') // no window/document in Node
})
it('connectWallet picks the first available wallet in preference order', async () => {
installXBull() // only xBull installed
const { adapter, connection } = await connectWallet({ network: 'testnet' })
expect(adapter.id).toBe('xbull')
expect(connection.publicKey).toBe(PUBKEY)
})
it('connectWallet respects a custom preference order', async () => {
installFreighter()
installXBull()
const { adapter } = await connectWallet({ preferred: ['xbull', 'freighter'] })
expect(adapter.id).toBe('xbull')
})
it('connectWallet fails gracefully with install links for every wallet', async () => {
const err = await connectWallet().catch((e) => e)
expect(err).toBeInstanceOf(WalletNotFoundError)
expect(err.message).toContain('freighter.app')
expect(err.message).toContain('xbull.app')
expect(err.message).toContain('albedo.link')
expect(err.message).toContain('Node.js')
})
it('getWalletAdapter returns the requested adapter', () => {
expect(getWalletAdapter('albedo').name).toBe('Albedo')
})
})