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/add xahau xah #6807

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ These packages are deployed to the official npm repository under the `@ledgerhq`
| [**@ledgerhq/hw-app-tezos**](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-app-tezos) | `pnpm ljs:hw-app-tezos` | [ledgerjs](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs) | [![npm](https://img.shields.io/npm/v/@ledgerhq/hw-app-tezos.svg)](https://www.npmjs.com/package/@ledgerhq/hw-app-tezos) |
| [**@ledgerhq/hw-app-trx**](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-app-trx) | `pnpm ljs:hw-app-trx` | [ledgerjs](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs) | [![npm](https://img.shields.io/npm/v/@ledgerhq/hw-app-trx.svg)](https://www.npmjs.com/package/@ledgerhq/hw-app-trx) |
| [**@ledgerhq/hw-app-xrp**](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-app-xrp) | `pnpm ljs:hw-app-xrp` | [ledgerjs](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs) | [![npm](https://img.shields.io/npm/v/@ledgerhq/hw-app-xrp.svg)](https://www.npmjs.com/package/@ledgerhq/hw-app-xrp) |
| [**@ledgerhq/hw-app-xah**](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-app-xah) | `pnpm ljs:hw-app-xah` | [ledgerjs](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs) | [![npm](https://img.shields.io/npm/v/@ledgerhq/hw-app-xah.svg)](https://www.npmjs.com/package/@ledgerhq/hw-app-xah) |
| [**@ledgerhq/hw-transport**](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-transport) | `pnpm ljs:hw-transport` | [ledgerjs](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs) | [![npm](https://img.shields.io/npm/v/@ledgerhq/hw-transport.svg)](https://www.npmjs.com/package/@ledgerhq/hw-transport) |
| [**@ledgerhq/hw-transport-http**](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-transport-http) | `pnpm ljs:hw-transport-http` | [ledgerjs](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs) | [![npm](https://img.shields.io/npm/v/@ledgerhq/hw-transport-http.svg)](https://www.npmjs.com/package/@ledgerhq/hw-transport-http) |
| [**@ledgerhq/hw-transport-mocker**](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-transport-mocker) | `pnpm ljs:hw-transport-mocker` | [ledgerjs](https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs) | [![npm](https://img.shields.io/npm/v/@ledgerhq/hw-transport-mocker.svg)](https://www.npmjs.com/package/@ledgerhq/hw-transport-mocker) |
Expand Down
2 changes: 1 addition & 1 deletion apps/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ Usage: ledger-live generateTestTransaction # Generate a test for transaction (li
--nonce <String> : set a nonce for this transaction
--data <String> : set the transaction data to use for signing the ETH transaction
--fee <String> : how much fee
--tag <Number> : ripple tag
--tag <Number> : ripple/xahau tag
--solanaValidator <String>: validator address to delegate to
--solanaStakeAccount <String>: stake account address to use in the transaction
--memoType <String> : stellar memo type
Expand Down
35,817 changes: 17,908 additions & 17,909 deletions apps/ledger-live-desktop/cryptoassets.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions apps/ledger-live-desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
"winston": "^3.2.1",
"winston-transport": "^4.3.0",
"write-file-atomic": "^5.0.0",
"xrpl-binary-codec-prerelease": "^8.0.1",
Copy link
Member

Choose a reason for hiding this comment

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

I don't see any reference to this in ledger-live-desktop project, why was it added ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for reviewing.

It is a replacement of ripple-binary-codec, where ripple-binary-codec only supports the native XRPL chains, with fixed network definitions: so whenever a new transaction type, field or amendment is introduced, it needs an update - as mentioned @ "Impact of changes" in this PR.

This package (xrpl-binary-codec-prerelease) implements dynamic network definitions as served by both XRPL and other similar protocol chains over RPC, so it can always deal with new TX types fields & netwoks.

The changes to make this possible have been PR'ed into ripple-binary-codec but haven't been merged for ages. Several projects now use xrpl-binary-codec-prerelease and most multi chain wallets with XRPL protocol support are using this one now.

-- See https://www.npmjs.com/package/xrpl-binary-codec-prerelease
XRPLF/xrpl.js@main...WietseWind:xrpl.js:main

(Fork of xrpl.js with the appropriate changes, the monorepo by Rippl)

Actively maintained by me, at https://github.com/xrpl-labs

"xstate": "^4.30.2"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ setSupportedCurrencies([
"polkadot",
"solana",
"ripple",
"xahau",
"litecoin",
"polygon",
"bitcoin_cash",
Expand Down
29 changes: 29 additions & 0 deletions apps/ledger-live-mobile/__mocks__/api/market/markets.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[

Check notice on line 1 in apps/ledger-live-mobile/__mocks__/api/market/markets.json

View check run for this annotation

Ledger Wiz (CSPM & secret detection) / Wiz Data Scanner

Sensitive data found: PII/Financial Metrics

Data Category: PII Data Classifier ID: BUILTIN-413 Sampled Examples: Key: roi/currency/roi/currency Key: roi/currency/roi/currency Key: roi/currency/roi/currency Key: roi/percentage/roi/percentage Key: roi/percentage/roi/percentage
{
"id": "bitcoin",
"symbol": "btc",
Expand Down Expand Up @@ -144,6 +144,35 @@
"last_updated": "2023-12-13T13:16:51.707Z",
"price_change_percentage_1y_in_currency": 47.608929868142205
},
{
"id": "xahau",
"symbol": "xah",
"name": "XAH",
"image": "https://assets.coingecko.com/coins/images/32719/standard/CM-xahau-icon-yellow.png?1699001599",
"current_price": 3.02,
"market_cap": 162907702875,
"market_cap_rank": 5,
"fully_diluted_valuation": 301883057200,
"total_volume": 6842120612,
"high_24h": 3.08,
"low_24h": 2.97,
"price_change_24h": -0.041739604358680626,
"price_change_percentage_24h": -1.36162,
"market_cap_change_24h": -3080276856.0314026,
"market_cap_change_percentage_24h": -1.85572,
"circulating_supply": 53957460767.0,
"total_supply": 99988170772.0,
"max_supply": 100000000000.0,
"ath": 11.16,
"ath_change_percentage": -73.10702,
"ath_date": "2021-04-14T05:40:00.104Z",
"atl": 0.00605732,
"atl_change_percentage": 49462.03668,
"atl_date": "2013-08-16T00:00:00.000Z",
"roi": null,
"last_updated": "2023-12-13T13:16:51.707Z",
"price_change_percentage_1y_in_currency": 47.608929868142205
},
{
"id": "solana",
"symbol": "sol",
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 @@ -54,6 +54,7 @@ setSupportedCurrencies([
"polkadot",
"solana",
"ripple",
"xahau",
"litecoin",
"polygon",
"bitcoin_cash",
Expand Down
1 change: 1 addition & 0 deletions libs/coin-framework/src/mocks/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const currencyIdApproxMarketPrice: Record<string, number> = {
bitcoin_gold: 0.00005004,
litecoin: 0.00011728,
ripple: 0.000057633,
xahau: 0.000057633,
dogecoin: 4.9e-9,
dash: 0.0003367,
peercoin: 0.000226,
Expand Down
5 changes: 5 additions & 0 deletions libs/env/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ const envDefinitions = {
def: "https://xrplcluster.com/ledgerlive",
desc: "XRP Ledger full history open JSON-RPC endpoint",
},
API_XAHAU_RPC: {
parser: stringParser,
def: "https://xahau.org/?r=ledgerlive",
desc: "XAHAU full history open WebSocket/JSON-RPC endpoint",
},
API_FILECOIN_ENDPOINT: {
parser: stringParser,
def: "https://filecoin.coin.ledger.com",
Expand Down
2 changes: 1 addition & 1 deletion libs/ledger-live-common/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ yarn upgrade-interactive -i --latest
| redux | general react helper | monthly |
| reselect | general react helper | monthly |
| ripemd160 | Bitcoin coin integration | monthly |
| ripple-binary-codec | XRP coin integration | monthly |
| xrpl-binary-codec-prerelease | XRP coin & Xahau (XAH coin) integration | monthly |
| ripple-bs58check | XRP coin integration | monthly |
| ripple-lib | XRP coin integration | monthly |
| rlp | Ethereum coin integration | monthly |
Expand Down
3 changes: 2 additions & 1 deletion libs/ledger-live-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
"@ledgerhq/hw-app-trx": "workspace:^",
"@ledgerhq/hw-app-vet": "workspace:^",
"@ledgerhq/hw-app-xrp": "workspace:^",
"@ledgerhq/hw-app-xah": "workspace:^",
"@ledgerhq/hw-transport": "workspace:^",
"@ledgerhq/hw-transport-mocker": "workspace:^",
"@ledgerhq/hw-transport-node-speculos": "workspace:^",
Expand Down Expand Up @@ -230,7 +231,7 @@
"prando": "^6.0.1",
"qs": "^6.10.1",
"reselect": "^4.1.5",
"ripple-binary-codec": "^1.3.0",
"xrpl-binary-codec-prerelease": "^8.0.1",
"ripple-bs58check": "^2.0.2",
"rlp": "^3.0.0",
"rxjs": "^7.8.1",
Expand Down
22 changes: 12 additions & 10 deletions libs/ledger-live-common/src/families/ripple/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ import { getEnv } from "@ledgerhq/live-env";
import { retry } from "../../../promise";
import { NEW_ACCOUNT_ERROR_MESSAGE } from "../bridge/js";

const defaultEndpoint = () => getEnv("API_RIPPLE_RPC");
// TODO: Pick different RPC endpoint if on another XRPL Protocol based chain

export const connectionTimeout = 30 * 1000; // default connectionTimeout is 2s and make the specs bot failed

const rippleUnit = getCryptoCurrencyById("ripple").units[0];

export const parseAPIValue = (value: string): BigNumber => parseCurrencyUnit(rippleUnit, value);

export const submit = async (signature: string): Promise<any> => {
export const submit = async (signature: string, endpoint?: string): Promise<any> => {
console.log('submit', signature, window, endpoint)
const res = await network({
method: "POST",
url: `${defaultEndpoint()}`,
url: endpoint || getEnv("API_RIPPLE_RPC"),
data: {
method: "submit",
params: [
Expand Down Expand Up @@ -47,11 +48,12 @@ type AccountInfo = {
export const getAccountInfo = async (
recipient: string,
current?: boolean,
endpoint?: string,
): Promise<AccountInfo> => {
const res = async () => {
const res = await network({
method: "POST",
url: `${defaultEndpoint()}`,
url: endpoint || getEnv("API_RIPPLE_RPC"),
data: {
method: "account_info",
params: [
Expand All @@ -77,11 +79,11 @@ export const getAccountInfo = async (
});
};

export const getServerInfo = async (endpointConfig?: string | null | undefined): Promise<any> => {
export const getServerInfo = async (endpoint?: string): Promise<any> => {
const res = async () => {
const res = await network({
method: "POST",
url: endpointConfig ?? `${defaultEndpoint()}`,
url: endpoint || getEnv("API_RIPPLE_RPC"),
data: {
method: "server_info",
params: [
Expand All @@ -104,11 +106,11 @@ export const getServerInfo = async (endpointConfig?: string | null | undefined):
});
};

export const getTransactions = async (address: string, options: any | undefined): Promise<any> => {
export const getTransactions = async (address: string, options: any | undefined, endpoint?: string): Promise<any> => {
const res = async () => {
const res = await network({
method: "POST",
url: `${defaultEndpoint()}`,
url: endpoint || getEnv("API_RIPPLE_RPC"),
data: {
method: "account_tx",
params: [
Expand All @@ -132,11 +134,11 @@ export const getTransactions = async (address: string, options: any | undefined)
});
};

export default async function getLedgerIndex(): Promise<number> {
export default async function getLedgerIndex(endpoint?: string): Promise<number> {
const res = async () => {
const ledgerResponse = await network({
method: "POST",
url: `${defaultEndpoint()}`,
url: endpoint || getEnv("API_RIPPLE_RPC"),
data: {
method: "ledger",
params: [
Expand Down
35 changes: 22 additions & 13 deletions libs/ledger-live-common/src/families/ripple/bridge/js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import type {
SignOperationFnSignature,
} from "@ledgerhq/types-live";

import { scanAccounts, sync } from "../js-synchronization";
import { scanAccounts, sync, getEndpoint } from "../js-synchronization";
import type { NetworkInfo, Transaction } from "../types";

export const NEW_ACCOUNT_ERROR_MESSAGE = "actNotFound";
Expand All @@ -48,7 +48,7 @@ const validateTag = tag => {
};

const getNextValidSequence = async (account: Account) => {
const accInfo = await getAccountInfo(account.freshAddress, true);
const accInfo = await getAccountInfo(account.freshAddress, true, getEndpoint(account.currency.id));
return accInfo.account_data.Sequence;
};

Expand All @@ -64,16 +64,22 @@ const signOperation: SignOperationFnSignature<Transaction> = ({ account, transac
try {
const tag = transaction.tag ? transaction.tag : undefined;
const nextSequenceNumber = await getNextValidSequence(account);
const NetworkID = // XRPL mainnet = 0, other networks may need NetworkID
transaction.networkInfo?.networkId || 0 > 1024
? transaction.networkInfo?.networkId
: undefined;

const payment = {
TransactionType: "Payment",
Account: account.freshAddress,
Amount: transaction.amount.toString(),
Destination: transaction.recipient,
DestinationTag: tag,
Fee: fee.toString(),
NetworkID,
Flags: 2147483648,
Sequence: nextSequenceNumber,
LastLedgerSequence: (await getLedgerIndex()) + LEDGER_OFFSET,
LastLedgerSequence: (await getLedgerIndex(getEndpoint(account.currency.id))) + LEDGER_OFFSET,
};
if (tag)
invariant(
Expand Down Expand Up @@ -110,7 +116,9 @@ const signOperation: SignOperationFnSignature<Transaction> = ({ account, transac
recipients: [transaction.recipient],
date: new Date(),
transactionSequenceNumber: nextSequenceNumber,
extra: {},
extra: {
currencyId: account.currency.id
},
};

o.next({
Expand All @@ -137,7 +145,7 @@ const signOperation: SignOperationFnSignature<Transaction> = ({ account, transac
);

const broadcast = async ({ signedOperation: { signature, operation } }): Promise<Operation> => {
const submittedPayment = await submit(signature);
const submittedPayment = await submit(signature, getEndpoint(operation.extra.currencyId));

if (
submittedPayment.engine_result !== "tesSUCCESS" &&
Expand All @@ -159,10 +167,10 @@ function isRecipientValid(recipient: string): boolean {
}
}

const recipientIsNew = async (recipient: string): Promise<boolean> => {
const recipientIsNew = async (recipient: string, account: Account): Promise<boolean> => {
if (!isRecipientValid(recipient)) return false;

const info = await getAccountInfo(recipient);
const info = await getAccountInfo(recipient, undefined, getEndpoint(account.currency.id));
if (info.error === NEW_ACCOUNT_ERROR_MESSAGE) {
return true;
}
Expand All @@ -182,9 +190,9 @@ const remapError = error => {

const cacheRecipientsNew = {};

const cachedRecipientIsNew = (recipient: string) => {
const cachedRecipientIsNew = (recipient: string, account: Account) => {
if (recipient in cacheRecipientsNew) return cacheRecipientsNew[recipient];
cacheRecipientsNew[recipient] = recipientIsNew(recipient);
cacheRecipientsNew[recipient] = recipientIsNew(recipient, account);
return cacheRecipientsNew[recipient];
};

Expand All @@ -209,11 +217,12 @@ const prepareTransaction = async (a: Account, t: Transaction): Promise<Transacti

if (!networkInfo) {
try {
const info = await getServerInfo();
const info = await getServerInfo(getEndpoint(a.currency.id));
const serverFee = parseAPIValue(info.info.validated_ledger.base_fee_xrp.toString());
networkInfo = {
family: "ripple",
serverFee,
networkId: info.info?.network_id || 0,
baseReserve: new BigNumber(0), // NOT USED. will refactor later.
};
} catch (e) {
Expand All @@ -239,7 +248,7 @@ const getTransactionStatus = async (a: Account, t: Transaction) => {
const warnings: {
feeTooHigh?: Error;
} = {};
const r = await getServerInfo();
const r = await getServerInfo(getEndpoint(a.currency.id));
const reserveBaseXRP = parseAPIValue(r.info.validated_ledger.reserve_base_xrp.toString());
const estimatedFees = new BigNumber(t.fee || 0);
const totalSpent = new BigNumber(t.amount).plus(estimatedFees);
Expand All @@ -263,7 +272,7 @@ const getTransactionStatus = async (a: Account, t: Transaction) => {
});
} else if (
t.recipient &&
(await cachedRecipientIsNew(t.recipient)) &&
(await cachedRecipientIsNew(t.recipient, a)) &&
t.amount.lt(reserveBaseXRP)
) {
errors.amount = new NotEnoughBalanceBecauseDestinationNotCreated("", {
Expand Down Expand Up @@ -308,7 +317,7 @@ const estimateMaxSpendable = async ({
transaction,
}): Promise<BigNumber> => {
const mainAccount = getMainAccount(account, parentAccount);
const r = await getServerInfo();
const r = await getServerInfo(getEndpoint(account));
const reserveBaseXRP = parseAPIValue(r.info.validated_ledger.reserve_base_xrp.toString());
const t = await prepareTransaction(mainAccount, {
...createTransaction(),
Expand Down
3 changes: 2 additions & 1 deletion libs/ledger-live-common/src/families/ripple/exchange.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { bip32asBuffer } from "../../crypto";
import { normalizeXrplProtocolPath } from "@ledgerhq/hw-app-xah";

const getSerializedAddressParameters = (
path: string,
): {
addressParameters: Buffer;
} => {
const addressParameters = bip32asBuffer(path);
const addressParameters = bip32asBuffer(normalizeXrplProtocolPath(path));
return {
addressParameters,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import Xrp from "@ledgerhq/hw-app-xrp";
import type { Resolver } from "../../hw/getAddress/types";
import { normalizeXrplProtocolPath } from "@ledgerhq/hw-app-xah";

const resolver: Resolver = async (transport, { path, verify, askChainCode }) => {
const xrp = new Xrp(transport);
const { address, publicKey, chainCode } = await xrp.getAddress(
path,
normalizeXrplProtocolPath(path),
verify,
askChainCode || false,
);
return {
path,
path: normalizeXrplProtocolPath(path),
address,
publicKey,
chainCode,
Expand Down