@ledgerhq/live-common 21.26.1 → 21.27.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 (178) hide show
  1. package/lib/__tests__/currencies.js +1 -1
  2. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.synced.unit.test.js +27 -26
  3. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.synced.unit.test.js.map +1 -1
  4. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.syncing.integration.test.js +9 -7
  5. package/lib/__tests__/families/bitcoin/wallet-btc/xpub.syncing.integration.test.js.map +1 -1
  6. package/lib/bridge/jsHelpers.js +1 -1
  7. package/lib/bridge/jsHelpers.js.map +1 -1
  8. package/lib/data/icons/react/index.d.ts +1 -0
  9. package/lib/data/icons/react/index.d.ts.map +1 -1
  10. package/lib/data/icons/react/index.js +4 -2
  11. package/lib/data/icons/react/index.js.map +1 -1
  12. package/lib/data/icons/react/sol.js +3 -3
  13. package/lib/data/icons/react/sol.js.map +1 -1
  14. package/lib/data/icons/react/tyc.d.ts +8 -0
  15. package/lib/data/icons/react/tyc.d.ts.map +1 -0
  16. package/lib/data/icons/react/tyc.js +33 -0
  17. package/lib/data/icons/react/tyc.js.map +1 -0
  18. package/lib/data/icons/reactNative/index.d.ts +1 -0
  19. package/lib/data/icons/reactNative/index.d.ts.map +1 -1
  20. package/lib/data/icons/reactNative/index.js +4 -2
  21. package/lib/data/icons/reactNative/index.js.map +1 -1
  22. package/lib/data/icons/reactNative/sol.js +3 -3
  23. package/lib/data/icons/reactNative/sol.js.map +1 -1
  24. package/lib/data/icons/reactNative/tyc.d.ts +8 -0
  25. package/lib/data/icons/reactNative/tyc.d.ts.map +1 -0
  26. package/lib/data/icons/reactNative/tyc.js +34 -0
  27. package/lib/data/icons/reactNative/tyc.js.map +1 -0
  28. package/lib/env.d.ts +19 -5
  29. package/lib/env.d.ts.map +1 -1
  30. package/lib/env.js +14 -0
  31. package/lib/env.js.map +1 -1
  32. package/lib/env.react.d.ts +1 -1
  33. package/lib/env.react.d.ts.map +1 -1
  34. package/lib/exchange/hw-app-exchange/Exchange.d.ts +12 -15
  35. package/lib/exchange/hw-app-exchange/Exchange.d.ts.map +1 -1
  36. package/lib/exchange/hw-app-exchange/Exchange.js +4 -13
  37. package/lib/exchange/hw-app-exchange/Exchange.js.map +1 -1
  38. package/lib/exchange/index.d.ts.map +1 -1
  39. package/lib/exchange/index.js +9 -2
  40. package/lib/exchange/index.js.map +1 -1
  41. package/lib/exchange/platform/completeExchange.d.ts +6 -0
  42. package/lib/exchange/platform/completeExchange.d.ts.map +1 -0
  43. package/lib/exchange/platform/completeExchange.js +24 -0
  44. package/lib/exchange/platform/completeExchange.js.map +1 -0
  45. package/lib/exchange/platform/serialization.d.ts +4 -0
  46. package/lib/exchange/platform/serialization.d.ts.map +1 -0
  47. package/lib/exchange/platform/serialization.js +57 -0
  48. package/lib/exchange/platform/serialization.js.map +1 -0
  49. package/lib/exchange/{swap → platform}/startExchange.d.ts +0 -0
  50. package/lib/exchange/platform/startExchange.d.ts.map +1 -0
  51. package/lib/exchange/{swap → platform}/startExchange.js +3 -3
  52. package/lib/exchange/platform/startExchange.js.map +1 -0
  53. package/lib/exchange/platform/transfer/completeExchange.d.ts +5 -0
  54. package/lib/exchange/platform/transfer/completeExchange.d.ts.map +1 -0
  55. package/lib/exchange/platform/transfer/completeExchange.js +198 -0
  56. package/lib/exchange/platform/transfer/completeExchange.js.map +1 -0
  57. package/lib/exchange/platform/transfer/index.d.ts +5 -0
  58. package/lib/exchange/platform/transfer/index.d.ts.map +1 -0
  59. package/lib/exchange/platform/transfer/index.js +49 -0
  60. package/lib/exchange/platform/transfer/index.js.map +1 -0
  61. package/lib/exchange/platform/types.d.ts +59 -0
  62. package/lib/exchange/platform/types.d.ts.map +1 -0
  63. package/lib/exchange/platform/types.js +3 -0
  64. package/lib/exchange/platform/types.js.map +1 -0
  65. package/lib/exchange/sell/checkSignatureAndPrepare.js +1 -2
  66. package/lib/exchange/sell/checkSignatureAndPrepare.js.map +1 -1
  67. package/lib/exchange/sell/getTransactionId.js +1 -2
  68. package/lib/exchange/sell/getTransactionId.js.map +1 -1
  69. package/lib/exchange/sell/index.d.ts +6 -0
  70. package/lib/exchange/sell/index.d.ts.map +1 -1
  71. package/lib/exchange/sell/index.js +3 -3
  72. package/lib/exchange/sell/index.js.map +1 -1
  73. package/lib/exchange/swap/completeExchange.d.ts +2 -13
  74. package/lib/exchange/swap/completeExchange.d.ts.map +1 -1
  75. package/lib/exchange/swap/completeExchange.js +2 -4
  76. package/lib/exchange/swap/completeExchange.js.map +1 -1
  77. package/lib/exchange/swap/initSwap.d.ts.map +1 -1
  78. package/lib/exchange/swap/initSwap.js +3 -4
  79. package/lib/exchange/swap/initSwap.js.map +1 -1
  80. package/lib/exchange/swap/types.d.ts +0 -12
  81. package/lib/exchange/swap/types.d.ts.map +1 -1
  82. package/lib/exchange/testCurrencyConfig/data/coins.d.ts +8 -0
  83. package/lib/exchange/testCurrencyConfig/data/coins.d.ts.map +1 -0
  84. package/lib/exchange/testCurrencyConfig/data/coins.js +21 -0
  85. package/lib/exchange/testCurrencyConfig/data/coins.js.map +1 -0
  86. package/lib/exchange/testCurrencyConfig/index.d.ts +8 -0
  87. package/lib/exchange/testCurrencyConfig/index.d.ts.map +1 -0
  88. package/lib/exchange/testCurrencyConfig/index.js +68 -0
  89. package/lib/exchange/testCurrencyConfig/index.js.map +1 -0
  90. package/lib/families/bitcoin/wallet-btc/wallet.d.ts.map +1 -1
  91. package/lib/families/bitcoin/wallet-btc/wallet.js +10 -2
  92. package/lib/families/bitcoin/wallet-btc/wallet.js.map +1 -1
  93. package/lib/families/ethereum/specs.d.ts.map +1 -1
  94. package/lib/families/ethereum/specs.js +2 -0
  95. package/lib/families/ethereum/specs.js.map +1 -1
  96. package/lib/hw/actions/app.d.ts +3 -0
  97. package/lib/hw/actions/app.d.ts.map +1 -1
  98. package/lib/hw/actions/app.js +7 -1
  99. package/lib/hw/actions/app.js.map +1 -1
  100. package/lib/hw/actions/completeExchange.d.ts +1 -0
  101. package/lib/hw/actions/completeExchange.d.ts.map +1 -1
  102. package/lib/hw/actions/completeExchange.js +4 -3
  103. package/lib/hw/actions/completeExchange.js.map +1 -1
  104. package/lib/hw/connectApp.d.ts +5 -0
  105. package/lib/hw/connectApp.d.ts.map +1 -1
  106. package/lib/hw/connectApp.js +11 -1
  107. package/lib/hw/connectApp.js.map +1 -1
  108. package/lib/market/MarketDataProvider.d.ts +26 -0
  109. package/lib/market/MarketDataProvider.d.ts.map +1 -0
  110. package/lib/market/MarketDataProvider.js +339 -0
  111. package/lib/market/MarketDataProvider.js.map +1 -0
  112. package/lib/market/api/api.d.ts +15 -0
  113. package/lib/market/api/api.d.ts.map +1 -0
  114. package/lib/market/api/api.js +261 -0
  115. package/lib/market/api/api.js.map +1 -0
  116. package/lib/market/api/api.mock.d.ts +15 -0
  117. package/lib/market/api/api.mock.d.ts.map +1 -0
  118. package/lib/market/api/api.mock.js +454 -0
  119. package/lib/market/api/api.mock.js.map +1 -0
  120. package/lib/market/types.d.ts +83 -0
  121. package/lib/market/types.d.ts.map +1 -0
  122. package/lib/market/types.js +3 -0
  123. package/lib/market/types.js.map +1 -0
  124. package/lib/market/utils/countervalueFormatter.d.ts +8 -0
  125. package/lib/market/utils/countervalueFormatter.d.ts.map +1 -0
  126. package/lib/market/utils/countervalueFormatter.js +18 -0
  127. package/lib/market/utils/countervalueFormatter.js.map +1 -0
  128. package/lib/market/utils/rangeDataTable.d.ts +10 -0
  129. package/lib/market/utils/rangeDataTable.d.ts.map +1 -0
  130. package/lib/market/utils/rangeDataTable.js +36 -0
  131. package/lib/market/utils/rangeDataTable.js.map +1 -0
  132. package/package.json +7 -7
  133. package/src/.DS_Store +0 -0
  134. package/src/__tests__/.DS_Store +0 -0
  135. package/src/__tests__/__snapshots__/all.libcore.ts.snap +144 -193
  136. package/src/__tests__/currencies.ts +1 -1
  137. package/src/__tests__/families/bitcoin/wallet-btc/xpub.synced.unit.test.ts +26 -25
  138. package/src/__tests__/families/bitcoin/wallet-btc/xpub.syncing.integration.test.ts +2 -0
  139. package/src/bridge/jsHelpers.ts +1 -1
  140. package/src/currencies/__snapshots__/.DS_Store +0 -0
  141. package/src/data/icons/react/index.tsx +1 -0
  142. package/src/data/icons/react/sol.tsx +1 -1
  143. package/src/data/icons/react/tyc.tsx +12 -0
  144. package/src/data/icons/reactNative/index.tsx +1 -0
  145. package/src/data/icons/reactNative/sol.tsx +1 -1
  146. package/src/data/icons/reactNative/tyc.tsx +13 -0
  147. package/src/data/icons/svg/SOL.svg +8 -1
  148. package/src/data/icons/svg/TYC.svg +6 -0
  149. package/src/env.ts +14 -0
  150. package/src/exchange/hw-app-exchange/Exchange.ts +22 -18
  151. package/src/exchange/index.ts +19 -1
  152. package/src/exchange/platform/completeExchange.ts +42 -0
  153. package/src/exchange/platform/serialization.ts +78 -0
  154. package/src/exchange/{swap → platform}/startExchange.ts +6 -2
  155. package/src/exchange/platform/transfer/completeExchange.ts +187 -0
  156. package/src/exchange/platform/transfer/index.ts +66 -0
  157. package/src/exchange/platform/types.ts +76 -0
  158. package/src/exchange/sell/checkSignatureAndPrepare.ts +2 -2
  159. package/src/exchange/sell/getTransactionId.ts +2 -2
  160. package/src/exchange/sell/index.ts +1 -1
  161. package/src/exchange/swap/completeExchange.ts +41 -50
  162. package/src/exchange/swap/initSwap.ts +4 -7
  163. package/src/exchange/swap/types.ts +1 -14
  164. package/src/exchange/testCurrencyConfig/data/coins.ts +20 -0
  165. package/src/exchange/testCurrencyConfig/index.ts +24 -0
  166. package/src/families/bitcoin/wallet-btc/wallet.ts +8 -2
  167. package/src/families/ethereum/specs.ts +2 -0
  168. package/src/hw/actions/app.ts +17 -1
  169. package/src/hw/actions/completeExchange.ts +9 -3
  170. package/src/hw/connectApp.ts +19 -0
  171. package/src/market/MarketDataProvider.tsx +440 -0
  172. package/src/market/api/api.mock.ts +374 -0
  173. package/src/market/api/api.ts +227 -0
  174. package/src/market/types.ts +92 -0
  175. package/src/market/utils/countervalueFormatter.ts +24 -0
  176. package/src/market/utils/rangeDataTable.ts +40 -0
  177. package/lib/exchange/swap/startExchange.d.ts.map +0 -1
  178. package/lib/exchange/swap/startExchange.js.map +0 -1
@@ -0,0 +1,187 @@
1
+ import secp256k1 from "secp256k1";
2
+ import { from, Observable } from "rxjs";
3
+ import { TransportStatusError, WrongDeviceForAccount } from "@ledgerhq/errors";
4
+
5
+ import { delay } from "../../../promise";
6
+ import ExchangeTransport, {
7
+ ExchangeTypes,
8
+ } from "../../hw-app-exchange/Exchange";
9
+ import perFamily from "../../../generated/exchange";
10
+ import { getAccountCurrency, getMainAccount } from "../../../account";
11
+ import { getAccountBridge } from "../../../bridge";
12
+ import { TransactionRefusedOnDevice } from "../../../errors";
13
+ import { withDevice } from "../../../hw/deviceAccess";
14
+ import { getCurrencyExchangeConfig } from "../..";
15
+ import { getProvider } from ".";
16
+
17
+ import type {
18
+ CompleteExchangeInputFund,
19
+ CompleteExchangeInputSell,
20
+ CompleteExchangeRequestEvent,
21
+ } from "../types";
22
+
23
+ const withDevicePromise = (deviceId, fn) =>
24
+ withDevice(deviceId)((transport) => from(fn(transport))).toPromise();
25
+
26
+ const completeExchange = (
27
+ input: CompleteExchangeInputFund | CompleteExchangeInputSell
28
+ ): Observable<CompleteExchangeRequestEvent> => {
29
+ let { transaction } = input; // TODO build a tx from the data
30
+
31
+ const {
32
+ deviceId,
33
+ exchange,
34
+ provider,
35
+ binaryPayload,
36
+ signature,
37
+ exchangeType,
38
+ rateType, // TODO Pass fixed/float for UI switch ?
39
+ } = input;
40
+
41
+ const { fromAccount, fromParentAccount } = exchange;
42
+
43
+ return new Observable((o) => {
44
+ let unsubscribed = false;
45
+ let ignoreTransportError = false;
46
+
47
+ const confirmExchange = async () => {
48
+ await withDevicePromise(deviceId, async (transport) => {
49
+ const providerNameAndSignature = getProvider(exchangeType, provider);
50
+
51
+ if (!providerNameAndSignature)
52
+ throw new Error("Could not get provider infos");
53
+
54
+ const exchange = new ExchangeTransport(
55
+ transport,
56
+ exchangeType,
57
+ rateType
58
+ );
59
+ const refundAccount = getMainAccount(fromAccount, fromParentAccount);
60
+ const accountBridge = getAccountBridge(refundAccount);
61
+ const refundCurrency = getAccountCurrency(refundAccount);
62
+
63
+ if (refundCurrency.type !== "CryptoCurrency")
64
+ throw new Error("This should be a cryptocurrency");
65
+
66
+ transaction = await accountBridge.prepareTransaction(
67
+ refundAccount,
68
+ transaction
69
+ );
70
+ if (unsubscribed) return;
71
+
72
+ const { errors, estimatedFees } =
73
+ await accountBridge.getTransactionStatus(refundAccount, transaction);
74
+ if (unsubscribed) return;
75
+
76
+ const errorsKeys = Object.keys(errors);
77
+ if (errorsKeys.length > 0) throw errors[errorsKeys[0]]; // throw the first error
78
+
79
+ await exchange.setPartnerKey(providerNameAndSignature.nameAndPubkey);
80
+ if (unsubscribed) return;
81
+
82
+ await exchange.checkPartner(providerNameAndSignature.signature);
83
+ if (unsubscribed) return;
84
+
85
+ await exchange.processTransaction(
86
+ Buffer.from(binaryPayload, "hex"),
87
+ estimatedFees
88
+ );
89
+ if (unsubscribed) return;
90
+
91
+ const bufferSignature = Buffer.from(signature, "hex");
92
+ /**
93
+ * For the Fund and Swap flow, the signature sent to the nano needs to
94
+ * be in DER format, which is not the case for Sell flow. Hence the
95
+ * ternary.
96
+ * cf. https://github.com/LedgerHQ/app-exchange/blob/e67848f136dc7227521791b91f608f7cd32e7da7/src/check_tx_signature.c#L14-L32
97
+ */
98
+ const goodSign =
99
+ exchangeType === ExchangeTypes.Sell
100
+ ? bufferSignature
101
+ : Buffer.from(secp256k1.signatureExport(bufferSignature));
102
+
103
+ if (!goodSign) {
104
+ throw new Error("Could not check provider signature");
105
+ }
106
+
107
+ await exchange.checkTransactionSignature(goodSign);
108
+ if (unsubscribed) return;
109
+
110
+ const payoutAddressParameters = await perFamily[
111
+ refundCurrency.family
112
+ ].getSerializedAddressParameters(
113
+ refundAccount.freshAddressPath,
114
+ refundAccount.derivationMode,
115
+ refundCurrency.id
116
+ );
117
+ if (unsubscribed) return;
118
+
119
+ const {
120
+ config: payoutAddressConfig,
121
+ signature: payoutAddressConfigSignature,
122
+ } = getCurrencyExchangeConfig(refundCurrency);
123
+
124
+ try {
125
+ await exchange.checkPayoutAddress(
126
+ payoutAddressConfig,
127
+ payoutAddressConfigSignature,
128
+ payoutAddressParameters.addressParameters
129
+ );
130
+ } catch (e) {
131
+ // @ts-expect-error TransportStatusError to be typed on ledgerjs
132
+ if (e instanceof TransportStatusError && e.statusCode === 0x6a83) {
133
+ throw new WrongDeviceForAccount(undefined, {
134
+ accountName: refundAccount.name,
135
+ });
136
+ }
137
+
138
+ throw e;
139
+ }
140
+
141
+ o.next({
142
+ type: "complete-exchange-requested",
143
+ estimatedFees,
144
+ });
145
+
146
+ if (unsubscribed) return;
147
+ ignoreTransportError = true;
148
+ await exchange.signCoinTransaction();
149
+ }).catch((e) => {
150
+ if (ignoreTransportError) return;
151
+
152
+ // @ts-expect-error TransportStatusError to be typed on ledgerjs
153
+ if (e instanceof TransportStatusError && e.statusCode === 0x6a84) {
154
+ throw new TransactionRefusedOnDevice();
155
+ }
156
+
157
+ throw e;
158
+ });
159
+ await delay(3000);
160
+ if (unsubscribed) return;
161
+ o.next({
162
+ type: "complete-exchange-result",
163
+ completeExchangeResult: transaction,
164
+ });
165
+ };
166
+
167
+ confirmExchange().then(
168
+ () => {
169
+ o.complete();
170
+ unsubscribed = true;
171
+ },
172
+ (e) => {
173
+ o.next({
174
+ type: "complete-exchange-error",
175
+ error: e,
176
+ });
177
+ o.complete();
178
+ unsubscribed = true;
179
+ }
180
+ );
181
+ return () => {
182
+ unsubscribed = true;
183
+ };
184
+ });
185
+ };
186
+
187
+ export default completeExchange;
@@ -0,0 +1,66 @@
1
+ import type { ExchangeProviderNameAndSignature } from "../..";
2
+ import { getEnv } from "../../../env";
3
+ import { ExchangeTypes } from "../../hw-app-exchange/Exchange";
4
+ // FIXME: to be move in this file alongide 'fundProviders' once 'src/exchange/sell/' is deprecated
5
+ import { sellProviders } from "../../sell";
6
+
7
+ const testFundProvider = {
8
+ nameAndPubkey: Buffer.from([
9
+ 0x9, 0x46, 0x55, 0x4e, 0x44, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x4, 0x0, 0xbe,
10
+ 0xef, 0x98, 0xb4, 0xb2, 0x99, 0x4f, 0x68, 0x8f, 0xd9, 0x8b, 0x56, 0x5e,
11
+ 0x17, 0x1e, 0xc9, 0x25, 0x9c, 0x89, 0x6, 0x14, 0xd2, 0xdb, 0xa6, 0x10, 0x52,
12
+ 0x2, 0x1, 0x8e, 0x3a, 0x76, 0x4a, 0xa6, 0x68, 0x3e, 0xa1, 0x16, 0xc9, 0xe0,
13
+ 0xe3, 0xc8, 0x1, 0xca, 0x5a, 0xb9, 0x72, 0xa2, 0xf8, 0xf7, 0x9f, 0x90, 0x6e,
14
+ 0x19, 0xf7, 0x3e, 0xdb, 0x91, 0x45, 0x0, 0xea, 0xd0, 0x2d, 0x70,
15
+ ]),
16
+ signature: Buffer.from([
17
+ 0x30, 0x44, 0x2, 0x20, 0x3c, 0x1c, 0xe9, 0xea, 0xf2, 0x1a, 0x18, 0x80, 0x3e,
18
+ 0xa9, 0x87, 0x6f, 0xab, 0x8f, 0x8a, 0x24, 0xb0, 0xd6, 0xe5, 0xf2, 0x6e,
19
+ 0xf7, 0x54, 0xf2, 0xd1, 0xa0, 0xac, 0x34, 0x24, 0xfc, 0xb8, 0xe1, 0x2, 0x20,
20
+ 0x4f, 0x6c, 0x92, 0xcf, 0xec, 0x8f, 0x23, 0x2c, 0x1b, 0x14, 0x89, 0x88,
21
+ 0x2f, 0x98, 0x7, 0xf, 0xe3, 0xe2, 0x0, 0x84, 0xd0, 0x23, 0xd6, 0x53, 0xe3,
22
+ 0xee, 0xf6, 0x96, 0xbc, 0xa0, 0x27, 0x78,
23
+ ]),
24
+ curve: "secpk256k1",
25
+ };
26
+
27
+ const fundProviders: Record<
28
+ string,
29
+ {
30
+ nameAndPubkey: Buffer;
31
+ signature: Buffer;
32
+ curve: string;
33
+ }
34
+ > = {
35
+ // FIXME: no prod provider for now
36
+ };
37
+
38
+ const getProvider = (
39
+ exchangeType: ExchangeTypes,
40
+ providerName: string
41
+ ): ExchangeProviderNameAndSignature => {
42
+ if (getEnv("MOCK_EXCHANGE_TEST_CONFIG")) {
43
+ return testFundProvider;
44
+ }
45
+
46
+ const res = (() => {
47
+ switch (exchangeType) {
48
+ case ExchangeTypes.Fund:
49
+ return fundProviders[providerName.toLowerCase()];
50
+
51
+ case ExchangeTypes.Sell:
52
+ return sellProviders[providerName.toLowerCase()];
53
+
54
+ default:
55
+ return null;
56
+ }
57
+ })();
58
+
59
+ if (!res) {
60
+ throw new Error(`Unknown partner ${providerName}`);
61
+ }
62
+
63
+ return res;
64
+ };
65
+
66
+ export { getProvider };
@@ -0,0 +1,76 @@
1
+ import { BigNumber } from "bignumber.js";
2
+
3
+ import type {
4
+ Transaction,
5
+ Account,
6
+ AccountLike,
7
+ AccountRaw,
8
+ AccountRawLike,
9
+ } from "../../types";
10
+ import { ExchangeTypes, RateTypes } from "../hw-app-exchange/Exchange";
11
+
12
+ export type CompleteExchangeRequestEvent =
13
+ | { type: "complete-exchange" }
14
+ | {
15
+ type: "complete-exchange-requested";
16
+ estimatedFees: BigNumber;
17
+ }
18
+ | {
19
+ type: "complete-exchange-error";
20
+ error: Error;
21
+ }
22
+ | {
23
+ type: "complete-exchange-result";
24
+ completeExchangeResult: Transaction;
25
+ };
26
+
27
+ export type ExchangeSwap = {
28
+ fromParentAccount: Account | null | undefined;
29
+ fromAccount: AccountLike;
30
+ toParentAccount: Account | null | undefined;
31
+ toAccount: AccountLike;
32
+ };
33
+
34
+ export type ExchangeSwapRaw = {
35
+ fromParentAccount: AccountRaw | null | undefined;
36
+ fromAccount: AccountRawLike;
37
+ toParentAccount: AccountRaw | null | undefined;
38
+ toAccount: AccountRawLike;
39
+ };
40
+
41
+ export type ExchangeSell = {
42
+ fromParentAccount: Account | null | undefined;
43
+ fromAccount: AccountLike;
44
+ };
45
+
46
+ export type ExchangeSellRaw = {
47
+ fromParentAccount: AccountRaw | null | undefined;
48
+ fromAccount: AccountRawLike;
49
+ };
50
+
51
+ interface CompleteExchangeInputCommon {
52
+ rateType: RateTypes;
53
+ deviceId: string;
54
+ provider: string;
55
+ binaryPayload: string;
56
+ signature: string;
57
+ transaction: Transaction;
58
+ }
59
+ export interface CompleteExchangeInputSell extends CompleteExchangeInputCommon {
60
+ readonly exchangeType: ExchangeTypes.Sell;
61
+ exchange: ExchangeSell;
62
+ }
63
+
64
+ export interface CompleteExchangeInputFund extends CompleteExchangeInputCommon {
65
+ readonly exchangeType: ExchangeTypes.Fund;
66
+ exchange: ExchangeSell;
67
+ }
68
+
69
+ export interface CompleteExchangeInputSwap extends CompleteExchangeInputCommon {
70
+ readonly exchangeType: ExchangeTypes.Swap;
71
+ exchange: ExchangeSwap;
72
+ }
73
+
74
+ export type Exchange = ExchangeSwap | ExchangeSell;
75
+
76
+ export type ExchangeRaw = ExchangeSwapRaw | ExchangeSellRaw;
@@ -7,7 +7,7 @@ import { getAccountCurrency, getMainAccount } from "../../account";
7
7
  import { getCurrencyExchangeConfig } from "../";
8
8
  import perFamily from "../../generated/exchange";
9
9
  import type { SellRequestEvent } from "./types";
10
- import { TRANSACTION_TYPES } from "../hw-app-exchange/Exchange";
10
+ import { ExchangeTypes } from "../hw-app-exchange/Exchange";
11
11
  import type {
12
12
  Account,
13
13
  AccountLike,
@@ -38,7 +38,7 @@ export default async (
38
38
  payloadSignature,
39
39
  transaction,
40
40
  } = input;
41
- const exchange = new Exchange(transport, TRANSACTION_TYPES.SELL);
41
+ const exchange = new Exchange(transport, ExchangeTypes.Sell);
42
42
  const mainAccount = getMainAccount(account, parentAccount);
43
43
  const { estimatedFees } = status;
44
44
  const provider = getProvider("coinify"); // FIXME Don't forget to switch to prod
@@ -1,14 +1,14 @@
1
1
  import Transport from "@ledgerhq/hw-transport";
2
2
  import Exchange from "../hw-app-exchange/Exchange";
3
3
  import type { SellRequestEvent } from "./types";
4
- import { TRANSACTION_TYPES } from "../hw-app-exchange/Exchange";
4
+ import { ExchangeTypes } from "../hw-app-exchange/Exchange";
5
5
 
6
6
  function base64EncodeUrl(str) {
7
7
  return str.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
8
8
  }
9
9
 
10
10
  export default async (transport: Transport): Promise<SellRequestEvent> => {
11
- const sell = new Exchange(transport, TRANSACTION_TYPES.SELL);
11
+ const sell = new Exchange(transport, ExchangeTypes.Sell);
12
12
  const txId = await sell.startNewTransaction();
13
13
  return {
14
14
  type: "init-sell-get-transaction-id",
@@ -1,6 +1,6 @@
1
1
  import type { ExchangeProviderNameAndSignature } from "../";
2
2
 
3
- const sellProviders: Record<
3
+ export const sellProviders: Record<
4
4
  string,
5
5
  {
6
6
  nameAndPubkey: Buffer;
@@ -1,36 +1,28 @@
1
1
  import { log } from "@ledgerhq/logs";
2
- import { from } from "rxjs";
2
+ import { from, Observable } from "rxjs";
3
3
  import secp256k1 from "secp256k1";
4
4
  import { TransportStatusError, WrongDeviceForAccount } from "@ledgerhq/errors";
5
+
5
6
  import { delay } from "../../promise";
6
7
  import ExchangeTransport from "../hw-app-exchange/Exchange";
7
8
  import perFamily from "../../generated/exchange";
8
9
  import { getAccountCurrency, getMainAccount } from "../../account";
9
10
  import { getAccountBridge } from "../../bridge";
10
11
  import { TransactionRefusedOnDevice } from "../../errors";
11
- import type { CompleteExchangeRequestEvent, Exchange } from "./types";
12
- import { Observable } from "rxjs";
13
12
  import { withDevice } from "../../hw/deviceAccess";
14
13
  import { getProviderNameAndSignature } from "./";
15
14
  import { getCurrencyExchangeConfig } from "../";
16
- import { Transaction } from "../../types";
15
+
16
+ import type {
17
+ CompleteExchangeInputSwap,
18
+ CompleteExchangeRequestEvent,
19
+ } from "../platform/types";
17
20
 
18
21
  const withDevicePromise = (deviceId, fn) =>
19
22
  withDevice(deviceId)((transport) => from(fn(transport))).toPromise();
20
23
 
21
- type CompleteExchangeInput = {
22
- exchange: Exchange;
23
- deviceId: string;
24
- provider: string;
25
- binaryPayload: string;
26
- signature: string;
27
- transaction: Transaction;
28
- exchangeType: number;
29
- rateType: number;
30
- };
31
-
32
24
  const completeExchange = (
33
- input: CompleteExchangeInput
25
+ input: CompleteExchangeInputSwap
34
26
  ): Observable<CompleteExchangeRequestEvent> => {
35
27
  let { transaction } = input; // TODO build a tx from the data
36
28
 
@@ -41,7 +33,7 @@ const completeExchange = (
41
33
  binaryPayload,
42
34
  signature,
43
35
  exchangeType,
44
- rateType = 0x00, // TODO Pass fixed/float for UI switch ?
36
+ rateType,
45
37
  } = input;
46
38
 
47
39
  const { fromAccount, fromParentAccount } = exchange;
@@ -131,41 +123,40 @@ const completeExchange = (
131
123
 
132
124
  throw e;
133
125
  }
134
- if (exchangeType === 0x00) {
135
- // Swap specific checks to confirm the refund address is correct.
136
- if (unsubscribed) return;
137
- const refundAddressParameters = await perFamily[
138
- refundCurrency.family
139
- ].getSerializedAddressParameters(
140
- refundAccount.freshAddressPath,
141
- refundAccount.derivationMode,
142
- refundCurrency.id
126
+
127
+ // Swap specific checks to confirm the refund address is correct.
128
+ if (unsubscribed) return;
129
+ const refundAddressParameters = await perFamily[
130
+ refundCurrency.family
131
+ ].getSerializedAddressParameters(
132
+ refundAccount.freshAddressPath,
133
+ refundAccount.derivationMode,
134
+ refundCurrency.id
135
+ );
136
+ if (unsubscribed) return;
137
+
138
+ const {
139
+ config: refundAddressConfig,
140
+ signature: refundAddressConfigSignature,
141
+ } = getCurrencyExchangeConfig(refundCurrency);
142
+ if (unsubscribed) return;
143
+
144
+ try {
145
+ await exchange.checkRefundAddress(
146
+ refundAddressConfig,
147
+ refundAddressConfigSignature,
148
+ refundAddressParameters.addressParameters
143
149
  );
144
- if (unsubscribed) return;
145
-
146
- const {
147
- config: refundAddressConfig,
148
- signature: refundAddressConfigSignature,
149
- } = getCurrencyExchangeConfig(refundCurrency);
150
- if (unsubscribed) return;
151
-
152
- try {
153
- await exchange.checkRefundAddress(
154
- refundAddressConfig,
155
- refundAddressConfigSignature,
156
- refundAddressParameters.addressParameters
157
- );
158
- log("exchange", "checkrefund address");
159
- } catch (e) {
160
- // @ts-expect-error TransportStatusError to be typed on ledgerjs
161
- if (e instanceof TransportStatusError && e.statusCode === 0x6a83) {
162
- log("exchange", "transport error");
163
- throw new WrongDeviceForAccount(undefined, {
164
- accountName: refundAccount.name,
165
- });
166
- }
167
- throw e;
150
+ log("exchange", "checkrefund address");
151
+ } catch (e) {
152
+ // @ts-expect-error TransportStatusError to be typed on ledgerjs
153
+ if (e instanceof TransportStatusError && e.statusCode === 0x6a83) {
154
+ log("exchange", "transport error");
155
+ throw new WrongDeviceForAccount(undefined, {
156
+ accountName: refundAccount.name,
157
+ });
168
158
  }
159
+ throw e;
169
160
  }
170
161
 
171
162
  o.next({
@@ -23,10 +23,7 @@ import { withDevice } from "../../hw/deviceAccess";
23
23
  import { getProviderNameAndSignature, getSwapAPIBaseURL } from "./";
24
24
  import { getCurrencyExchangeConfig } from "../";
25
25
  import { getEnv } from "../../env";
26
- import {
27
- TRANSACTION_RATES,
28
- TRANSACTION_TYPES,
29
- } from "../hw-app-exchange/Exchange";
26
+ import { RateTypes, ExchangeTypes } from "../hw-app-exchange/Exchange";
30
27
 
31
28
  const withDevicePromise = (deviceId, fn) =>
32
29
  withDevice(deviceId)((transport) => from(fn(transport))).toPromise();
@@ -48,9 +45,9 @@ const initSwap = (input: InitSwapInput): Observable<SwapRequestEvent> => {
48
45
  await withDevicePromise(deviceId, async (transport) => {
49
46
  const ratesFlag =
50
47
  exchangeRate.tradeMethod === "fixed"
51
- ? TRANSACTION_RATES.FIXED
52
- : TRANSACTION_RATES.FLOATING;
53
- const swap = new Exchange(transport, TRANSACTION_TYPES.SWAP, ratesFlag);
48
+ ? RateTypes.Fixed
49
+ : RateTypes.Floating;
50
+ const swap = new Exchange(transport, ExchangeTypes.Swap, ratesFlag);
54
51
  // NB this id is crucial to prevent replay attacks, if it changes
55
52
  // we need to start the flow again.
56
53
  const deviceTransactionId = await swap.startNewTransaction();
@@ -130,20 +130,7 @@ export type SwapRequestEvent =
130
130
  type: "init-swap-result";
131
131
  initSwapResult: InitSwapResult;
132
132
  };
133
- export type CompleteExchangeRequestEvent =
134
- | { type: "complete-exchange" }
135
- | {
136
- type: "complete-exchange-requested";
137
- estimatedFees: BigNumber;
138
- }
139
- | {
140
- type: "complete-exchange-error";
141
- error: Error;
142
- }
143
- | {
144
- type: "complete-exchange-result";
145
- completeExchangeResult: Transaction;
146
- };
133
+
147
134
  export type SwapHistorySection = {
148
135
  day: Date;
149
136
  data: MappedSwapOperation[];
@@ -0,0 +1,20 @@
1
+ /**
2
+ * FIXME:
3
+ * Minimal config for now, need to extend it to match prod config
4
+ * cf. https://github.com/LedgerHQ/ledgerjs/tree/master/packages/cryptoassets/data/exchange
5
+ */
6
+
7
+ const coins = [
8
+ [
9
+ "bitcoin",
10
+ "0342544307426974636f696e00",
11
+ "3045022100cb174382302219dca359c0a4d457b2569e31a06b2c25c0088a2bd3fd6c04386a02202c6d0a5b924a414621067e316f021aa13aa5b2eee2bf36ea3cfddebc053b201b",
12
+ ],
13
+ [
14
+ "ethereum",
15
+ "0345544808457468657265756d050345544812",
16
+ "3044022065d7931ab3144362d57e3fdcc5de921fb65024737d917f0ab1f8b173d1ed3c2e022027493568d112dc53c7177f8e5fc915d91a903780a067badf109085a73d360323",
17
+ ],
18
+ ];
19
+
20
+ export default coins;
@@ -0,0 +1,24 @@
1
+ import coins from "./data/coins";
2
+ const all = [...coins];
3
+ const configs = {};
4
+
5
+ for (const [id, config, signature] of all) {
6
+ configs[id] = {
7
+ config,
8
+ signature,
9
+ };
10
+ }
11
+
12
+ /**
13
+ *
14
+ */
15
+ export const findTestExchangeCurrencyConfig = (
16
+ id: string
17
+ ):
18
+ | {
19
+ config: string;
20
+
21
+ signature: string;
22
+ }
23
+ | null
24
+ | undefined => configs[id];
@@ -229,7 +229,6 @@ class BitcoinLikeWallet {
229
229
  btc,
230
230
  fromAccount,
231
231
  txInfo,
232
- hasTimestamp,
233
232
  initialTimestamp,
234
233
  additionals,
235
234
  hasExtraData,
@@ -237,7 +236,7 @@ class BitcoinLikeWallet {
237
236
  onDeviceSignatureGranted,
238
237
  onDeviceStreaming,
239
238
  } = params;
240
-
239
+ let hasTimestamp = params.hasTimestamp;
241
240
  let length = txInfo.outputs.reduce((sum, output) => {
242
241
  return sum + 8 + output.script.length + 1;
243
242
  }, 1);
@@ -270,6 +269,13 @@ class BitcoinLikeWallet {
270
269
  number | null | undefined
271
270
  ][];
272
271
  const inputs: Inputs = txInfo.inputs.map((i) => {
272
+ if (additionals && additionals.includes("peercoin")) {
273
+ // remove timestamp for new version of peercoin input, refer to https://github.com/peercoin/rfcs/issues/5 and https://github.com/LedgerHQ/ledgerjs/issues/701
274
+ const version = i.txHex.substring(0, 8);
275
+ if (version !== "01000000" && version !== "02000000") {
276
+ hasTimestamp = false;
277
+ }
278
+ }
273
279
  log("hw", `splitTransaction`, {
274
280
  transactionHex: i.txHex,
275
281
  isSegwitSupported: true,
@@ -406,6 +406,7 @@ const bsc: AppSpec<Transaction> = {
406
406
  model: DeviceModelId.nanoS,
407
407
  appName: "Binance Smart Chain",
408
408
  },
409
+ dependency: "Ethereum",
409
410
  testTimeout: 2 * 60 * 1000,
410
411
  transactionCheck: ({ maxSpendable }) => {
411
412
  invariant(
@@ -452,6 +453,7 @@ const polygon: AppSpec<Transaction> = {
452
453
  model: DeviceModelId.nanoS,
453
454
  appName: "Polygon",
454
455
  },
456
+ dependency: "Ethereum",
455
457
  testTimeout: 2 * 60 * 1000,
456
458
  transactionCheck: ({ maxSpendable }) => {
457
459
  invariant(