@lifi/sdk 4.0.0-alpha.1 → 4.0.0-alpha.3
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 +201 -165
- package/dist/cjs/client/getClientStorage.js +3 -4
- package/dist/cjs/client/getClientStorage.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/getClientStorage.js +4 -4
- package/dist/esm/client/getClientStorage.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/types/client/getClientStorage.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +17 -2
- package/src/client/getClientStorage.ts +5 -4
- package/src/version.ts +1 -1
- package/CHANGELOG.md +0 -1272
- package/package.json.tmp +0 -103
- package/src/actions/actions.unit.handlers.ts +0 -78
- package/src/actions/getChains.unit.spec.ts +0 -19
- package/src/actions/getConnections.unit.spec.ts +0 -45
- package/src/actions/getContractCallsQuote.unit.spec.ts +0 -323
- package/src/actions/getGasRecommendation.unit.spec.ts +0 -40
- package/src/actions/getNameServiceAddress.unit.spec.ts +0 -169
- package/src/actions/getQuote.int.spec.ts +0 -18
- package/src/actions/getQuote.unit.spec.ts +0 -154
- package/src/actions/getRelayedTransactionStatus.unit.spec.ts +0 -243
- package/src/actions/getRelayerQuote.unit.spec.ts +0 -220
- package/src/actions/getRoutes.unit.spec.ts +0 -112
- package/src/actions/getStatus.unit.spec.ts +0 -53
- package/src/actions/getStepTransaction.unit.spec.ts +0 -140
- package/src/actions/getToken.unit.spec.ts +0 -45
- package/src/actions/getTokenBalance.unit.spec.ts +0 -61
- package/src/actions/getTokenBalances.unit.spec.ts +0 -68
- package/src/actions/getTokenBalancesByChain.unit.spec.ts +0 -108
- package/src/actions/getTokens.unit.spec.ts +0 -16
- package/src/actions/getTools.unit.spec.ts +0 -20
- package/src/actions/getTransactionHistory.unit.spec.ts +0 -36
- package/src/actions/getWalletBalances.unit.spec.ts +0 -90
- package/src/actions/relayTransaction.unit.spec.ts +0 -229
- package/src/client/createClient.unit.spec.ts +0 -274
- package/src/client/getClientStorage.unit.spec.ts +0 -382
- package/src/core/StatusManager.unit.spec.ts +0 -298
- package/src/core/execution.unit.handlers.ts +0 -32
- package/src/core/execution.unit.mock.ts +0 -252
- package/src/core/execution.unit.spec.ts +0 -86
- package/src/core/stepComparison.unit.spec.ts +0 -89
- package/src/errors/SDKError.unit.spec.ts +0 -160
- package/src/errors/baseError.unit.spec.ts +0 -22
- package/src/errors/httpError.unit.spec.ts +0 -125
- package/src/errors/utils/baseErrorRootCause.unit.spec.ts +0 -89
- package/src/errors/utils/rootCause.unit.spec.ts +0 -36
- package/src/utils/checkPackageUpdates.unit.spec.ts +0 -71
- package/src/utils/convertQuoteToRoute.unit.spec.ts +0 -56
- package/src/utils/fetchTxErrorDetails.unit.spec.ts +0 -42
- package/src/utils/getTransactionMessage.unit.spec.ts +0 -38
- package/src/utils/isRoutesRequest.unit.spec.ts +0 -46
- package/src/utils/isStep.unit.spec.ts +0 -55
- package/src/utils/isToken.unit.spec.ts +0 -49
- package/src/utils/request.unit.spec.ts +0 -159
- package/src/utils/sleep.unit.spec.ts +0 -17
- package/src/utils/waitForResult.unit.spec.ts +0 -75
- package/src/utils/withDedupe.unit.spec.ts +0 -26
- package/tsconfig.json +0 -18
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
LiFiStep,
|
|
3
|
-
RelayerQuoteResponse,
|
|
4
|
-
RequestOptions,
|
|
5
|
-
} from '@lifi/types'
|
|
6
|
-
import { ChainId } from '@lifi/types'
|
|
7
|
-
import { HttpResponse, http } from 'msw'
|
|
8
|
-
import { describe, expect, it } from 'vitest'
|
|
9
|
-
import { BaseError } from '../errors/baseError.js'
|
|
10
|
-
import { ErrorName } from '../errors/constants.js'
|
|
11
|
-
import { ValidationError } from '../errors/errors.js'
|
|
12
|
-
import { SDKError } from '../errors/SDKError.js'
|
|
13
|
-
import type { QuoteRequestFromAmount } from '../types/actions.js'
|
|
14
|
-
import { client, setupTestServer } from './actions.unit.handlers.js'
|
|
15
|
-
import { getRelayerQuote } from './getRelayerQuote.js'
|
|
16
|
-
|
|
17
|
-
describe('getRelayerQuote', () => {
|
|
18
|
-
const server = setupTestServer()
|
|
19
|
-
|
|
20
|
-
const createMockQuoteRequest = (
|
|
21
|
-
overrides: Partial<QuoteRequestFromAmount> = {}
|
|
22
|
-
): QuoteRequestFromAmount => ({
|
|
23
|
-
fromChain: ChainId.ETH,
|
|
24
|
-
fromToken: '0xA0b86a33E6441c8C06DDD4f36e4C4C5B4c3B4c3B',
|
|
25
|
-
fromAddress: '0x1234567890123456789012345678901234567890',
|
|
26
|
-
fromAmount: '1000000',
|
|
27
|
-
toChain: ChainId.POL,
|
|
28
|
-
toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
|
|
29
|
-
...overrides,
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
const mockLiFiStep: LiFiStep = {
|
|
33
|
-
id: 'test-step-id',
|
|
34
|
-
type: 'lifi',
|
|
35
|
-
includedSteps: [],
|
|
36
|
-
tool: 'test-tool',
|
|
37
|
-
toolDetails: {
|
|
38
|
-
key: 'test-tool',
|
|
39
|
-
name: 'Test Tool',
|
|
40
|
-
logoURI: 'https://example.com/logo.png',
|
|
41
|
-
},
|
|
42
|
-
action: {
|
|
43
|
-
fromChainId: ChainId.ETH,
|
|
44
|
-
toChainId: ChainId.POL,
|
|
45
|
-
fromToken: {
|
|
46
|
-
address: '0xA0b86a33E6441c8C06DDD4f36e4C4C5B4c3B4c3B',
|
|
47
|
-
symbol: 'USDC',
|
|
48
|
-
decimals: 6,
|
|
49
|
-
chainId: ChainId.ETH,
|
|
50
|
-
name: 'USD Coin',
|
|
51
|
-
priceUSD: '1.00',
|
|
52
|
-
},
|
|
53
|
-
toToken: {
|
|
54
|
-
address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
|
|
55
|
-
symbol: 'USDC',
|
|
56
|
-
decimals: 6,
|
|
57
|
-
chainId: ChainId.POL,
|
|
58
|
-
name: 'USD Coin',
|
|
59
|
-
priceUSD: '1.00',
|
|
60
|
-
},
|
|
61
|
-
fromAmount: '1000000',
|
|
62
|
-
fromAddress: '0x1234567890123456789012345678901234567890',
|
|
63
|
-
toAddress: '0x1234567890123456789012345678901234567890',
|
|
64
|
-
},
|
|
65
|
-
estimate: {
|
|
66
|
-
fromAmount: '1000000',
|
|
67
|
-
toAmount: '1000000',
|
|
68
|
-
toAmountMin: '970000',
|
|
69
|
-
approvalAddress: '0x1234567890123456789012345678901234567890',
|
|
70
|
-
tool: 'test-tool',
|
|
71
|
-
executionDuration: 30000,
|
|
72
|
-
},
|
|
73
|
-
transactionRequest: {
|
|
74
|
-
to: '0x1234567890123456789012345678901234567890',
|
|
75
|
-
data: '0x',
|
|
76
|
-
value: '0',
|
|
77
|
-
gasLimit: '100000',
|
|
78
|
-
},
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const mockSuccessResponse: RelayerQuoteResponse = {
|
|
82
|
-
status: 'ok',
|
|
83
|
-
data: mockLiFiStep,
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const mockErrorResponse: RelayerQuoteResponse = {
|
|
87
|
-
status: 'error',
|
|
88
|
-
data: {
|
|
89
|
-
code: 400,
|
|
90
|
-
message: 'Invalid request parameters',
|
|
91
|
-
},
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
describe('success scenarios', () => {
|
|
95
|
-
it('should get relayer quote successfully', async () => {
|
|
96
|
-
server.use(
|
|
97
|
-
http.get(`${client.config.apiUrl}/relayer/quote`, async () => {
|
|
98
|
-
return HttpResponse.json(mockSuccessResponse)
|
|
99
|
-
})
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
const request = createMockQuoteRequest()
|
|
103
|
-
|
|
104
|
-
const result = await getRelayerQuote(client, request)
|
|
105
|
-
|
|
106
|
-
expect(result).toEqual(mockLiFiStep)
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it('should pass request options correctly', async () => {
|
|
110
|
-
const mockAbortController = new AbortController()
|
|
111
|
-
const options: RequestOptions = {
|
|
112
|
-
signal: mockAbortController.signal,
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
let capturedOptions: any
|
|
116
|
-
server.use(
|
|
117
|
-
http.get(
|
|
118
|
-
`${client.config.apiUrl}/relayer/quote`,
|
|
119
|
-
async ({ request }) => {
|
|
120
|
-
capturedOptions = request
|
|
121
|
-
return HttpResponse.json(mockSuccessResponse)
|
|
122
|
-
}
|
|
123
|
-
)
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
const request = createMockQuoteRequest()
|
|
127
|
-
|
|
128
|
-
await getRelayerQuote(client, request, options)
|
|
129
|
-
|
|
130
|
-
expect(capturedOptions.signal).toBeDefined()
|
|
131
|
-
expect(capturedOptions.signal).toBeInstanceOf(AbortSignal)
|
|
132
|
-
})
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
describe('validation scenarios', () => {
|
|
136
|
-
it('should throw SDKError when required parameters are missing', async () => {
|
|
137
|
-
const testCases = [
|
|
138
|
-
{ param: 'fromChain', value: undefined },
|
|
139
|
-
{ param: 'fromToken', value: undefined },
|
|
140
|
-
{ param: 'fromAddress', value: undefined },
|
|
141
|
-
{ param: 'fromAmount', value: undefined },
|
|
142
|
-
{ param: 'toChain', value: undefined },
|
|
143
|
-
{ param: 'toToken', value: undefined },
|
|
144
|
-
]
|
|
145
|
-
|
|
146
|
-
for (const testCase of testCases) {
|
|
147
|
-
const invalidRequest = createMockQuoteRequest({
|
|
148
|
-
[testCase.param]: testCase.value,
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
await expect(getRelayerQuote(client, invalidRequest)).rejects.toThrow(
|
|
152
|
-
SDKError
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
try {
|
|
156
|
-
await getRelayerQuote(client, invalidRequest)
|
|
157
|
-
} catch (error) {
|
|
158
|
-
expect(error).toBeInstanceOf(SDKError)
|
|
159
|
-
expect((error as SDKError).cause).toBeInstanceOf(ValidationError)
|
|
160
|
-
expect((error as SDKError).cause.message).toBe(
|
|
161
|
-
`Required parameter "${testCase.param}" is missing.`
|
|
162
|
-
)
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
})
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
describe('error scenarios', () => {
|
|
169
|
-
it('should throw BaseError when server returns error status', async () => {
|
|
170
|
-
server.use(
|
|
171
|
-
http.get(`${client.config.apiUrl}/relayer/quote`, async () => {
|
|
172
|
-
return HttpResponse.json(mockErrorResponse)
|
|
173
|
-
})
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
const request = createMockQuoteRequest()
|
|
177
|
-
|
|
178
|
-
await expect(getRelayerQuote(client, request)).rejects.toThrow(BaseError)
|
|
179
|
-
|
|
180
|
-
try {
|
|
181
|
-
await getRelayerQuote(client, request)
|
|
182
|
-
} catch (error) {
|
|
183
|
-
expect(error).toBeInstanceOf(BaseError)
|
|
184
|
-
expect((error as BaseError).name).toBe(ErrorName.ServerError)
|
|
185
|
-
expect((error as BaseError).code).toBe(400)
|
|
186
|
-
expect((error as BaseError).message).toBe('Invalid request parameters')
|
|
187
|
-
}
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
it('should throw SDKError when network request fails', async () => {
|
|
191
|
-
server.use(
|
|
192
|
-
http.get(`${client.config.apiUrl}/relayer/quote`, async () => {
|
|
193
|
-
return HttpResponse.error()
|
|
194
|
-
})
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
const request = createMockQuoteRequest()
|
|
198
|
-
|
|
199
|
-
await expect(getRelayerQuote(client, request)).rejects.toThrow(SDKError)
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
it('should throw SDKError when request times out', async () => {
|
|
203
|
-
server.use(
|
|
204
|
-
http.get(`${client.config.apiUrl}/relayer/quote`, async () => {
|
|
205
|
-
// Simulate timeout by not responding
|
|
206
|
-
await new Promise(() => {}) // Never resolves
|
|
207
|
-
})
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
const request = createMockQuoteRequest()
|
|
211
|
-
const timeoutOptions: RequestOptions = {
|
|
212
|
-
signal: AbortSignal.timeout(100), // 100ms timeout
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
await expect(
|
|
216
|
-
getRelayerQuote(client, request, timeoutOptions)
|
|
217
|
-
).rejects.toThrow()
|
|
218
|
-
})
|
|
219
|
-
})
|
|
220
|
-
})
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { findDefaultToken } from '@lifi/data-types'
|
|
2
|
-
import type { RoutesRequest } from '@lifi/types'
|
|
3
|
-
import { ChainId, CoinKey } from '@lifi/types'
|
|
4
|
-
import { describe, expect, it, vi } from 'vitest'
|
|
5
|
-
import * as request from '../utils/request.js'
|
|
6
|
-
import { client, setupTestServer } from './actions.unit.handlers.js'
|
|
7
|
-
import { getRoutes } from './getRoutes.js'
|
|
8
|
-
|
|
9
|
-
const mockedFetch = vi.spyOn(request, 'request')
|
|
10
|
-
|
|
11
|
-
describe('getRoutes', () => {
|
|
12
|
-
setupTestServer()
|
|
13
|
-
|
|
14
|
-
const getRoutesRequest = ({
|
|
15
|
-
fromChainId = ChainId.BSC,
|
|
16
|
-
fromAmount = '10000000000000',
|
|
17
|
-
fromTokenAddress = findDefaultToken(CoinKey.USDC, ChainId.BSC).address,
|
|
18
|
-
toChainId = ChainId.DAI,
|
|
19
|
-
toTokenAddress = findDefaultToken(CoinKey.USDC, ChainId.DAI).address,
|
|
20
|
-
options = { slippage: 0.03 },
|
|
21
|
-
}: {
|
|
22
|
-
fromChainId?: ChainId
|
|
23
|
-
fromAmount?: string
|
|
24
|
-
fromTokenAddress?: string
|
|
25
|
-
toChainId?: ChainId
|
|
26
|
-
toTokenAddress?: string
|
|
27
|
-
options?: { slippage: number }
|
|
28
|
-
}): RoutesRequest => ({
|
|
29
|
-
fromChainId,
|
|
30
|
-
fromAmount,
|
|
31
|
-
fromTokenAddress,
|
|
32
|
-
toChainId,
|
|
33
|
-
toTokenAddress,
|
|
34
|
-
options,
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
describe('user input is invalid', () => {
|
|
38
|
-
it('should throw Error because of invalid fromChainId type', async () => {
|
|
39
|
-
const request = getRoutesRequest({
|
|
40
|
-
fromChainId: 'xxx' as unknown as ChainId,
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
await expect(getRoutes(client, request)).rejects.toThrow(
|
|
44
|
-
'Invalid routes request.'
|
|
45
|
-
)
|
|
46
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
it('should throw Error because of invalid fromAmount type', async () => {
|
|
50
|
-
const request = getRoutesRequest({
|
|
51
|
-
fromAmount: 10000000000000 as unknown as string,
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
await expect(getRoutes(client, request)).rejects.toThrow(
|
|
55
|
-
'Invalid routes request.'
|
|
56
|
-
)
|
|
57
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('should throw Error because of invalid fromTokenAddress type', async () => {
|
|
61
|
-
const request = getRoutesRequest({
|
|
62
|
-
fromTokenAddress: 1234 as unknown as string,
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
await expect(getRoutes(client, request)).rejects.toThrow(
|
|
66
|
-
'Invalid routes request.'
|
|
67
|
-
)
|
|
68
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('should throw Error because of invalid toChainId type', async () => {
|
|
72
|
-
const request = getRoutesRequest({
|
|
73
|
-
toChainId: 'xxx' as unknown as ChainId,
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
await expect(getRoutes(client, request)).rejects.toThrow(
|
|
77
|
-
'Invalid routes request.'
|
|
78
|
-
)
|
|
79
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('should throw Error because of invalid toTokenAddress type', async () => {
|
|
83
|
-
const request = getRoutesRequest({ toTokenAddress: '' })
|
|
84
|
-
|
|
85
|
-
await expect(getRoutes(client, request)).rejects.toThrow(
|
|
86
|
-
'Invalid routes request.'
|
|
87
|
-
)
|
|
88
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
it('should throw Error because of invalid options type', async () => {
|
|
92
|
-
const request = getRoutesRequest({
|
|
93
|
-
options: { slippage: 'not a number' as unknown as number },
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
await expect(getRoutes(client, request)).rejects.toThrow(
|
|
97
|
-
'Invalid routes request.'
|
|
98
|
-
)
|
|
99
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
100
|
-
})
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
describe('user input is valid', () => {
|
|
104
|
-
describe('and the backend call is successful', () => {
|
|
105
|
-
it('call the server once', async () => {
|
|
106
|
-
const request = getRoutesRequest({})
|
|
107
|
-
await getRoutes(client, request)
|
|
108
|
-
expect(mockedFetch).toHaveBeenCalledTimes(1)
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
})
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { ChainId } from '@lifi/types'
|
|
2
|
-
import { describe, expect, it, vi } from 'vitest'
|
|
3
|
-
import { ValidationError } from '../errors/errors.js'
|
|
4
|
-
import { SDKError } from '../errors/SDKError.js'
|
|
5
|
-
import * as request from '../utils/request.js'
|
|
6
|
-
import { client, setupTestServer } from './actions.unit.handlers.js'
|
|
7
|
-
import { getStatus } from './getStatus.js'
|
|
8
|
-
|
|
9
|
-
const mockedFetch = vi.spyOn(request, 'request')
|
|
10
|
-
|
|
11
|
-
describe('getStatus', () => {
|
|
12
|
-
setupTestServer()
|
|
13
|
-
|
|
14
|
-
const fromChain = ChainId.DAI
|
|
15
|
-
const toChain = ChainId.POL
|
|
16
|
-
const txHash = 'some tx hash'
|
|
17
|
-
const bridge = 'some bridge tool'
|
|
18
|
-
|
|
19
|
-
describe('user input is invalid', () => {
|
|
20
|
-
it('throw an error', async () => {
|
|
21
|
-
await expect(
|
|
22
|
-
getStatus(client, {
|
|
23
|
-
bridge,
|
|
24
|
-
fromChain,
|
|
25
|
-
toChain,
|
|
26
|
-
txHash: undefined as unknown as string,
|
|
27
|
-
})
|
|
28
|
-
).rejects.toThrowError(
|
|
29
|
-
new SDKError(
|
|
30
|
-
new ValidationError(
|
|
31
|
-
'Either "taskId" or "txHash" must be provided and non-empty.'
|
|
32
|
-
)
|
|
33
|
-
)
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
37
|
-
})
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
describe('user input is valid', () => {
|
|
41
|
-
describe('and the backend call is successful', () => {
|
|
42
|
-
it('call the server once', async () => {
|
|
43
|
-
await getStatus(client, {
|
|
44
|
-
bridge,
|
|
45
|
-
fromChain,
|
|
46
|
-
toChain,
|
|
47
|
-
txHash,
|
|
48
|
-
})
|
|
49
|
-
expect(mockedFetch).toHaveBeenCalledTimes(1)
|
|
50
|
-
})
|
|
51
|
-
})
|
|
52
|
-
})
|
|
53
|
-
})
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { findDefaultToken } from '@lifi/data-types'
|
|
2
|
-
import type { Action, Estimate, LiFiStep, StepTool, Token } from '@lifi/types'
|
|
3
|
-
import { ChainId, CoinKey } from '@lifi/types'
|
|
4
|
-
import { describe, expect, it, vi } from 'vitest'
|
|
5
|
-
import * as request from '../utils/request.js'
|
|
6
|
-
import { client, setupTestServer } from './actions.unit.handlers.js'
|
|
7
|
-
import { getStepTransaction } from './getStepTransaction.js'
|
|
8
|
-
|
|
9
|
-
const mockedFetch = vi.spyOn(request, 'request')
|
|
10
|
-
|
|
11
|
-
describe('getStepTransaction', () => {
|
|
12
|
-
setupTestServer()
|
|
13
|
-
|
|
14
|
-
const getAction = ({
|
|
15
|
-
fromChainId = ChainId.BSC,
|
|
16
|
-
fromAmount = '10000000000000',
|
|
17
|
-
fromToken = findDefaultToken(CoinKey.USDC, ChainId.BSC),
|
|
18
|
-
fromAddress = 'some from address', // we don't validate the format of addresses atm
|
|
19
|
-
toChainId = ChainId.DAI,
|
|
20
|
-
toToken = findDefaultToken(CoinKey.USDC, ChainId.DAI),
|
|
21
|
-
toAddress = 'some to address',
|
|
22
|
-
slippage = 0.03,
|
|
23
|
-
}): Action => ({
|
|
24
|
-
fromChainId,
|
|
25
|
-
fromAmount,
|
|
26
|
-
fromToken: fromToken as Token,
|
|
27
|
-
fromAddress,
|
|
28
|
-
toChainId,
|
|
29
|
-
toToken: toToken as Token,
|
|
30
|
-
toAddress,
|
|
31
|
-
slippage,
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
const getEstimate = ({
|
|
35
|
-
fromAmount = '10000000000000',
|
|
36
|
-
toAmount = '10000000000000',
|
|
37
|
-
toAmountMin = '999999999999',
|
|
38
|
-
approvalAddress = 'some approval address', // we don't validate the format of addresses atm;
|
|
39
|
-
executionDuration = 300,
|
|
40
|
-
tool = '1inch',
|
|
41
|
-
}): Estimate => ({
|
|
42
|
-
fromAmount,
|
|
43
|
-
toAmount,
|
|
44
|
-
toAmountMin,
|
|
45
|
-
approvalAddress,
|
|
46
|
-
executionDuration,
|
|
47
|
-
tool,
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
const getStep = ({
|
|
51
|
-
id = 'some random id',
|
|
52
|
-
type = 'lifi',
|
|
53
|
-
tool = 'some swap tool',
|
|
54
|
-
action = getAction({}),
|
|
55
|
-
estimate = getEstimate({}),
|
|
56
|
-
}: {
|
|
57
|
-
id?: string
|
|
58
|
-
type?: 'lifi'
|
|
59
|
-
tool?: StepTool
|
|
60
|
-
action?: Action
|
|
61
|
-
estimate?: Estimate
|
|
62
|
-
}): LiFiStep => ({
|
|
63
|
-
id,
|
|
64
|
-
type,
|
|
65
|
-
tool,
|
|
66
|
-
toolDetails: {
|
|
67
|
-
key: tool,
|
|
68
|
-
name: tool,
|
|
69
|
-
logoURI: '',
|
|
70
|
-
},
|
|
71
|
-
action,
|
|
72
|
-
estimate,
|
|
73
|
-
includedSteps: [],
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
describe('with a swap step', () => {
|
|
77
|
-
// While the validation fails for some users we should not enforce it
|
|
78
|
-
describe.skip('user input is invalid', () => {
|
|
79
|
-
it('should throw Error because of invalid id', async () => {
|
|
80
|
-
const step = getStep({ id: null as unknown as string })
|
|
81
|
-
|
|
82
|
-
await expect(getStepTransaction(client, step)).rejects.toThrow(
|
|
83
|
-
'Invalid step.'
|
|
84
|
-
)
|
|
85
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('should throw Error because of invalid type', async () => {
|
|
89
|
-
const step = getStep({ type: 42 as unknown as 'lifi' })
|
|
90
|
-
|
|
91
|
-
await expect(getStepTransaction(client, step)).rejects.toThrow(
|
|
92
|
-
'Invalid Step'
|
|
93
|
-
)
|
|
94
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('should throw Error because of invalid tool', async () => {
|
|
98
|
-
const step = getStep({ tool: null as unknown as StepTool })
|
|
99
|
-
|
|
100
|
-
await expect(getStepTransaction(client, step)).rejects.toThrow(
|
|
101
|
-
'Invalid step.'
|
|
102
|
-
)
|
|
103
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
// more indepth checks for the action type should be done once we have real schema validation
|
|
107
|
-
it('should throw Error because of invalid action', async () => {
|
|
108
|
-
const step = getStep({ action: 'xxx' as unknown as Action })
|
|
109
|
-
|
|
110
|
-
await expect(getStepTransaction(client, step)).rejects.toThrow(
|
|
111
|
-
'Invalid step.'
|
|
112
|
-
)
|
|
113
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
// more indepth checks for the estimate type should be done once we have real schema validation
|
|
117
|
-
it('should throw Error because of invalid estimate', async () => {
|
|
118
|
-
const step = getStep({
|
|
119
|
-
estimate: 'Is this really an estimate?' as unknown as Estimate,
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
await expect(getStepTransaction(client, step)).rejects.toThrow(
|
|
123
|
-
'Invalid step.'
|
|
124
|
-
)
|
|
125
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
126
|
-
})
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
describe('user input is valid', () => {
|
|
130
|
-
describe('and the backend call is successful', () => {
|
|
131
|
-
it('call the server once', async () => {
|
|
132
|
-
const step = getStep({})
|
|
133
|
-
|
|
134
|
-
await getStepTransaction(client, step)
|
|
135
|
-
expect(mockedFetch).toHaveBeenCalledTimes(1)
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
})
|
|
139
|
-
})
|
|
140
|
-
})
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { ChainId } from '@lifi/types'
|
|
2
|
-
import { describe, expect, it, vi } from 'vitest'
|
|
3
|
-
import { ValidationError } from '../errors/errors.js'
|
|
4
|
-
import { SDKError } from '../errors/SDKError.js'
|
|
5
|
-
import * as request from '../utils/request.js'
|
|
6
|
-
import { client, setupTestServer } from './actions.unit.handlers.js'
|
|
7
|
-
import { getToken } from './getToken.js'
|
|
8
|
-
|
|
9
|
-
const mockedFetch = vi.spyOn(request, 'request')
|
|
10
|
-
|
|
11
|
-
describe('getToken', () => {
|
|
12
|
-
setupTestServer()
|
|
13
|
-
|
|
14
|
-
describe('user input is invalid', () => {
|
|
15
|
-
it('throw an error', async () => {
|
|
16
|
-
await expect(
|
|
17
|
-
getToken(client, undefined as unknown as ChainId, 'DAI')
|
|
18
|
-
).rejects.toThrowError(
|
|
19
|
-
new SDKError(
|
|
20
|
-
new ValidationError('Required parameter "chain" is missing.')
|
|
21
|
-
)
|
|
22
|
-
)
|
|
23
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
24
|
-
|
|
25
|
-
await expect(
|
|
26
|
-
getToken(client, ChainId.ETH, undefined as unknown as string)
|
|
27
|
-
).rejects.toThrowError(
|
|
28
|
-
new SDKError(
|
|
29
|
-
new ValidationError('Required parameter "token" is missing.')
|
|
30
|
-
)
|
|
31
|
-
)
|
|
32
|
-
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
33
|
-
})
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
describe('user input is valid', () => {
|
|
37
|
-
describe('and the backend call is successful', () => {
|
|
38
|
-
it('call the server once', async () => {
|
|
39
|
-
await getToken(client, ChainId.DAI, 'DAI')
|
|
40
|
-
|
|
41
|
-
expect(mockedFetch).toHaveBeenCalledTimes(1)
|
|
42
|
-
})
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
})
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { findDefaultToken } from '@lifi/data-types'
|
|
2
|
-
import type { Token } from '@lifi/types'
|
|
3
|
-
import { ChainId, CoinKey } from '@lifi/types'
|
|
4
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
5
|
-
import { client } from './actions.unit.handlers.js'
|
|
6
|
-
import { getTokenBalance } from './getTokenBalance.js'
|
|
7
|
-
|
|
8
|
-
const mockedGetTokenBalance = vi.spyOn(
|
|
9
|
-
await import('./getTokenBalance.js'),
|
|
10
|
-
'getTokenBalance'
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
describe('getTokenBalance', () => {
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
vi.clearAllMocks()
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
const SOME_TOKEN = {
|
|
19
|
-
...findDefaultToken(CoinKey.USDC, ChainId.DAI),
|
|
20
|
-
priceUSD: '',
|
|
21
|
-
}
|
|
22
|
-
const SOME_WALLET_ADDRESS = 'some wallet address'
|
|
23
|
-
|
|
24
|
-
describe('user input is invalid', () => {
|
|
25
|
-
it('should throw Error because of missing walletAddress', async () => {
|
|
26
|
-
await expect(getTokenBalance(client, '', SOME_TOKEN)).rejects.toThrow(
|
|
27
|
-
'Missing walletAddress.'
|
|
28
|
-
)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('should throw Error because of invalid token', async () => {
|
|
32
|
-
await expect(
|
|
33
|
-
getTokenBalance(client, SOME_WALLET_ADDRESS, {
|
|
34
|
-
address: 'some wrong stuff',
|
|
35
|
-
chainId: 'not a chain Id',
|
|
36
|
-
} as unknown as Token)
|
|
37
|
-
).rejects.toThrow('Invalid tokens passed.')
|
|
38
|
-
})
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
describe('user input is valid', () => {
|
|
42
|
-
it('should call the balance service', async () => {
|
|
43
|
-
const balanceResponse = {
|
|
44
|
-
...SOME_TOKEN,
|
|
45
|
-
amount: 123n,
|
|
46
|
-
blockNumber: 1n,
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
mockedGetTokenBalance.mockReturnValue(Promise.resolve(balanceResponse))
|
|
50
|
-
|
|
51
|
-
const result = await getTokenBalance(
|
|
52
|
-
client,
|
|
53
|
-
SOME_WALLET_ADDRESS,
|
|
54
|
-
SOME_TOKEN
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
expect(mockedGetTokenBalance).toHaveBeenCalledTimes(1)
|
|
58
|
-
expect(result).toEqual(balanceResponse)
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
})
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { findDefaultToken } from '@lifi/data-types'
|
|
2
|
-
import type { Token } from '@lifi/types'
|
|
3
|
-
import { ChainId, CoinKey } from '@lifi/types'
|
|
4
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
5
|
-
import { client } from './actions.unit.handlers.js'
|
|
6
|
-
import { getTokenBalances } from './getTokenBalances.js'
|
|
7
|
-
|
|
8
|
-
const mockedGetTokenBalances = vi.spyOn(
|
|
9
|
-
await import('./getTokenBalances.js'),
|
|
10
|
-
'getTokenBalances'
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
describe('getTokenBalances', () => {
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
vi.clearAllMocks()
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
const SOME_TOKEN = {
|
|
19
|
-
...findDefaultToken(CoinKey.USDC, ChainId.DAI),
|
|
20
|
-
priceUSD: '',
|
|
21
|
-
}
|
|
22
|
-
const SOME_WALLET_ADDRESS = 'some wallet address'
|
|
23
|
-
|
|
24
|
-
describe('user input is invalid', () => {
|
|
25
|
-
it('should throw Error because of missing walletAddress', async () => {
|
|
26
|
-
await expect(getTokenBalances(client, '', [SOME_TOKEN])).rejects.toThrow(
|
|
27
|
-
'Missing walletAddress.'
|
|
28
|
-
)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('should throw Error because of an invalid token', async () => {
|
|
32
|
-
await expect(
|
|
33
|
-
getTokenBalances(client, SOME_WALLET_ADDRESS, [
|
|
34
|
-
SOME_TOKEN,
|
|
35
|
-
{ not: 'a token' } as unknown as Token,
|
|
36
|
-
])
|
|
37
|
-
).rejects.toThrow('Invalid tokens passed.')
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('should return empty token list as it is', async () => {
|
|
41
|
-
mockedGetTokenBalances.mockReturnValue(Promise.resolve([]))
|
|
42
|
-
const result = await getTokenBalances(client, SOME_WALLET_ADDRESS, [])
|
|
43
|
-
expect(result).toEqual([])
|
|
44
|
-
expect(mockedGetTokenBalances).toHaveBeenCalledTimes(1)
|
|
45
|
-
})
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
describe('user input is valid', () => {
|
|
49
|
-
it('should call the balance service', async () => {
|
|
50
|
-
const balanceResponse = [
|
|
51
|
-
{
|
|
52
|
-
...SOME_TOKEN,
|
|
53
|
-
amount: 123n,
|
|
54
|
-
blockNumber: 1n,
|
|
55
|
-
},
|
|
56
|
-
]
|
|
57
|
-
|
|
58
|
-
mockedGetTokenBalances.mockReturnValue(Promise.resolve(balanceResponse))
|
|
59
|
-
|
|
60
|
-
const result = await getTokenBalances(client, SOME_WALLET_ADDRESS, [
|
|
61
|
-
SOME_TOKEN,
|
|
62
|
-
])
|
|
63
|
-
|
|
64
|
-
expect(mockedGetTokenBalances).toHaveBeenCalledTimes(1)
|
|
65
|
-
expect(result).toEqual(balanceResponse)
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
|
-
})
|