diff --git a/apps/ledger-live-desktop/src/renderer/modals/AddAccounts/steps/StepChooseCurrency.tsx b/apps/ledger-live-desktop/src/renderer/modals/AddAccounts/steps/StepChooseCurrency.tsx index 8797137d853f..c1bca968a42b 100644 --- a/apps/ledger-live-desktop/src/renderer/modals/AddAccounts/steps/StepChooseCurrency.tsx +++ b/apps/ledger-live-desktop/src/renderer/modals/AddAccounts/steps/StepChooseCurrency.tsx @@ -82,6 +82,7 @@ const StepChooseCurrency = ({ currency, setCurrency }: StepProps) => { const icon = useFeature("currencyIcon"); const ton = useFeature("currencyTon"); const etherlink = useFeature("currencyEtherlink"); + const mantra = useFeature("currencyMantra"); const featureFlaggedCurrencies = useMemo( (): Partial | null>> => ({ @@ -132,6 +133,7 @@ const StepChooseCurrency = ({ currency, setCurrency }: StepProps) => { scroll_sepolia: scrollSepolia, icon, etherlink, + mantra, }), [ axelar, @@ -181,6 +183,7 @@ const StepChooseCurrency = ({ currency, setCurrency }: StepProps) => { scrollSepolia, icon, etherlink, + mantra, ], ); diff --git a/apps/ledger-live-mobile/src/screens/AddAccounts/01-SelectCrypto.tsx b/apps/ledger-live-mobile/src/screens/AddAccounts/01-SelectCrypto.tsx index c9f1b11a3052..441d45839f0d 100644 --- a/apps/ledger-live-mobile/src/screens/AddAccounts/01-SelectCrypto.tsx +++ b/apps/ledger-live-mobile/src/screens/AddAccounts/01-SelectCrypto.tsx @@ -104,6 +104,7 @@ export default function AddAccountsSelectCrypto({ navigation, route }: Props) { const icon = useFeature("currencyIcon"); const ton = useFeature("currencyTon"); const etherlink = useFeature("currencyEtherlink"); + const mantra = useFeature("currencyMantra"); const featureFlaggedCurrencies = useMemo( (): Partial | null>> => ({ @@ -154,6 +155,7 @@ export default function AddAccountsSelectCrypto({ navigation, route }: Props) { scroll_sepolia: scrollSepolia, icon, etherlink, + mantra, }), [ axelar, @@ -203,6 +205,7 @@ export default function AddAccountsSelectCrypto({ navigation, route }: Props) { scrollSepolia, icon, etherlink, + mantra, ], ); diff --git a/apps/web-tools/live-common-setup.ts b/apps/web-tools/live-common-setup.ts index b157df940854..c9d959db1272 100644 --- a/apps/web-tools/live-common-setup.ts +++ b/apps/web-tools/live-common-setup.ts @@ -69,4 +69,5 @@ setSupportedCurrencies([ "optimism_sepolia", "linea", "linea_sepolia", + "mantra", ]); diff --git a/libs/coin-framework/src/currencies/__snapshots__/formatCurrencyUnit.test.ts.snap b/libs/coin-framework/src/currencies/__snapshots__/formatCurrencyUnit.test.ts.snap index 520fc5d77e22..66fe5950dd5d 100644 --- a/libs/coin-framework/src/currencies/__snapshots__/formatCurrencyUnit.test.ts.snap +++ b/libs/coin-framework/src/currencies/__snapshots__/formatCurrencyUnit.test.ts.snap @@ -176,6 +176,8 @@ exports[`formatCurrencyUnit with custom options with locale de-DE should correct exports[`formatCurrencyUnit with custom options with locale de-DE should correctly format MIX Blockchain unit (MIX) 1`] = `"123.456.789,00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale de-DE should correctly format Mantra unit (Mantra) 1`] = `"12.345.678.900,000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale de-DE should correctly format Metis unit (METIS) 1`] = `"0,012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale de-DE should correctly format Monero unit (XMR) 1`] = `"12.345,678900000000- -XMR"`; @@ -502,6 +504,8 @@ exports[`formatCurrencyUnit with custom options with locale en-US should correct exports[`formatCurrencyUnit with custom options with locale en-US should correctly format MIX Blockchain unit (MIX) 1`] = `"123,456,789.00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale en-US should correctly format Mantra unit (Mantra) 1`] = `"12,345,678,900.000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale en-US should correctly format Metis unit (METIS) 1`] = `"0.012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale en-US should correctly format Monero unit (XMR) 1`] = `"12,345.678900000000- -XMR"`; @@ -828,6 +832,8 @@ exports[`formatCurrencyUnit with custom options with locale es-ES should correct exports[`formatCurrencyUnit with custom options with locale es-ES should correctly format MIX Blockchain unit (MIX) 1`] = `"123.456.789,00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale es-ES should correctly format Mantra unit (Mantra) 1`] = `"12.345.678.900,000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale es-ES should correctly format Metis unit (METIS) 1`] = `"0,012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale es-ES should correctly format Monero unit (XMR) 1`] = `"12.345,678900000000- -XMR"`; @@ -1154,6 +1160,8 @@ exports[`formatCurrencyUnit with custom options with locale fr-FR should correct exports[`formatCurrencyUnit with custom options with locale fr-FR should correctly format MIX Blockchain unit (MIX) 1`] = `"123 456 789,00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale fr-FR should correctly format Mantra unit (Mantra) 1`] = `"12 345 678 900,000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale fr-FR should correctly format Metis unit (METIS) 1`] = `"0,012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale fr-FR should correctly format Monero unit (XMR) 1`] = `"12 345,678900000000- -XMR"`; @@ -1480,6 +1488,8 @@ exports[`formatCurrencyUnit with custom options with locale ja-JP should correct exports[`formatCurrencyUnit with custom options with locale ja-JP should correctly format MIX Blockchain unit (MIX) 1`] = `"123,456,789.00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale ja-JP should correctly format Mantra unit (Mantra) 1`] = `"12,345,678,900.000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale ja-JP should correctly format Metis unit (METIS) 1`] = `"0.012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale ja-JP should correctly format Monero unit (XMR) 1`] = `"12,345.678900000000- -XMR"`; @@ -1806,6 +1816,8 @@ exports[`formatCurrencyUnit with custom options with locale ko-KR should correct exports[`formatCurrencyUnit with custom options with locale ko-KR should correctly format MIX Blockchain unit (MIX) 1`] = `"123,456,789.00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale ko-KR should correctly format Mantra unit (Mantra) 1`] = `"12,345,678,900.000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale ko-KR should correctly format Metis unit (METIS) 1`] = `"0.012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale ko-KR should correctly format Monero unit (XMR) 1`] = `"12,345.678900000000- -XMR"`; @@ -2132,6 +2144,8 @@ exports[`formatCurrencyUnit with custom options with locale pt-BR should correct exports[`formatCurrencyUnit with custom options with locale pt-BR should correctly format MIX Blockchain unit (MIX) 1`] = `"123.456.789,00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale pt-BR should correctly format Mantra unit (Mantra) 1`] = `"12.345.678.900,000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale pt-BR should correctly format Metis unit (METIS) 1`] = `"0,012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale pt-BR should correctly format Monero unit (XMR) 1`] = `"12.345,678900000000- -XMR"`; @@ -2458,6 +2472,8 @@ exports[`formatCurrencyUnit with custom options with locale ru-RU should correct exports[`formatCurrencyUnit with custom options with locale ru-RU should correctly format MIX Blockchain unit (MIX) 1`] = `"123 456 789,00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale ru-RU should correctly format Mantra unit (Mantra) 1`] = `"12 345 678 900,000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale ru-RU should correctly format Metis unit (METIS) 1`] = `"0,012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale ru-RU should correctly format Monero unit (XMR) 1`] = `"12 345,678900000000- -XMR"`; @@ -2784,6 +2800,8 @@ exports[`formatCurrencyUnit with custom options with locale tr-TR should correct exports[`formatCurrencyUnit with custom options with locale tr-TR should correctly format MIX Blockchain unit (MIX) 1`] = `"123.456.789,00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale tr-TR should correctly format Mantra unit (Mantra) 1`] = `"12.345.678.900,000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale tr-TR should correctly format Metis unit (METIS) 1`] = `"0,012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale tr-TR should correctly format Monero unit (XMR) 1`] = `"12.345,678900000000- -XMR"`; @@ -3110,6 +3128,8 @@ exports[`formatCurrencyUnit with custom options with locale zh-CN should correct exports[`formatCurrencyUnit with custom options with locale zh-CN should correctly format MIX Blockchain unit (MIX) 1`] = `"123,456,789.00000000- -MIX"`; +exports[`formatCurrencyUnit with custom options with locale zh-CN should correctly format Mantra unit (Mantra) 1`] = `"12,345,678,900.000000- -OM"`; + exports[`formatCurrencyUnit with custom options with locale zh-CN should correctly format Metis unit (METIS) 1`] = `"0.012345678900000000- -METIS"`; exports[`formatCurrencyUnit with custom options with locale zh-CN should correctly format Monero unit (XMR) 1`] = `"12,345.678900000000- -XMR"`; @@ -3436,6 +3456,8 @@ exports[`formatCurrencyUnit with default options should correctly format Lukso u exports[`formatCurrencyUnit with default options should correctly format MIX Blockchain unit (MIX) 1`] = `"123,456,789"`; +exports[`formatCurrencyUnit with default options should correctly format Mantra unit (Mantra) 1`] = `"12,345,678,900"`; + exports[`formatCurrencyUnit with default options should correctly format Metis unit (METIS) 1`] = `"0.0123456"`; exports[`formatCurrencyUnit with default options should correctly format Monero unit (XMR) 1`] = `"12,345.6"`; diff --git a/libs/ledger-live-common/src/families/cosmos/datasets/__snapshots__/mantra.integration.test.ts.snap b/libs/ledger-live-common/src/families/cosmos/datasets/__snapshots__/mantra.integration.test.ts.snap new file mode 100644 index 000000000000..9180ecd83478 --- /dev/null +++ b/libs/ledger-live-common/src/families/cosmos/datasets/__snapshots__/mantra.integration.test.ts.snap @@ -0,0 +1,143 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`mantra currency bridge scanAccounts mantra seed 1 1`] = ` +[ + { + "balance": "715363", + "currencyId": "mantra", + "derivationMode": "", + "freshAddress": "mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn", + "freshAddressPath": "44'/118'/0'/0/0", + "id": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:", + "index": 0, + "pendingOperations": [], + "seedIdentifier": "03d5e0ebb3f1ae2afe87e5d5a24b5029a59cc12f8fd1056840091b2f0b97e54e83", + "spendableBalance": "215363", + "swapHistory": [], + "syncHash": undefined, + "used": true, + "xpub": "mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn", + }, + { + "balance": "0", + "currencyId": "mantra", + "derivationMode": "", + "freshAddress": "mantra1v2mp0m7k96dm9qv60fkspcqlzpkzrwnefwef05", + "freshAddressPath": "44'/118'/1'/0/0", + "id": "js:2:mantra:mantra1v2mp0m7k96dm9qv60fkspcqlzpkzrwnefwef05:", + "index": 1, + "pendingOperations": [], + "seedIdentifier": "03d5e0ebb3f1ae2afe87e5d5a24b5029a59cc12f8fd1056840091b2f0b97e54e83", + "spendableBalance": "0", + "swapHistory": [], + "syncHash": undefined, + "used": false, + "xpub": "mantra1v2mp0m7k96dm9qv60fkspcqlzpkzrwnefwef05", + }, +] +`; + +exports[`mantra currency bridge scanAccounts mantra seed 1 2`] = ` +[ + [ + { + "accountId": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:", + "blockHash": null, + "blockHeight": 446099, + "extra": {}, + "fee": "1950", + "hasFailed": false, + "hash": "4855629335DD67EEB42CC089311697D7F5FAE587CD7E33F81E0AAE5227B4FB8F", + "id": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:-4855629335DD67EEB42CC089311697D7F5FAE587CD7E33F81E0AAE5227B4FB8F-IN", + "recipients": [ + "mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn", + ], + "senders": [ + "mantra1g84934jpu3v5de5yqukkkhxmcvsw3u2aedx9w9", + ], + "transactionSequenceNumber": 6, + "type": "IN", + "value": "1000000", + }, + { + "accountId": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:", + "blockHash": null, + "blockHeight": 446137, + "extra": {}, + "fee": "1949", + "hasFailed": false, + "hash": "8F9934B90FC0006941F24FA783970CCC6480F991725E8D7A0BFDB3E917DECCB0", + "id": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:-8F9934B90FC0006941F24FA783970CCC6480F991725E8D7A0BFDB3E917DECCB0-OUT", + "recipients": [ + "mantra1g84934jpu3v5de5yqukkkhxmcvsw3u2aedx9w9", + ], + "senders": [ + "mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn", + ], + "transactionSequenceNumber": 1, + "type": "OUT", + "value": "301949", + }, + { + "accountId": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:", + "blockHash": null, + "blockHeight": 446147, + "extra": { + "memo": "Ledger Live", + }, + "fee": "2385", + "hasFailed": false, + "hash": "AAC85BCAA8EB83298CABABB6A6574082C056092C7139FD8C8ED8849A207B8C8A", + "id": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:-AAC85BCAA8EB83298CABABB6A6574082C056092C7139FD8C8ED8849A207B8C8A-REWARD", + "recipients": [], + "senders": [], + "transactionSequenceNumber": 2, + "type": "REWARD", + "value": "0", + }, + { + "accountId": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:", + "blockHash": null, + "blockHeight": 446122, + "extra": { + "memo": "Ledger Live", + "validators": [ + { + "address": "mantravaloper1y8hxa8q0qk6h2fxtugkx67re38k03888eeqmpd", + "amount": "500000", + }, + ], + }, + "fee": "2906", + "hasFailed": false, + "hash": "B1FE340869D47C458F2B6CCD6029E9996B3CC957BE01E8426A7686E50B2987B4", + "id": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:-B1FE340869D47C458F2B6CCD6029E9996B3CC957BE01E8426A7686E50B2987B4-DELEGATE", + "recipients": [], + "senders": [], + "transactionSequenceNumber": 0, + "type": "DELEGATE", + "value": "2906", + }, + { + "accountId": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:", + "blockHash": null, + "blockHeight": 445531, + "extra": {}, + "fee": "2125", + "hasFailed": false, + "hash": "E6FA7ACE758FE1C371CDE0503651D07D3F25F65BE2A57B642CC5F3B3D6A3A5F7", + "id": "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:-E6FA7ACE758FE1C371CDE0503651D07D3F25F65BE2A57B642CC5F3B3D6A3A5F7-IN", + "recipients": [ + "mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn", + ], + "senders": [ + "mantra1g84934jpu3v5de5yqukkkhxmcvsw3u2aedx9w9", + ], + "transactionSequenceNumber": 5, + "type": "IN", + "value": "20000", + }, + ], + [], +] +`; diff --git a/libs/ledger-live-common/src/families/cosmos/datasets/mantra.integration.test.ts b/libs/ledger-live-common/src/families/cosmos/datasets/mantra.integration.test.ts new file mode 100644 index 000000000000..6461577f5410 --- /dev/null +++ b/libs/ledger-live-common/src/families/cosmos/datasets/mantra.integration.test.ts @@ -0,0 +1,14 @@ +import { DatasetTest } from "@ledgerhq/types-live"; +import { testBridge } from "../../../__tests__/test-helpers/bridge"; +import "../../../__tests__/test-helpers/setup"; +import type { Transaction } from "../types"; +import mantra from "./mantra"; + +const dataset: DatasetTest = { + implementations: ["js"], + currencies: { + mantra, + }, +}; + +testBridge(dataset); diff --git a/libs/ledger-live-common/src/families/cosmos/datasets/mantra.ts b/libs/ledger-live-common/src/families/cosmos/datasets/mantra.ts new file mode 100644 index 000000000000..4e80fdf421c2 --- /dev/null +++ b/libs/ledger-live-common/src/families/cosmos/datasets/mantra.ts @@ -0,0 +1,70 @@ +import { fromTransactionRaw } from "@ledgerhq/coin-cosmos/transaction"; +import { CurrenciesData } from "@ledgerhq/types-live"; +import { BigNumber } from "bignumber.js"; +import type { Transaction } from "../types"; + +const dataset: CurrenciesData = { + FIXME_ignoreAccountFields: ["cosmosResources", "operationsCount", "operations"], + FIXME_ignorePreloadFields: ["validators"], // the APY of validators changes over time + scanAccounts: [ + { + name: "mantra seed 1", + apdus: ` + => 550400001b066d616e7472612c00008076000080000000800000000000000000 + <= 03d5e0ebb3f1ae2afe87e5d5a24b5029a59cc12f8fd1056840091b2f0b97e54e836d616e7472613167796175766c3434713261706e33753361756a6d333671387a726a3734767279376e356e766e9000 + => 550400001b066d616e7472612c00008076000080000000800000000000000000 + <= 03d5e0ebb3f1ae2afe87e5d5a24b5029a59cc12f8fd1056840091b2f0b97e54e836d616e7472613167796175766c3434713261706e33753361756a6d333671387a726a3734767279376e356e766e9000 + => 550400001b066d616e7472612c00008076000080010000800000000000000000 + <= 02c8f29e73a2c99d11de0544615a87afc6c6575d22746af18a8ef733066f088b1f6d616e7472613176326d70306d376b3936646d3971763630666b737063716c7a706b7a72776e656677656630359000 + `, + }, + ], + accounts: [ + { + FIXME_tests: ["balance is sum of ops", "pendingOperations are cleaned up"], + raw: { + id: "js:2:mantra:mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn:", + seedIdentifier: "03d5e0ebb3f1ae2afe87e5d5a24b5029a59cc12f8fd1056840091b2f0b97e54e83", + xpub: "mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn", + derivationMode: "", + index: 0, + freshAddress: "mantra1gyauvl44q2apn3u3aujm36q8zrj74vry7n5nvn", + freshAddressPath: "44'/118'/0'/0/0", + name: "Mantra 1 - Nano X", + blockHeight: 446179, + balance: "715363", + spendableBalance: "215363", + operations: [], + operationsCount: 5, + pendingOperations: [], + currencyId: "mantra", + lastSyncDate: "", + }, + transactions: [ + { + name: "Normal transaction", + transaction: fromTransactionRaw({ + amount: "10000", + recipient: "mantra108uy5q9jt59gwugq5yrdhkzcd9jryslm2n604w", + useAllAmount: false, + family: "cosmos", + mode: "send", + networkInfo: null, + fees: "8744", + gas: "87440", + validators: [], + memo: "", + sourceValidator: "", + }), + expectedStatus: () => ({ + errors: {}, + warnings: {}, + amount: BigNumber("10000"), + }), + }, + ], + }, + ], +}; + +export default dataset; diff --git a/libs/ledger-live-common/src/featureFlags/defaultFeatures.ts b/libs/ledger-live-common/src/featureFlags/defaultFeatures.ts index 1821b3bbbedc..bb83c156a9b6 100644 --- a/libs/ledger-live-common/src/featureFlags/defaultFeatures.ts +++ b/libs/ledger-live-common/src/featureFlags/defaultFeatures.ts @@ -80,6 +80,7 @@ export const CURRENCY_DEFAULT_FEATURES = { currencyIcon: DEFAULT_FEATURE, currencyTon: DEFAULT_FEATURE, currencyEtherlink: DEFAULT_FEATURE, + currencyMantra: DEFAULT_FEATURE, }; /** diff --git a/libs/ledgerjs/packages/types-live/src/feature.ts b/libs/ledgerjs/packages/types-live/src/feature.ts index 408842b58745..b389d175a946 100644 --- a/libs/ledgerjs/packages/types-live/src/feature.ts +++ b/libs/ledgerjs/packages/types-live/src/feature.ts @@ -121,6 +121,7 @@ export type CurrencyFeatures = { currencyIcon: DefaultFeature; currencyTon: DefaultFeature; currencyEtherlink: DefaultFeature; + currencyMantra: DefaultFeature; }; /** diff --git a/libs/ui/packages/crypto-icons/src/svg/OM.svg b/libs/ui/packages/crypto-icons/src/svg/OM.svg index d57313e3fabc..a37c03c4b34f 100644 --- a/libs/ui/packages/crypto-icons/src/svg/OM.svg +++ b/libs/ui/packages/crypto-icons/src/svg/OM.svg @@ -1,3 +1,17 @@ - - + + + + + + +