@ledgerhq/live-common 27.2.0 → 27.3.0-nightly.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.
Files changed (219) hide show
  1. package/lib/bot/index.d.ts.map +1 -1
  2. package/lib/bot/index.js +8 -3
  3. package/lib/bot/index.js.map +1 -1
  4. package/lib/bot/specs.d.ts +9 -0
  5. package/lib/bot/specs.d.ts.map +1 -1
  6. package/lib/bot/specs.js +49 -1
  7. package/lib/bot/specs.js.map +1 -1
  8. package/lib/currencies/support.d.ts.map +1 -1
  9. package/lib/currencies/support.js +2 -1
  10. package/lib/currencies/support.js.map +1 -1
  11. package/lib/derivation.d.ts.map +1 -1
  12. package/lib/derivation.js +2 -4
  13. package/lib/derivation.js.map +1 -1
  14. package/lib/env.js +1 -1
  15. package/lib/exchange/swap/getExchangeRates.d.ts.map +1 -1
  16. package/lib/exchange/swap/getExchangeRates.js +1 -1
  17. package/lib/exchange/swap/getExchangeRates.js.map +1 -1
  18. package/lib/exchange/swap/getProviders.d.ts.map +1 -1
  19. package/lib/exchange/swap/getProviders.js +45 -5
  20. package/lib/exchange/swap/getProviders.js.map +1 -1
  21. package/lib/exchange/swap/getProviders.test.d.ts +2 -0
  22. package/lib/exchange/swap/getProviders.test.d.ts.map +1 -0
  23. package/lib/exchange/swap/getProviders.test.js +519 -0
  24. package/lib/exchange/swap/getProviders.test.js.map +1 -0
  25. package/lib/exchange/swap/hooks/useProviderRates.d.ts +1 -0
  26. package/lib/exchange/swap/hooks/useProviderRates.d.ts.map +1 -1
  27. package/lib/exchange/swap/hooks/useProviderRates.js +19 -4
  28. package/lib/exchange/swap/hooks/useProviderRates.js.map +1 -1
  29. package/lib/exchange/swap/hooks/useProviderRates.test.js +42 -0
  30. package/lib/exchange/swap/hooks/useProviderRates.test.js.map +1 -1
  31. package/lib/exchange/swap/hooks/useSwapTransaction.d.ts +1 -0
  32. package/lib/exchange/swap/hooks/useSwapTransaction.d.ts.map +1 -1
  33. package/lib/exchange/swap/hooks/useSwapTransaction.js +2 -1
  34. package/lib/exchange/swap/hooks/useSwapTransaction.js.map +1 -1
  35. package/lib/exchange/swap/index.d.ts +2 -1
  36. package/lib/exchange/swap/index.d.ts.map +1 -1
  37. package/lib/exchange/swap/index.js +11 -1
  38. package/lib/exchange/swap/index.js.map +1 -1
  39. package/lib/exchange/swap/index.test.js +22 -0
  40. package/lib/exchange/swap/index.test.js.map +1 -1
  41. package/lib/exchange/swap/mock.js +1 -1
  42. package/lib/exchange/swap/mock.js.map +1 -1
  43. package/lib/exchange/swap/types.d.ts +14 -0
  44. package/lib/exchange/swap/types.d.ts.map +1 -1
  45. package/lib/exchange/swap/utils/index.d.ts +1 -0
  46. package/lib/exchange/swap/utils/index.d.ts.map +1 -1
  47. package/lib/exchange/swap/utils/index.js +6 -1
  48. package/lib/exchange/swap/utils/index.js.map +1 -1
  49. package/lib/exchange/swap/utils/index.test.js +12 -0
  50. package/lib/exchange/swap/utils/index.test.js.map +1 -1
  51. package/lib/families/algorand/speculos-deviceActions.d.ts.map +1 -1
  52. package/lib/families/algorand/speculos-deviceActions.js +2 -29
  53. package/lib/families/algorand/speculos-deviceActions.js.map +1 -1
  54. package/lib/families/bitcoin/specs.d.ts.map +1 -1
  55. package/lib/families/bitcoin/specs.js +0 -1
  56. package/lib/families/bitcoin/specs.js.map +1 -1
  57. package/lib/families/bitcoin/speculos-deviceActions.d.ts.map +1 -1
  58. package/lib/families/bitcoin/speculos-deviceActions.js +2 -22
  59. package/lib/families/bitcoin/speculos-deviceActions.js.map +1 -1
  60. package/lib/families/cardano/specs.d.ts.map +1 -1
  61. package/lib/families/cardano/specs.js +4 -3
  62. package/lib/families/cardano/specs.js.map +1 -1
  63. package/lib/families/cardano/speculos-deviceActions.d.ts.map +1 -1
  64. package/lib/families/cardano/speculos-deviceActions.js +2 -10
  65. package/lib/families/cardano/speculos-deviceActions.js.map +1 -1
  66. package/lib/families/celo/speculos-deviceActions.d.ts.map +1 -1
  67. package/lib/families/celo/speculos-deviceActions.js +3 -10
  68. package/lib/families/celo/speculos-deviceActions.js.map +1 -1
  69. package/lib/families/elrond/speculos-deviceActions.d.ts.map +1 -1
  70. package/lib/families/elrond/speculos-deviceActions.js +3 -8
  71. package/lib/families/elrond/speculos-deviceActions.js.map +1 -1
  72. package/lib/families/ethereum/speculos-deviceActions.d.ts.map +1 -1
  73. package/lib/families/ethereum/speculos-deviceActions.js +10 -33
  74. package/lib/families/ethereum/speculos-deviceActions.js.map +1 -1
  75. package/lib/families/evm/specs.d.ts.map +1 -1
  76. package/lib/families/evm/specs.js +9 -5
  77. package/lib/families/evm/specs.js.map +1 -1
  78. package/lib/families/evm/speculos-deviceActions.d.ts.map +1 -1
  79. package/lib/families/evm/speculos-deviceActions.js +5 -25
  80. package/lib/families/evm/speculos-deviceActions.js.map +1 -1
  81. package/lib/families/filecoin/speculos-deviceActions.d.ts.map +1 -1
  82. package/lib/families/filecoin/speculos-deviceActions.js +6 -7
  83. package/lib/families/filecoin/speculos-deviceActions.js.map +1 -1
  84. package/lib/families/polkadot/speculos-deviceActions.d.ts.map +1 -1
  85. package/lib/families/polkadot/speculos-deviceActions.js +3 -10
  86. package/lib/families/polkadot/speculos-deviceActions.js.map +1 -1
  87. package/lib/families/ripple/speculos-deviceActions.d.ts.map +1 -1
  88. package/lib/families/ripple/speculos-deviceActions.js +2 -22
  89. package/lib/families/ripple/speculos-deviceActions.js.map +1 -1
  90. package/lib/families/solana/speculos-deviceActions.d.ts.map +1 -1
  91. package/lib/families/solana/speculos-deviceActions.js +5 -7
  92. package/lib/families/solana/speculos-deviceActions.js.map +1 -1
  93. package/lib/families/stellar/speculos-deviceActions.d.ts.map +1 -1
  94. package/lib/families/stellar/speculos-deviceActions.js +4 -8
  95. package/lib/families/stellar/speculos-deviceActions.js.map +1 -1
  96. package/lib/families/tezos/speculos-deviceActions.d.ts.map +1 -1
  97. package/lib/families/tezos/speculos-deviceActions.js +6 -11
  98. package/lib/families/tezos/speculos-deviceActions.js.map +1 -1
  99. package/lib/families/tron/speculos-deviceActions.d.ts.map +1 -1
  100. package/lib/families/tron/speculos-deviceActions.js +2 -14
  101. package/lib/families/tron/speculos-deviceActions.js.map +1 -1
  102. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
  103. package/lib/featureFlags/defaultFeatures.js +3 -0
  104. package/lib/featureFlags/defaultFeatures.js.map +1 -1
  105. package/lib/hw/extractOnboardingState.d.ts +5 -1
  106. package/lib/hw/extractOnboardingState.d.ts.map +1 -1
  107. package/lib/hw/extractOnboardingState.js +17 -9
  108. package/lib/hw/extractOnboardingState.js.map +1 -1
  109. package/lib/hw/extractOnboardingState.test.js +21 -11
  110. package/lib/hw/extractOnboardingState.test.js.map +1 -1
  111. package/lib/postOnboarding/PostOnboardingProvider.d.ts +20 -0
  112. package/lib/postOnboarding/PostOnboardingProvider.d.ts.map +1 -0
  113. package/lib/postOnboarding/PostOnboardingProvider.js +33 -0
  114. package/lib/postOnboarding/PostOnboardingProvider.js.map +1 -0
  115. package/lib/postOnboarding/actions.d.ts +20 -0
  116. package/lib/postOnboarding/actions.d.ts.map +1 -0
  117. package/lib/postOnboarding/actions.js +37 -0
  118. package/lib/postOnboarding/actions.js.map +1 -0
  119. package/lib/postOnboarding/hooks/index.d.ts +6 -0
  120. package/lib/postOnboarding/hooks/index.d.ts.map +1 -0
  121. package/lib/postOnboarding/hooks/index.js +22 -0
  122. package/lib/postOnboarding/hooks/index.js.map +1 -0
  123. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.d.ts +8 -0
  124. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.d.ts.map +1 -0
  125. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.js +16 -0
  126. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.js.map +1 -0
  127. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.d.ts +2 -0
  128. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.d.ts.map +1 -0
  129. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.js +75 -0
  130. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.js.map +1 -0
  131. package/lib/postOnboarding/hooks/usePostOnboardingContext.d.ts +3 -0
  132. package/lib/postOnboarding/hooks/usePostOnboardingContext.d.ts.map +1 -0
  133. package/lib/postOnboarding/hooks/usePostOnboardingContext.js +10 -0
  134. package/lib/postOnboarding/hooks/usePostOnboardingContext.js.map +1 -0
  135. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.d.ts +8 -0
  136. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.d.ts.map +1 -0
  137. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.js +20 -0
  138. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.js.map +1 -0
  139. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.d.ts +2 -0
  140. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.d.ts.map +1 -0
  141. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.js +64 -0
  142. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.js.map +1 -0
  143. package/lib/postOnboarding/hooks/usePostOnboardingHubState.d.ts +12 -0
  144. package/lib/postOnboarding/hooks/usePostOnboardingHubState.d.ts.map +1 -0
  145. package/lib/postOnboarding/hooks/usePostOnboardingHubState.js +65 -0
  146. package/lib/postOnboarding/hooks/usePostOnboardingHubState.js.map +1 -0
  147. package/lib/postOnboarding/hooks/usePostOnboardingHubState.test.d.ts +2 -0
  148. package/lib/postOnboarding/hooks/usePostOnboardingHubState.test.d.ts.map +1 -0
  149. package/lib/postOnboarding/hooks/usePostOnboardingHubState.test.js +129 -0
  150. package/lib/postOnboarding/hooks/usePostOnboardingHubState.test.js.map +1 -0
  151. package/lib/postOnboarding/hooks/useStartPostOnboardingCallback.d.ts +13 -0
  152. package/lib/postOnboarding/hooks/useStartPostOnboardingCallback.d.ts.map +1 -0
  153. package/lib/postOnboarding/hooks/useStartPostOnboardingCallback.js +34 -0
  154. package/lib/postOnboarding/hooks/useStartPostOnboardingCallback.js.map +1 -0
  155. package/lib/postOnboarding/mock.d.ts +8 -0
  156. package/lib/postOnboarding/mock.d.ts.map +1 -0
  157. package/lib/postOnboarding/mock.js +46 -0
  158. package/lib/postOnboarding/mock.js.map +1 -0
  159. package/lib/postOnboarding/reducer.d.ts +22 -0
  160. package/lib/postOnboarding/reducer.d.ts.map +1 -0
  161. package/lib/postOnboarding/reducer.js +71 -0
  162. package/lib/postOnboarding/reducer.js.map +1 -0
  163. package/lib/postOnboarding/reducer.test.d.ts +2 -0
  164. package/lib/postOnboarding/reducer.test.d.ts.map +1 -0
  165. package/lib/postOnboarding/reducer.test.js +251 -0
  166. package/lib/postOnboarding/reducer.test.js.map +1 -0
  167. package/package.json +8 -4
  168. package/src/bot/index.ts +11 -12
  169. package/src/bot/specs.ts +45 -0
  170. package/src/currencies/__snapshots__/sortByMarketcap.test.ts.snap +1 -35
  171. package/src/currencies/support.ts +2 -1
  172. package/src/derivation.ts +2 -4
  173. package/src/env.ts +1 -1
  174. package/src/exchange/swap/getExchangeRates.ts +7 -3
  175. package/src/exchange/swap/getProviders.test.ts +450 -0
  176. package/src/exchange/swap/getProviders.ts +31 -8
  177. package/src/exchange/swap/hooks/useProviderRates.test.ts +43 -0
  178. package/src/exchange/swap/hooks/useProviderRates.ts +22 -3
  179. package/src/exchange/swap/hooks/useSwapTransaction.ts +3 -1
  180. package/src/exchange/swap/index.test.ts +36 -1
  181. package/src/exchange/swap/index.ts +15 -0
  182. package/src/exchange/swap/mock.ts +2 -2
  183. package/src/exchange/swap/types.ts +11 -0
  184. package/src/exchange/swap/utils/index.test.ts +19 -0
  185. package/src/exchange/swap/utils/index.ts +5 -0
  186. package/src/families/algorand/speculos-deviceActions.ts +4 -35
  187. package/src/families/bitcoin/specs.ts +0 -1
  188. package/src/families/bitcoin/speculos-deviceActions.ts +3 -26
  189. package/src/families/cardano/specs.ts +4 -3
  190. package/src/families/cardano/speculos-deviceActions.ts +3 -14
  191. package/src/families/celo/speculos-deviceActions.ts +6 -14
  192. package/src/families/elrond/speculos-deviceActions.ts +4 -9
  193. package/src/families/ethereum/speculos-deviceActions.ts +16 -46
  194. package/src/families/evm/specs.ts +12 -8
  195. package/src/families/evm/speculos-deviceActions.ts +7 -35
  196. package/src/families/filecoin/speculos-deviceActions.ts +7 -8
  197. package/src/families/polkadot/speculos-deviceActions.ts +5 -16
  198. package/src/families/ripple/speculos-deviceActions.ts +3 -28
  199. package/src/families/solana/speculos-deviceActions.ts +6 -8
  200. package/src/families/stellar/speculos-deviceActions.ts +5 -11
  201. package/src/families/tezos/speculos-deviceActions.ts +9 -16
  202. package/src/families/tron/speculos-deviceActions.ts +4 -12
  203. package/src/featureFlags/defaultFeatures.ts +3 -0
  204. package/src/hw/extractOnboardingState.test.ts +29 -12
  205. package/src/hw/extractOnboardingState.ts +17 -9
  206. package/src/postOnboarding/PostOnboardingProvider.tsx +49 -0
  207. package/src/postOnboarding/actions.ts +40 -0
  208. package/src/postOnboarding/hooks/index.ts +5 -0
  209. package/src/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.ts +82 -0
  210. package/src/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.ts +12 -0
  211. package/src/postOnboarding/hooks/usePostOnboardingContext.ts +9 -0
  212. package/src/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.ts +83 -0
  213. package/src/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.ts +22 -0
  214. package/src/postOnboarding/hooks/usePostOnboardingHubState.test.ts +184 -0
  215. package/src/postOnboarding/hooks/usePostOnboardingHubState.ts +56 -0
  216. package/src/postOnboarding/hooks/useStartPostOnboardingCallback.ts +38 -0
  217. package/src/postOnboarding/mock.ts +53 -0
  218. package/src/postOnboarding/reducer.test.ts +247 -0
  219. package/src/postOnboarding/reducer.ts +105 -0
@@ -0,0 +1,450 @@
1
+ import axios from "axios";
2
+ import getProviders from "./getProviders";
3
+ import { getEnv, setEnv } from "../../env";
4
+
5
+ const EXPECTED_RESULT_V4 = [
6
+ {
7
+ provider: "changelly",
8
+ pairs: [
9
+ {
10
+ from: "bitcoin",
11
+ to: "ethereum",
12
+ tradeMethod: "float",
13
+ },
14
+ {
15
+ from: "bitcoin",
16
+ to: "zcash",
17
+ tradeMethod: "float",
18
+ },
19
+ {
20
+ from: "bitcoin",
21
+ to: "ethereum_classic",
22
+ tradeMethod: "float",
23
+ },
24
+ {
25
+ from: "ethereum",
26
+ to: "bitcoin",
27
+ tradeMethod: "float",
28
+ },
29
+ {
30
+ from: "ethereum",
31
+ to: "zcash",
32
+ tradeMethod: "float",
33
+ },
34
+ {
35
+ from: "ethereum",
36
+ to: "ethereum_classic",
37
+ tradeMethod: "float",
38
+ },
39
+ {
40
+ from: "bitcoin",
41
+ to: "ethereum",
42
+ tradeMethod: "float",
43
+ },
44
+ {
45
+ from: "bitcoin",
46
+ to: "zcash",
47
+ tradeMethod: "float",
48
+ },
49
+ {
50
+ from: "bitcoin",
51
+ to: "ethereum_classic",
52
+ tradeMethod: "float",
53
+ },
54
+ {
55
+ from: "ethereum",
56
+ to: "bitcoin",
57
+ tradeMethod: "float",
58
+ },
59
+ {
60
+ from: "ethereum",
61
+ to: "zcash",
62
+ tradeMethod: "float",
63
+ },
64
+ {
65
+ from: "ethereum",
66
+ to: "ethereum_classic",
67
+ tradeMethod: "float",
68
+ },
69
+ {
70
+ from: "zcash",
71
+ to: "bitcoin",
72
+ tradeMethod: "float",
73
+ },
74
+ {
75
+ from: "zcash",
76
+ to: "ethereum_classic",
77
+ tradeMethod: "float",
78
+ },
79
+ {
80
+ from: "ethereum_classic",
81
+ to: "bitcoin",
82
+ tradeMethod: "float",
83
+ },
84
+ {
85
+ from: "ethereum_classic",
86
+ to: "ethereum",
87
+ tradeMethod: "float",
88
+ },
89
+ {
90
+ from: "bitcoin",
91
+ to: "ethereum",
92
+ tradeMethod: "fixed",
93
+ },
94
+ {
95
+ from: "bitcoin",
96
+ to: "zcash",
97
+ tradeMethod: "fixed",
98
+ },
99
+ {
100
+ from: "bitcoin",
101
+ to: "ethereum_classic",
102
+ tradeMethod: "fixed",
103
+ },
104
+ {
105
+ from: "ethereum",
106
+ to: "bitcoin",
107
+ tradeMethod: "fixed",
108
+ },
109
+ {
110
+ from: "ethereum",
111
+ to: "zcash",
112
+ tradeMethod: "fixed",
113
+ },
114
+ {
115
+ from: "ethereum",
116
+ to: "ethereum_classic",
117
+ tradeMethod: "fixed",
118
+ },
119
+ {
120
+ from: "zcash",
121
+ to: "bitcoin",
122
+ tradeMethod: "fixed",
123
+ },
124
+ {
125
+ from: "zcash",
126
+ to: "ethereum_classic",
127
+ tradeMethod: "fixed",
128
+ },
129
+ {
130
+ from: "ethereum_classic",
131
+ to: "bitcoin",
132
+ tradeMethod: "fixed",
133
+ },
134
+ {
135
+ from: "ethereum_classic",
136
+ to: "ethereum",
137
+ tradeMethod: "fixed",
138
+ },
139
+ {
140
+ from: "zcash",
141
+ to: "bitcoin",
142
+ tradeMethod: "fixed",
143
+ },
144
+ {
145
+ from: "zcash",
146
+ to: "ethereum_classic",
147
+ tradeMethod: "fixed",
148
+ },
149
+ {
150
+ from: "ethereum_classic",
151
+ to: "bitcoin",
152
+ tradeMethod: "fixed",
153
+ },
154
+ {
155
+ from: "ethereum_classic",
156
+ to: "ethereum",
157
+ tradeMethod: "fixed",
158
+ },
159
+ ],
160
+ },
161
+ {
162
+ provider: "ftx",
163
+ pairs: [
164
+ {
165
+ from: "bitcoin",
166
+ to: "ethereum",
167
+ tradeMethod: "float",
168
+ },
169
+ {
170
+ from: "bitcoin",
171
+ to: "zcash",
172
+ tradeMethod: "float",
173
+ },
174
+ {
175
+ from: "bitcoin",
176
+ to: "ethereum_classic",
177
+ tradeMethod: "float",
178
+ },
179
+ {
180
+ from: "ethereum",
181
+ to: "bitcoin",
182
+ tradeMethod: "float",
183
+ },
184
+ {
185
+ from: "ethereum",
186
+ to: "zcash",
187
+ tradeMethod: "float",
188
+ },
189
+ {
190
+ from: "ethereum",
191
+ to: "ethereum_classic",
192
+ tradeMethod: "float",
193
+ },
194
+ {
195
+ from: "zcash",
196
+ to: "bitcoin",
197
+ tradeMethod: "float",
198
+ },
199
+ {
200
+ from: "zcash",
201
+ to: "ethereum",
202
+ tradeMethod: "float",
203
+ },
204
+ {
205
+ from: "zcash",
206
+ to: "ethereum_classic",
207
+ tradeMethod: "float",
208
+ },
209
+ {
210
+ from: "ethereum_classic",
211
+ to: "bitcoin",
212
+ tradeMethod: "float",
213
+ },
214
+ {
215
+ from: "ethereum_classic",
216
+ to: "ethereum",
217
+ tradeMethod: "float",
218
+ },
219
+ {
220
+ from: "ethereum_classic",
221
+ to: "zcash",
222
+ tradeMethod: "float",
223
+ },
224
+ ],
225
+ },
226
+ ];
227
+
228
+ jest.mock("axios");
229
+ const mockedAxios = jest.mocked(axios);
230
+
231
+ describe("swap/getProviders", () => {
232
+ const DEFAULT_SWAP_API_BASE = getEnv("SWAP_API_BASE");
233
+
234
+ afterAll(() => {
235
+ // Restore DEFAULT_SWAP_API_BASE
236
+ setEnv("SWAP_API_BASE", DEFAULT_SWAP_API_BASE);
237
+ });
238
+
239
+ describe("version 2", () => {
240
+ const data = [
241
+ {
242
+ provider: "changelly",
243
+ pairs: [
244
+ {
245
+ from: "bitcoin",
246
+ to: "ethereum",
247
+ tradeMethod: ["float", "fixed"],
248
+ },
249
+ {
250
+ from: "bitcoin",
251
+ to: "ethereum_classic",
252
+ tradeMethod: ["float", "fixed"],
253
+ },
254
+ ],
255
+ },
256
+ ];
257
+ const resp = {
258
+ data,
259
+ status: 200,
260
+ statusText: "",
261
+ headers: {},
262
+ config: {},
263
+ };
264
+
265
+ beforeAll(() => {
266
+ // set SWAP_API_BASE
267
+ setEnv("SWAP_API_BASE", "https://swap.ledger.com/v2");
268
+ });
269
+
270
+ beforeEach(() => {
271
+ mockedAxios.mockResolvedValue(Promise.resolve(resp));
272
+ });
273
+
274
+ afterEach(() => {
275
+ mockedAxios.mockClear();
276
+ });
277
+
278
+ test("should not be called with whitelist", async () => {
279
+ await getProviders();
280
+
281
+ expect(mockedAxios).toBeCalledWith(
282
+ expect.objectContaining({
283
+ params: undefined,
284
+ })
285
+ );
286
+ });
287
+ });
288
+
289
+ describe("version 3", () => {
290
+ const data = [
291
+ {
292
+ provider: "changelly",
293
+ pairs: [
294
+ {
295
+ from: "bitcoin",
296
+ to: "ethereum",
297
+ tradeMethod: ["float", "fixed"],
298
+ },
299
+ {
300
+ from: "bitcoin",
301
+ to: "ethereum_classic",
302
+ tradeMethod: ["float", "fixed"],
303
+ },
304
+ ],
305
+ },
306
+ ];
307
+ const resp = {
308
+ data,
309
+ status: 200,
310
+ statusText: "",
311
+ headers: {},
312
+ config: {},
313
+ };
314
+
315
+ beforeAll(() => {
316
+ // set SWAP_API_BASE
317
+ setEnv("SWAP_API_BASE", "https://swap.ledger.com/v3");
318
+ });
319
+
320
+ beforeEach(() => {
321
+ mockedAxios.mockResolvedValue(Promise.resolve(resp));
322
+ });
323
+
324
+ afterEach(() => {
325
+ mockedAxios.mockClear();
326
+ });
327
+
328
+ test("should be called with whitelist", async () => {
329
+ await getProviders();
330
+
331
+ expect(mockedAxios).toBeCalledWith(
332
+ expect.objectContaining({
333
+ params: expect.objectContaining({
334
+ whitelist: expect.any(Array),
335
+ }),
336
+ })
337
+ );
338
+ });
339
+
340
+ test("should throw error if no data", async () => {
341
+ const emptyResp = { ...resp, data: [] };
342
+
343
+ mockedAxios.mockResolvedValue(Promise.resolve(emptyResp));
344
+
345
+ await expect(getProviders).rejects.toThrow("SwapNoAvailableProviders");
346
+ });
347
+
348
+ test("should return list of providers with pairs", async () => {
349
+ const res = await getProviders();
350
+
351
+ expect(res).toEqual(data);
352
+ });
353
+ });
354
+
355
+ describe("version 4", () => {
356
+ const data = {
357
+ currencies: {
358
+ "1": "bitcoin",
359
+ "2": "ethereum",
360
+ "3": "zcash",
361
+ "4": "ethereum_classic",
362
+ },
363
+ providers: {
364
+ changelly: [
365
+ {
366
+ methods: ["float"],
367
+ pairs: {
368
+ "1": [2, 3, 4],
369
+ "2": [1, 3, 4],
370
+ },
371
+ },
372
+ {
373
+ methods: ["float", "fixed"],
374
+ pairs: {
375
+ "1": [2, 3, 4],
376
+ "2": [1, 3, 4],
377
+ "3": [1, 4],
378
+ "4": [1, 2],
379
+ },
380
+ },
381
+ {
382
+ methods: ["fixed"],
383
+ pairs: {
384
+ "3": [1, 4],
385
+ "4": [1, 2],
386
+ },
387
+ },
388
+ ],
389
+ ftx: [
390
+ {
391
+ methods: ["float"],
392
+ pairs: {
393
+ "1": [2, 3, 4],
394
+ "2": [1, 3, 4],
395
+ "3": [1, 2, 4],
396
+ "4": [1, 2, 3],
397
+ },
398
+ },
399
+ ],
400
+ },
401
+ };
402
+
403
+ const resp = {
404
+ data,
405
+ status: 200,
406
+ statusText: "",
407
+ headers: {},
408
+ config: {},
409
+ };
410
+
411
+ beforeAll(() => {
412
+ // set SWAP_API_BASE
413
+ setEnv("SWAP_API_BASE", "https://swap.ledger.com/v4");
414
+ });
415
+
416
+ beforeEach(() => {
417
+ mockedAxios.mockResolvedValue(Promise.resolve(resp));
418
+ });
419
+
420
+ afterEach(() => {
421
+ mockedAxios.mockClear();
422
+ });
423
+
424
+ test("should be called with whitelist", async () => {
425
+ await getProviders();
426
+
427
+ expect(mockedAxios).toBeCalledWith(
428
+ expect.objectContaining({
429
+ params: expect.objectContaining({
430
+ whitelist: expect.any(Array),
431
+ }),
432
+ })
433
+ );
434
+ });
435
+
436
+ test("should throw error if no providers", async () => {
437
+ const emptyResp = { ...resp, data: { ...data, providers: {} } };
438
+
439
+ mockedAxios.mockResolvedValue(Promise.resolve(emptyResp));
440
+
441
+ await expect(getProviders).rejects.toThrow("SwapNoAvailableProviders");
442
+ });
443
+
444
+ test("should return list of providers with pairs", async () => {
445
+ const res = await getProviders();
446
+
447
+ expect(res).toEqual(EXPECTED_RESULT_V4);
448
+ });
449
+ });
450
+ });
@@ -2,29 +2,52 @@ import qs from "qs";
2
2
  import { getEnv } from "../../env";
3
3
  import { SwapNoAvailableProviders } from "../../errors";
4
4
  import network from "../../network";
5
- import { getAvailableProviders, getSwapAPIBaseURL } from "./";
5
+ import {
6
+ getAvailableProviders,
7
+ getSwapAPIBaseURL,
8
+ getSwapAPIVersion,
9
+ } from "./";
6
10
  import { mockGetProviders } from "./mock";
7
- import type { GetProviders } from "./types";
11
+ import type { GetProviders, ProvidersResponseV4 } from "./types";
8
12
 
9
13
  const getProviders: GetProviders = async () => {
10
14
  if (getEnv("MOCK")) return mockGetProviders();
11
15
 
12
- // Rely on the api base to determine the version logic
13
- const usesV3 = getSwapAPIBaseURL().endsWith("v3");
16
+ const version = getSwapAPIVersion();
14
17
 
15
18
  const res = await network({
16
19
  method: "GET",
17
20
  url: `${getSwapAPIBaseURL()}/providers`,
18
- params: usesV3 ? { whitelist: getAvailableProviders() } : undefined,
21
+ params: version >= 3 ? { whitelist: getAvailableProviders() } : undefined,
19
22
  paramsSerializer: (params) =>
20
23
  qs.stringify(params, { arrayFormat: "comma" }),
21
24
  });
22
25
 
23
- if (!res.data.length) {
24
- throw new SwapNoAvailableProviders();
26
+ if (version < 4) {
27
+ if (!res.data.length) {
28
+ throw new SwapNoAvailableProviders();
29
+ }
30
+ return res.data;
25
31
  }
26
32
 
27
- return res.data;
33
+ const responseV4 = res.data as ProvidersResponseV4;
34
+ if (!responseV4.providers || !Object.keys(responseV4.providers).length) {
35
+ throw new SwapNoAvailableProviders();
36
+ }
37
+ return Object.entries(responseV4.providers).flatMap(([provider, groups]) => ({
38
+ provider: provider,
39
+ pairs: groups.flatMap((group) =>
40
+ group.methods.flatMap((tradeMethod) =>
41
+ Object.entries(group.pairs).flatMap(([from, toArray]) =>
42
+ (toArray as number[]).map((to) => ({
43
+ from: responseV4.currencies[from],
44
+ to: responseV4.currencies[to.toString()],
45
+ tradeMethod,
46
+ }))
47
+ )
48
+ )
49
+ ),
50
+ }));
28
51
  };
29
52
 
30
53
  export default getProviders;
@@ -137,6 +137,49 @@ describe("useProviderRates", () => {
137
137
  expect(mockedGetExchangeRates).toHaveBeenCalledTimes(1);
138
138
  });
139
139
 
140
+ it("should refetch with the corrected selected rate", async () => {
141
+ const setExchangeRate = jest.fn();
142
+
143
+ mockedGetExchangeRates.mockResolvedValue(mockedRatesPromise);
144
+
145
+ const { result, waitForNextUpdate } = renderHook(useProviderRates, {
146
+ initialProps: { ...baseInitalProps, setExchangeRate },
147
+ });
148
+
149
+ mockedGetExchangeRates.mockClear();
150
+
151
+ act(() => {
152
+ result.current.refetchRates();
153
+ });
154
+ await waitForNextUpdate({ timeout: 1000 });
155
+
156
+ expect(setExchangeRate).toBeCalledWith(
157
+ expect.objectContaining({
158
+ provider: "ftx",
159
+ tradeMethod: "fixed",
160
+ })
161
+ );
162
+
163
+ act(() => {
164
+ result.current.updateSelectedRate({
165
+ rate: new BigNumber(1),
166
+ toAmount: new BigNumber(1),
167
+ magnitudeAwareRate: new BigNumber(1),
168
+ provider: "ftx",
169
+ tradeMethod: "float",
170
+ });
171
+ result.current.refetchRates();
172
+ });
173
+ await waitForNextUpdate({ timeout: 1000 });
174
+
175
+ expect(setExchangeRate).toBeCalledWith(
176
+ expect.objectContaining({
177
+ provider: "ftx",
178
+ tradeMethod: "float",
179
+ })
180
+ );
181
+ });
182
+
140
183
  it("should refetch the rates if refetchRates is called", async () => {
141
184
  const { result, waitForNextUpdate } = renderHook(useProviderRates, {
142
185
  initialProps: baseInitalProps,
@@ -45,6 +45,7 @@ export const useProviderRates = ({
45
45
  }): {
46
46
  rates: RatesReducerState;
47
47
  refetchRates: () => void;
48
+ updateSelectedRate: (selected?: ExchangeRate) => void;
48
49
  } => {
49
50
  const { account: fromAccount } = fromState;
50
51
  const { currency: toCurrency } = toState;
@@ -55,8 +56,15 @@ export const useProviderRates = ({
55
56
  const [getRatesDependency, setGetRatesDependency] = useState<unknown | null>(
56
57
  null
57
58
  );
59
+ const [getSelectedRate, setGetSelectedRate] = useState<ExchangeRate | {}>({});
60
+
58
61
  const refetchRates = useCallback(() => setGetRatesDependency({}), []);
59
62
 
63
+ const updateSelectedRate = useCallback(
64
+ (selected = {}) => setGetSelectedRate(selected),
65
+ []
66
+ );
67
+
60
68
  useEffect(
61
69
  () => {
62
70
  let abort = false;
@@ -141,12 +149,22 @@ export const useProviderRates = ({
141
149
  dispatchRates({ type: "set", payload: rates });
142
150
 
143
151
  /**
144
- * Select the first rate returned by the API. Should be the prefered
152
+ * By default select the first rate returned by the API. Should be the prefered
145
153
  * rate for the user. Rate ordering logic is handeled on backend side
146
154
  */
147
- const rate = rates?.length > 0 ? rates[0] : null;
148
155
 
149
- setExchangeRate && setExchangeRate(rate);
156
+ const getRate = () => {
157
+ if (!(rates?.length > 0)) {
158
+ return null;
159
+ }
160
+ const { provider, tradeMethod } = getSelectedRate as ExchangeRate;
161
+ const rate = rates.find(
162
+ (rate) =>
163
+ rate.provider === provider && rate.tradeMethod === tradeMethod
164
+ );
165
+ return rate ? rate : rates[0];
166
+ };
167
+ setExchangeRate && setExchangeRate(getRate());
150
168
  }
151
169
  } catch (error) {
152
170
  !abort && dispatchRates({ type: "error", payload: error });
@@ -174,5 +192,6 @@ export const useProviderRates = ({
174
192
  return {
175
193
  rates,
176
194
  refetchRates,
195
+ updateSelectedRate,
177
196
  };
178
197
  };
@@ -32,6 +32,7 @@ export type SwapDataType = {
32
32
  isSwapReversable: boolean;
33
33
  rates: RatesReducerState;
34
34
  refetchRates: () => void;
35
+ updateSelectedRate: (selected?: ExchangeRate) => void;
35
36
  targetAccounts?: Account[];
36
37
  };
37
38
  export const selectorStateDefaultValues = {
@@ -139,7 +140,7 @@ export const useSwapTransaction = ({
139
140
  setIsSendMaxLoading,
140
141
  });
141
142
 
142
- const { rates, refetchRates } = useProviderRates({
143
+ const { rates, refetchRates, updateSelectedRate } = useProviderRates({
143
144
  fromState,
144
145
  toState,
145
146
  transaction,
@@ -156,6 +157,7 @@ export const useSwapTransaction = ({
156
157
  isSwapReversable,
157
158
  rates,
158
159
  refetchRates,
160
+ updateSelectedRate,
159
161
  targetAccounts,
160
162
  },
161
163
  setFromAmount,
@@ -1,4 +1,6 @@
1
- import { isSwapOperationPending } from ".";
1
+ import { isSwapOperationPending, getSwapAPIVersion } from ".";
2
+
3
+ import { getEnv, setEnv } from "../../env";
2
4
 
3
5
  describe("swap/index", () => {
4
6
  describe("isSwapOperationPending", () => {
@@ -33,4 +35,37 @@ describe("swap/index", () => {
33
35
  expect(result).toBe(true);
34
36
  });
35
37
  });
38
+
39
+ describe("getSwapAPIVersion", () => {
40
+ const DEFAULT_SWAP_API_BASE = getEnv("SWAP_API_BASE");
41
+
42
+ afterEach(() => {
43
+ // Restore DEFAULT_SWAP_API_BASE
44
+ setEnv("SWAP_API_BASE", DEFAULT_SWAP_API_BASE);
45
+ });
46
+
47
+ test("should return version when SWAP_API_BASE contains one", () => {
48
+ const result = getSwapAPIVersion();
49
+
50
+ expect(result).toBe(4);
51
+ });
52
+
53
+ test("should throw an error if no version in SWAP_API_BASE", () => {
54
+ setEnv("SWAP_API_BASE", "https://swap.ledger.com");
55
+
56
+ expect(getSwapAPIVersion).toThrow(Error);
57
+ expect(getSwapAPIVersion).toThrow(
58
+ "Configured swap API base URL is invalid, should end with /v<number>"
59
+ );
60
+ });
61
+
62
+ test("should throw an error if version is NaN", () => {
63
+ setEnv("SWAP_API_BASE", "https://swap.ledger.com/vtest");
64
+
65
+ expect(getSwapAPIVersion).toThrow(Error);
66
+ expect(getSwapAPIVersion).toThrow(
67
+ "Configured swap API base URL is invalid, should end with /v<number>"
68
+ );
69
+ });
70
+ });
36
71
  });