@ledgerhq/live-common 34.54.0 → 34.54.1

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 (125) hide show
  1. package/lib/e2e/speculosCI.d.ts.map +1 -1
  2. package/lib/e2e/speculosCI.js +1 -6
  3. package/lib/e2e/speculosCI.js.map +1 -1
  4. package/lib/exchange/swap/postSwapState.d.ts.map +1 -1
  5. package/lib/exchange/swap/postSwapState.js +10 -6
  6. package/lib/exchange/swap/postSwapState.js.map +1 -1
  7. package/lib/exchange/swap/transactionStrategies.d.ts +2 -1
  8. package/lib/exchange/swap/transactionStrategies.d.ts.map +1 -1
  9. package/lib/exchange/swap/transactionStrategies.js +7 -6
  10. package/lib/exchange/swap/transactionStrategies.js.map +1 -1
  11. package/lib/exchange/swap/types.d.ts +3 -1
  12. package/lib/exchange/swap/types.d.ts.map +1 -1
  13. package/lib/hw/connectAppEventMapper.d.ts.map +1 -1
  14. package/lib/hw/connectAppEventMapper.js +21 -2
  15. package/lib/hw/connectAppEventMapper.js.map +1 -1
  16. package/lib/hw/getAppAndVersion.d.ts +3 -1
  17. package/lib/hw/getAppAndVersion.d.ts.map +1 -1
  18. package/lib/hw/getAppAndVersion.js +2 -2
  19. package/lib/hw/getAppAndVersion.js.map +1 -1
  20. package/lib/wallet-api/Exchange/SwapError.d.ts +93 -0
  21. package/lib/wallet-api/Exchange/SwapError.d.ts.map +1 -0
  22. package/lib/wallet-api/Exchange/SwapError.js +142 -0
  23. package/lib/wallet-api/Exchange/SwapError.js.map +1 -0
  24. package/lib/wallet-api/Exchange/handleSwapErrors.d.ts +40 -0
  25. package/lib/wallet-api/Exchange/handleSwapErrors.d.ts.map +1 -0
  26. package/lib/wallet-api/Exchange/handleSwapErrors.js +112 -0
  27. package/lib/wallet-api/Exchange/handleSwapErrors.js.map +1 -0
  28. package/lib/wallet-api/Exchange/index.d.ts +4 -0
  29. package/lib/wallet-api/Exchange/index.d.ts.map +1 -0
  30. package/lib/wallet-api/Exchange/index.js +27 -0
  31. package/lib/wallet-api/Exchange/index.js.map +1 -0
  32. package/lib/wallet-api/Exchange/parser.d.ts +46 -0
  33. package/lib/wallet-api/Exchange/parser.d.ts.map +1 -0
  34. package/lib/wallet-api/Exchange/parser.js +97 -0
  35. package/lib/wallet-api/Exchange/parser.js.map +1 -0
  36. package/lib/wallet-api/Exchange/server.d.ts.map +1 -1
  37. package/lib/wallet-api/Exchange/server.js +227 -174
  38. package/lib/wallet-api/Exchange/server.js.map +1 -1
  39. package/lib/wallet-api/Exchange/tracking.d.ts +7 -6
  40. package/lib/wallet-api/Exchange/tracking.d.ts.map +1 -1
  41. package/lib/wallet-api/Exchange/tracking.js +52 -13
  42. package/lib/wallet-api/Exchange/tracking.js.map +1 -1
  43. package/lib/wallet-api/logic.d.ts +1 -1
  44. package/lib/wallet-api/logic.d.ts.map +1 -1
  45. package/lib/wallet-api/logic.js +5 -5
  46. package/lib/wallet-api/logic.js.map +1 -1
  47. package/lib/wallet-api/react.d.ts.map +1 -1
  48. package/lib/wallet-api/react.js +9 -6
  49. package/lib/wallet-api/react.js.map +1 -1
  50. package/lib/wallet-api/tracking.d.ts +5 -5
  51. package/lib/wallet-api/tracking.d.ts.map +1 -1
  52. package/lib/wallet-api/tracking.js +30 -10
  53. package/lib/wallet-api/tracking.js.map +1 -1
  54. package/lib-es/e2e/speculosCI.d.ts.map +1 -1
  55. package/lib-es/e2e/speculosCI.js +1 -6
  56. package/lib-es/e2e/speculosCI.js.map +1 -1
  57. package/lib-es/exchange/swap/postSwapState.d.ts.map +1 -1
  58. package/lib-es/exchange/swap/postSwapState.js +10 -6
  59. package/lib-es/exchange/swap/postSwapState.js.map +1 -1
  60. package/lib-es/exchange/swap/transactionStrategies.d.ts +2 -1
  61. package/lib-es/exchange/swap/transactionStrategies.d.ts.map +1 -1
  62. package/lib-es/exchange/swap/transactionStrategies.js +7 -6
  63. package/lib-es/exchange/swap/transactionStrategies.js.map +1 -1
  64. package/lib-es/exchange/swap/types.d.ts +3 -1
  65. package/lib-es/exchange/swap/types.d.ts.map +1 -1
  66. package/lib-es/hw/connectAppEventMapper.d.ts.map +1 -1
  67. package/lib-es/hw/connectAppEventMapper.js +23 -4
  68. package/lib-es/hw/connectAppEventMapper.js.map +1 -1
  69. package/lib-es/hw/getAppAndVersion.d.ts +3 -1
  70. package/lib-es/hw/getAppAndVersion.d.ts.map +1 -1
  71. package/lib-es/hw/getAppAndVersion.js +2 -2
  72. package/lib-es/hw/getAppAndVersion.js.map +1 -1
  73. package/lib-es/wallet-api/Exchange/SwapError.d.ts +93 -0
  74. package/lib-es/wallet-api/Exchange/SwapError.d.ts.map +1 -0
  75. package/lib-es/wallet-api/Exchange/SwapError.js +128 -0
  76. package/lib-es/wallet-api/Exchange/SwapError.js.map +1 -0
  77. package/lib-es/wallet-api/Exchange/handleSwapErrors.d.ts +40 -0
  78. package/lib-es/wallet-api/Exchange/handleSwapErrors.d.ts.map +1 -0
  79. package/lib-es/wallet-api/Exchange/handleSwapErrors.js +106 -0
  80. package/lib-es/wallet-api/Exchange/handleSwapErrors.js.map +1 -0
  81. package/lib-es/wallet-api/Exchange/index.d.ts +4 -0
  82. package/lib-es/wallet-api/Exchange/index.d.ts.map +1 -0
  83. package/lib-es/wallet-api/Exchange/index.js +7 -0
  84. package/lib-es/wallet-api/Exchange/index.js.map +1 -0
  85. package/lib-es/wallet-api/Exchange/parser.d.ts +46 -0
  86. package/lib-es/wallet-api/Exchange/parser.d.ts.map +1 -0
  87. package/lib-es/wallet-api/Exchange/parser.js +90 -0
  88. package/lib-es/wallet-api/Exchange/parser.js.map +1 -0
  89. package/lib-es/wallet-api/Exchange/server.d.ts.map +1 -1
  90. package/lib-es/wallet-api/Exchange/server.js +224 -174
  91. package/lib-es/wallet-api/Exchange/server.js.map +1 -1
  92. package/lib-es/wallet-api/Exchange/tracking.d.ts +7 -6
  93. package/lib-es/wallet-api/Exchange/tracking.d.ts.map +1 -1
  94. package/lib-es/wallet-api/Exchange/tracking.js +52 -13
  95. package/lib-es/wallet-api/Exchange/tracking.js.map +1 -1
  96. package/lib-es/wallet-api/logic.d.ts +1 -1
  97. package/lib-es/wallet-api/logic.d.ts.map +1 -1
  98. package/lib-es/wallet-api/logic.js +5 -5
  99. package/lib-es/wallet-api/logic.js.map +1 -1
  100. package/lib-es/wallet-api/react.d.ts.map +1 -1
  101. package/lib-es/wallet-api/react.js +9 -6
  102. package/lib-es/wallet-api/react.js.map +1 -1
  103. package/lib-es/wallet-api/tracking.d.ts +5 -5
  104. package/lib-es/wallet-api/tracking.d.ts.map +1 -1
  105. package/lib-es/wallet-api/tracking.js +30 -10
  106. package/lib-es/wallet-api/tracking.js.map +1 -1
  107. package/package.json +68 -68
  108. package/src/e2e/speculosCI.ts +1 -6
  109. package/src/exchange/swap/postSwapState.ts +10 -5
  110. package/src/exchange/swap/transactionStrategies.ts +8 -7
  111. package/src/exchange/swap/types.ts +3 -1
  112. package/src/hw/connectAppEventMapper.ts +28 -4
  113. package/src/hw/getAppAndVersion.ts +2 -1
  114. package/src/wallet-api/Exchange/SwapError.test.ts +126 -0
  115. package/src/wallet-api/Exchange/SwapError.ts +159 -0
  116. package/src/wallet-api/Exchange/handleSwapErrors.test.ts +46 -0
  117. package/src/wallet-api/Exchange/handleSwapErrors.ts +161 -0
  118. package/src/wallet-api/Exchange/index.ts +26 -0
  119. package/src/wallet-api/Exchange/parser.test.ts +86 -0
  120. package/src/wallet-api/Exchange/parser.ts +119 -0
  121. package/src/wallet-api/Exchange/server.ts +289 -232
  122. package/src/wallet-api/Exchange/tracking.ts +56 -13
  123. package/src/wallet-api/logic.ts +5 -4
  124. package/src/wallet-api/react.ts +10 -5
  125. package/src/wallet-api/tracking.ts +30 -10
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ledgerhq/live-common",
3
3
  "description": "Common ground for the Ledger Live apps",
4
- "version": "34.54.0",
4
+ "version": "34.54.1",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/LedgerHQ/ledger-live.git"
@@ -120,7 +120,7 @@
120
120
  "dependencies": {
121
121
  "@blooo/hw-app-acre": "^1.1.1",
122
122
  "@cardano-foundation/ledgerjs-hw-app-cardano": "^7.1.2",
123
- "@ledgerhq/device-management-kit": "0.11.1",
123
+ "@ledgerhq/device-management-kit": "0.13.0",
124
124
  "@ledgerhq/speculos-device-controller": "0.1.0",
125
125
  "@ledgerhq/live-app-sdk": "^0.8.1",
126
126
  "@ledgerhq/wallet-api-client": "^1.12.5",
@@ -182,79 +182,79 @@
182
182
  "xstate": "^5.19.2",
183
183
  "yargs": "^17.0.0",
184
184
  "zod": "^3.22.4",
185
- "@ledgerhq/coin-algorand": "^0.14.0",
186
- "@ledgerhq/coin-aptos": "^3.7.0",
187
- "@ledgerhq/coin-bitcoin": "^0.26.0",
188
- "@ledgerhq/coin-canton": "^0.11.0",
189
- "@ledgerhq/coin-cardano": "^0.15.1",
190
- "@ledgerhq/coin-casper": "^2.4.1",
191
- "@ledgerhq/coin-celo": "^1.7.2",
192
- "@ledgerhq/coin-cosmos": "^0.20.1",
193
- "@ledgerhq/coin-evm": "^2.36.0",
194
- "@ledgerhq/coin-filecoin": "^1.15.0",
195
- "@ledgerhq/coin-framework": "^6.10.0",
196
- "@ledgerhq/coin-hedera": "^1.15.0",
197
- "@ledgerhq/coin-icon": "^0.15.1",
198
- "@ledgerhq/coin-internet_computer": "^1.11.1",
199
- "@ledgerhq/coin-kaspa": "^1.5.0",
200
- "@ledgerhq/coin-mina": "^1.4.2",
201
- "@ledgerhq/coin-multiversx": "^0.8.1",
202
- "@ledgerhq/coin-near": "^0.16.1",
203
- "@ledgerhq/coin-polkadot": "^6.13.1",
204
- "@ledgerhq/coin-solana": "^0.38.0",
205
- "@ledgerhq/coin-stacks": "^0.12.1",
206
- "@ledgerhq/coin-stellar": "^6.8.0",
207
- "@ledgerhq/coin-sui": "^0.18.1",
208
- "@ledgerhq/coin-tezos": "^6.10.0",
209
- "@ledgerhq/coin-ton": "^0.17.1",
210
- "@ledgerhq/coin-tron": "^5.7.1",
211
- "@ledgerhq/coin-vechain": "^2.13.0",
212
- "@ledgerhq/coin-xrp": "^7.9.0",
185
+ "@ledgerhq/coin-algorand": "^0.14.1",
186
+ "@ledgerhq/coin-aptos": "^3.7.1",
187
+ "@ledgerhq/coin-bitcoin": "^0.26.1",
188
+ "@ledgerhq/coin-canton": "^0.11.1",
189
+ "@ledgerhq/coin-cardano": "^0.15.2",
190
+ "@ledgerhq/coin-casper": "^2.4.2",
191
+ "@ledgerhq/coin-celo": "^1.7.3",
192
+ "@ledgerhq/coin-cosmos": "^0.20.2",
193
+ "@ledgerhq/coin-evm": "^2.36.1",
194
+ "@ledgerhq/coin-filecoin": "^1.15.1",
195
+ "@ledgerhq/coin-framework": "^6.10.1",
196
+ "@ledgerhq/coin-hedera": "^1.15.1",
197
+ "@ledgerhq/coin-icon": "^0.15.2",
198
+ "@ledgerhq/coin-internet_computer": "^1.11.2",
199
+ "@ledgerhq/coin-kaspa": "^1.5.1",
200
+ "@ledgerhq/coin-mina": "^1.4.3",
201
+ "@ledgerhq/coin-multiversx": "^0.8.2",
202
+ "@ledgerhq/coin-near": "^0.16.2",
203
+ "@ledgerhq/coin-polkadot": "^6.13.2",
204
+ "@ledgerhq/coin-solana": "^0.38.1",
205
+ "@ledgerhq/coin-stacks": "^0.12.2",
206
+ "@ledgerhq/coin-stellar": "^6.8.1",
207
+ "@ledgerhq/coin-sui": "^0.18.2",
208
+ "@ledgerhq/coin-tezos": "^6.10.1",
209
+ "@ledgerhq/coin-ton": "^0.17.2",
210
+ "@ledgerhq/coin-tron": "^5.7.2",
211
+ "@ledgerhq/coin-vechain": "^2.13.1",
212
+ "@ledgerhq/coin-xrp": "^7.9.1",
213
213
  "@ledgerhq/crypto-icons-ui": "^1.24.0",
214
- "@ledgerhq/cryptoassets": "^13.34.0",
215
- "@ledgerhq/device-core": "^0.6.9",
216
- "@ledgerhq/devices": "8.7.0",
217
- "@ledgerhq/errors": "^6.27.0",
218
- "@ledgerhq/hw-app-algorand": "^6.31.9",
219
- "@ledgerhq/hw-app-aptos": "^6.34.9",
220
- "@ledgerhq/hw-app-btc": "^10.13.0",
221
- "@ledgerhq/hw-app-celo": "^6.35.4",
222
- "@ledgerhq/hw-app-cosmos": "^6.32.9",
223
- "@ledgerhq/hw-app-eth": "^7.0.0",
224
- "@ledgerhq/hw-app-exchange": "^0.18.0",
225
- "@ledgerhq/hw-app-hedera": "^1.2.9",
226
- "@ledgerhq/hw-app-icon": "^1.3.9",
227
- "@ledgerhq/hw-app-kaspa": "^1.3.2",
228
- "@ledgerhq/hw-app-multiversx": "^6.26.0",
229
- "@ledgerhq/hw-app-near": "^6.31.9",
230
- "@ledgerhq/hw-app-polkadot": "^6.34.9",
231
- "@ledgerhq/hw-app-str": "^7.2.9",
214
+ "@ledgerhq/cryptoassets": "^13.34.1",
215
+ "@ledgerhq/device-core": "^0.6.10",
216
+ "@ledgerhq/devices": "8.7.1",
217
+ "@ledgerhq/errors": "^6.27.1",
218
+ "@ledgerhq/hw-app-algorand": "^6.31.10",
219
+ "@ledgerhq/hw-app-aptos": "^6.34.10",
220
+ "@ledgerhq/hw-app-btc": "^10.13.1",
221
+ "@ledgerhq/hw-app-celo": "^6.35.5",
222
+ "@ledgerhq/hw-app-cosmos": "^6.32.10",
223
+ "@ledgerhq/hw-app-eth": "^7.0.1",
224
+ "@ledgerhq/hw-app-exchange": "^0.18.1",
225
+ "@ledgerhq/hw-app-hedera": "^1.2.10",
226
+ "@ledgerhq/hw-app-icon": "^1.3.10",
227
+ "@ledgerhq/hw-app-kaspa": "^1.3.3",
228
+ "@ledgerhq/hw-app-multiversx": "^6.26.1",
229
+ "@ledgerhq/hw-app-near": "^6.31.10",
230
+ "@ledgerhq/hw-app-polkadot": "^6.34.10",
231
+ "@ledgerhq/hw-app-str": "^7.2.10",
232
232
  "@ledgerhq/hw-app-sui": "^1.4.0",
233
- "@ledgerhq/hw-app-tezos": "^6.31.9",
234
- "@ledgerhq/hw-app-trx": "^6.31.9",
235
- "@ledgerhq/hw-app-vet": "^0.8.0",
236
- "@ledgerhq/hw-app-xrp": "^6.32.7",
237
- "@ledgerhq/hw-bolos": "^6.32.9",
238
- "@ledgerhq/hw-transport": "6.31.13",
239
- "@ledgerhq/hw-transport-mocker": "^6.29.13",
240
- "@ledgerhq/ledger-cal-service": "^1.9.1",
241
- "@ledgerhq/ledger-trust-service": "^0.4.3",
233
+ "@ledgerhq/hw-app-tezos": "^6.31.10",
234
+ "@ledgerhq/hw-app-trx": "^6.31.10",
235
+ "@ledgerhq/hw-app-vet": "^0.8.1",
236
+ "@ledgerhq/hw-app-xrp": "^6.32.8",
237
+ "@ledgerhq/hw-bolos": "^6.32.10",
238
+ "@ledgerhq/hw-transport": "6.31.14",
239
+ "@ledgerhq/hw-transport-mocker": "^6.29.14",
240
+ "@ledgerhq/ledger-cal-service": "^1.9.2",
241
+ "@ledgerhq/ledger-trust-service": "^0.4.4",
242
242
  "@ledgerhq/live-config": "^3.2.0",
243
- "@ledgerhq/live-countervalues": "^0.10.1",
244
- "@ledgerhq/live-countervalues-react": "^0.7.3",
245
- "@ledgerhq/live-dmk-shared": "^0.15.0",
243
+ "@ledgerhq/live-countervalues": "^0.10.2",
244
+ "@ledgerhq/live-countervalues-react": "^0.7.4",
245
+ "@ledgerhq/live-dmk-shared": "^0.15.1",
246
246
  "@ledgerhq/live-env": "^2.22.0",
247
247
  "@ledgerhq/live-hooks": "0.2.0",
248
- "@ledgerhq/live-network": "^2.1.2",
248
+ "@ledgerhq/live-network": "^2.1.3",
249
249
  "@ledgerhq/live-promise": "^0.1.1",
250
- "@ledgerhq/live-signer-canton": "^0.5.2",
251
- "@ledgerhq/live-signer-evm": "^0.10.2",
252
- "@ledgerhq/live-signer-solana": "^0.7.0",
253
- "@ledgerhq/live-wallet": "^0.16.1",
254
- "@ledgerhq/speculos-transport": "^0.3.0",
250
+ "@ledgerhq/live-signer-canton": "^0.5.3",
251
+ "@ledgerhq/live-signer-evm": "^0.10.3",
252
+ "@ledgerhq/live-signer-solana": "^0.7.1",
253
+ "@ledgerhq/live-wallet": "^0.16.2",
255
254
  "@ledgerhq/logs": "^6.13.0",
255
+ "@ledgerhq/speculos-transport": "^0.3.1",
256
256
  "@ledgerhq/wallet-api-acre-module": "^0.10.0",
257
- "@ledgerhq/wallet-api-exchange-module": "^0.19.0"
257
+ "@ledgerhq/wallet-api-exchange-module": "^0.19.1"
258
258
  },
259
259
  "devDependencies": {
260
260
  "@solana/web3.js": "1.95.4",
@@ -302,7 +302,7 @@
302
302
  "undici": "6.19.2",
303
303
  "uuid": "^8.3.2",
304
304
  "ws": "7",
305
- "@ledgerhq/device-react": "^0.3.3",
305
+ "@ledgerhq/device-react": "^0.3.4",
306
306
  "@ledgerhq/types-cryptoassets": "^7.30.0",
307
307
  "@ledgerhq/types-devices": "^6.27.0",
308
308
  "@ledgerhq/types-live": "^6.90.0"
@@ -7,7 +7,7 @@ import {
7
7
  import { SpeculosDevice } from "./speculos";
8
8
  import https from "https";
9
9
 
10
- const { SEED, GITHUB_TOKEN, AWS_ROLE, CLUSTER, SPECULOS_IMAGE_TAG } = process.env;
10
+ const { GITHUB_TOKEN, SPECULOS_IMAGE_TAG } = process.env;
11
11
  const GIT_API_URL = "https://api.github.com/repos/LedgerHQ/actions/actions/";
12
12
  const START_WORKFLOW_ID = "workflows/161487603/dispatches";
13
13
  const STOP_WORKFLOW_ID = "workflows/161487604/dispatches";
@@ -152,9 +152,6 @@ function createStartPayload(deviceParams: DeviceParams, runId: string) {
152
152
  coin_app_version: appVersion,
153
153
  device: reverseModelMap[model],
154
154
  device_os_version: firmware,
155
- aws_role: AWS_ROLE,
156
- cluster: CLUSTER,
157
- seed: SEED,
158
155
  run_id: runId,
159
156
  additional_args,
160
157
  },
@@ -192,8 +189,6 @@ export async function releaseSpeculosDeviceCI(runId: string) {
192
189
  ref: GITHUB_REF,
193
190
  inputs: {
194
191
  run_id: runId.toString(),
195
- aws_role: AWS_ROLE,
196
- cluster: CLUSTER,
197
192
  },
198
193
  };
199
194
  await githubApiRequest({ urlSuffix: STOP_WORKFLOW_ID, data });
@@ -106,6 +106,7 @@ export const postSwapCancelled: PostSwapCancelled = async ({
106
106
  seedIdTo,
107
107
  refundAddress,
108
108
  payoutAddress,
109
+ data,
109
110
  ...rest
110
111
  }) => {
111
112
  if (isIntegrationTestEnv()) return mockPostSwapCancelled({ provider, swapId, ...rest });
@@ -138,7 +139,8 @@ export const postSwapCancelled: PostSwapCancelled = async ({
138
139
 
139
140
  const shouldIncludeAddresses =
140
141
  rest.statusCode === "WrongDeviceForAccountPayout" ||
141
- rest.statusCode === "WrongDeviceForAccountRefund";
142
+ rest.statusCode === "WrongDeviceForAccountRefund" ||
143
+ rest.statusCode === "FeeNotLoaded";
142
144
 
143
145
  const requestData = {
144
146
  provider,
@@ -147,11 +149,14 @@ export const postSwapCancelled: PostSwapCancelled = async ({
147
149
  swapIntentWithoutProvider,
148
150
  payloadAddressMatchAccountAddress,
149
151
  fromAmount,
150
- fromAccountAddress: shouldIncludeAddresses ? fromAccountAddress : undefined,
151
- toAccountAddress: shouldIncludeAddresses ? toAccountAddress : undefined,
152
- payloadRefundAddress: shouldIncludeAddresses ? refundAddress : undefined,
153
- payloadPayoutAddress: shouldIncludeAddresses ? payoutAddress : undefined,
152
+ ...(shouldIncludeAddresses && {
153
+ fromAccountAddress,
154
+ toAccountAddress,
155
+ payloadRefundAddress: refundAddress,
156
+ payloadPayoutAddress: payoutAddress,
157
+ }),
154
158
  maybeSeedMatch: seedIdFrom === seedIdTo, // Only true if both accounts are from the same seed and from the same chain type
159
+ data,
155
160
  ...rest,
156
161
  };
157
162
 
@@ -2,6 +2,7 @@ import { BigNumber } from "bignumber.js";
2
2
 
3
3
  import { Transaction } from "../../generated/types";
4
4
  import { TransactionCommon } from "@ledgerhq/types-live";
5
+ import { createStepError, StepError, CustomErrorType } from "../../wallet-api/Exchange";
5
6
  export type { SwapLiveError } from "@ledgerhq/wallet-api-exchange-module";
6
7
 
7
8
  export function defaultTransaction({
@@ -85,11 +86,11 @@ export function stellarTransaction({
85
86
  customErrorType,
86
87
  }: TransactionWithCustomFee): Extract<Transaction, { family: "stellar" }> {
87
88
  if (!payinExtraId)
88
- throw {
89
+ throw createStepError({
89
90
  error: new Error("Missing payinExtraId"),
90
- step: "PayinExtraIdStepError",
91
+ step: StepError.PAYIN_EXTRA_ID,
91
92
  customErrorType,
92
- };
93
+ });
93
94
 
94
95
  return {
95
96
  family: "stellar",
@@ -110,11 +111,11 @@ export function rippleTransaction({
110
111
  customErrorType,
111
112
  }: TransactionWithCustomFee): Partial<Extract<Transaction, { family: "xrp" }>> {
112
113
  if (!payinExtraId)
113
- throw {
114
+ throw createStepError({
114
115
  error: new Error("Missing payinExtraId"),
115
- step: "PayinExtraIdStepError",
116
+ step: StepError.PAYIN_EXTRA_ID,
116
117
  customErrorType,
117
- };
118
+ });
118
119
 
119
120
  return {
120
121
  family: "xrp",
@@ -257,7 +258,7 @@ export type TransactionWithCustomFee = TransactionCommon & {
257
258
  [key: string]: BigNumber;
258
259
  };
259
260
  payinExtraId?: string;
260
- customErrorType?: "swap";
261
+ customErrorType?: CustomErrorType;
261
262
  extraTransactionParameters?: string;
262
263
  family: string;
263
264
  sponsored?: boolean;
@@ -214,7 +214,9 @@ export type SwapStateAcceptedRequest = SwapStateRequest & {
214
214
  transactionId: string;
215
215
  };
216
216
 
217
- export type SwapStateCancelledRequest = SwapStateRequest;
217
+ export type SwapStateCancelledRequest = SwapStateRequest & {
218
+ data?: string;
219
+ };
218
220
 
219
221
  export type PostSwapAccepted = (arg0: SwapStateAcceptedRequest) => Promise<null>;
220
222
 
@@ -11,11 +11,10 @@ import type {
11
11
  } from "@ledgerhq/device-management-kit";
12
12
  import {
13
13
  DeviceActionStatus,
14
- DeviceDisconnectedWhileSendingError,
15
14
  DeviceSessionStateType,
16
15
  UserInteractionRequired,
17
16
  OutOfMemoryDAError,
18
- UnsupportedFirmwareDAError,
17
+ DeviceModelId,
19
18
  } from "@ledgerhq/device-management-kit";
20
19
  import type {
21
20
  ConnectAppDAOutput,
@@ -27,12 +26,14 @@ import {
27
26
  UserRefusedAllowManager,
28
27
  UserRefusedOnDevice,
29
28
  LatestFirmwareVersionRequired,
29
+ UnsupportedFeatureError,
30
30
  } from "@ledgerhq/errors";
31
31
 
32
32
  import type { SkippedAppOp } from "../apps/types";
33
33
  import { SkipReason } from "../apps/types";
34
34
  import { parseDeviceInfo } from "../deviceSDK/tasks/getDeviceInfo";
35
35
  import { ConnectAppEvent } from "./connectApp";
36
+ import { NoSuchAppOnProvider } from "../errors";
36
37
 
37
38
  export class ConnectAppEventMapper {
38
39
  private openAppRequested: boolean = false;
@@ -241,7 +242,8 @@ export class ConnectAppEventMapper {
241
242
  });
242
243
  this.eventSubject.complete();
243
244
  } else if (
244
- error instanceof UnsupportedFirmwareDAError &&
245
+ "_tag" in error &&
246
+ error._tag === "UnsupportedFirmwareDAError" &&
245
247
  deviceState.sessionStateType !== DeviceSessionStateType.Connected
246
248
  ) {
247
249
  this.eventSubject.error(
@@ -252,12 +254,34 @@ export class ConnectAppEventMapper {
252
254
  deviceState.firmwareUpdateContext!.currentFirmware.version,
253
255
  }),
254
256
  );
257
+ } else if (
258
+ "_tag" in error &&
259
+ error._tag === "UnsupportedApplicationDAError" &&
260
+ deviceState.sessionStateType !== DeviceSessionStateType.Connected
261
+ ) {
262
+ if (deviceState.deviceModelId === DeviceModelId.NANO_S) {
263
+ // This will show an error modal with upsell link
264
+ this.eventSubject.error(
265
+ new NoSuchAppOnProvider(`Ledger Nano S does not support this feature`, {
266
+ appName: this.appName,
267
+ }),
268
+ );
269
+ return;
270
+ }
271
+ // This will show an error modal with contact support link
272
+ this.eventSubject.error(
273
+ new UnsupportedFeatureError(`App ${this.appName} not supported on this device`, {
274
+ appName: this.appName,
275
+ deviceModelId: deviceState.deviceModelId,
276
+ deviceVersion: deviceState.firmwareVersion?.os,
277
+ }),
278
+ );
255
279
  } else if ("_tag" in error && error._tag === "DeviceLockedError") {
256
280
  this.eventSubject.next({ type: "lockedDevice" });
257
281
  this.eventSubject.complete();
258
282
  } else if ("_tag" in error && error._tag === "RefusedByUserDAError") {
259
283
  this.eventSubject.error(new UserRefusedAllowManager());
260
- } else if (error instanceof DeviceDisconnectedWhileSendingError) {
284
+ } else if ("_tag" in error && error._tag === "DeviceDisconnectedWhileSendingError") {
261
285
  this.eventSubject.next({ type: "disconnected", expected: false });
262
286
  } else if ("_tag" in error && error._tag === "WebHidSendReportError") {
263
287
  this.eventSubject.next({ type: "disconnected", expected: false });
@@ -2,12 +2,13 @@ import { GetAppAndVersionUnsupportedFormat } from "../errors";
2
2
  import Transport from "@ledgerhq/hw-transport";
3
3
  export default async (
4
4
  transport: Transport,
5
+ { abortTimeoutMs }: { abortTimeoutMs?: number } = {},
5
6
  ): Promise<{
6
7
  name: string;
7
8
  version: string;
8
9
  flags: number | Buffer;
9
10
  }> => {
10
- const r = await transport.send(0xb0, 0x01, 0x00, 0x00);
11
+ const r = await transport.send(0xb0, 0x01, 0x00, 0x00, undefined, undefined, { abortTimeoutMs });
11
12
  let i = 0;
12
13
  const format = r[i++];
13
14
 
@@ -0,0 +1,126 @@
1
+ /* eslint-env jest */
2
+ import {
3
+ IgnoredSignatureStepError,
4
+ ListAccountError,
5
+ ListCurrencyError,
6
+ NonceStepError,
7
+ NotEnoughFunds,
8
+ PayloadStepError,
9
+ PayinExtraIdError,
10
+ SignatureStepError,
11
+ SwapError,
12
+ UnknownAccountError,
13
+ } from "./SwapError";
14
+
15
+ describe("SwapError", () => {
16
+ it("captures nested error metadata", () => {
17
+ const nested = new Error("payload failed");
18
+ Object.assign(nested, { code: "E500" });
19
+
20
+ const error = new SwapError("swap999", nested);
21
+
22
+ expect(error).toBeInstanceOf(SwapError);
23
+ expect(error.cause.swapCode).toBe("swap999");
24
+ expect(error.cause.message).toBe(String(nested));
25
+ expect(error.cause.code).toBe("E500");
26
+ expect(error.message).toBe("payload failed");
27
+ });
28
+
29
+ it("defaults to swap000 when no code provided", () => {
30
+ const error = new SwapError();
31
+
32
+ expect(error.cause.swapCode).toBe("swap000");
33
+ expect(error.message).toBe("undefined");
34
+ });
35
+ });
36
+
37
+ type DerivedErrorCase = {
38
+ label: string;
39
+ create: (nested?: Error) => SwapError;
40
+ swapCode: string;
41
+ name: string;
42
+ propagatesMessage?: boolean;
43
+ };
44
+
45
+ const DERIVED_ERROR_CASES: DerivedErrorCase[] = [
46
+ {
47
+ label: "NonceStepError",
48
+ create: nested => new NonceStepError(nested),
49
+ swapCode: "swap001",
50
+ name: "NonceStepError",
51
+ propagatesMessage: true,
52
+ },
53
+ {
54
+ label: "PayloadStepError",
55
+ create: nested => new PayloadStepError(nested),
56
+ swapCode: "swap002",
57
+ name: "PayloadStepError",
58
+ propagatesMessage: true,
59
+ },
60
+ {
61
+ label: "SignatureStepError",
62
+ create: nested => new SignatureStepError(nested),
63
+ swapCode: "swap003",
64
+ name: "SignatureStepError",
65
+ propagatesMessage: true,
66
+ },
67
+ {
68
+ label: "IgnoredSignatureStepError",
69
+ create: nested => new IgnoredSignatureStepError(nested),
70
+ swapCode: "swap003Ignored",
71
+ name: "SignatureStepError",
72
+ propagatesMessage: true,
73
+ },
74
+ {
75
+ label: "NotEnoughFunds",
76
+ create: () => new NotEnoughFunds(),
77
+ swapCode: "swap004",
78
+ name: "NotEnoughFunds",
79
+ },
80
+ {
81
+ label: "ListAccountError",
82
+ create: nested => new ListAccountError(nested),
83
+ swapCode: "swap005",
84
+ name: "ListAccountError",
85
+ propagatesMessage: true,
86
+ },
87
+ {
88
+ label: "ListCurrencyError",
89
+ create: nested => new ListCurrencyError(nested),
90
+ swapCode: "swap006",
91
+ name: "ListCurrencyError",
92
+ propagatesMessage: true,
93
+ },
94
+ {
95
+ label: "UnknownAccountError",
96
+ create: nested => new UnknownAccountError(nested),
97
+ swapCode: "swap007",
98
+ name: "UnknownAccountError",
99
+ propagatesMessage: true,
100
+ },
101
+ {
102
+ label: "PayinExtraIdError",
103
+ create: nested => new PayinExtraIdError(nested),
104
+ swapCode: "swap010",
105
+ name: "PayinExtraIdError",
106
+ propagatesMessage: true,
107
+ },
108
+ ];
109
+
110
+ describe.each(DERIVED_ERROR_CASES)(
111
+ "Derived $label",
112
+ ({ create, swapCode, name, propagatesMessage }) => {
113
+ it("inherits SwapError defaults", () => {
114
+ const nested = new Error("step failure");
115
+ const error = create(propagatesMessage ? nested : undefined);
116
+
117
+ expect(error).toBeInstanceOf(SwapError);
118
+ expect(error.name).toBe(name);
119
+ expect(error.cause.swapCode).toBe(swapCode);
120
+
121
+ if (propagatesMessage) {
122
+ expect(error.message).toBe("step failure");
123
+ }
124
+ });
125
+ },
126
+ );
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Simplified Swap Error System
3
+ * Base error class and specific error types for swap transaction flows
4
+ */
5
+
6
+ /**
7
+ * Base error class for all swap-related errors
8
+ * Contains error code and nested error information
9
+ */
10
+ export class SwapError extends Error {
11
+ cause: {
12
+ swapCode: string;
13
+ [key: string]: string | Error | unknown | undefined;
14
+ };
15
+ message: string;
16
+
17
+ constructor(code = "swap000", nestedError?: Error) {
18
+ super();
19
+ this.name = "SwapError";
20
+
21
+ // Preserve nested error information
22
+ this.cause = {
23
+ swapCode: code,
24
+ ...(nestedError?.constructor !== Object && nestedError?.constructor !== Array
25
+ ? { message: `${nestedError}` }
26
+ : {}),
27
+ ...nestedError,
28
+ };
29
+
30
+ this.message = nestedError?.message ? nestedError.message : `${nestedError}`;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Error during nonce/deviceTransactionId generation step
36
+ * Typically occurs when calling startSwap()
37
+ */
38
+ export class NonceStepError extends SwapError {
39
+ constructor(nestedError?: Error) {
40
+ super("swap001", nestedError);
41
+ this.name = "NonceStepError";
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Error during payload retrieval step
47
+ * Occurs when communicating with backend to get transaction payload
48
+ */
49
+ export class PayloadStepError extends SwapError {
50
+ constructor(nestedError?: Error) {
51
+ super("swap002", nestedError);
52
+ this.name = "PayloadStepError";
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Error during transaction signature step
58
+ * Occurs when user rejects or device fails during completeSwap()
59
+ */
60
+ export class SignatureStepError extends SwapError {
61
+ constructor(nestedError?: Error) {
62
+ super("swap003", nestedError);
63
+ this.name = "SignatureStepError";
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Special case: signature error that should be ignored/handled silently
69
+ * Used for expected user cancellations
70
+ */
71
+ export class IgnoredSignatureStepError extends SwapError {
72
+ constructor(nestedError?: Error) {
73
+ super("swap003Ignored", nestedError);
74
+ this.name = "SignatureStepError";
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Error when user doesn't have sufficient funds
80
+ * Thrown during balance validation
81
+ */
82
+ export class NotEnoughFunds extends SwapError {
83
+ constructor() {
84
+ super("swap004");
85
+ this.name = "NotEnoughFunds";
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Error when unable to retrieve account list
91
+ * Occurs during account lookup phase
92
+ */
93
+ export class ListAccountError extends SwapError {
94
+ constructor(nestedError?: Error) {
95
+ super("swap005", nestedError);
96
+ this.name = "ListAccountError";
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Error when unable to retrieve currency information
102
+ * Occurs during currency lookup phase
103
+ */
104
+ export class ListCurrencyError extends SwapError {
105
+ constructor(nestedError?: Error) {
106
+ super("swap006", nestedError);
107
+ this.name = "ListCurrencyError";
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Error when specified account ID cannot be found
113
+ * Thrown when fromAccountId or toAccountId is invalid
114
+ */
115
+ export class UnknownAccountError extends SwapError {
116
+ constructor(nestedError?: Error) {
117
+ super("swap007", nestedError);
118
+ this.name = "UnknownAccountError";
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Error when extra identifier is required but missing
124
+ * Some chains require payinExtraId (e.g., XLM memo, XRP tag)
125
+ */
126
+ export class PayinExtraIdError extends SwapError {
127
+ constructor(nestedError?: Error) {
128
+ super("swap010", nestedError);
129
+ this.name = "PayinExtraIdError";
130
+ }
131
+ }
132
+
133
+ /**
134
+ * CompleteSwap/CompleteExchange step information
135
+ * Tracks which hardware wallet step failed
136
+ */
137
+ export type CompleteExchangeStep =
138
+ | "INIT"
139
+ | "SET_PARTNER_KEY"
140
+ | "CHECK_PARTNER"
141
+ | "PROCESS_TRANSACTION"
142
+ | "CHECK_TRANSACTION_SIGNATURE"
143
+ | "CHECK_PAYOUT_ADDRESS"
144
+ | "CHECK_REFUND_ADDRESS"
145
+ | "SIGN_COIN_TRANSACTION";
146
+
147
+ /**
148
+ * Error that occurs during completeSwap with step tracking
149
+ * Useful for debugging hardware wallet interactions
150
+ */
151
+ export class CompleteExchangeError extends Error {
152
+ step: CompleteExchangeStep;
153
+
154
+ constructor(step: CompleteExchangeStep, message?: string) {
155
+ super(message);
156
+ this.name = "CompleteExchangeError";
157
+ this.step = step;
158
+ }
159
+ }