-
Notifications
You must be signed in to change notification settings - Fork 113
Expand file tree
/
Copy pathoperator.test.ts
More file actions
137 lines (114 loc) · 4.03 KB
/
Copy pathoperator.test.ts
File metadata and controls
137 lines (114 loc) · 4.03 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
import { describe, it, expect, vi, beforeEach } from 'vitest';
import RouteOperator from '../operator';
import { TransactionId } from '@wormhole-foundation/sdk';
// Mock the config
vi.mock('config', () => ({
default: {
wormholeApi: 'https://api.wormholescan.io/',
},
}));
// Mock fetch
global.fetch = vi.fn();
describe('RouteOperator', () => {
let routeOperator: RouteOperator;
beforeEach(() => {
routeOperator = new RouteOperator();
vi.clearAllMocks();
});
describe('resumeFromTx with Wormholescan API', () => {
it('should use Wormholescan API to identify CCTP routes', async () => {
const mockTx: TransactionId = {
chain: 'Ethereum',
txid: '0x1234567890abcdef',
};
// Mock Wormholescan API response for CCTP transfer
(global.fetch as any).mockResolvedValueOnce({
ok: true,
json: async () => ({
operations: [
{
content: {
standarizedProperties: {
appIds: ['CCTP_WORMHOLE_INTEGRATION'],
},
},
},
],
}),
});
// Mock the route's resumeIfManual to simulate CCTP route success
const mockReceipt = { state: 'Attested' };
const cctpRoute = routeOperator.routes['ManualCCTP'];
if (cctpRoute) {
cctpRoute.resumeIfManual = vi.fn().mockResolvedValue(mockReceipt);
}
const result = await routeOperator.resumeFromTx(mockTx);
// Verify Wormholescan API was called
expect(global.fetch).toHaveBeenCalledWith(
'https://api.wormholescan.io/api/v1/operations?txHash=0x1234567890abcdef',
{ headers: { accept: 'application/json' } },
);
// Verify only CCTP routes were tried
if (cctpRoute) {
expect(cctpRoute.resumeIfManual).toHaveBeenCalled();
}
// Verify non-CCTP routes were not tried
const tokenBridgeRoute = routeOperator.routes['ManualTokenBridge'];
if (tokenBridgeRoute && tokenBridgeRoute.resumeIfManual) {
expect(tokenBridgeRoute.resumeIfManual).not.toHaveBeenCalled();
}
});
it('should fall back to brute force when Wormholescan API fails', async () => {
const mockTx: TransactionId = {
chain: 'Ethereum',
txid: '0x1234567890abcdef',
};
// Mock Wormholescan API to fail
(global.fetch as any).mockRejectedValueOnce(new Error('API Error'));
// Mock all routes to fail except one
Object.values(routeOperator.routes).forEach((route) => {
route.resumeIfManual = vi.fn().mockResolvedValue(null);
});
const tokenBridgeRoute = routeOperator.routes['ManualTokenBridge'];
const mockReceipt = { state: 'Attested' };
if (tokenBridgeRoute) {
tokenBridgeRoute.resumeIfManual = vi
.fn()
.mockResolvedValue(mockReceipt);
}
const result = await routeOperator.resumeFromTx(mockTx);
// Verify all routes were tried (brute force)
Object.values(routeOperator.routes).forEach((route) => {
expect(route.resumeIfManual).toHaveBeenCalled();
});
expect(result).toEqual({
route: 'ManualTokenBridge',
receipt: mockReceipt,
});
});
it('should handle Wormholescan API returning no operations', async () => {
const mockTx: TransactionId = {
chain: 'Ethereum',
txid: '0x1234567890abcdef',
};
// Mock Wormholescan API response with no operations
(global.fetch as any).mockResolvedValueOnce({
ok: true,
json: async () => ({
operations: [],
}),
});
// Mock a route to succeed
const tokenBridgeRoute = routeOperator.routes['ManualTokenBridge'];
const mockReceipt = { state: 'Attested' };
if (tokenBridgeRoute) {
tokenBridgeRoute.resumeIfManual = vi
.fn()
.mockResolvedValue(mockReceipt);
}
await routeOperator.resumeFromTx(mockTx);
// Verify it fell back to brute force
expect(tokenBridgeRoute.resumeIfManual).toHaveBeenCalled();
});
});
});