@ledgerhq/live-common 34.54.0-nightly.20251209023841 → 34.54.0-nightly.20251209144712

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 (103) hide show
  1. package/lib/__tests__/test-helpers/environment.js +2 -0
  2. package/lib/__tests__/test-helpers/environment.js.map +1 -1
  3. package/lib/bridge/generic-alpaca/getAccountShape.d.ts.map +1 -1
  4. package/lib/bridge/generic-alpaca/getAccountShape.js +3 -2
  5. package/lib/bridge/generic-alpaca/getAccountShape.js.map +1 -1
  6. package/lib/bridge/generic-alpaca/prepareTransaction.d.ts.map +1 -1
  7. package/lib/bridge/generic-alpaca/prepareTransaction.js +7 -0
  8. package/lib/bridge/generic-alpaca/prepareTransaction.js.map +1 -1
  9. package/lib/e2e/index.d.ts +6 -0
  10. package/lib/e2e/index.d.ts.map +1 -1
  11. package/lib/exchange/swap/getIncompatibleCurrencyKeys.d.ts.map +1 -1
  12. package/lib/exchange/swap/getIncompatibleCurrencyKeys.js +4 -0
  13. package/lib/exchange/swap/getIncompatibleCurrencyKeys.js.map +1 -1
  14. package/lib/exchange/swap/transactionStrategies.d.ts +2 -1
  15. package/lib/exchange/swap/transactionStrategies.d.ts.map +1 -1
  16. package/lib/exchange/swap/transactionStrategies.js +7 -6
  17. package/lib/exchange/swap/transactionStrategies.js.map +1 -1
  18. package/lib/featureFlags/defaultFeatures.d.ts +2 -0
  19. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
  20. package/lib/featureFlags/defaultFeatures.js +2 -0
  21. package/lib/featureFlags/defaultFeatures.js.map +1 -1
  22. package/lib/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.d.ts.map +1 -1
  23. package/lib/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.js +6 -0
  24. package/lib/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.js.map +1 -1
  25. package/lib/wallet-api/Exchange/SwapError.d.ts +93 -0
  26. package/lib/wallet-api/Exchange/SwapError.d.ts.map +1 -0
  27. package/lib/wallet-api/Exchange/SwapError.js +142 -0
  28. package/lib/wallet-api/Exchange/SwapError.js.map +1 -0
  29. package/lib/wallet-api/Exchange/handleSwapErrors.d.ts +40 -0
  30. package/lib/wallet-api/Exchange/handleSwapErrors.d.ts.map +1 -0
  31. package/lib/wallet-api/Exchange/handleSwapErrors.js +112 -0
  32. package/lib/wallet-api/Exchange/handleSwapErrors.js.map +1 -0
  33. package/lib/wallet-api/Exchange/index.d.ts +4 -0
  34. package/lib/wallet-api/Exchange/index.d.ts.map +1 -0
  35. package/lib/wallet-api/Exchange/index.js +27 -0
  36. package/lib/wallet-api/Exchange/index.js.map +1 -0
  37. package/lib/wallet-api/Exchange/parser.d.ts +46 -0
  38. package/lib/wallet-api/Exchange/parser.d.ts.map +1 -0
  39. package/lib/wallet-api/Exchange/parser.js +97 -0
  40. package/lib/wallet-api/Exchange/parser.js.map +1 -0
  41. package/lib/wallet-api/Exchange/server.d.ts.map +1 -1
  42. package/lib/wallet-api/Exchange/server.js +226 -179
  43. package/lib/wallet-api/Exchange/server.js.map +1 -1
  44. package/lib-es/__tests__/test-helpers/environment.js +2 -0
  45. package/lib-es/__tests__/test-helpers/environment.js.map +1 -1
  46. package/lib-es/bridge/generic-alpaca/getAccountShape.d.ts.map +1 -1
  47. package/lib-es/bridge/generic-alpaca/getAccountShape.js +3 -2
  48. package/lib-es/bridge/generic-alpaca/getAccountShape.js.map +1 -1
  49. package/lib-es/bridge/generic-alpaca/prepareTransaction.d.ts.map +1 -1
  50. package/lib-es/bridge/generic-alpaca/prepareTransaction.js +7 -0
  51. package/lib-es/bridge/generic-alpaca/prepareTransaction.js.map +1 -1
  52. package/lib-es/e2e/index.d.ts +6 -0
  53. package/lib-es/e2e/index.d.ts.map +1 -1
  54. package/lib-es/exchange/swap/getIncompatibleCurrencyKeys.d.ts.map +1 -1
  55. package/lib-es/exchange/swap/getIncompatibleCurrencyKeys.js +4 -0
  56. package/lib-es/exchange/swap/getIncompatibleCurrencyKeys.js.map +1 -1
  57. package/lib-es/exchange/swap/transactionStrategies.d.ts +2 -1
  58. package/lib-es/exchange/swap/transactionStrategies.d.ts.map +1 -1
  59. package/lib-es/exchange/swap/transactionStrategies.js +7 -6
  60. package/lib-es/exchange/swap/transactionStrategies.js.map +1 -1
  61. package/lib-es/featureFlags/defaultFeatures.d.ts +2 -0
  62. package/lib-es/featureFlags/defaultFeatures.d.ts.map +1 -1
  63. package/lib-es/featureFlags/defaultFeatures.js +2 -0
  64. package/lib-es/featureFlags/defaultFeatures.js.map +1 -1
  65. package/lib-es/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.d.ts.map +1 -1
  66. package/lib-es/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.js +6 -0
  67. package/lib-es/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.js.map +1 -1
  68. package/lib-es/wallet-api/Exchange/SwapError.d.ts +93 -0
  69. package/lib-es/wallet-api/Exchange/SwapError.d.ts.map +1 -0
  70. package/lib-es/wallet-api/Exchange/SwapError.js +128 -0
  71. package/lib-es/wallet-api/Exchange/SwapError.js.map +1 -0
  72. package/lib-es/wallet-api/Exchange/handleSwapErrors.d.ts +40 -0
  73. package/lib-es/wallet-api/Exchange/handleSwapErrors.d.ts.map +1 -0
  74. package/lib-es/wallet-api/Exchange/handleSwapErrors.js +106 -0
  75. package/lib-es/wallet-api/Exchange/handleSwapErrors.js.map +1 -0
  76. package/lib-es/wallet-api/Exchange/index.d.ts +4 -0
  77. package/lib-es/wallet-api/Exchange/index.d.ts.map +1 -0
  78. package/lib-es/wallet-api/Exchange/index.js +7 -0
  79. package/lib-es/wallet-api/Exchange/index.js.map +1 -0
  80. package/lib-es/wallet-api/Exchange/parser.d.ts +46 -0
  81. package/lib-es/wallet-api/Exchange/parser.d.ts.map +1 -0
  82. package/lib-es/wallet-api/Exchange/parser.js +90 -0
  83. package/lib-es/wallet-api/Exchange/parser.js.map +1 -0
  84. package/lib-es/wallet-api/Exchange/server.d.ts.map +1 -1
  85. package/lib-es/wallet-api/Exchange/server.js +223 -179
  86. package/lib-es/wallet-api/Exchange/server.js.map +1 -1
  87. package/package.json +73 -73
  88. package/src/__tests__/test-helpers/environment.ts +2 -0
  89. package/src/bridge/generic-alpaca/getAccountShape.ts +4 -2
  90. package/src/bridge/generic-alpaca/prepareTransaction.ts +7 -0
  91. package/src/bridge/generic-alpaca/tests/prepareTransaction.test.ts +42 -0
  92. package/src/exchange/swap/getIncompatibleCurrencyKeys.ts +4 -0
  93. package/src/exchange/swap/transactionStrategies.ts +8 -7
  94. package/src/featureFlags/defaultFeatures.ts +2 -0
  95. package/src/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.ts +6 -0
  96. package/src/wallet-api/Exchange/SwapError.test.ts +126 -0
  97. package/src/wallet-api/Exchange/SwapError.ts +159 -0
  98. package/src/wallet-api/Exchange/handleSwapErrors.test.ts +46 -0
  99. package/src/wallet-api/Exchange/handleSwapErrors.ts +161 -0
  100. package/src/wallet-api/Exchange/index.ts +26 -0
  101. package/src/wallet-api/Exchange/parser.test.ts +86 -0
  102. package/src/wallet-api/Exchange/parser.ts +119 -0
  103. package/src/wallet-api/Exchange/server.ts +287 -238
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-nightly.20251209023841",
4
+ "version": "34.54.0-nightly.20251209144712",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/LedgerHQ/ledger-live.git"
@@ -176,78 +176,78 @@
176
176
  "xstate": "^5.19.2",
177
177
  "yargs": "^17.0.0",
178
178
  "zod": "^3.22.4",
179
- "@ledgerhq/coin-algorand": "^0.14.0-nightly.20251209023841",
180
- "@ledgerhq/coin-aptos": "^3.7.0-nightly.20251209023841",
181
- "@ledgerhq/coin-bitcoin": "^0.26.0-nightly.20251209023841",
182
- "@ledgerhq/coin-canton": "^0.11.0-nightly.20251209023841",
183
- "@ledgerhq/coin-cardano": "^0.16.0-nightly.20251209023841",
184
- "@ledgerhq/coin-casper": "^2.5.0-nightly.20251209023841",
185
- "@ledgerhq/coin-celo": "^1.8.0-nightly.20251209023841",
186
- "@ledgerhq/coin-cosmos": "^0.21.0-nightly.20251209023841",
187
- "@ledgerhq/coin-evm": "^2.36.0-nightly.20251209023841",
188
- "@ledgerhq/coin-filecoin": "^1.15.0-nightly.20251209023841",
189
- "@ledgerhq/coin-framework": "^6.10.0-nightly.20251209023841",
190
- "@ledgerhq/coin-hedera": "^1.15.0-nightly.20251209023841",
191
- "@ledgerhq/coin-icon": "^0.16.0-nightly.20251209023841",
192
- "@ledgerhq/coin-internet_computer": "^1.12.0-nightly.20251209023841",
193
- "@ledgerhq/coin-kaspa": "^1.5.0-nightly.20251209023841",
194
- "@ledgerhq/coin-mina": "^1.5.0-nightly.20251209023841",
195
- "@ledgerhq/coin-multiversx": "^0.9.0-nightly.20251209023841",
196
- "@ledgerhq/coin-near": "^0.17.0-nightly.20251209023841",
197
- "@ledgerhq/coin-polkadot": "^6.14.0-nightly.20251209023841",
198
- "@ledgerhq/coin-solana": "^0.38.0-nightly.20251209023841",
199
- "@ledgerhq/coin-stacks": "^0.13.0-nightly.20251209023841",
200
- "@ledgerhq/coin-stellar": "^6.8.0-nightly.20251209023841",
201
- "@ledgerhq/coin-sui": "^0.19.0-nightly.20251209023841",
202
- "@ledgerhq/coin-tezos": "^6.10.0-nightly.20251209023841",
203
- "@ledgerhq/coin-ton": "^0.18.0-nightly.20251209023841",
204
- "@ledgerhq/coin-tron": "^5.8.0-nightly.20251209023841",
205
- "@ledgerhq/coin-vechain": "^2.13.0-nightly.20251209023841",
206
- "@ledgerhq/coin-xrp": "^7.9.0-nightly.20251209023841",
207
- "@ledgerhq/cryptoassets": "^13.34.0-nightly.20251209023841",
208
- "@ledgerhq/device-core": "^0.6.9-nightly.20251209023841",
209
- "@ledgerhq/devices": "8.8.0-nightly.20251209023841",
210
- "@ledgerhq/errors": "^6.28.0-nightly.20251209023841",
211
- "@ledgerhq/hw-app-algorand": "^6.31.10-nightly.20251209023841",
212
- "@ledgerhq/hw-app-aptos": "^6.34.10-nightly.20251209023841",
213
- "@ledgerhq/hw-app-btc": "^10.13.0-nightly.20251209023841",
214
- "@ledgerhq/hw-app-celo": "^6.35.4-nightly.20251209023841",
215
- "@ledgerhq/hw-app-cosmos": "^6.32.10-nightly.20251209023841",
216
- "@ledgerhq/hw-app-eth": "^7.0.0-nightly.20251209023841",
217
- "@ledgerhq/hw-app-exchange": "^0.18.0-nightly.20251209023841",
218
- "@ledgerhq/hw-app-hedera": "^1.2.10-nightly.20251209023841",
219
- "@ledgerhq/hw-app-icon": "^1.3.10-nightly.20251209023841",
220
- "@ledgerhq/hw-app-kaspa": "^1.3.3-nightly.20251209023841",
221
- "@ledgerhq/hw-app-multiversx": "^6.26.1-nightly.20251209023841",
222
- "@ledgerhq/hw-app-near": "^6.31.10-nightly.20251209023841",
223
- "@ledgerhq/hw-app-polkadot": "^6.34.10-nightly.20251209023841",
224
- "@ledgerhq/hw-app-str": "^7.2.10-nightly.20251209023841",
179
+ "@ledgerhq/coin-algorand": "^0.14.0-nightly.20251209144712",
180
+ "@ledgerhq/coin-aptos": "^3.7.0-nightly.20251209144712",
181
+ "@ledgerhq/coin-bitcoin": "^0.26.0-nightly.20251209144712",
182
+ "@ledgerhq/coin-canton": "^0.11.0-nightly.20251209144712",
183
+ "@ledgerhq/coin-cardano": "^0.16.0-nightly.20251209144712",
184
+ "@ledgerhq/coin-casper": "^2.5.0-nightly.20251209144712",
185
+ "@ledgerhq/coin-celo": "^1.8.0-nightly.20251209144712",
186
+ "@ledgerhq/coin-cosmos": "^0.21.0-nightly.20251209144712",
187
+ "@ledgerhq/coin-evm": "^2.36.0-nightly.20251209144712",
188
+ "@ledgerhq/coin-filecoin": "^1.15.0-nightly.20251209144712",
189
+ "@ledgerhq/coin-framework": "^6.10.0-nightly.20251209144712",
190
+ "@ledgerhq/coin-hedera": "^1.15.0-nightly.20251209144712",
191
+ "@ledgerhq/coin-icon": "^0.16.0-nightly.20251209144712",
192
+ "@ledgerhq/coin-internet_computer": "^1.12.0-nightly.20251209144712",
193
+ "@ledgerhq/coin-kaspa": "^1.5.0-nightly.20251209144712",
194
+ "@ledgerhq/coin-mina": "^1.5.0-nightly.20251209144712",
195
+ "@ledgerhq/coin-multiversx": "^0.9.0-nightly.20251209144712",
196
+ "@ledgerhq/coin-near": "^0.17.0-nightly.20251209144712",
197
+ "@ledgerhq/coin-polkadot": "^6.14.0-nightly.20251209144712",
198
+ "@ledgerhq/coin-solana": "^0.38.0-nightly.20251209144712",
199
+ "@ledgerhq/coin-stacks": "^0.13.0-nightly.20251209144712",
200
+ "@ledgerhq/coin-stellar": "^6.8.0-nightly.20251209144712",
201
+ "@ledgerhq/coin-sui": "^0.19.0-nightly.20251209144712",
202
+ "@ledgerhq/coin-tezos": "^6.10.0-nightly.20251209144712",
203
+ "@ledgerhq/coin-ton": "^0.18.0-nightly.20251209144712",
204
+ "@ledgerhq/coin-tron": "^5.8.0-nightly.20251209144712",
205
+ "@ledgerhq/coin-vechain": "^2.13.0-nightly.20251209144712",
206
+ "@ledgerhq/device-core": "^0.6.9-nightly.20251209144712",
207
+ "@ledgerhq/coin-xrp": "^7.9.0-nightly.20251209144712",
208
+ "@ledgerhq/hw-app-algorand": "^6.31.10-nightly.20251209144712",
209
+ "@ledgerhq/devices": "8.8.0-nightly.20251209144712",
210
+ "@ledgerhq/cryptoassets": "^13.34.0-nightly.20251209144712",
211
+ "@ledgerhq/errors": "^6.28.0-nightly.20251209144712",
212
+ "@ledgerhq/hw-app-aptos": "^6.34.10-nightly.20251209144712",
213
+ "@ledgerhq/hw-app-btc": "^10.13.0-nightly.20251209144712",
214
+ "@ledgerhq/hw-app-celo": "^6.35.4-nightly.20251209144712",
215
+ "@ledgerhq/hw-app-cosmos": "^6.32.10-nightly.20251209144712",
216
+ "@ledgerhq/hw-app-eth": "^7.0.0-nightly.20251209144712",
217
+ "@ledgerhq/hw-app-exchange": "^0.18.0-nightly.20251209144712",
218
+ "@ledgerhq/hw-app-hedera": "^1.2.10-nightly.20251209144712",
219
+ "@ledgerhq/hw-app-icon": "^1.3.10-nightly.20251209144712",
220
+ "@ledgerhq/hw-app-kaspa": "^1.3.3-nightly.20251209144712",
221
+ "@ledgerhq/hw-app-multiversx": "^6.26.1-nightly.20251209144712",
222
+ "@ledgerhq/hw-app-polkadot": "^6.34.10-nightly.20251209144712",
223
+ "@ledgerhq/hw-app-str": "^7.2.10-nightly.20251209144712",
224
+ "@ledgerhq/hw-app-near": "^6.31.10-nightly.20251209144712",
225
225
  "@ledgerhq/hw-app-sui": "^1.4.0",
226
- "@ledgerhq/hw-app-tezos": "^6.31.10-nightly.20251209023841",
227
- "@ledgerhq/hw-app-trx": "^6.31.10-nightly.20251209023841",
228
- "@ledgerhq/hw-app-vet": "^0.8.0-nightly.20251209023841",
229
- "@ledgerhq/hw-app-xrp": "^6.32.8-nightly.20251209023841",
230
- "@ledgerhq/hw-bolos": "^6.32.10-nightly.20251209023841",
231
- "@ledgerhq/hw-transport": "6.31.14-nightly.20251209023841",
232
- "@ledgerhq/hw-transport-mocker": "^6.30.0-nightly.20251209023841",
233
- "@ledgerhq/ledger-cal-service": "^1.9.1-nightly.20251209023841",
234
- "@ledgerhq/ledger-trust-service": "^0.4.3-nightly.20251209023841",
235
- "@ledgerhq/live-config": "^3.3.0-nightly.20251209023841",
236
- "@ledgerhq/live-countervalues": "^0.10.1-nightly.20251209023841",
237
- "@ledgerhq/live-countervalues-react": "^0.7.3-nightly.20251209023841",
238
- "@ledgerhq/live-dmk-shared": "^0.16.0-nightly.20251209023841",
239
- "@ledgerhq/live-env": "^2.22.0-nightly.20251209023841",
240
- "@ledgerhq/live-hooks": "0.3.0-nightly.20251209023841",
241
- "@ledgerhq/live-network": "^2.1.2-nightly.20251209023841",
226
+ "@ledgerhq/hw-app-tezos": "^6.31.10-nightly.20251209144712",
227
+ "@ledgerhq/hw-app-trx": "^6.31.10-nightly.20251209144712",
228
+ "@ledgerhq/hw-app-vet": "^0.8.0-nightly.20251209144712",
229
+ "@ledgerhq/hw-app-xrp": "^6.32.8-nightly.20251209144712",
230
+ "@ledgerhq/hw-bolos": "^6.32.10-nightly.20251209144712",
231
+ "@ledgerhq/hw-transport": "6.31.14-nightly.20251209144712",
232
+ "@ledgerhq/hw-transport-mocker": "^6.30.0-nightly.20251209144712",
233
+ "@ledgerhq/ledger-cal-service": "^1.9.1-nightly.20251209144712",
234
+ "@ledgerhq/ledger-trust-service": "^0.4.3-nightly.20251209144712",
235
+ "@ledgerhq/live-config": "^3.3.0-nightly.20251209144712",
236
+ "@ledgerhq/live-countervalues": "^0.10.1-nightly.20251209144712",
237
+ "@ledgerhq/live-countervalues-react": "^0.7.3-nightly.20251209144712",
238
+ "@ledgerhq/live-dmk-shared": "^0.16.0-nightly.20251209144712",
239
+ "@ledgerhq/live-env": "^2.22.0-nightly.20251209144712",
240
+ "@ledgerhq/live-hooks": "0.3.0-nightly.20251209144712",
241
+ "@ledgerhq/live-network": "^2.1.2-nightly.20251209144712",
242
242
  "@ledgerhq/live-promise": "^0.1.1",
243
- "@ledgerhq/live-signer-canton": "^0.5.2-nightly.20251209023841",
244
- "@ledgerhq/live-signer-evm": "^0.11.0-nightly.20251209023841",
245
- "@ledgerhq/live-signer-solana": "^0.7.0-nightly.20251209023841",
246
- "@ledgerhq/live-wallet": "^0.17.0-nightly.20251209023841",
243
+ "@ledgerhq/live-signer-evm": "^0.11.0-nightly.20251209144712",
244
+ "@ledgerhq/live-signer-canton": "^0.5.2-nightly.20251209144712",
245
+ "@ledgerhq/live-signer-solana": "^0.7.0-nightly.20251209144712",
246
+ "@ledgerhq/live-wallet": "^0.17.0-nightly.20251209144712",
247
247
  "@ledgerhq/logs": "^6.13.0",
248
- "@ledgerhq/speculos-transport": "^0.3.0-nightly.20251209023841",
249
- "@ledgerhq/wallet-api-acre-module": "^0.10.0-nightly.20251209023841",
250
- "@ledgerhq/wallet-api-exchange-module": "^0.19.0-nightly.20251209023841"
248
+ "@ledgerhq/speculos-transport": "^0.3.0-nightly.20251209144712",
249
+ "@ledgerhq/wallet-api-acre-module": "^0.10.0-nightly.20251209144712",
250
+ "@ledgerhq/wallet-api-exchange-module": "^0.19.0-nightly.20251209144712"
251
251
  },
252
252
  "devDependencies": {
253
253
  "@solana/web3.js": "1.95.4",
@@ -294,10 +294,10 @@
294
294
  "undici": "6.19.2",
295
295
  "uuid": "^8.3.2",
296
296
  "ws": "8.18.3",
297
- "@ledgerhq/device-react": "^0.3.3-nightly.20251209023841",
298
- "@ledgerhq/types-cryptoassets": "^7.31.0-nightly.20251209023841",
297
+ "@ledgerhq/device-react": "^0.3.3-nightly.20251209144712",
298
+ "@ledgerhq/types-cryptoassets": "^7.31.0-nightly.20251209144712",
299
299
  "@ledgerhq/types-devices": "^6.27.0",
300
- "@ledgerhq/types-live": "^6.90.0-nightly.20251209023841"
300
+ "@ledgerhq/types-live": "^6.90.0-nightly.20251209144712"
301
301
  },
302
302
  "scripts": {
303
303
  "build": "zx ./scripts/build-ts.mjs",
@@ -128,6 +128,8 @@ setSupportedCurrencies([
128
128
  "monad_testnet",
129
129
  "somnia",
130
130
  "zero_gravity",
131
+ "concordium",
132
+ "concordium_testnet",
131
133
  ]);
132
134
  LiveConfig.setConfig(liveConfig);
133
135
 
@@ -102,10 +102,12 @@ export function genericGetAccountShape(network: string, kind: string): GetAccoun
102
102
  internalOperations,
103
103
  });
104
104
  });
105
- // Try to refresh known pending operations (if not already updated)
105
+ // Try to refresh known pending and broadcasted operations (if not already updated)
106
106
  // Useful for integrations without explorers
107
107
  const operationsToRefresh = initialAccount?.pendingOperations.filter(
108
- pendingOp => !newOpsWithSubs.some(newOp => pendingOp.hash === newOp.hash),
108
+ pendingOp =>
109
+ pendingOp.hash && // operation has been broadcasted
110
+ !newOpsWithSubs.some(newOp => pendingOp.hash === newOp.hash), // operation is not confirmed yet
109
111
  );
110
112
  const confirmedOperations =
111
113
  alpacaApi.refreshOperations && operationsToRefresh?.length
@@ -71,10 +71,15 @@ export function genericPrepareTransaction(
71
71
  }
72
72
 
73
73
  // Pass any parameters that help estimating fees
74
+ // This includes `assetOwner` and `assetReference` that are not used by some apps that only rely on `subAccountId`
75
+ // TODO Remove `assetOwner` and `assetReference` in order to maintain one unique way of identifying the type of asset
76
+ // https://ledgerhq.atlassian.net/browse/LIVE-24044
74
77
  const intent = transactionToIntent(
75
78
  account,
76
79
  {
77
80
  ...transaction,
81
+ assetOwner,
82
+ assetReference,
78
83
  amount,
79
84
  },
80
85
  computeIntentType,
@@ -125,6 +130,8 @@ export function genericPrepareTransaction(
125
130
  account,
126
131
  {
127
132
  ...transaction,
133
+ assetOwner,
134
+ assetReference,
128
135
  },
129
136
  computeIntentType,
130
137
  ),
@@ -3,6 +3,8 @@ import { getAlpacaApi } from "../alpaca";
3
3
  import { transactionToIntent } from "../utils";
4
4
  import BigNumber from "bignumber.js";
5
5
  import { GenericTransaction } from "../types";
6
+ import { setupMockCryptoAssetsStore } from "@ledgerhq/cryptoassets/cal-client/test-helpers";
7
+ import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
6
8
 
7
9
  jest.mock("../alpaca", () => ({
8
10
  getAlpacaApi: jest.fn(),
@@ -154,4 +156,44 @@ describe("genericPrepareTransaction", () => {
154
156
 
155
157
  expect(estimateFees).toHaveBeenCalledWith(expect.objectContaining({ amount: 100n }), {});
156
158
  });
159
+
160
+ it("fills 'assetOwner' and 'assetReference' from 'subAccountId' for retro compatibility", async () => {
161
+ setupMockCryptoAssetsStore({
162
+ findTokenById: tokenId =>
163
+ Promise.resolve(tokenId === "usdc" ? ({ id: tokenId } as TokenCurrency) : undefined),
164
+ });
165
+ (getAlpacaApi as jest.Mock).mockReturnValue({
166
+ estimateFees: () => Promise.resolve({ value: 0n }),
167
+ getAssetFromToken: (token, owner) =>
168
+ token.id === "usdc" ? { assetOwner: owner, assetReference: token.id } : undefined,
169
+ });
170
+ const prepareTransaction = genericPrepareTransaction(network, kind);
171
+
172
+ await prepareTransaction(
173
+ {
174
+ ...account,
175
+ freshAddress: "test-account-address",
176
+ subAccounts: [{ id: "test-sub-account+usdc" }],
177
+ },
178
+ {
179
+ subAccountId: "test-sub-account+usdc",
180
+ amount: new BigNumber(10),
181
+ } as GenericTransaction,
182
+ );
183
+
184
+ expect(transactionToIntent).toHaveBeenCalledWith(
185
+ {
186
+ ...account,
187
+ freshAddress: "test-account-address",
188
+ subAccounts: [{ id: "test-sub-account+usdc" }],
189
+ },
190
+ {
191
+ subAccountId: "test-sub-account+usdc",
192
+ amount: new BigNumber(10),
193
+ assetOwner: "test-account-address",
194
+ assetReference: "usdc",
195
+ },
196
+ undefined,
197
+ );
198
+ });
157
199
  });
@@ -83,6 +83,10 @@ const INCOMPATIBLE_NANO_S_CURRENCY_KEYS: Keys = {
83
83
  title: "swap.incompatibility.celo_title",
84
84
  description: "swap.incompatibility.celo_description",
85
85
  },
86
+ monad: {
87
+ title: "swap.incompatibility.monad_title",
88
+ description: "swap.incompatibility.monad_description",
89
+ },
86
90
  };
87
91
 
88
92
  export const getIncompatibleCurrencyKeys = (exchange: ExchangeSwap) => {
@@ -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;
@@ -110,6 +110,8 @@ export const CURRENCY_DEFAULT_FEATURES = {
110
110
  currencyMonadTestnet: DEFAULT_FEATURE,
111
111
  currencySomnia: DEFAULT_FEATURE,
112
112
  currencyZeroGravity: DEFAULT_FEATURE,
113
+ currencyConcordium: DEFAULT_FEATURE,
114
+ currencyConcordiumTestnet: DEFAULT_FEATURE,
113
115
  };
114
116
 
115
117
  /**
@@ -83,6 +83,8 @@ export function useCurrenciesUnderFeatureFlag() {
83
83
  const monadTestnet = useFeature("currencyMonadTestnet");
84
84
  const somnia = useFeature("currencySomnia");
85
85
  const zeroGravity = useFeature("currencyZeroGravity");
86
+ const concordium = useFeature("currencyConcordium");
87
+ const concordiumTestnet = useFeature("currencyConcordiumTestnet");
86
88
 
87
89
  const featureFlaggedCurrencies = useMemo(
88
90
  (): Partial<Record<CryptoCurrencyId, Feature<unknown> | null>> => ({
@@ -162,6 +164,8 @@ export function useCurrenciesUnderFeatureFlag() {
162
164
  monad_testnet: monadTestnet,
163
165
  somnia,
164
166
  zero_gravity: zeroGravity,
167
+ concordium,
168
+ concordium_testnet: concordiumTestnet,
165
169
  }),
166
170
  [
167
171
  aptos,
@@ -240,6 +244,8 @@ export function useCurrenciesUnderFeatureFlag() {
240
244
  monadTestnet,
241
245
  somnia,
242
246
  zeroGravity,
247
+ concordium,
248
+ concordiumTestnet,
243
249
  ],
244
250
  );
245
251
 
@@ -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
+ }