Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: injective integration #4583

Merged
merged 4 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/lemon-taxis-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@ledgerhq/types-cryptoassets": minor
"@ledgerhq/cryptoassets": minor
"@ledgerhq/types-live": minor
"ledger-live-desktop": minor
"live-mobile": minor
"@ledgerhq/live-common": minor
"@ledgerhq/live-cli": minor
---

Integrate injective + gas rework
1 change: 1 addition & 0 deletions apps/cli/src/live-common-setup-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ setSupportedCurrencies([
"stacks",
"telos_evm",
"coreum",
"injective",
]);

for (const k in process.env) setEnvUnsafe(k as EnvName, process.env[k]);
Expand Down
3 changes: 2 additions & 1 deletion apps/ledger-live-desktop/cryptoassets.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- this file is generated by generate-cryptoassets-md.test.ts -->
# Supported crypto assets
## Crypto currencies (135)
## Crypto currencies (136)
| name | ticker | supported on Ledger Live? | ledger id |
|--|--|--|--|
| Algorand | ALGO | YES | algorand |
Expand Down Expand Up @@ -35,6 +35,7 @@
| Flare | FLR | YES | flare |
| Hedera | HBAR | YES | hedera |
| Horizen | ZEN | YES | zencash |
| Injective | INJ | YES | injective |
| Internet Computer | ICP | YES | internet_computer |
| Kava EVM | KAVA | YES | kava_evm |
| Klaytn | KLAY | YES | klaytn |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,5 @@ setSupportedCurrencies([
"stacks",
"telos_evm",
"coreum",
"injective",
]);
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const StepChooseCurrency = ({ currency, setCurrency }: StepProps) => {
const baseGoerli = useFeature("currencyBaseGoerli");
const klaytn = useFeature("currencyKlaytn");
const mock = useEnv("MOCK");
const injective = useFeature("currencyInjective");

const featureFlaggedCurrencies = useMemo(
(): Partial<Record<CryptoCurrencyId, Feature<unknown> | null>> => ({
Expand Down Expand Up @@ -103,6 +104,7 @@ const StepChooseCurrency = ({ currency, setCurrency }: StepProps) => {
base,
base_goerli: baseGoerli,
klaytn,
injective,
}),
[
axelar,
Expand Down Expand Up @@ -138,6 +140,7 @@ const StepChooseCurrency = ({ currency, setCurrency }: StepProps) => {
base,
baseGoerli,
klaytn,
injective,
],
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useCallback, memo } from "react";
import { useHistory } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { accountsSelector } from "~/renderer/reducers/accounts";
import styled, { CSSProperties } from "styled-components";
import styled from "styled-components";
import { Flex, Text, Icon } from "@ledgerhq/react-ui";
import FormattedVal from "~/renderer/components/FormattedVal";
import { setTrackingSource } from "~/renderer/analytics/TrackPage";
Expand Down Expand Up @@ -42,7 +42,7 @@ const EllipsisText = styled(Text)`
type Props = {
currency?: CurrencyData | null;
counterCurrency?: string;
style: CSSProperties;
style: React.CSSProperties;
loading: boolean;
locale: string;
isStarred: boolean;
Expand Down
4 changes: 4 additions & 0 deletions apps/ledger-live-desktop/static/i18n/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -5338,6 +5338,10 @@
"title": "Action rejected",
"description": "User rejected the operation on the device"
},
"ExpertModeRequired": {
"title": "Expert mode required",
"description": "Expert mode needs to be enabled."
},
"TransactionRefusedOnDevice": {
"title": "Operation denied on device",
"description": "Please retry or contact Ledger Support if in doubt"
Expand Down
1 change: 1 addition & 0 deletions apps/ledger-live-mobile/src/live-common-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ setSupportedCurrencies([
"stacks",
"telos_evm",
"coreum",
"injective",
]);

if (Config.VERBOSE) {
Expand Down
4 changes: 4 additions & 0 deletions apps/ledger-live-mobile/src/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,10 @@
"title": "Operation canceled on device",
"description": "You rejected the operation on the device."
},
"ExpertModeRequired": {
"title": "Expert mode required",
"description": "Expert mode needs to be enabled."
},
"WebsocketConnectionError": {
"title": "Sorry, connection failed",
"description": "Please try again with a better network connection (websocket error)."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export default function AddAccountsSelectCrypto({ navigation, route }: Props) {
const baseGoerli = useFeature("currencyBaseGoerli");
const klaytn = useFeature("currencyKlaytn");
const mock = useEnv("MOCK");
const injective = useFeature("currencyInjective");
const featureFlaggedCurrencies = useMemo(
(): Partial<Record<CryptoCurrencyId, Feature<unknown> | null>> => ({
axelar,
Expand Down Expand Up @@ -123,6 +124,7 @@ export default function AddAccountsSelectCrypto({ navigation, route }: Props) {
base,
base_goerli: baseGoerli,
klaytn,
injective,
}),
[
axelar,
Expand Down Expand Up @@ -158,6 +160,7 @@ export default function AddAccountsSelectCrypto({ navigation, route }: Props) {
base,
baseGoerli,
klaytn,
injective,
],
);

Expand Down
2 changes: 2 additions & 0 deletions libs/coin-framework/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@
"rxjs": "^6.6.7"
},
"devDependencies": {
"@ledgerhq/hw-transport-node-speculos": "workspace:^",
"@ledgerhq/hw-transport-node-speculos-http": "workspace:^",
"@types/invariant": "^2.2.2",
"@types/jest": "^29.2.4",
"@types/lodash": "^4.14.191",
Expand Down
10 changes: 10 additions & 0 deletions libs/coin-framework/src/bot/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import {
import { BigNumber } from "bignumber.js";
import { SpeculosButton } from "./specs";

import type SpeculosTransportHttp from "@ledgerhq/hw-transport-node-speculos-http";
import type SpeculosTransportWebsocket from "@ledgerhq/hw-transport-node-speculos";
export type SpeculosTransport = SpeculosTransportHttp | SpeculosTransportWebsocket;

// Type coming from live-common/src/load/speculos.ts
export type AppCandidate = {
path: string;
Expand Down Expand Up @@ -147,6 +151,12 @@ export type AppSpec<T extends TransactionCommon> = {
allowEmptyAccounts?: boolean;
// do not keep operations in accounts (Cosmos family case)
skipOperationHistory?: boolean;
// executed when speculos device is created, used for example to enable expert mode on cosmos nano app
onSpeculosDeviceCreated?: (device: {
hedi-edelbloute marked this conversation as resolved.
Show resolved Hide resolved
transport: SpeculosTransport;
id: string;
appPath: string;
}) => Promise<void>;
};
export type SpecReport<T extends TransactionCommon> = {
spec: AppSpec<T>;
Expand Down
2 changes: 1 addition & 1 deletion libs/env/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const envDefinitions = {
desc: "Node endpoint for celo",
},
COSMOS_GAS_AMPLIFIER: {
def: 1.2,
def: 1.5,
parser: intParser,
desc: "Cosmos gas estimate multiplier",
},
Expand Down
8 changes: 3 additions & 5 deletions libs/ledger-live-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,9 @@
"@celo/utils": "^3.0.1",
"@celo/wallet-base": "^3.0.1",
"@celo/wallet-ledger": "^3.0.1",
"@cosmjs/amino": "^0.28.4",
"@cosmjs/crypto": "^0.26.5",
"@cosmjs/launchpad": "^0.26.5",
"@cosmjs/ledger-amino": "^0.26.5",
"@cosmjs/proto-signing": "^0.26.5",
"@cosmjs/crypto": "^0.31.0",
"@cosmjs/stargate": "^0.26.5",
"@cosmjs/amino": "^0.31.1",
"@crypto-org-chain/chain-jslib": "1.1.2",
"@dfinity/agent": "^0.15.6",
"@dfinity/candid": "^0.15.6",
Expand Down Expand Up @@ -188,6 +185,7 @@
"@xstate/react": "^1.6.3",
"@zondax/cbor": "v8.1.0-zondax-no-bigint",
"@zondax/izari-filecoin": "^1.2.0",
"@zondax/ledger-cosmos-js": "^3.0.3",
"@zondax/ledger-filecoin": "^0.11.2",
"@zondax/ledger-icp": "^0.7.0",
"@zondax/ledger-stacks": "^1.0.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ setSupportedCurrencies([
"stacks",
"telos_evm",
"coreum",
"injective",
]);

for (const k in process.env) setEnvUnsafe(k as EnvName, process.env[k]);
Expand Down
6 changes: 6 additions & 0 deletions libs/ledger-live-common/src/bot/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ export async function runWithAppSpec<T extends Transaction>(
try {
device = await createSpeculosDevice(deviceParams);
appReport.appPath = device.appPath;
if (spec.onSpeculosDeviceCreated) {
await spec.onSpeculosDeviceCreated(device);
}
const bridge = getCurrencyBridge(currency);
const syncConfig = {
paginationConfig: {},
Expand Down Expand Up @@ -300,6 +303,9 @@ export async function runWithAppSpec<T extends Transaction>(
);
await releaseSpeculosDevice(device.id);
device = await createSpeculosDevice(deviceParams);
if (spec.onSpeculosDeviceCreated) {
await spec.onSpeculosDeviceCreated(device);
}
}
}
mutationsCount = {};
Expand Down
4 changes: 4 additions & 0 deletions libs/ledger-live-common/src/config/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ const defaultConfig = {
lcd: "https://full-node.mainnet-1.coreum.dev:1317",
minGasPrice: 0.1,
},
injective: {
lcd: "https://injective-api.polkachu.com",
minGasPrice: 900000000,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the the low gas price for keplr is
higher than ours. Can you confirm that this value is enough?
https://github.com/chainapsis/keplr-wallet/blob/04f394ac30a8c5923f01dad0a4fb5ff6f8faee47/packages/extension/src/config.ts#L1918

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any definitive answer here?
What do you think is the better source of truth between chain-registry and kepler?

Copy link
Member Author

@hedi-edelbloute hedi-edelbloute Sep 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't change it as I had failing txs with 700000000 (but maybe it was due to other things since it was early testing...), and fees are already low dollar wise

},
} as { [currency: string]: CosmosCurrencyConfig },
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,7 @@ Array [
"stride",
"umee",
"internet_computer",
"injective",
"arbitrum",
"cronos",
"flare",
Expand Down
16 changes: 16 additions & 0 deletions libs/ledger-live-common/src/data/icons/svg/INJ.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 64 additions & 8 deletions libs/ledger-live-common/src/families/cosmos/api/Cosmos.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import network from "@ledgerhq/live-network/network";
import { AxiosResponse } from "axios";
import BigNumber from "bignumber.js";
import cryptoFactory from "../chain/chain";
import { CosmosAPI } from "./Cosmos";
jest.mock("@ledgerhq/live-network/network");
const mockedNetwork = jest.mocked(network);

describe("CosmosApi", () => {
let cosmosApi: CosmosAPI;
Expand All @@ -14,36 +17,89 @@ describe("CosmosApi", () => {
jest.resetAllMocks();
});

describe("getAccount", () => {
it("should return base_account if available", async () => {
mockedNetwork.mockResolvedValue({
data: {
account: {
account_number: 1,
sequence: 0,
pub_key: { key: "k", "@type": "type" },
base_account: {
account_number: 2,
sequence: 42,
pub_key: { key: "k2", "@type": "type2" },
},
},
},
} as AxiosResponse);

const account = await cosmosApi.getAccount("addr");
expect(account.accountNumber).toEqual(2);
expect(account.sequence).toEqual(42);
expect(account.pubKey).toEqual("k2");
expect(account.pubKeyType).toEqual("type2");
});

it("should return account if base_account isn't available", async () => {
mockedNetwork.mockResolvedValue({
data: {
account: { account_number: 1, sequence: 0, pub_key: { key: "k", "@type": "type" } },
},
} as AxiosResponse);

const account = await cosmosApi.getAccount("addr");
expect(account.accountNumber).toEqual(1);
expect(account.sequence).toEqual(0);
expect(account.pubKey).toEqual("k");
expect(account.pubKeyType).toEqual("type");
});

it("should return default sequence value if network fails", async () => {
mockedNetwork.mockImplementation(() => {
throw new Error();
});
const account = await cosmosApi.getAccount("addr");
expect(account.sequence).toEqual(0);
});

it("should return default pubkeytype value if network fails", async () => {
mockedNetwork.mockImplementation(() => {
throw new Error();
});
const account = await cosmosApi.getAccount("addr");
expect(account.pubKeyType).toEqual(cryptoFactory("cosmos").defaultPubKeyType);
});
});

describe("simulate", () => {
it("should return gas used when the network call returns gas used", async () => {
// @ts-expect-error method is mocked
network.mockResolvedValue({
mockedNetwork.mockResolvedValue({
data: {
gas_info: {
gas_used: 42000,
},
},
});
} as AxiosResponse);
const gas = await cosmosApi.simulate([]);
expect(gas).toEqual(new BigNumber(42000));
});

it("should throw an error when the network call does not return gas used", async () => {
// @ts-expect-error method is mocked
network.mockResolvedValue({
mockedNetwork.mockResolvedValue({
data: { gas_info: {} },
});
} as AxiosResponse);
await expect(cosmosApi.simulate([])).rejects.toThrowError();
});

it("should throw an error when the network call fails", async () => {
// @ts-expect-error method is mocked
network.mockImplementation(() => {
mockedNetwork.mockImplementation(() => {
throw new Error();
});
await expect(cosmosApi.simulate([])).rejects.toThrowError();
});
});

describe("getTransactions", () => {
it("should return an empty array when network call fails", async () => {
// @ts-expect-error method is mocked
Expand Down
Loading
Loading