Skip to content

Commit

Permalink
chore: add evm mock test
Browse files Browse the repository at this point in the history
  • Loading branch information
hzheng-ledger committed Aug 15, 2023
1 parent 46f0f99 commit ba7a41b
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const StepChooseCurrency = ({ currency, setCurrency }: StepProps) => {
const base = useFeature("currencyBase");
const baseGoerli = useFeature("currencyBaseGoerli");
const klaytn = useFeature("currencyKlaytn");

const mock = useEnv("MOCK");
const featureFlaggedCurrencies = useMemo(
() => ({
// Keys in this list must match an existing currency.id
Expand Down Expand Up @@ -141,11 +141,13 @@ const StepChooseCurrency = ({ currency, setCurrency }: StepProps) => {
const currencies = (listSupportedCurrencies() as CryptoOrTokenCurrency[]).concat(
listSupportedTokens(),
);
const deactivatedCurrencies = Object.entries(featureFlaggedCurrencies)
.filter(([, feature]) => !feature?.enabled)
.map(([name]) => name);
const deactivatedCurrencies = mock
? []
: Object.entries(featureFlaggedCurrencies)
.filter(([, feature]) => !feature?.enabled)
.map(([name]) => name);
return currencies.filter(c => !deactivatedCurrencies.includes(c.id));
}, [featureFlaggedCurrencies]);
}, [featureFlaggedCurrencies, mock]);
const url =
currency && currency.type === "TokenCurrency"
? supportLinkByTokenType[currency.tokenType as keyof typeof supportLinkByTokenType]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { StepProps } from "..";
import { getEnv } from "@ledgerhq/live-common/env";
import { mockedEventEmitter } from "~/renderer/components/debug/DebugMock";
import connectApp from "@ledgerhq/live-common/hw/connectApp";
if (getEnv("MOCK")) {
window.mock.events.mockDeviceEvent({ type: "opened" });
}
const action = createAction(getEnv("MOCK") ? mockedEventEmitter : connectApp);
const StepConnectDevice = ({ currency, transitionTo, flow }: StepProps) => {
invariant(currency, "No crypto asset given");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { AccountsPage } from "../../models/AccountsPage";

test.use({ userdata: "skip-onboarding" });

const currencies = ["BTC", "LTC", "ETH", "ATOM", "XTZ", "XRP", "Tron"];
const currencies = ["BTC", "LTC", "ETH", "ATOM", "XTZ", "XRP", "Tron", "optimism", "kava evm"];

test.describe.parallel("Accounts @smoke", () => {
for (const currency of currencies) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export default function AddAccountsSelectCrypto({ navigation, route }: Props) {
const base = useFeature("currencyBase");
const baseGoerli = useFeature("currencyBaseGoerli");
const klaytn = useFeature("currencyKlaytn");

const mock = useEnv("MOCK");
const featureFlaggedCurrencies = useMemo(
() => ({
// Keys in this list must match an existing currency.id
Expand Down Expand Up @@ -165,17 +165,19 @@ export default function AddAccountsSelectCrypto({ navigation, route }: Props) {
const currencies = [...listSupportedCurrencies(), ...listSupportedTokens()].filter(
({ id }) => filterCurrencyIds.length <= 0 || filterCurrencyIds.includes(id),
);
const deactivatedCurrencies = Object.entries(featureFlaggedCurrencies)
.filter(([, feature]) => !feature?.enabled)
.map(([name]) => name);
const deactivatedCurrencies = mock
? []
: Object.entries(featureFlaggedCurrencies)
.filter(([, feature]) => !feature?.enabled)
.map(([name]) => name);

const currenciesFiltered = currencies.filter(c => !deactivatedCurrencies.includes(c.id));

if (!devMode) {
return currenciesFiltered.filter(c => c.type !== "CryptoCurrency" || !c.isTestnetFor);
}
return currenciesFiltered;
}, [devMode, featureFlaggedCurrencies, filterCurrencyIds]);
}, [devMode, featureFlaggedCurrencies, filterCurrencyIds, mock]);

const sortedCryptoCurrencies = useCurrenciesByMarketcap(cryptoCurrencies);

Expand Down
6 changes: 6 additions & 0 deletions libs/coin-framework/src/mocks/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ const hardcodedMarketcap = [
"qtum",
"ethereum/erc20/huobitoken",
"bitcoin_gold",
"kava_evm",
"optimism",
"ethereum/erc20/paxos_standard__pax_",
"ethereum/erc20/trueusd",
"ethereum/erc20/omg",
Expand Down Expand Up @@ -177,6 +179,10 @@ const currencyIdApproxMarketPrice: Record<string, number> = {
dash: 0.0003367,
peercoin: 0.000226,
zcash: 0.000205798,
polygon: 1.0e-15,
bsc: 5.0e-14,
optimism: 2.0e-15,
kava_evm: 2.0e-16,
};
// mock only use subset of cryptocurrencies to not affect tests when adding coins
const currencies = listCryptoCurrencies().filter(c => currencyIdApproxMarketPrice[c.id]);
Expand Down
2 changes: 1 addition & 1 deletion libs/coin-framework/src/mocks/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function genHex(length: number, rng: Prando): string {
export function genAddress(currency: CryptoCurrency | TokenCurrency, rng: Prando): string {
if (
currency.type === "CryptoCurrency"
? currency.family === "ethereum" // all eth family
? currency.family === "ethereum" || currency.family === "evm" // all evm family
: currency.id.startsWith("ethereum") // erc20 case
) {
return `0x${genHex(40, rng)}`;
Expand Down
114 changes: 114 additions & 0 deletions libs/ledger-live-common/src/families/evm/bridge/mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { BigNumber } from "bignumber.js";
import { NotEnoughBalance, RecipientRequired } from "@ledgerhq/errors";
import type { Transaction } from "@ledgerhq/coin-evm/types/index";
import type { AccountBridge, CurrencyBridge } from "@ledgerhq/types-live";
import { getMainAccount } from "../../../account";
import {
scanAccounts,
signOperation,
broadcast,
sync,
makeAccountBridgeReceive,
} from "../../../bridge/mockHelpers";
import { defaultUpdateTransaction } from "@ledgerhq/coin-framework/bridge/jsHelpers";
import { getGasLimit } from "@ledgerhq/coin-evm/logic";
import { getTypedTransaction } from "@ledgerhq/coin-evm/transaction";
const receive = makeAccountBridgeReceive();

const defaultGetFees = (_a, t: any) => (t.gasPrice || new BigNumber(0)).times(getGasLimit(t));

const createTransaction = (): Transaction => ({
family: "evm",
mode: "send",
amount: new BigNumber(10000000000),
nonce: 0,
recipient: "",
gasPrice: new BigNumber(10000000000),
gasLimit: new BigNumber(21000),
chainId: 2222,
useAllAmount: false,
subAccountId: null,
});

const estimateMaxSpendable = ({ account, parentAccount, transaction }) => {
const mainAccount = getMainAccount(account, parentAccount);
const estimatedFees = parentAccount
? new BigNumber(0)
: transaction
? defaultGetFees(mainAccount, transaction)
: new BigNumber(1000000000000);
return Promise.resolve(BigNumber.max(0, account.balance.minus(estimatedFees)));
};

const getTransactionStatus = (a, t) => {
const errors: {
amount?: Error;
recipient?: Error;
} = {};
const warnings: {
feeTooHigh?: Error;
gasLimit?: Error;
} = {};
const tokenAccount = !t.subAccountId
? null
: a.subAccounts && a.subAccounts.find(ta => ta.id === t.subAccountId);
const account = tokenAccount || a;
const useAllAmount = !!t.useAllAmount;
const estimatedFees = defaultGetFees(a, t);
const totalSpent = useAllAmount
? account.balance
: tokenAccount
? new BigNumber(t.amount)
: new BigNumber(t.amount).plus(estimatedFees);
const amount = useAllAmount
? tokenAccount
? new BigNumber(t.amount)
: account.balance.minus(estimatedFees)
: new BigNumber(t.amount);

// Fill up transaction errors...
if (totalSpent.gt(account.balance)) {
errors.amount = new NotEnoughBalance();
}
if (!t.recipient) {
errors.recipient = new RecipientRequired("");
}
return Promise.resolve({
errors,
warnings,
estimatedFees,
amount,
totalSpent,
});
};

const prepareTransaction = async (_a, t) => {
const typedTransaction = getTypedTransaction(t, {
gasPrice: new BigNumber(50),
maxFeePerGas: new BigNumber(50),
maxPriorityFeePerGas: new BigNumber(50),
nextBaseFee: new BigNumber(50),
});
return typedTransaction;
};

const accountBridge: AccountBridge<Transaction> = {
createTransaction,
updateTransaction: defaultUpdateTransaction,
getTransactionStatus,
estimateMaxSpendable,
prepareTransaction,
sync,
receive,
signOperation,
broadcast,
};
const currencyBridge: CurrencyBridge = {
preload: () => Promise.resolve({}),
hydrate: () => {},
scanAccounts,
};
export default {
currencyBridge,
accountBridge,
};
2 changes: 2 additions & 0 deletions libs/ledger-live-common/src/generated/bridge/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import algorand from "../../families/algorand/bridge/mock";
import bitcoin from "../../families/bitcoin/bridge/mock";
import cosmos from "../../families/cosmos/bridge/mock";
import ethereum from "../../families/ethereum/bridge/mock";
import evm from "../../families/evm/bridge/mock";
import polkadot from "../../families/polkadot/bridge/mock";
import ripple from "../../families/ripple/bridge/mock";
import solana from "../../families/solana/bridge/mock";
Expand All @@ -14,6 +15,7 @@ export default {
bitcoin,
cosmos,
ethereum,
evm,
polkadot,
ripple,
solana,
Expand Down

0 comments on commit ba7a41b

Please sign in to comment.