@ledgerhq/cryptoassets 13.32.0-nightly.2 → 13.32.0-nightly.3
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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +11 -0
- package/lib/api-token-converter.d.ts +29 -0
- package/lib/api-token-converter.d.ts.map +1 -1
- package/lib/api-token-converter.js +101 -110
- package/lib/api-token-converter.js.map +1 -1
- package/lib/cal-client/entities/index.d.ts +12 -12
- package/lib/cal-client/entities/index.js +2 -2
- package/lib/cal-client/entities/index.js.map +1 -1
- package/lib/cal-client/state-manager/api.js +16 -17
- package/lib/cal-client/state-manager/api.js.map +1 -1
- package/lib-es/api-token-converter.d.ts +29 -0
- package/lib-es/api-token-converter.d.ts.map +1 -1
- package/lib-es/api-token-converter.js +99 -109
- package/lib-es/api-token-converter.js.map +1 -1
- package/lib-es/cal-client/entities/index.d.ts +12 -12
- package/lib-es/cal-client/entities/index.js +2 -2
- package/lib-es/cal-client/entities/index.js.map +1 -1
- package/lib-es/cal-client/state-manager/api.js +16 -17
- package/lib-es/cal-client/state-manager/api.js.map +1 -1
- package/package.json +2 -2
- package/src/api-token-converter.test.ts +217 -221
- package/src/api-token-converter.ts +124 -140
- package/src/cal-client/entities/index.ts +2 -2
- package/src/cal-client/state-manager/api.ts +18 -18
|
@@ -1,33 +1,5 @@
|
|
|
1
1
|
import type { TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
2
|
-
import {
|
|
3
|
-
convertERC20,
|
|
4
|
-
convertSplTokens,
|
|
5
|
-
convertJettonToken,
|
|
6
|
-
convertAlgorandASATokens,
|
|
7
|
-
convertVechainToken,
|
|
8
|
-
convertTRONTokens,
|
|
9
|
-
convertMultiversXESDTTokens,
|
|
10
|
-
convertCardanoNativeTokens,
|
|
11
|
-
convertStellarTokens,
|
|
12
|
-
convertSuiTokens,
|
|
13
|
-
convertAptCoinTokens,
|
|
14
|
-
convertAptFaTokens,
|
|
15
|
-
} from "./legacy/legacy-utils";
|
|
16
|
-
import {
|
|
17
|
-
AlgorandASAToken,
|
|
18
|
-
CardanoNativeToken,
|
|
19
|
-
ERC20Token,
|
|
20
|
-
MultiversXESDTToken,
|
|
21
|
-
StellarToken,
|
|
22
|
-
TRC10Token,
|
|
23
|
-
TRC20Token,
|
|
24
|
-
} from "./types";
|
|
25
|
-
import type { AptosToken } from "./data/apt_coin";
|
|
26
|
-
import type { AptosToken as AptosFAToken } from "./data/apt_fungible_asset";
|
|
27
|
-
import type { SuiToken } from "./data/sui";
|
|
28
|
-
import type { Vip180Token } from "./data/vip180";
|
|
29
|
-
import type { TonJettonToken } from "./data/ton-jetton";
|
|
30
|
-
import type { SPLToken } from "./data/spl";
|
|
2
|
+
import { findCryptoCurrencyById } from "./currencies";
|
|
31
3
|
|
|
32
4
|
export interface ApiTokenData {
|
|
33
5
|
id: string;
|
|
@@ -39,121 +11,133 @@ export interface ApiTokenData {
|
|
|
39
11
|
delisted?: boolean;
|
|
40
12
|
disableCountervalue?: boolean;
|
|
41
13
|
tokenIdentifier?: string;
|
|
14
|
+
ledgerSignature?: string;
|
|
42
15
|
}
|
|
43
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Transforms Ledger Live token ID to backend API format for querying
|
|
19
|
+
*
|
|
20
|
+
* This handles cases where LL uses different ID conventions than backend APIs.
|
|
21
|
+
* Applied BEFORE querying the API to ensure the request uses the correct format:
|
|
22
|
+
*
|
|
23
|
+
* - MultiversX: multiversx/esdt/* → elrond/esdt/* (API uses old name) [LIVE-22557]
|
|
24
|
+
* - Stellar: UPPERCASE → lowercase (API uses lowercase) [LIVE-22558]
|
|
25
|
+
*
|
|
26
|
+
* @param legacyId - Token ID in Ledger Live format
|
|
27
|
+
* @returns Token ID in backend API format
|
|
28
|
+
*/
|
|
29
|
+
export function legacyIdToApiId(legacyId: string): string {
|
|
30
|
+
let apiId = legacyId;
|
|
31
|
+
|
|
32
|
+
// LIVE-22557: MultiversX - API uses old "elrond" name
|
|
33
|
+
if (apiId.startsWith("multiversx/esdt/")) {
|
|
34
|
+
apiId = apiId.replace("multiversx/esdt/", "elrond/esdt/");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// LIVE-22558: Stellar - API uses all lowercase (including the address part)
|
|
38
|
+
if (apiId.startsWith("stellar/asset/")) {
|
|
39
|
+
apiId = apiId.toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return apiId;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Converts API token data to Ledger Live TokenCurrency format
|
|
47
|
+
*
|
|
48
|
+
* This function applies client-side transformations to reconcile differences between
|
|
49
|
+
* backend APIs (CAL/DaDa) and Ledger Live's expected token format:
|
|
50
|
+
*
|
|
51
|
+
* - MultiversX: elrond/esdt/* → multiversx/esdt/* [LIVE-22557]
|
|
52
|
+
* - Stellar: Normalizes casing to stellar/asset/UPPERCASE_ADDRESS and tokenType asset → stellar [LIVE-22558]
|
|
53
|
+
* - Cardano: Reconstructs contractAddress from policyId + tokenIdentifier [LIVE-22559]
|
|
54
|
+
* - Sui: Transforms tokenType from "coin" to "sui" [LIVE-22560]
|
|
55
|
+
* - TON Jetton: Removes name prefix from ID (ton/jetton/name_address → ton/jetton/address) [LIVE-22561]
|
|
56
|
+
*
|
|
57
|
+
* @param apiToken - Token data from backend API
|
|
58
|
+
* @returns TokenCurrency object in Ledger Live format, or undefined if parent currency not found
|
|
59
|
+
*/
|
|
44
60
|
export function convertApiToken(apiToken: ApiTokenData): TokenCurrency | undefined {
|
|
45
|
-
const {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
tokenIdentifier,
|
|
57
|
-
ticker,
|
|
58
|
-
magnitude,
|
|
59
|
-
name,
|
|
60
|
-
"",
|
|
61
|
-
contractAddress,
|
|
62
|
-
false,
|
|
63
|
-
delisted,
|
|
64
|
-
];
|
|
65
|
-
return convertERC20(erc20Data);
|
|
66
|
-
}
|
|
67
|
-
case "spl": {
|
|
68
|
-
const parentCurrencyId = id.split("/")[0];
|
|
69
|
-
const splData: SPLToken = [id, parentCurrencyId, name, ticker, contractAddress, magnitude];
|
|
70
|
-
return convertSplTokens(splData);
|
|
71
|
-
}
|
|
72
|
-
case "jetton": {
|
|
73
|
-
const jettonData: TonJettonToken = [contractAddress, name, ticker, magnitude, delisted];
|
|
74
|
-
return convertJettonToken(jettonData);
|
|
75
|
-
}
|
|
76
|
-
case "asa": {
|
|
77
|
-
const tokenId = id.split("/")[2] || contractAddress;
|
|
78
|
-
const asaData: AlgorandASAToken = [tokenId, ticker, name, contractAddress, magnitude];
|
|
79
|
-
return convertAlgorandASATokens(asaData);
|
|
80
|
-
}
|
|
81
|
-
case "esdt": {
|
|
82
|
-
const tokenIdentifier = id.split("/")[2] || contractAddress;
|
|
83
|
-
const esdtData: MultiversXESDTToken = [ticker, tokenIdentifier, magnitude, "", name];
|
|
84
|
-
return convertMultiversXESDTTokens(esdtData);
|
|
85
|
-
}
|
|
86
|
-
case "trc10": {
|
|
87
|
-
const tokenId = parseInt(id.split("/")[2] || contractAddress);
|
|
88
|
-
const trc10Data: TRC10Token = [
|
|
89
|
-
tokenId,
|
|
90
|
-
ticker,
|
|
91
|
-
name,
|
|
92
|
-
contractAddress,
|
|
93
|
-
magnitude,
|
|
94
|
-
delisted,
|
|
95
|
-
"",
|
|
96
|
-
];
|
|
97
|
-
return convertTRONTokens("trc10")(trc10Data);
|
|
98
|
-
}
|
|
99
|
-
case "trc20": {
|
|
100
|
-
const tokenId = id.split("/")[2] || contractAddress;
|
|
101
|
-
const trc20Data: TRC20Token = [
|
|
102
|
-
tokenId,
|
|
103
|
-
ticker,
|
|
104
|
-
name,
|
|
105
|
-
contractAddress,
|
|
106
|
-
magnitude,
|
|
107
|
-
delisted,
|
|
108
|
-
"",
|
|
109
|
-
];
|
|
110
|
-
return convertTRONTokens("trc20")(trc20Data);
|
|
111
|
-
}
|
|
112
|
-
case "vip180": {
|
|
113
|
-
const tokenIdentifier = id.split("/")[2] || contractAddress;
|
|
114
|
-
const vip180Data: Vip180Token = [tokenIdentifier, ticker, name, contractAddress, magnitude];
|
|
115
|
-
return convertVechainToken(vip180Data);
|
|
116
|
-
}
|
|
117
|
-
case "native": {
|
|
118
|
-
const parentCurrencyId = id.split("/")[0];
|
|
119
|
-
if (parentCurrencyId !== "cardano") return undefined;
|
|
120
|
-
|
|
121
|
-
const tokenIdentifier = id.split("/")[2] || contractAddress;
|
|
122
|
-
const parts = tokenIdentifier.split(".");
|
|
123
|
-
const [policyId, assetName = ""] = parts;
|
|
124
|
-
|
|
125
|
-
const cardanoData: CardanoNativeToken = [
|
|
126
|
-
"cardano",
|
|
127
|
-
policyId,
|
|
128
|
-
assetName,
|
|
129
|
-
name,
|
|
130
|
-
ticker,
|
|
131
|
-
magnitude,
|
|
132
|
-
delisted,
|
|
133
|
-
];
|
|
134
|
-
return convertCardanoNativeTokens(cardanoData);
|
|
135
|
-
}
|
|
136
|
-
case "stellar": {
|
|
137
|
-
const parts = contractAddress.split(":");
|
|
138
|
-
const assetCode = parts[0] || ticker;
|
|
139
|
-
const assetIssuer = parts[1] || contractAddress;
|
|
61
|
+
const {
|
|
62
|
+
standard,
|
|
63
|
+
id,
|
|
64
|
+
contractAddress,
|
|
65
|
+
name,
|
|
66
|
+
ticker,
|
|
67
|
+
units,
|
|
68
|
+
delisted = false,
|
|
69
|
+
tokenIdentifier,
|
|
70
|
+
ledgerSignature,
|
|
71
|
+
} = apiToken;
|
|
140
72
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
73
|
+
// Apply client-side patches to reconcile CAL format with LL format
|
|
74
|
+
let patchedId = id;
|
|
75
|
+
let patchedContractAddress = contractAddress;
|
|
76
|
+
let patchedStandard = standard;
|
|
77
|
+
|
|
78
|
+
// Get parent currency from the ORIGINAL ID (before transformation)
|
|
79
|
+
// This is important for currencies that changed names (elrond -> multiversx)
|
|
80
|
+
const parentCurrencyId = id.split("/")[0];
|
|
81
|
+
const parentCurrency = findCryptoCurrencyById(parentCurrencyId);
|
|
82
|
+
|
|
83
|
+
if (!parentCurrency) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// LIVE-22557: MultiversX - Transform elrond/* to multiversx/*
|
|
88
|
+
if (patchedId.startsWith("elrond/esdt/")) {
|
|
89
|
+
patchedId = patchedId.replace("elrond/esdt/", "multiversx/esdt/");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// LIVE-22558: Stellar - Transform to LL mixed-case format: stellar/asset/ + UPPERCASE_REST
|
|
93
|
+
// Also fix tokenType: API returns "asset", LL expects "stellar"
|
|
94
|
+
const stellarPrefix = "stellar/asset/";
|
|
95
|
+
if (patchedId.toLowerCase().startsWith(stellarPrefix)) {
|
|
96
|
+
const rest = patchedId.substring(stellarPrefix.length);
|
|
97
|
+
patchedId = stellarPrefix + rest.toUpperCase();
|
|
98
|
+
patchedStandard = patchedStandard === "asset" ? "stellar" : patchedStandard;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// LIVE-22559: Cardano - Reconstruct full assetId (policyId + assetName)
|
|
102
|
+
if (standard === "native" && tokenIdentifier) {
|
|
103
|
+
patchedContractAddress = contractAddress + tokenIdentifier;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// LIVE-22560: Sui - Transform "coin" standard to "sui" tokenType (LL format)
|
|
107
|
+
if (standard === "coin" && patchedId.startsWith("sui/")) {
|
|
108
|
+
patchedStandard = "sui";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// LIVE-22561: TON Jetton - Remove name prefix from ID (API: ton/jetton/name_address -> LL: ton/jetton/address)
|
|
112
|
+
if (patchedId.startsWith("ton/jetton/") && patchedId.indexOf("_") > 0) {
|
|
113
|
+
const parts = patchedId.split("_");
|
|
114
|
+
if (parts.length === 2) {
|
|
115
|
+
patchedId = "ton/jetton/" + parts[1];
|
|
155
116
|
}
|
|
156
|
-
default:
|
|
157
|
-
return undefined;
|
|
158
117
|
}
|
|
118
|
+
|
|
119
|
+
// Construct TokenCurrency directly from API data
|
|
120
|
+
const tokenCurrency: TokenCurrency = {
|
|
121
|
+
type: "TokenCurrency",
|
|
122
|
+
id: patchedId,
|
|
123
|
+
contractAddress: patchedContractAddress,
|
|
124
|
+
parentCurrency,
|
|
125
|
+
tokenType: patchedStandard,
|
|
126
|
+
name,
|
|
127
|
+
ticker,
|
|
128
|
+
delisted,
|
|
129
|
+
disableCountervalue: !!parentCurrency.isTestnetFor || !!apiToken.disableCountervalue,
|
|
130
|
+
units: units.map(unit => ({
|
|
131
|
+
name: unit.name,
|
|
132
|
+
code: unit.code,
|
|
133
|
+
magnitude: unit.magnitude,
|
|
134
|
+
})),
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Add ledgerSignature if present
|
|
138
|
+
if (ledgerSignature) {
|
|
139
|
+
tokenCurrency.ledgerSignature = ledgerSignature;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return tokenCurrency;
|
|
159
143
|
}
|
|
@@ -45,7 +45,7 @@ export const ApiTokenResponseSchema = z.object({
|
|
|
45
45
|
/** Chain ID */
|
|
46
46
|
chain_id: z.string(),
|
|
47
47
|
/** Token identifier */
|
|
48
|
-
token_identifier: z.string(),
|
|
48
|
+
token_identifier: z.string().optional(),
|
|
49
49
|
/** Network type */
|
|
50
50
|
network_type: z.string(),
|
|
51
51
|
/** Meta currency ID */
|
|
@@ -53,7 +53,7 @@ export const ApiTokenResponseSchema = z.object({
|
|
|
53
53
|
/** Blockchain name */
|
|
54
54
|
blockchain_name: z.string(),
|
|
55
55
|
/** Live signature */
|
|
56
|
-
live_signature: z.string(),
|
|
56
|
+
live_signature: z.string().optional(),
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
export type ApiTokenResponse = z.infer<typeof ApiTokenResponseSchema>;
|
|
@@ -4,7 +4,7 @@ import { getEnv } from "@ledgerhq/live-env";
|
|
|
4
4
|
import { GetTokensDataParams, PageParam, TokensDataTags, TokensDataWithPagination } from "./types";
|
|
5
5
|
import { TOKEN_OUTPUT_FIELDS } from "./fields";
|
|
6
6
|
import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
7
|
-
import {
|
|
7
|
+
import { convertApiToken } from "../../api-token-converter";
|
|
8
8
|
|
|
9
9
|
function transformTokensResponse(
|
|
10
10
|
response: ApiTokenResponse[],
|
|
@@ -24,28 +24,28 @@ function transformTokensResponse(
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
function transformApiTokenToTokenCurrency(token: ApiTokenResponse): TokenCurrency | undefined {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return undefined;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
type: "TokenCurrency",
|
|
27
|
+
// convertApiToken handles all format reconciliation internally
|
|
28
|
+
const result = convertApiToken({
|
|
34
29
|
id: token.id,
|
|
35
|
-
ledgerSignature: token.live_signature,
|
|
36
30
|
contractAddress: token.contract_address,
|
|
37
|
-
parentCurrency,
|
|
38
|
-
tokenType: token.standard,
|
|
39
31
|
name: token.name,
|
|
40
32
|
ticker: token.ticker,
|
|
41
|
-
units: token.units
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
magnitude: unit.magnitude,
|
|
45
|
-
})),
|
|
33
|
+
units: token.units,
|
|
34
|
+
standard: token.standard,
|
|
35
|
+
tokenIdentifier: token.token_identifier,
|
|
46
36
|
delisted: token.delisted,
|
|
47
|
-
|
|
48
|
-
};
|
|
37
|
+
ledgerSignature: token.live_signature,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Add symbol if result exists
|
|
41
|
+
if (result && token.symbol) {
|
|
42
|
+
return {
|
|
43
|
+
...result,
|
|
44
|
+
symbol: token.symbol,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return result;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export const cryptoAssetsApi = createApi({
|