@sip-protocol/sdk 0.1.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/LICENSE +21 -0
- package/dist/index.d.mts +3640 -0
- package/dist/index.d.ts +3640 -0
- package/dist/index.js +5725 -0
- package/dist/index.mjs +5606 -0
- package/package.json +61 -0
- package/src/adapters/index.ts +19 -0
- package/src/adapters/near-intents.ts +475 -0
- package/src/adapters/oneclick-client.ts +367 -0
- package/src/commitment.ts +470 -0
- package/src/crypto.ts +93 -0
- package/src/errors.ts +471 -0
- package/src/index.ts +369 -0
- package/src/intent.ts +488 -0
- package/src/privacy.ts +382 -0
- package/src/proofs/index.ts +52 -0
- package/src/proofs/interface.ts +228 -0
- package/src/proofs/mock.ts +258 -0
- package/src/proofs/noir.ts +233 -0
- package/src/sip.ts +299 -0
- package/src/solver/index.ts +25 -0
- package/src/solver/mock-solver.ts +278 -0
- package/src/stealth.ts +414 -0
- package/src/validation.ts +401 -0
- package/src/wallet/base-adapter.ts +407 -0
- package/src/wallet/errors.ts +106 -0
- package/src/wallet/ethereum/adapter.ts +655 -0
- package/src/wallet/ethereum/index.ts +48 -0
- package/src/wallet/ethereum/mock.ts +505 -0
- package/src/wallet/ethereum/types.ts +364 -0
- package/src/wallet/index.ts +116 -0
- package/src/wallet/registry.ts +207 -0
- package/src/wallet/solana/adapter.ts +533 -0
- package/src/wallet/solana/index.ts +40 -0
- package/src/wallet/solana/mock.ts +522 -0
- package/src/wallet/solana/types.ts +253 -0
- package/src/zcash/index.ts +53 -0
- package/src/zcash/rpc-client.ts +623 -0
- package/src/zcash/shielded-service.ts +641 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock Solana Wallet Adapter
|
|
3
|
+
*
|
|
4
|
+
* Testing implementation of Solana wallet adapter.
|
|
5
|
+
* Provides full mock functionality without requiring browser environment.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
HexString,
|
|
10
|
+
Asset,
|
|
11
|
+
Signature,
|
|
12
|
+
UnsignedTransaction,
|
|
13
|
+
SignedTransaction,
|
|
14
|
+
TransactionReceipt,
|
|
15
|
+
} from '@sip-protocol/types'
|
|
16
|
+
import { WalletErrorCode } from '@sip-protocol/types'
|
|
17
|
+
import { BaseWalletAdapter } from '../base-adapter'
|
|
18
|
+
import { WalletError } from '../errors'
|
|
19
|
+
import type {
|
|
20
|
+
SolanaWalletProvider,
|
|
21
|
+
SolanaPublicKey,
|
|
22
|
+
SolanaTransaction,
|
|
23
|
+
SolanaVersionedTransaction,
|
|
24
|
+
SolanaCluster,
|
|
25
|
+
SolanaConnection,
|
|
26
|
+
} from './types'
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Mock Solana public key
|
|
30
|
+
*/
|
|
31
|
+
class MockPublicKey implements SolanaPublicKey {
|
|
32
|
+
private base58: string
|
|
33
|
+
private bytes: Uint8Array
|
|
34
|
+
|
|
35
|
+
constructor(base58OrBytes: string | Uint8Array) {
|
|
36
|
+
if (typeof base58OrBytes === 'string') {
|
|
37
|
+
this.base58 = base58OrBytes
|
|
38
|
+
// Create deterministic bytes from base58
|
|
39
|
+
this.bytes = new Uint8Array(32)
|
|
40
|
+
for (let i = 0; i < 32; i++) {
|
|
41
|
+
this.bytes[i] = base58OrBytes.charCodeAt(i % base58OrBytes.length) ^ i
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
this.bytes = base58OrBytes
|
|
45
|
+
// Create deterministic base58 from bytes
|
|
46
|
+
this.base58 = 'Mock' + Buffer.from(base58OrBytes.slice(0, 8)).toString('hex')
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
toBase58(): string {
|
|
51
|
+
return this.base58
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
toBytes(): Uint8Array {
|
|
55
|
+
return this.bytes
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
toString(): string {
|
|
59
|
+
return this.base58
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Mock Solana transaction
|
|
65
|
+
*/
|
|
66
|
+
class MockSolanaTransaction implements SolanaTransaction {
|
|
67
|
+
signature?: Uint8Array
|
|
68
|
+
private data: Uint8Array
|
|
69
|
+
|
|
70
|
+
constructor(data?: unknown) {
|
|
71
|
+
this.data = new TextEncoder().encode(JSON.stringify(data ?? { mock: true }))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
serialize(): Uint8Array {
|
|
75
|
+
return this.data
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
addSignature(_pubkey: SolanaPublicKey, signature: Uint8Array): void {
|
|
79
|
+
this.signature = signature
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Configuration for mock Solana adapter
|
|
85
|
+
*/
|
|
86
|
+
export interface MockSolanaAdapterConfig {
|
|
87
|
+
/** Mock address (base58) */
|
|
88
|
+
address?: string
|
|
89
|
+
/** Mock balance in lamports */
|
|
90
|
+
balance?: bigint
|
|
91
|
+
/** Token balances by mint address */
|
|
92
|
+
tokenBalances?: Record<string, bigint>
|
|
93
|
+
/** Whether to simulate connection failure */
|
|
94
|
+
shouldFailConnect?: boolean
|
|
95
|
+
/** Whether to simulate signing failure */
|
|
96
|
+
shouldFailSign?: boolean
|
|
97
|
+
/** Whether to simulate transaction failure */
|
|
98
|
+
shouldFailTransaction?: boolean
|
|
99
|
+
/** Simulated cluster */
|
|
100
|
+
cluster?: SolanaCluster
|
|
101
|
+
/** Simulated latency in ms */
|
|
102
|
+
latency?: number
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Mock Solana wallet adapter for testing
|
|
107
|
+
*
|
|
108
|
+
* Provides full Solana wallet functionality with mock data.
|
|
109
|
+
* No browser environment or actual wallet required.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* const wallet = new MockSolanaAdapter({
|
|
114
|
+
* address: 'TestWalletAddress123',
|
|
115
|
+
* balance: 5_000_000_000n, // 5 SOL
|
|
116
|
+
* })
|
|
117
|
+
*
|
|
118
|
+
* await wallet.connect()
|
|
119
|
+
* const balance = await wallet.getBalance() // 5_000_000_000n
|
|
120
|
+
*
|
|
121
|
+
* // Simulate failures
|
|
122
|
+
* const failingWallet = new MockSolanaAdapter({
|
|
123
|
+
* shouldFailSign: true,
|
|
124
|
+
* })
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export class MockSolanaAdapter extends BaseWalletAdapter {
|
|
128
|
+
readonly chain = 'solana' as const
|
|
129
|
+
readonly name = 'mock-solana'
|
|
130
|
+
|
|
131
|
+
private mockAddress: string
|
|
132
|
+
private mockPublicKey: MockPublicKey
|
|
133
|
+
private mockBalance: bigint
|
|
134
|
+
private mockTokenBalances: Map<string, bigint>
|
|
135
|
+
private shouldFailConnect: boolean
|
|
136
|
+
private shouldFailSign: boolean
|
|
137
|
+
private shouldFailTransaction: boolean
|
|
138
|
+
private cluster: SolanaCluster
|
|
139
|
+
private latency: number
|
|
140
|
+
|
|
141
|
+
// Track signed transactions for verification
|
|
142
|
+
private signedTransactions: Array<SolanaTransaction | SolanaVersionedTransaction> = []
|
|
143
|
+
private sentTransactions: string[] = []
|
|
144
|
+
|
|
145
|
+
constructor(config: MockSolanaAdapterConfig = {}) {
|
|
146
|
+
super()
|
|
147
|
+
this.mockAddress = config.address ?? 'MockSo1anaWa11etAddress123456789'
|
|
148
|
+
this.mockPublicKey = new MockPublicKey(this.mockAddress)
|
|
149
|
+
this.mockBalance = config.balance ?? 1_000_000_000n // 1 SOL default
|
|
150
|
+
this.mockTokenBalances = new Map(Object.entries(config.tokenBalances ?? {}))
|
|
151
|
+
this.shouldFailConnect = config.shouldFailConnect ?? false
|
|
152
|
+
this.shouldFailSign = config.shouldFailSign ?? false
|
|
153
|
+
this.shouldFailTransaction = config.shouldFailTransaction ?? false
|
|
154
|
+
this.cluster = config.cluster ?? 'devnet'
|
|
155
|
+
this.latency = config.latency ?? 10
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get the current Solana cluster
|
|
160
|
+
*/
|
|
161
|
+
getCluster(): SolanaCluster {
|
|
162
|
+
return this.cluster
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Connect to the mock wallet
|
|
167
|
+
*/
|
|
168
|
+
async connect(): Promise<void> {
|
|
169
|
+
this._connectionState = 'connecting'
|
|
170
|
+
|
|
171
|
+
// Simulate network latency
|
|
172
|
+
await this.simulateLatency()
|
|
173
|
+
|
|
174
|
+
if (this.shouldFailConnect) {
|
|
175
|
+
this.setError(WalletErrorCode.CONNECTION_FAILED, 'Mock connection failure')
|
|
176
|
+
throw new WalletError('Mock connection failure', WalletErrorCode.CONNECTION_FAILED)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const hexPubKey = ('0x' + Buffer.from(this.mockPublicKey.toBytes()).toString('hex')) as HexString
|
|
180
|
+
this.setConnected(this.mockAddress, hexPubKey)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Disconnect from the mock wallet
|
|
185
|
+
*/
|
|
186
|
+
async disconnect(): Promise<void> {
|
|
187
|
+
await this.simulateLatency()
|
|
188
|
+
this.setDisconnected('User disconnected')
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Sign a message
|
|
193
|
+
*/
|
|
194
|
+
async signMessage(message: Uint8Array): Promise<Signature> {
|
|
195
|
+
this.requireConnected()
|
|
196
|
+
await this.simulateLatency()
|
|
197
|
+
|
|
198
|
+
if (this.shouldFailSign) {
|
|
199
|
+
throw new WalletError('Mock signing failure', WalletErrorCode.SIGNING_REJECTED)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Create deterministic mock signature
|
|
203
|
+
const mockSig = new Uint8Array(64)
|
|
204
|
+
for (let i = 0; i < 64; i++) {
|
|
205
|
+
mockSig[i] = (message[i % message.length] ?? 0) ^ (i * 7) ^ this.mockAddress.charCodeAt(i % this.mockAddress.length)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
signature: ('0x' + Buffer.from(mockSig).toString('hex')) as HexString,
|
|
210
|
+
publicKey: this._publicKey as HexString,
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Sign a transaction
|
|
216
|
+
*/
|
|
217
|
+
async signTransaction(tx: UnsignedTransaction): Promise<SignedTransaction> {
|
|
218
|
+
this.requireConnected()
|
|
219
|
+
await this.simulateLatency()
|
|
220
|
+
|
|
221
|
+
if (this.shouldFailSign) {
|
|
222
|
+
throw new WalletError('Mock signing failure', WalletErrorCode.SIGNING_REJECTED)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const solTx = tx.data as SolanaTransaction | SolanaVersionedTransaction
|
|
226
|
+
this.signedTransactions.push(solTx)
|
|
227
|
+
|
|
228
|
+
const signature = await this.signMessage(
|
|
229
|
+
new TextEncoder().encode(JSON.stringify(tx.data))
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
unsigned: tx,
|
|
234
|
+
signatures: [signature],
|
|
235
|
+
serialized: ('0x' + Buffer.from(JSON.stringify(tx.data)).toString('hex')) as HexString,
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Sign and send a transaction
|
|
241
|
+
*/
|
|
242
|
+
async signAndSendTransaction(tx: UnsignedTransaction): Promise<TransactionReceipt> {
|
|
243
|
+
this.requireConnected()
|
|
244
|
+
await this.simulateLatency()
|
|
245
|
+
|
|
246
|
+
if (this.shouldFailSign) {
|
|
247
|
+
throw new WalletError('Mock signing failure', WalletErrorCode.SIGNING_REJECTED)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (this.shouldFailTransaction) {
|
|
251
|
+
throw new WalletError('Mock transaction failure', WalletErrorCode.TRANSACTION_FAILED)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Generate mock transaction signature
|
|
255
|
+
const txSig = `mock_tx_${Date.now()}_${Math.random().toString(36).slice(2)}`
|
|
256
|
+
this.sentTransactions.push(txSig)
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
txHash: ('0x' + Buffer.from(txSig).toString('hex')) as HexString,
|
|
260
|
+
status: 'confirmed',
|
|
261
|
+
blockNumber: BigInt(Math.floor(Math.random() * 1000000)),
|
|
262
|
+
feeUsed: 5000n, // 0.000005 SOL
|
|
263
|
+
timestamp: Date.now(),
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Sign multiple transactions
|
|
269
|
+
*/
|
|
270
|
+
async signAllTransactions<T extends SolanaTransaction | SolanaVersionedTransaction>(
|
|
271
|
+
transactions: T[]
|
|
272
|
+
): Promise<T[]> {
|
|
273
|
+
this.requireConnected()
|
|
274
|
+
await this.simulateLatency()
|
|
275
|
+
|
|
276
|
+
if (this.shouldFailSign) {
|
|
277
|
+
throw new WalletError('Mock signing failure', WalletErrorCode.SIGNING_REJECTED)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Record all signed transactions
|
|
281
|
+
this.signedTransactions.push(...transactions)
|
|
282
|
+
|
|
283
|
+
// Return transactions with mock signatures
|
|
284
|
+
return transactions.map((tx) => {
|
|
285
|
+
if ('signature' in tx) {
|
|
286
|
+
(tx as SolanaTransaction).signature = new Uint8Array(64).fill(1)
|
|
287
|
+
}
|
|
288
|
+
return tx
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Get SOL balance
|
|
294
|
+
*/
|
|
295
|
+
async getBalance(): Promise<bigint> {
|
|
296
|
+
this.requireConnected()
|
|
297
|
+
await this.simulateLatency()
|
|
298
|
+
return this.mockBalance
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Get token balance
|
|
303
|
+
*/
|
|
304
|
+
async getTokenBalance(asset: Asset): Promise<bigint> {
|
|
305
|
+
this.requireConnected()
|
|
306
|
+
await this.simulateLatency()
|
|
307
|
+
|
|
308
|
+
if (asset.chain !== 'solana') {
|
|
309
|
+
throw new WalletError(
|
|
310
|
+
`Asset chain ${asset.chain} not supported by Solana adapter`,
|
|
311
|
+
WalletErrorCode.UNSUPPORTED_CHAIN
|
|
312
|
+
)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Native SOL
|
|
316
|
+
if (!asset.address) {
|
|
317
|
+
return this.mockBalance
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return this.mockTokenBalances.get(asset.address) ?? 0n
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ── Mock Control Methods ──────────────────────────────────────────────────
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Set mock balance
|
|
327
|
+
*/
|
|
328
|
+
setMockBalance(balance: bigint): void {
|
|
329
|
+
this.mockBalance = balance
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Set mock token balance
|
|
334
|
+
*/
|
|
335
|
+
setMockTokenBalance(mintAddress: string, balance: bigint): void {
|
|
336
|
+
this.mockTokenBalances.set(mintAddress, balance)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Get all signed transactions (for verification)
|
|
341
|
+
*/
|
|
342
|
+
getSignedTransactions(): Array<SolanaTransaction | SolanaVersionedTransaction> {
|
|
343
|
+
return [...this.signedTransactions]
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Get all sent transaction signatures (for verification)
|
|
348
|
+
*/
|
|
349
|
+
getSentTransactions(): string[] {
|
|
350
|
+
return [...this.sentTransactions]
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Clear transaction history
|
|
355
|
+
*/
|
|
356
|
+
clearTransactionHistory(): void {
|
|
357
|
+
this.signedTransactions = []
|
|
358
|
+
this.sentTransactions = []
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Simulate an account change event
|
|
363
|
+
*/
|
|
364
|
+
simulateAccountChange(newAddress: string): void {
|
|
365
|
+
const previousAddress = this._address
|
|
366
|
+
this.mockAddress = newAddress
|
|
367
|
+
this.mockPublicKey = new MockPublicKey(newAddress)
|
|
368
|
+
this._address = newAddress
|
|
369
|
+
this._publicKey = ('0x' + Buffer.from(this.mockPublicKey.toBytes()).toString('hex')) as HexString
|
|
370
|
+
this.emitAccountChanged(previousAddress, newAddress)
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Simulate a disconnect event
|
|
375
|
+
*/
|
|
376
|
+
simulateDisconnect(): void {
|
|
377
|
+
this.setDisconnected('Simulated disconnect')
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
private async simulateLatency(): Promise<void> {
|
|
381
|
+
if (this.latency > 0) {
|
|
382
|
+
await new Promise((resolve) => setTimeout(resolve, this.latency))
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Create a mock Solana wallet provider for testing real adapter
|
|
389
|
+
*/
|
|
390
|
+
export function createMockSolanaProvider(
|
|
391
|
+
config: MockSolanaAdapterConfig = {}
|
|
392
|
+
): SolanaWalletProvider {
|
|
393
|
+
const address = config.address ?? 'MockSo1anaWa11etAddress123456789'
|
|
394
|
+
const pubkey = new MockPublicKey(address)
|
|
395
|
+
let isConnected = false
|
|
396
|
+
|
|
397
|
+
const eventHandlers: Record<string, Set<(...args: unknown[]) => void>> = {
|
|
398
|
+
connect: new Set(),
|
|
399
|
+
disconnect: new Set(),
|
|
400
|
+
accountChanged: new Set(),
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return {
|
|
404
|
+
isPhantom: true,
|
|
405
|
+
publicKey: null,
|
|
406
|
+
isConnected: false,
|
|
407
|
+
|
|
408
|
+
async connect() {
|
|
409
|
+
if (config.shouldFailConnect) {
|
|
410
|
+
throw new Error('User rejected the request')
|
|
411
|
+
}
|
|
412
|
+
isConnected = true
|
|
413
|
+
;(this as SolanaWalletProvider).isConnected = true
|
|
414
|
+
;(this as SolanaWalletProvider).publicKey = pubkey
|
|
415
|
+
eventHandlers.connect.forEach((h) => h(pubkey))
|
|
416
|
+
return { publicKey: pubkey }
|
|
417
|
+
},
|
|
418
|
+
|
|
419
|
+
async disconnect() {
|
|
420
|
+
isConnected = false
|
|
421
|
+
;(this as SolanaWalletProvider).isConnected = false
|
|
422
|
+
;(this as SolanaWalletProvider).publicKey = null
|
|
423
|
+
eventHandlers.disconnect.forEach((h) => h())
|
|
424
|
+
},
|
|
425
|
+
|
|
426
|
+
async signMessage(message: Uint8Array) {
|
|
427
|
+
if (config.shouldFailSign) {
|
|
428
|
+
throw new Error('User rejected the request')
|
|
429
|
+
}
|
|
430
|
+
const signature = new Uint8Array(64)
|
|
431
|
+
for (let i = 0; i < 64; i++) {
|
|
432
|
+
signature[i] = message[i % message.length] ^ i
|
|
433
|
+
}
|
|
434
|
+
return { signature }
|
|
435
|
+
},
|
|
436
|
+
|
|
437
|
+
async signTransaction<T extends SolanaTransaction | SolanaVersionedTransaction>(tx: T): Promise<T> {
|
|
438
|
+
if (config.shouldFailSign) {
|
|
439
|
+
throw new Error('User rejected the request')
|
|
440
|
+
}
|
|
441
|
+
return tx
|
|
442
|
+
},
|
|
443
|
+
|
|
444
|
+
async signAllTransactions<T extends SolanaTransaction | SolanaVersionedTransaction>(txs: T[]): Promise<T[]> {
|
|
445
|
+
if (config.shouldFailSign) {
|
|
446
|
+
throw new Error('User rejected the request')
|
|
447
|
+
}
|
|
448
|
+
return txs
|
|
449
|
+
},
|
|
450
|
+
|
|
451
|
+
async signAndSendTransaction<T extends SolanaTransaction | SolanaVersionedTransaction>(_tx: T) {
|
|
452
|
+
if (config.shouldFailSign) {
|
|
453
|
+
throw new Error('User rejected the request')
|
|
454
|
+
}
|
|
455
|
+
if (config.shouldFailTransaction) {
|
|
456
|
+
throw new Error('Transaction failed')
|
|
457
|
+
}
|
|
458
|
+
return { signature: 'mock_signature_' + Date.now() }
|
|
459
|
+
},
|
|
460
|
+
|
|
461
|
+
on(event, handler) {
|
|
462
|
+
eventHandlers[event]?.add(handler)
|
|
463
|
+
},
|
|
464
|
+
|
|
465
|
+
off(event, handler) {
|
|
466
|
+
eventHandlers[event]?.delete(handler)
|
|
467
|
+
},
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Create a mock Solana connection for testing
|
|
473
|
+
*/
|
|
474
|
+
export function createMockSolanaConnection(
|
|
475
|
+
config: MockSolanaAdapterConfig = {}
|
|
476
|
+
): SolanaConnection {
|
|
477
|
+
const balance = config.balance ?? 1_000_000_000n
|
|
478
|
+
|
|
479
|
+
return {
|
|
480
|
+
async getBalance() {
|
|
481
|
+
return Number(balance)
|
|
482
|
+
},
|
|
483
|
+
|
|
484
|
+
async getTokenAccountBalance(publicKey) {
|
|
485
|
+
const mint = publicKey.toBase58()
|
|
486
|
+
const tokenBalance = config.tokenBalances?.[mint] ?? 0n
|
|
487
|
+
return {
|
|
488
|
+
value: {
|
|
489
|
+
amount: tokenBalance.toString(),
|
|
490
|
+
decimals: 9,
|
|
491
|
+
},
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
|
|
495
|
+
async getLatestBlockhash() {
|
|
496
|
+
return {
|
|
497
|
+
blockhash: 'mock_blockhash_' + Date.now(),
|
|
498
|
+
lastValidBlockHeight: 12345678,
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
|
|
502
|
+
async sendRawTransaction() {
|
|
503
|
+
if (config.shouldFailTransaction) {
|
|
504
|
+
throw new Error('Transaction failed')
|
|
505
|
+
}
|
|
506
|
+
return 'mock_signature_' + Date.now()
|
|
507
|
+
},
|
|
508
|
+
|
|
509
|
+
async confirmTransaction() {
|
|
510
|
+
return { value: { err: null } }
|
|
511
|
+
},
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Create a mock Solana adapter
|
|
517
|
+
*/
|
|
518
|
+
export function createMockSolanaAdapter(
|
|
519
|
+
config: MockSolanaAdapterConfig = {}
|
|
520
|
+
): MockSolanaAdapter {
|
|
521
|
+
return new MockSolanaAdapter(config)
|
|
522
|
+
}
|