@ledgerhq/coin-solana 0.37.0 → 0.38.0-nightly.20251126160702
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/CHANGELOG.md +31 -0
- package/lib/bridge/bridge.d.ts +2 -4
- package/lib/bridge/bridge.d.ts.map +1 -1
- package/lib/bridge/bridge.js +16 -16
- package/lib/bridge/bridge.js.map +1 -1
- package/lib/bridge/js.d.ts +1 -2
- package/lib/bridge/js.d.ts.map +1 -1
- package/lib/bridge/js.js +9 -11
- package/lib/bridge/js.js.map +1 -1
- package/lib/cli-transaction.js +2 -2
- package/lib/cli-transaction.js.map +1 -1
- package/lib/config.d.ts +0 -1
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js.map +1 -1
- package/lib/helpers/token.js +2 -2
- package/lib/helpers/token.js.map +1 -1
- package/lib/network/chain/index.d.ts.map +1 -1
- package/lib/network/chain/index.js +29 -38
- package/lib/network/chain/index.js.map +1 -1
- package/lib/network/chain/web3.d.ts.map +1 -1
- package/lib/network/chain/web3.js +9 -5
- package/lib/network/chain/web3.js.map +1 -1
- package/lib/network/index.d.ts +0 -2
- package/lib/network/index.d.ts.map +1 -1
- package/lib/network/index.js +1 -5
- package/lib/network/index.js.map +1 -1
- package/lib/network/nft/index.js +3 -3
- package/lib/network/nft/index.js.map +1 -1
- package/lib/preload-data.d.ts.map +1 -1
- package/lib/preload-data.js +0 -1
- package/lib/preload-data.js.map +1 -1
- package/lib/preload.d.ts +2 -6
- package/lib/preload.d.ts.map +1 -1
- package/lib/preload.js +2 -107
- package/lib/preload.js.map +1 -1
- package/lib/prepareTransaction.js +2 -2
- package/lib/prepareTransaction.js.map +1 -1
- package/lib/signOperation.d.ts +1 -1
- package/lib/signOperation.d.ts.map +1 -1
- package/lib/signOperation.js +1 -1
- package/lib/signOperation.js.map +1 -1
- package/lib/synchronization.d.ts.map +1 -1
- package/lib/synchronization.js +11 -7
- package/lib/synchronization.js.map +1 -1
- package/lib/transaction.js +2 -2
- package/lib/transaction.js.map +1 -1
- package/lib/types.d.ts +0 -2
- package/lib/types.d.ts.map +1 -1
- package/lib-es/bridge/bridge.d.ts +2 -4
- package/lib-es/bridge/bridge.d.ts.map +1 -1
- package/lib-es/bridge/bridge.js +17 -17
- package/lib-es/bridge/bridge.js.map +1 -1
- package/lib-es/bridge/js.d.ts +1 -2
- package/lib-es/bridge/js.d.ts.map +1 -1
- package/lib-es/bridge/js.js +10 -12
- package/lib-es/bridge/js.js.map +1 -1
- package/lib-es/cli-transaction.js +1 -1
- package/lib-es/cli-transaction.js.map +1 -1
- package/lib-es/config.d.ts +0 -1
- package/lib-es/config.d.ts.map +1 -1
- package/lib-es/config.js.map +1 -1
- package/lib-es/helpers/token.js +1 -1
- package/lib-es/helpers/token.js.map +1 -1
- package/lib-es/network/chain/index.d.ts.map +1 -1
- package/lib-es/network/chain/index.js +29 -38
- package/lib-es/network/chain/index.js.map +1 -1
- package/lib-es/network/chain/web3.d.ts.map +1 -1
- package/lib-es/network/chain/web3.js +9 -5
- package/lib-es/network/chain/web3.js.map +1 -1
- package/lib-es/network/index.d.ts +0 -2
- package/lib-es/network/index.d.ts.map +1 -1
- package/lib-es/network/index.js +0 -2
- package/lib-es/network/index.js.map +1 -1
- package/lib-es/network/nft/index.js +1 -1
- package/lib-es/network/nft/index.js.map +1 -1
- package/lib-es/preload-data.d.ts.map +1 -1
- package/lib-es/preload-data.js +0 -1
- package/lib-es/preload-data.js.map +1 -1
- package/lib-es/preload.d.ts +2 -6
- package/lib-es/preload.d.ts.map +1 -1
- package/lib-es/preload.js +2 -81
- package/lib-es/preload.js.map +1 -1
- package/lib-es/prepareTransaction.js +1 -1
- package/lib-es/prepareTransaction.js.map +1 -1
- package/lib-es/signOperation.d.ts +1 -1
- package/lib-es/signOperation.d.ts.map +1 -1
- package/lib-es/signOperation.js +1 -1
- package/lib-es/signOperation.js.map +1 -1
- package/lib-es/synchronization.d.ts.map +1 -1
- package/lib-es/synchronization.js +10 -6
- package/lib-es/synchronization.js.map +1 -1
- package/lib-es/transaction.js +1 -1
- package/lib-es/transaction.js.map +1 -1
- package/lib-es/types.d.ts +0 -2
- package/lib-es/types.d.ts.map +1 -1
- package/package.json +6 -8
- package/src/__tests__/getTransactions.test.ts +81 -0
- package/src/__tests__/unit/hw-signMessage.unit.test.ts +0 -1
- package/src/bridge/bridge.ts +27 -35
- package/src/bridge/js.ts +9 -29
- package/src/cli-transaction.ts +1 -1
- package/src/config.ts +0 -1
- package/src/helpers/token.ts +1 -1
- package/src/network/chain/index.ts +29 -38
- package/src/network/chain/web3.integration.test.ts +21 -1
- package/src/network/chain/web3.ts +11 -5
- package/src/network/index.ts +0 -2
- package/src/network/nft/index.ts +1 -1
- package/src/preload-data.ts +0 -1
- package/src/preload.test.ts +121 -12
- package/src/preload.ts +2 -111
- package/src/prepareTransaction.ts +1 -1
- package/src/signOperation.test.ts +2 -2
- package/src/signOperation.ts +2 -2
- package/src/synchronization.ts +10 -6
- package/src/tests/tokens-bridge.unit.test.ts +11 -16
- package/src/transaction.ts +1 -1
- package/src/types.ts +0 -2
- package/lib/cryptoAssetsStore.d.ts +0 -5
- package/lib/cryptoAssetsStore.d.ts.map +0 -1
- package/lib/cryptoAssetsStore.js +0 -17
- package/lib/cryptoAssetsStore.js.map +0 -1
- package/lib/network/cached.d.ts +0 -3
- package/lib/network/cached.d.ts.map +0 -1
- package/lib/network/cached.js +0 -56
- package/lib/network/cached.js.map +0 -1
- package/lib/network/queued.d.ts +0 -3
- package/lib/network/queued.d.ts.map +0 -1
- package/lib/network/queued.js +0 -27
- package/lib/network/queued.js.map +0 -1
- package/lib/network/traced.d.ts +0 -3
- package/lib/network/traced.d.ts.map +0 -1
- package/lib/network/traced.js +0 -80
- package/lib/network/traced.js.map +0 -1
- package/lib-es/cryptoAssetsStore.d.ts +0 -5
- package/lib-es/cryptoAssetsStore.d.ts.map +0 -1
- package/lib-es/cryptoAssetsStore.js +0 -12
- package/lib-es/cryptoAssetsStore.js.map +0 -1
- package/lib-es/network/cached.d.ts +0 -3
- package/lib-es/network/cached.d.ts.map +0 -1
- package/lib-es/network/cached.js +0 -49
- package/lib-es/network/cached.js.map +0 -1
- package/lib-es/network/queued.d.ts +0 -3
- package/lib-es/network/queued.d.ts.map +0 -1
- package/lib-es/network/queued.js +0 -23
- package/lib-es/network/queued.js.map +0 -1
- package/lib-es/network/traced.d.ts +0 -3
- package/lib-es/network/traced.d.ts.map +0 -1
- package/lib-es/network/traced.js +0 -76
- package/lib-es/network/traced.js.map +0 -1
- package/src/cryptoAssetsStore.test.ts +0 -19
- package/src/cryptoAssetsStore.ts +0 -16
- package/src/network/cached.ts +0 -111
- package/src/network/queued.ts +0 -25
- package/src/network/traced.ts +0 -89
- package/src/tests/preload.unit.test.ts +0 -182
package/src/bridge/bridge.ts
CHANGED
|
@@ -13,7 +13,7 @@ import type { AccountBridge, AccountLike, CurrencyBridge } from "@ledgerhq/types
|
|
|
13
13
|
import type { SolanaAccount, SolanaPreloadDataV1, Transaction, TransactionStatus } from "../types";
|
|
14
14
|
import { prepareTransaction as prepareTransactionWithAPI } from "../prepareTransaction";
|
|
15
15
|
import { estimateMaxSpendableWithAPI } from "../estimateMaxSpendable";
|
|
16
|
-
import { PRELOAD_MAX_AGE,
|
|
16
|
+
import { PRELOAD_MAX_AGE, preloadWithAPI } from "../preload";
|
|
17
17
|
import { getTransactionStatus } from "../getTransactionStatus";
|
|
18
18
|
import { getAccountShapeWithAPI } from "../synchronization";
|
|
19
19
|
import { createTransaction } from "../createTransaction";
|
|
@@ -32,33 +32,31 @@ import {
|
|
|
32
32
|
assignToTokenAccountRaw,
|
|
33
33
|
} from "../serialization";
|
|
34
34
|
import nftResolvers from "../nftResolvers";
|
|
35
|
+
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
35
36
|
|
|
36
|
-
function makePrepare(getChainAPI: (config: Config) =>
|
|
37
|
-
const prepareTransaction: AccountBridge<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
function makePrepare(getChainAPI: (config: Config) => ChainAPI) {
|
|
38
|
+
const prepareTransaction: AccountBridge<Transaction, SolanaAccount>["prepareTransaction"] = (
|
|
39
|
+
mainAccount,
|
|
40
|
+
transaction,
|
|
41
|
+
) => {
|
|
41
42
|
const config: Config = {
|
|
42
43
|
endpoint: endpointByCurrencyId(mainAccount.currency.id),
|
|
43
44
|
};
|
|
44
45
|
|
|
45
|
-
const chainAPI =
|
|
46
|
+
const chainAPI = getChainAPI(config);
|
|
46
47
|
return prepareTransactionWithAPI(mainAccount, transaction, chainAPI);
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
return prepareTransaction;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
function makeSyncAndScan(
|
|
53
|
-
|
|
54
|
-
getAddress: GetAddressFn,
|
|
55
|
-
) {
|
|
56
|
-
const getAccountShape: GetAccountShape<SolanaAccount> = async info => {
|
|
53
|
+
function makeSyncAndScan(getChainAPI: (config: Config) => ChainAPI, getAddress: GetAddressFn) {
|
|
54
|
+
const getAccountShape: GetAccountShape<SolanaAccount> = info => {
|
|
57
55
|
const config: Config = {
|
|
58
56
|
endpoint: endpointByCurrencyId(info.currency.id),
|
|
59
57
|
};
|
|
60
58
|
|
|
61
|
-
const chainAPI =
|
|
59
|
+
const chainAPI = getChainAPI(config);
|
|
62
60
|
return getAccountShapeWithAPI(info, chainAPI);
|
|
63
61
|
};
|
|
64
62
|
return {
|
|
@@ -67,11 +65,11 @@ function makeSyncAndScan(
|
|
|
67
65
|
};
|
|
68
66
|
}
|
|
69
67
|
|
|
70
|
-
function makeEstimateMaxSpendable(getChainAPI: (config: Config) =>
|
|
68
|
+
function makeEstimateMaxSpendable(getChainAPI: (config: Config) => ChainAPI) {
|
|
71
69
|
const estimateMaxSpendable: AccountBridge<
|
|
72
70
|
Transaction,
|
|
73
71
|
SolanaAccount
|
|
74
|
-
>["estimateMaxSpendable"] =
|
|
72
|
+
>["estimateMaxSpendable"] = arg => {
|
|
75
73
|
const { account, parentAccount } = arg;
|
|
76
74
|
|
|
77
75
|
const currencyId =
|
|
@@ -85,7 +83,7 @@ function makeEstimateMaxSpendable(getChainAPI: (config: Config) => Promise<Chain
|
|
|
85
83
|
endpoint: endpointByCurrencyId(currencyId),
|
|
86
84
|
};
|
|
87
85
|
|
|
88
|
-
const api =
|
|
86
|
+
const api = getChainAPI(config);
|
|
89
87
|
|
|
90
88
|
return estimateMaxSpendableWithAPI(arg, api);
|
|
91
89
|
};
|
|
@@ -106,38 +104,36 @@ function makeEstimateMaxSpendable(getChainAPI: (config: Config) => Promise<Chain
|
|
|
106
104
|
}
|
|
107
105
|
|
|
108
106
|
function makeBroadcast(
|
|
109
|
-
getChainAPI: (config: Config) =>
|
|
107
|
+
getChainAPI: (config: Config) => ChainAPI,
|
|
110
108
|
): AccountBridge<Transaction, SolanaAccount>["broadcast"] {
|
|
111
|
-
return
|
|
109
|
+
return info => {
|
|
112
110
|
const config: Config = {
|
|
113
111
|
endpoint: endpointByCurrencyId(info.account.currency.id),
|
|
114
112
|
};
|
|
115
|
-
const api =
|
|
113
|
+
const api = getChainAPI(config);
|
|
116
114
|
return broadcastWithAPI(info, api);
|
|
117
115
|
};
|
|
118
116
|
}
|
|
119
117
|
|
|
120
118
|
function makeSign(
|
|
121
|
-
getChainAPI: (config: Config) =>
|
|
119
|
+
getChainAPI: (config: Config) => ChainAPI,
|
|
122
120
|
signerContext: SignerContext<SolanaSigner>,
|
|
123
121
|
): AccountBridge<Transaction, SolanaAccount>["signOperation"] {
|
|
124
122
|
return info => {
|
|
125
123
|
const config: Config = {
|
|
126
124
|
endpoint: endpointByCurrencyId(info.account.currency.id),
|
|
127
125
|
};
|
|
128
|
-
const api =
|
|
126
|
+
const api = getChainAPI(config);
|
|
129
127
|
return buildSignOperation(signerContext, api)(info);
|
|
130
128
|
};
|
|
131
129
|
}
|
|
132
130
|
|
|
133
|
-
function makePreload(
|
|
134
|
-
getChainAPI: (config: Config) => Promise<ChainAPI>,
|
|
135
|
-
): CurrencyBridge["preload"] {
|
|
131
|
+
function makePreload(getChainAPI: (config: Config) => ChainAPI): CurrencyBridge["preload"] {
|
|
136
132
|
const preload: CurrencyBridge["preload"] = (currency): Promise<SolanaPreloadDataV1> => {
|
|
137
133
|
const config: Config = {
|
|
138
134
|
endpoint: endpointByCurrencyId(currency.id),
|
|
139
135
|
};
|
|
140
|
-
const api =
|
|
136
|
+
const api = getChainAPI(config);
|
|
141
137
|
return preloadWithAPI(currency, api);
|
|
142
138
|
};
|
|
143
139
|
return preload;
|
|
@@ -151,29 +147,25 @@ function getPreloadStrategy() {
|
|
|
151
147
|
|
|
152
148
|
export function makeBridges({
|
|
153
149
|
getAPI,
|
|
154
|
-
getQueuedAPI,
|
|
155
|
-
getQueuedAndCachedAPI,
|
|
156
150
|
signerContext,
|
|
157
151
|
}: {
|
|
158
|
-
getAPI: (config: Config) =>
|
|
159
|
-
getQueuedAPI: (config: Config) => Promise<ChainAPI>;
|
|
160
|
-
getQueuedAndCachedAPI: (config: Config) => Promise<ChainAPI>;
|
|
152
|
+
getAPI: (config: Config) => ChainAPI;
|
|
161
153
|
signerContext: SignerContext<SolanaSigner>;
|
|
162
154
|
}): {
|
|
163
155
|
currencyBridge: CurrencyBridge;
|
|
164
156
|
accountBridge: AccountBridge<Transaction, SolanaAccount, TransactionStatus>;
|
|
165
157
|
} {
|
|
166
158
|
const getAddress = resolver(signerContext);
|
|
167
|
-
const { sync, scan } = makeSyncAndScan(
|
|
159
|
+
const { sync, scan } = makeSyncAndScan(getAPI, getAddress);
|
|
168
160
|
|
|
169
161
|
const accountBridge: AccountBridge<Transaction, SolanaAccount, TransactionStatus> = {
|
|
170
162
|
createTransaction,
|
|
171
163
|
updateTransaction,
|
|
172
|
-
estimateMaxSpendable: makeEstimateMaxSpendable(
|
|
164
|
+
estimateMaxSpendable: makeEstimateMaxSpendable(getAPI),
|
|
173
165
|
getTransactionStatus,
|
|
174
166
|
sync,
|
|
175
167
|
receive: makeAccountBridgeReceive(getAddress),
|
|
176
|
-
prepareTransaction: makePrepare(
|
|
168
|
+
prepareTransaction: makePrepare(getAPI),
|
|
177
169
|
broadcast: makeBroadcast(getAPI),
|
|
178
170
|
signOperation: makeSign(getAPI, signerContext),
|
|
179
171
|
signRawOperation: () => {
|
|
@@ -189,8 +181,8 @@ export function makeBridges({
|
|
|
189
181
|
};
|
|
190
182
|
|
|
191
183
|
const currencyBridge: CurrencyBridge = {
|
|
192
|
-
preload: makePreload(
|
|
193
|
-
hydrate,
|
|
184
|
+
preload: makePreload(getAPI),
|
|
185
|
+
hydrate: (_data: unknown, _currency: CryptoCurrency) => {},
|
|
194
186
|
scanAccounts: scan,
|
|
195
187
|
getPreloadStrategy,
|
|
196
188
|
nftResolvers,
|
package/src/bridge/js.ts
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import { makeLRUCache, minutes } from "@ledgerhq/live-network/cache";
|
|
2
1
|
import { log } from "@ledgerhq/logs";
|
|
3
|
-
import {
|
|
4
|
-
import { traced } from "../network/traced";
|
|
2
|
+
import { Config, getChainAPI } from "../network";
|
|
5
3
|
import { makeBridges } from "./bridge";
|
|
6
4
|
import { SignerContext } from "@ledgerhq/coin-framework/signer";
|
|
7
5
|
import { SolanaSigner } from "../signer";
|
|
8
6
|
import { CoinConfig } from "@ledgerhq/coin-framework/config";
|
|
9
7
|
import solanaCoinConfig, { SolanaCoinConfig } from "../config";
|
|
10
|
-
import { setCryptoAssetsStoreGetter } from "../cryptoAssetsStore";
|
|
11
|
-
import { CryptoAssetsStoreGetter } from "@ledgerhq/types-live";
|
|
12
8
|
|
|
13
9
|
const httpRequestLogger = (url: string, options: any) => {
|
|
14
10
|
log("network", url, {
|
|
@@ -18,36 +14,20 @@ const httpRequestLogger = (url: string, options: any) => {
|
|
|
18
14
|
});
|
|
19
15
|
};
|
|
20
16
|
|
|
21
|
-
const getAPI = makeLRUCache(
|
|
22
|
-
(config: Config) => Promise.resolve(traced(getChainAPI(config, httpRequestLogger))),
|
|
23
|
-
config => config.endpoint,
|
|
24
|
-
minutes(1000),
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
const getQueuedAPI = makeLRUCache(
|
|
28
|
-
(config: Config) =>
|
|
29
|
-
getAPI(config).then(api => queued(api, solanaCoinConfig.getCoinConfig().queuedInterval)),
|
|
30
|
-
config => config.endpoint,
|
|
31
|
-
minutes(1000),
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
const getQueuedAndCachedAPI = makeLRUCache(
|
|
35
|
-
(config: Config) => getQueuedAPI(config).then(cached),
|
|
36
|
-
config => config.endpoint,
|
|
37
|
-
minutes(1000),
|
|
38
|
-
);
|
|
39
|
-
|
|
40
17
|
export function createBridges(
|
|
41
18
|
signerContext: SignerContext<SolanaSigner>,
|
|
42
19
|
coinConfig: CoinConfig<SolanaCoinConfig>,
|
|
43
|
-
cryptoAssetsStoreGetter: CryptoAssetsStoreGetter,
|
|
44
20
|
) {
|
|
45
21
|
solanaCoinConfig.setCoinConfig(coinConfig);
|
|
46
|
-
|
|
22
|
+
const chainAPICache = new Map<string, ReturnType<typeof getChainAPI>>();
|
|
47
23
|
return makeBridges({
|
|
48
|
-
getAPI
|
|
49
|
-
|
|
50
|
-
|
|
24
|
+
getAPI: (config: Config) => {
|
|
25
|
+
const endpoint = config.endpoint;
|
|
26
|
+
if (!chainAPICache.has(endpoint)) {
|
|
27
|
+
chainAPICache.set(endpoint, getChainAPI(config, httpRequestLogger));
|
|
28
|
+
}
|
|
29
|
+
return chainAPICache.get(endpoint)!;
|
|
30
|
+
},
|
|
51
31
|
signerContext,
|
|
52
32
|
});
|
|
53
33
|
}
|
package/src/cli-transaction.ts
CHANGED
|
@@ -3,7 +3,7 @@ import invariant from "invariant";
|
|
|
3
3
|
import { getAccountCurrency } from "@ledgerhq/coin-framework/account/index";
|
|
4
4
|
import { Transaction } from "./types";
|
|
5
5
|
import { assertUnreachable } from "./utils";
|
|
6
|
-
import { getCryptoAssetsStore } from "
|
|
6
|
+
import { getCryptoAssetsStore } from "@ledgerhq/cryptoassets/state";
|
|
7
7
|
|
|
8
8
|
const modes = [
|
|
9
9
|
"send",
|
package/src/config.ts
CHANGED
package/src/helpers/token.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "../types";
|
|
11
11
|
import { TransferFeeConfigExt } from "../network/chain/account/tokenExtensions";
|
|
12
12
|
import { PARSED_PROGRAMS } from "../network/chain/program/constants";
|
|
13
|
-
import { getCryptoAssetsStore } from "
|
|
13
|
+
import { getCryptoAssetsStore } from "@ledgerhq/cryptoassets/state";
|
|
14
14
|
|
|
15
15
|
export async function tokenIsListedOnLedger(currencyId: string, mint: string): Promise<boolean> {
|
|
16
16
|
const token = await getCryptoAssetsStore().findTokenByAddressInCurrency(mint, currencyId);
|
|
@@ -154,44 +154,38 @@ export function getChainAPI(
|
|
|
154
154
|
fetch(url, options);
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
commitment: "confirmed",
|
|
164
|
-
confirmTransactionInitialTimeout: getEnv("SOLANA_TX_CONFIRMATION_TIMEOUT") || 0,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
return _connection;
|
|
168
|
-
};
|
|
157
|
+
const connection = new Connection(config.endpoint, {
|
|
158
|
+
...(fetchMiddleware ? { fetchMiddleware } : {}),
|
|
159
|
+
fetch: kyNoTimeout as typeof fetch, // Type cast for jest test having an issue with the type
|
|
160
|
+
commitment: "confirmed",
|
|
161
|
+
confirmTransactionInitialTimeout: getEnv("SOLANA_TX_CONFIRMATION_TIMEOUT") || 0,
|
|
162
|
+
});
|
|
169
163
|
|
|
170
164
|
return {
|
|
171
165
|
getBalance: (address: string) =>
|
|
172
|
-
connection
|
|
166
|
+
connection.getBalance(new PublicKey(address)).catch(remapErrors),
|
|
173
167
|
|
|
174
168
|
getLatestBlockhash: (commitmentOrConfig?: Commitment | GetLatestBlockhashConfig) =>
|
|
175
|
-
connection
|
|
169
|
+
connection.getLatestBlockhash(commitmentOrConfig).catch(remapErrors),
|
|
176
170
|
|
|
177
171
|
getFeeForMessage: (msg: VersionedMessage) =>
|
|
178
|
-
connection
|
|
172
|
+
connection
|
|
179
173
|
.getFeeForMessage(msg)
|
|
180
174
|
.then(r => r.value)
|
|
181
175
|
.catch(remapErrors),
|
|
182
176
|
|
|
183
177
|
getBalanceAndContext: (address: string) =>
|
|
184
|
-
connection
|
|
178
|
+
connection.getBalanceAndContext(new PublicKey(address)).catch(remapErrors),
|
|
185
179
|
|
|
186
180
|
getParsedTokenAccountsByOwner: (address: string) =>
|
|
187
|
-
connection
|
|
181
|
+
connection
|
|
188
182
|
.getParsedTokenAccountsByOwner(new PublicKey(address), {
|
|
189
183
|
programId: TOKEN_PROGRAM_ID,
|
|
190
184
|
})
|
|
191
185
|
.catch(remapErrors),
|
|
192
186
|
|
|
193
187
|
getParsedToken2022AccountsByOwner: (address: string) =>
|
|
194
|
-
connection
|
|
188
|
+
connection
|
|
195
189
|
.getParsedTokenAccountsByOwner(new PublicKey(address), {
|
|
196
190
|
programId: TOKEN_2022_PROGRAM_ID,
|
|
197
191
|
})
|
|
@@ -199,7 +193,7 @@ export function getChainAPI(
|
|
|
199
193
|
|
|
200
194
|
getStakeAccountsByStakeAuth: makeLRUCache(
|
|
201
195
|
(authAddr: string) =>
|
|
202
|
-
connection
|
|
196
|
+
connection
|
|
203
197
|
.getParsedProgramAccounts(StakeProgram.programId, {
|
|
204
198
|
filters: [
|
|
205
199
|
{
|
|
@@ -217,7 +211,7 @@ export function getChainAPI(
|
|
|
217
211
|
|
|
218
212
|
getStakeAccountsByWithdrawAuth: makeLRUCache(
|
|
219
213
|
(authAddr: string) =>
|
|
220
|
-
connection
|
|
214
|
+
connection
|
|
221
215
|
.getParsedProgramAccounts(StakeProgram.programId, {
|
|
222
216
|
filters: [
|
|
223
217
|
{
|
|
@@ -234,51 +228,48 @@ export function getChainAPI(
|
|
|
234
228
|
),
|
|
235
229
|
|
|
236
230
|
getInflationReward: (addresses: string[]) =>
|
|
237
|
-
connection()
|
|
238
|
-
.getInflationReward(addresses.map(addr => new PublicKey(addr)))
|
|
239
|
-
.catch(remapErrors),
|
|
231
|
+
connection.getInflationReward(addresses.map(addr => new PublicKey(addr))).catch(remapErrors),
|
|
240
232
|
|
|
241
|
-
getVoteAccounts: () => connection
|
|
233
|
+
getVoteAccounts: () => connection.getVoteAccounts().catch(remapErrors),
|
|
242
234
|
|
|
243
235
|
getSignaturesForAddress: (address: string, opts?: SignaturesForAddressOptions) => {
|
|
244
236
|
const callback = () => {
|
|
245
|
-
return connection
|
|
237
|
+
return connection.getSignaturesForAddress(new PublicKey(address), opts);
|
|
246
238
|
};
|
|
247
239
|
return callback().catch(remapErrorsWithRetry(callback));
|
|
248
240
|
},
|
|
249
241
|
|
|
250
242
|
getParsedTransactions: (signatures: string[]) =>
|
|
251
|
-
connection
|
|
243
|
+
connection
|
|
252
244
|
.getParsedTransactions(signatures, {
|
|
253
245
|
maxSupportedTransactionVersion: 0,
|
|
254
246
|
})
|
|
255
247
|
.catch(remapErrors),
|
|
256
248
|
|
|
257
249
|
getAccountInfo: (address: string) =>
|
|
258
|
-
connection
|
|
250
|
+
connection
|
|
259
251
|
.getParsedAccountInfo(new PublicKey(address))
|
|
260
252
|
.then(r => r.value)
|
|
261
253
|
.catch(remapErrors),
|
|
262
254
|
|
|
263
255
|
getMultipleAccounts: (addresses: string[]) =>
|
|
264
|
-
connection
|
|
256
|
+
connection
|
|
265
257
|
.getMultipleParsedAccounts(addresses.map(address => new PublicKey(address)))
|
|
266
258
|
.then(r => r.value)
|
|
267
259
|
.catch(remapErrors),
|
|
268
260
|
|
|
269
261
|
sendRawTransaction: (buffer: Buffer, recentBlockhash?: BlockhashWithExpiryBlockHeight) => {
|
|
270
262
|
return (async () => {
|
|
271
|
-
const conn = connection();
|
|
272
263
|
const commitment = "confirmed";
|
|
273
264
|
|
|
274
|
-
const signature = await
|
|
265
|
+
const signature = await connection.sendRawTransaction(buffer, {
|
|
275
266
|
preflightCommitment: commitment,
|
|
276
267
|
});
|
|
277
268
|
|
|
278
269
|
if (!recentBlockhash) {
|
|
279
|
-
recentBlockhash = await
|
|
270
|
+
recentBlockhash = await connection.getLatestBlockhash(commitment);
|
|
280
271
|
}
|
|
281
|
-
const { value: status } = await
|
|
272
|
+
const { value: status } = await connection.confirmTransaction(
|
|
282
273
|
{
|
|
283
274
|
blockhash: recentBlockhash.blockhash,
|
|
284
275
|
lastValidBlockHeight: recentBlockhash.lastValidBlockHeight,
|
|
@@ -312,15 +303,15 @@ export function getChainAPI(
|
|
|
312
303
|
},
|
|
313
304
|
|
|
314
305
|
getAssocTokenAccMinNativeBalance: () =>
|
|
315
|
-
getMinimumBalanceForRentExemptAccount(connection
|
|
306
|
+
getMinimumBalanceForRentExemptAccount(connection).catch(remapErrors),
|
|
316
307
|
|
|
317
308
|
getMinimumBalanceForRentExemption: (dataLength: number) =>
|
|
318
|
-
connection
|
|
309
|
+
connection.getMinimumBalanceForRentExemption(dataLength).catch(remapErrors),
|
|
319
310
|
|
|
320
|
-
getEpochInfo: () => connection
|
|
311
|
+
getEpochInfo: () => connection.getEpochInfo().catch(remapErrors),
|
|
321
312
|
|
|
322
313
|
getRecentPrioritizationFees: (accounts: string[]) => {
|
|
323
|
-
return connection
|
|
314
|
+
return connection
|
|
324
315
|
.getRecentPrioritizationFees({
|
|
325
316
|
lockedWritableAccounts: accounts.map(acc => new PublicKey(acc)),
|
|
326
317
|
})
|
|
@@ -345,7 +336,7 @@ export function getChainAPI(
|
|
|
345
336
|
recentBlockhash: PublicKey.default.toString(),
|
|
346
337
|
}).compileToLegacyMessage(),
|
|
347
338
|
);
|
|
348
|
-
const rpcResponse = await connection
|
|
339
|
+
const rpcResponse = await connection.simulateTransaction(testTransaction, {
|
|
349
340
|
replaceRecentBlockhash: true,
|
|
350
341
|
sigVerify: false,
|
|
351
342
|
});
|
|
@@ -353,6 +344,6 @@ export function getChainAPI(
|
|
|
353
344
|
},
|
|
354
345
|
|
|
355
346
|
config,
|
|
356
|
-
connection
|
|
347
|
+
connection,
|
|
357
348
|
};
|
|
358
349
|
}
|
|
@@ -2,7 +2,7 @@ import { create } from "superstruct";
|
|
|
2
2
|
import { getChainAPI } from ".";
|
|
3
3
|
import { PARSED_PROGRAMS } from "./program/constants";
|
|
4
4
|
import { PublicKeyFromString } from "./validators/pubkey";
|
|
5
|
-
import { getMaybeTokenAccount } from "./web3";
|
|
5
|
+
import { getMaybeTokenAccount, getTransactions } from "./web3";
|
|
6
6
|
|
|
7
7
|
const api = getChainAPI({
|
|
8
8
|
endpoint: "https://solana.coin.ledger.com",
|
|
@@ -74,3 +74,23 @@ describe("findTokenAccAddress", () => {
|
|
|
74
74
|
expect(ata).toEqual(address);
|
|
75
75
|
});
|
|
76
76
|
});
|
|
77
|
+
|
|
78
|
+
describe("getTransactions", () => {
|
|
79
|
+
it.each([
|
|
80
|
+
{
|
|
81
|
+
address: "Cv9b7PuxVdKXTKTBXvZSQfSqbMNmPHP8brv77ZL2D95m",
|
|
82
|
+
untilTxSignature: undefined,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
address: "Hj69wRzkrFuf1Nby4yzPEFHdsmQdMoVYjvDKZSLjZFEp",
|
|
86
|
+
untilTxSignature: undefined,
|
|
87
|
+
},
|
|
88
|
+
])(
|
|
89
|
+
"returns the expected transactions without any fail transactions",
|
|
90
|
+
async ({ address, untilTxSignature }) => {
|
|
91
|
+
const txs = await getTransactions(address, untilTxSignature, api);
|
|
92
|
+
const hasError = txs.some(tx => tx.info.err);
|
|
93
|
+
expect(hasError).toBe(false);
|
|
94
|
+
},
|
|
95
|
+
);
|
|
96
|
+
});
|
|
@@ -122,12 +122,18 @@ async function* getTransactionsBatched(
|
|
|
122
122
|
const transactions = await api.getParsedTransactions(
|
|
123
123
|
signaturesInfoBatch.map(tx => tx.signature),
|
|
124
124
|
);
|
|
125
|
-
const
|
|
125
|
+
const sortedTransactions = transactions.sort((a, b) => (b?.slot ?? 0) - (a?.slot ?? 0));
|
|
126
|
+
const txsDetails = sortedTransactions.reduce((acc, tx) => {
|
|
126
127
|
if (tx && !tx.meta?.err && tx.blockTime) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
const info = signaturesInfoBatch.find(s =>
|
|
129
|
+
tx.transaction.signatures.includes(s.signature),
|
|
130
|
+
)!;
|
|
131
|
+
if (info) {
|
|
132
|
+
acc.push({
|
|
133
|
+
info,
|
|
134
|
+
parsed: tx,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
131
137
|
}
|
|
132
138
|
return acc;
|
|
133
139
|
}, [] as TransactionDescriptor[]);
|
package/src/network/index.ts
CHANGED
package/src/network/nft/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getEnv } from "@ledgerhq/live-env";
|
|
2
|
-
import network from "@ledgerhq/live-network
|
|
2
|
+
import network from "@ledgerhq/live-network";
|
|
3
3
|
import { NFTCollectionMetadataResponse, NFTMetadataResponse } from "@ledgerhq/types-live";
|
|
4
4
|
import { CollectionMetadataInput, NftMetadataInput } from "@ledgerhq/coin-framework/nft/types";
|
|
5
5
|
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
package/src/preload-data.ts
CHANGED
package/src/preload.test.ts
CHANGED
|
@@ -1,14 +1,123 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/consistent-type-assertions */
|
|
2
|
+
|
|
1
3
|
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
import { preloadWithAPI } from "./preload";
|
|
5
|
+
import { ChainAPI } from "./network";
|
|
6
|
+
import { getValidators, ValidatorsAppValidator } from "./network/validator-app";
|
|
7
|
+
import { Cluster } from "@solana/web3.js";
|
|
8
|
+
import { LEDGER_VALIDATOR_BY_CHORUS_ONE, LEDGER_VALIDATOR_BY_FIGMENT } from "./utils";
|
|
9
|
+
import { getSolanaPreloadData } from "./preload-data";
|
|
10
|
+
import { firstValueFrom } from "rxjs";
|
|
11
|
+
|
|
12
|
+
jest.mock("./network/validator-app");
|
|
13
|
+
|
|
14
|
+
const mockedGetValidators = jest.mocked(getValidators);
|
|
15
|
+
|
|
16
|
+
describe("preloadWithAPI", () => {
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
jest.clearAllMocks();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should return correctly the preloaded data for solana", async () => {
|
|
22
|
+
const validators: ValidatorsAppValidator[] = [
|
|
23
|
+
{
|
|
24
|
+
activeStake: 0,
|
|
25
|
+
commission: 1,
|
|
26
|
+
totalScore: 2,
|
|
27
|
+
voteAccount: "some random account",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
activeStake: 3,
|
|
31
|
+
commission: 4,
|
|
32
|
+
totalScore: 5,
|
|
33
|
+
voteAccount: "some random account 2",
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
mockedGetValidators.mockImplementationOnce((_cluster: Cluster) => Promise.resolve(validators));
|
|
37
|
+
|
|
38
|
+
const currency = {
|
|
39
|
+
id: "solana",
|
|
40
|
+
} as unknown as CryptoCurrency;
|
|
41
|
+
|
|
42
|
+
const result = await preloadWithAPI(currency, {} as unknown as ChainAPI);
|
|
43
|
+
expect(result).toEqual({
|
|
44
|
+
validators: expect.arrayContaining([
|
|
45
|
+
...validators,
|
|
46
|
+
LEDGER_VALIDATOR_BY_FIGMENT,
|
|
47
|
+
LEDGER_VALIDATOR_BY_CHORUS_ONE,
|
|
48
|
+
]),
|
|
49
|
+
validatorsWithMeta: [],
|
|
50
|
+
version: "1",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const solanaPreloadedData = await firstValueFrom(getSolanaPreloadData(currency));
|
|
54
|
+
expect(solanaPreloadedData).toEqual(result);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should return correctly the preloaded data for solana_devnet", async () => {
|
|
58
|
+
const voteAccount = {
|
|
59
|
+
activatedStake: 6,
|
|
60
|
+
commission: 7,
|
|
61
|
+
votePubkey: "some random account from account",
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const api = {
|
|
65
|
+
getVoteAccounts: () =>
|
|
66
|
+
Promise.resolve({
|
|
67
|
+
current: [voteAccount],
|
|
68
|
+
}),
|
|
69
|
+
} as unknown as ChainAPI;
|
|
70
|
+
|
|
71
|
+
const currency = {
|
|
72
|
+
id: "solana_devnet",
|
|
73
|
+
} as unknown as CryptoCurrency;
|
|
74
|
+
const result = await preloadWithAPI(currency, api);
|
|
75
|
+
expect(result).toEqual({
|
|
76
|
+
validators: expect.arrayContaining([
|
|
77
|
+
{
|
|
78
|
+
activeStake: voteAccount.activatedStake,
|
|
79
|
+
commission: voteAccount.commission,
|
|
80
|
+
voteAccount: voteAccount.votePubkey,
|
|
81
|
+
totalScore: 0,
|
|
82
|
+
},
|
|
83
|
+
]),
|
|
84
|
+
validatorsWithMeta: [],
|
|
85
|
+
version: "1",
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const solanaPreloadedData = await firstValueFrom(getSolanaPreloadData(currency));
|
|
89
|
+
expect(solanaPreloadedData).toEqual(result);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should return correctly the preloaded data for solana_testnet", async () => {
|
|
93
|
+
const validators: ValidatorsAppValidator[] = [
|
|
94
|
+
{
|
|
95
|
+
activeStake: 0,
|
|
96
|
+
commission: 1,
|
|
97
|
+
totalScore: 2,
|
|
98
|
+
voteAccount: "some random account",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
activeStake: 3,
|
|
102
|
+
commission: 4,
|
|
103
|
+
totalScore: 5,
|
|
104
|
+
voteAccount: "some random account 2",
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
mockedGetValidators.mockImplementationOnce((_cluster: Cluster) => Promise.resolve(validators));
|
|
108
|
+
|
|
109
|
+
const currency = {
|
|
110
|
+
id: "solana_testnet",
|
|
111
|
+
} as unknown as CryptoCurrency;
|
|
112
|
+
|
|
113
|
+
const result = await preloadWithAPI(currency, {} as unknown as ChainAPI);
|
|
114
|
+
expect(result).toEqual({
|
|
115
|
+
validators: expect.arrayContaining(validators),
|
|
116
|
+
validatorsWithMeta: [],
|
|
117
|
+
version: "1",
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const solanaPreloadedData = await firstValueFrom(getSolanaPreloadData(currency));
|
|
121
|
+
expect(solanaPreloadedData).toEqual(result);
|
|
122
|
+
});
|
|
14
123
|
});
|