@atomiqlabs/chain-solana 13.5.13 → 13.5.14
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/LICENSE +201 -201
- package/README.md +73 -73
- package/dist/index.d.ts +81 -81
- package/dist/index.js +102 -102
- package/dist/node/index.d.ts +9 -9
- package/dist/node/index.js +13 -13
- package/dist/solana/SolanaChainType.d.ts +15 -15
- package/dist/solana/SolanaChainType.js +2 -2
- package/dist/solana/SolanaChains.d.ts +12 -12
- package/dist/solana/SolanaChains.js +45 -45
- package/dist/solana/SolanaInitializer.d.ts +94 -94
- package/dist/solana/SolanaInitializer.js +174 -174
- package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +222 -222
- package/dist/solana/btcrelay/SolanaBtcRelay.js +455 -455
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.d.ts +84 -84
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.js +70 -70
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.d.ts +92 -92
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.js +109 -109
- package/dist/solana/btcrelay/program/programIdl.json +671 -671
- package/dist/solana/chain/SolanaAction.d.ts +26 -26
- package/dist/solana/chain/SolanaAction.js +87 -87
- package/dist/solana/chain/SolanaChainInterface.d.ts +224 -224
- package/dist/solana/chain/SolanaChainInterface.js +275 -275
- package/dist/solana/chain/SolanaModule.d.ts +14 -14
- package/dist/solana/chain/SolanaModule.js +13 -13
- package/dist/solana/chain/modules/SolanaAddresses.d.ts +8 -8
- package/dist/solana/chain/modules/SolanaAddresses.js +22 -22
- package/dist/solana/chain/modules/SolanaBlocks.d.ts +32 -32
- package/dist/solana/chain/modules/SolanaBlocks.js +78 -78
- package/dist/solana/chain/modules/SolanaEvents.d.ts +68 -68
- package/dist/solana/chain/modules/SolanaEvents.js +238 -238
- package/dist/solana/chain/modules/SolanaFees.d.ts +189 -189
- package/dist/solana/chain/modules/SolanaFees.js +434 -434
- package/dist/solana/chain/modules/SolanaSignatures.d.ts +24 -24
- package/dist/solana/chain/modules/SolanaSignatures.js +39 -39
- package/dist/solana/chain/modules/SolanaSlots.d.ts +33 -33
- package/dist/solana/chain/modules/SolanaSlots.js +72 -72
- package/dist/solana/chain/modules/SolanaTokens.d.ts +123 -123
- package/dist/solana/chain/modules/SolanaTokens.js +242 -242
- package/dist/solana/chain/modules/SolanaTransactions.d.ts +149 -149
- package/dist/solana/chain/modules/SolanaTransactions.js +445 -445
- package/dist/solana/connection/ConnectionWithRetries.d.ts +35 -35
- package/dist/solana/connection/ConnectionWithRetries.js +86 -71
- package/dist/solana/events/SolanaChainEvents.d.ts +45 -45
- package/dist/solana/events/SolanaChainEvents.js +108 -108
- package/dist/solana/events/SolanaChainEventsBrowser.d.ts +205 -205
- package/dist/solana/events/SolanaChainEventsBrowser.js +404 -404
- package/dist/solana/program/SolanaProgramBase.d.ts +73 -73
- package/dist/solana/program/SolanaProgramBase.js +54 -54
- package/dist/solana/program/SolanaProgramModule.d.ts +8 -8
- package/dist/solana/program/SolanaProgramModule.js +11 -11
- package/dist/solana/program/modules/SolanaProgramEvents.d.ts +53 -53
- package/dist/solana/program/modules/SolanaProgramEvents.js +117 -117
- package/dist/solana/swaps/SolanaSwapData.d.ts +333 -333
- package/dist/solana/swaps/SolanaSwapData.js +535 -535
- package/dist/solana/swaps/SolanaSwapModule.d.ts +11 -11
- package/dist/solana/swaps/SolanaSwapModule.js +12 -12
- package/dist/solana/swaps/SolanaSwapProgram.d.ts +376 -376
- package/dist/solana/swaps/SolanaSwapProgram.js +769 -769
- package/dist/solana/swaps/SwapTypeEnum.d.ts +11 -11
- package/dist/solana/swaps/SwapTypeEnum.js +43 -43
- package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +95 -95
- package/dist/solana/swaps/modules/SolanaDataAccount.js +232 -232
- package/dist/solana/swaps/modules/SolanaLpVault.d.ts +69 -69
- package/dist/solana/swaps/modules/SolanaLpVault.js +171 -171
- package/dist/solana/swaps/modules/SwapClaim.d.ts +126 -126
- package/dist/solana/swaps/modules/SwapClaim.js +294 -294
- package/dist/solana/swaps/modules/SwapInit.d.ts +213 -213
- package/dist/solana/swaps/modules/SwapInit.js +658 -658
- package/dist/solana/swaps/modules/SwapRefund.d.ts +87 -87
- package/dist/solana/swaps/modules/SwapRefund.js +293 -293
- package/dist/solana/swaps/programIdl.json +945 -945
- package/dist/solana/swaps/programTypes.d.ts +943 -943
- package/dist/solana/swaps/programTypes.js +945 -945
- package/dist/solana/swaps/v1/programIdl.json +945 -945
- package/dist/solana/swaps/v1/programTypes.d.ts +943 -943
- package/dist/solana/swaps/v1/programTypes.js +945 -945
- package/dist/solana/swaps/v2/programIdl.json +952 -952
- package/dist/solana/swaps/v2/programTypes.d.ts +950 -950
- package/dist/solana/swaps/v2/programTypes.js +952 -952
- package/dist/solana/wallet/SolanaKeypairWallet.d.ts +29 -29
- package/dist/solana/wallet/SolanaKeypairWallet.js +50 -50
- package/dist/solana/wallet/SolanaSigner.d.ts +30 -30
- package/dist/solana/wallet/SolanaSigner.js +30 -30
- package/dist/utils/Utils.d.ts +58 -58
- package/dist/utils/Utils.js +170 -170
- package/node/index.d.ts +1 -1
- package/node/index.js +3 -3
- package/package.json +46 -46
- package/src/index.ts +87 -87
- package/src/node/index.ts +9 -9
- package/src/solana/SolanaChainType.ts +32 -32
- package/src/solana/SolanaChains.ts +46 -46
- package/src/solana/SolanaInitializer.ts +278 -278
- package/src/solana/btcrelay/SolanaBtcRelay.ts +615 -615
- package/src/solana/btcrelay/headers/SolanaBtcHeader.ts +116 -116
- package/src/solana/btcrelay/headers/SolanaBtcStoredHeader.ts +148 -148
- package/src/solana/btcrelay/program/programIdl.json +670 -670
- package/src/solana/chain/SolanaAction.ts +109 -109
- package/src/solana/chain/SolanaChainInterface.ts +404 -404
- package/src/solana/chain/SolanaModule.ts +20 -20
- package/src/solana/chain/modules/SolanaAddresses.ts +20 -20
- package/src/solana/chain/modules/SolanaBlocks.ts +89 -89
- package/src/solana/chain/modules/SolanaEvents.ts +271 -271
- package/src/solana/chain/modules/SolanaFees.ts +522 -522
- package/src/solana/chain/modules/SolanaSignatures.ts +39 -39
- package/src/solana/chain/modules/SolanaSlots.ts +85 -85
- package/src/solana/chain/modules/SolanaTokens.ts +300 -300
- package/src/solana/chain/modules/SolanaTransactions.ts +503 -503
- package/src/solana/connection/ConnectionWithRetries.ts +113 -96
- package/src/solana/events/SolanaChainEvents.ts +127 -127
- package/src/solana/events/SolanaChainEventsBrowser.ts +495 -495
- package/src/solana/program/SolanaProgramBase.ts +119 -119
- package/src/solana/program/SolanaProgramModule.ts +15 -15
- package/src/solana/program/modules/SolanaProgramEvents.ts +157 -157
- package/src/solana/swaps/SolanaSwapData.ts +735 -735
- package/src/solana/swaps/SolanaSwapModule.ts +19 -19
- package/src/solana/swaps/SolanaSwapProgram.ts +1074 -1074
- package/src/solana/swaps/SwapTypeEnum.ts +30 -30
- package/src/solana/swaps/modules/SolanaDataAccount.ts +302 -302
- package/src/solana/swaps/modules/SolanaLpVault.ts +208 -208
- package/src/solana/swaps/modules/SwapClaim.ts +387 -387
- package/src/solana/swaps/modules/SwapInit.ts +785 -785
- package/src/solana/swaps/modules/SwapRefund.ts +353 -353
- package/src/solana/swaps/v1/programIdl.json +944 -944
- package/src/solana/swaps/v1/programTypes.ts +1885 -1885
- package/src/solana/swaps/v2/programIdl.json +951 -951
- package/src/solana/swaps/v2/programTypes.ts +1899 -1899
- package/src/solana/wallet/SolanaKeypairWallet.ts +56 -56
- package/src/solana/wallet/SolanaSigner.ts +43 -43
- package/src/utils/Utils.ts +194 -194
|
@@ -1,404 +1,404 @@
|
|
|
1
|
-
import {Connection, Keypair, PublicKey, SendOptions, Transaction} from "@solana/web3.js";
|
|
2
|
-
import {SolanaFees} from "./modules/SolanaFees";
|
|
3
|
-
import {SolanaBlocks} from "./modules/SolanaBlocks";
|
|
4
|
-
import {SolanaSlots} from "./modules/SolanaSlots";
|
|
5
|
-
import {SolanaTokens} from "./modules/SolanaTokens";
|
|
6
|
-
import {SignedSolanaTx, SolanaTransactions, SolanaTx} from "./modules/SolanaTransactions";
|
|
7
|
-
import {SolanaSignatures} from "./modules/SolanaSignatures";
|
|
8
|
-
import {SolanaEvents} from "./modules/SolanaEvents";
|
|
9
|
-
import {getLogger} from "../../utils/Utils";
|
|
10
|
-
import {BitcoinNetwork, ChainInterface, TransactionConfirmationOptions} from "@atomiqlabs/base";
|
|
11
|
-
import {SolanaAddresses} from "./modules/SolanaAddresses";
|
|
12
|
-
import {SolanaSigner} from "../wallet/SolanaSigner";
|
|
13
|
-
import {Buffer} from "buffer";
|
|
14
|
-
import {SolanaKeypairWallet} from "../wallet/SolanaKeypairWallet";
|
|
15
|
-
import {Wallet} from "@coral-xyz/anchor/dist/cjs/provider";
|
|
16
|
-
import {SolanaChains} from "../SolanaChains";
|
|
17
|
-
// @ts-ignore
|
|
18
|
-
import * as bs58 from "bs58";
|
|
19
|
-
|
|
20
|
-
const CLUSTER_BY_GENESIS_HASH: Record<string, "mainnet-beta" | "devnet" | "testnet"> = {
|
|
21
|
-
"5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d": "mainnet-beta",
|
|
22
|
-
"EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG": "devnet",
|
|
23
|
-
"4uhcVJyU9pJkvQyS88uRDiswHXSCkY3zQawwpjk2NsNY": "testnet",
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Retry policy configuration for Solana RPC calls
|
|
28
|
-
* @category Chain Interface
|
|
29
|
-
*/
|
|
30
|
-
export type SolanaRetryPolicy = {
|
|
31
|
-
/**
|
|
32
|
-
* Maximum retries to be attempted
|
|
33
|
-
*/
|
|
34
|
-
maxRetries?: number,
|
|
35
|
-
/**
|
|
36
|
-
* Default delay between retries
|
|
37
|
-
*/
|
|
38
|
-
delay?: number,
|
|
39
|
-
/**
|
|
40
|
-
* Whether the delays should scale exponentially, i.e. 1 second, 2 seconds, 4 seconds, 8 seconds
|
|
41
|
-
*/
|
|
42
|
-
exponential?: boolean,
|
|
43
|
-
/**
|
|
44
|
-
* Interval between re-sending Solana transaction to the RPC
|
|
45
|
-
*/
|
|
46
|
-
transactionResendInterval?: number
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Main chain interface for interacting with Solana blockchain
|
|
51
|
-
* @category Chain Interface
|
|
52
|
-
*/
|
|
53
|
-
export class SolanaChainInterface implements ChainInterface<
|
|
54
|
-
SolanaTx,
|
|
55
|
-
SignedSolanaTx,
|
|
56
|
-
SolanaSigner,
|
|
57
|
-
"SOLANA",
|
|
58
|
-
Wallet
|
|
59
|
-
> {
|
|
60
|
-
/**
|
|
61
|
-
* @inheritDoc
|
|
62
|
-
*/
|
|
63
|
-
readonly chainId = "SOLANA";
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Average Solana slot time in milliseconds.
|
|
67
|
-
* @internal
|
|
68
|
-
*/
|
|
69
|
-
readonly _SLOT_TIME = 400;
|
|
70
|
-
/**
|
|
71
|
-
* Approximate number of recent slots for which a transaction remains valid.
|
|
72
|
-
* @internal
|
|
73
|
-
*/
|
|
74
|
-
readonly _TX_SLOT_VALIDITY = 151;
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Underlying Solana web3.js connection.
|
|
78
|
-
* @internal
|
|
79
|
-
*/
|
|
80
|
-
readonly _connection: Connection;
|
|
81
|
-
/**
|
|
82
|
-
* Retry policy used by chain modules.
|
|
83
|
-
* @internal
|
|
84
|
-
*/
|
|
85
|
-
readonly _retryPolicy?: SolanaRetryPolicy;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Block-related read module.
|
|
89
|
-
*/
|
|
90
|
-
public readonly Blocks: SolanaBlocks;
|
|
91
|
-
/**
|
|
92
|
-
* Fee estimation and fee-rate module.
|
|
93
|
-
*/
|
|
94
|
-
public Fees: SolanaFees;
|
|
95
|
-
/**
|
|
96
|
-
* Slot-related read module.
|
|
97
|
-
*/
|
|
98
|
-
public readonly Slots: SolanaSlots;
|
|
99
|
-
/**
|
|
100
|
-
* Token operations module.
|
|
101
|
-
*/
|
|
102
|
-
public readonly Tokens: SolanaTokens;
|
|
103
|
-
/**
|
|
104
|
-
* Transaction send/confirm/serialization module.
|
|
105
|
-
*/
|
|
106
|
-
public readonly Transactions: SolanaTransactions;
|
|
107
|
-
/**
|
|
108
|
-
* Signature utilities module.
|
|
109
|
-
*/
|
|
110
|
-
public readonly Signatures: SolanaSignatures;
|
|
111
|
-
/**
|
|
112
|
-
* Event/log scanning module.
|
|
113
|
-
*/
|
|
114
|
-
public readonly Events: SolanaEvents;
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* @internal
|
|
118
|
-
*/
|
|
119
|
-
protected readonly logger = getLogger(this.constructor.name+": ");
|
|
120
|
-
|
|
121
|
-
constructor(
|
|
122
|
-
connection: Connection,
|
|
123
|
-
retryPolicy?: SolanaRetryPolicy,
|
|
124
|
-
solanaFeeEstimator: SolanaFees = new SolanaFees(connection)
|
|
125
|
-
) {
|
|
126
|
-
this._connection = connection;
|
|
127
|
-
this._retryPolicy = retryPolicy;
|
|
128
|
-
|
|
129
|
-
this.Blocks = new SolanaBlocks(this);
|
|
130
|
-
this.Fees = solanaFeeEstimator;
|
|
131
|
-
this.Slots = new SolanaSlots(this);
|
|
132
|
-
this.Tokens = new SolanaTokens(this);
|
|
133
|
-
this.Transactions = new SolanaTransactions(this);
|
|
134
|
-
this.Signatures = new SolanaSignatures(this);
|
|
135
|
-
this.Events = new SolanaEvents(this);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* @inheritDoc
|
|
140
|
-
*/
|
|
141
|
-
async getBalance(signer: string, tokenAddress: string): Promise<bigint> {
|
|
142
|
-
const token = new PublicKey(tokenAddress);
|
|
143
|
-
const publicKey = new PublicKey(signer);
|
|
144
|
-
|
|
145
|
-
let { balance } = await this.Tokens.getTokenBalance(publicKey, token);
|
|
146
|
-
if(token.equals(SolanaTokens.WSOL_ADDRESS)) {
|
|
147
|
-
const accountRentExemptCost = 1000000n;
|
|
148
|
-
balance = balance - accountRentExemptCost;
|
|
149
|
-
if(balance < 0n) balance = 0n;
|
|
150
|
-
}
|
|
151
|
-
this.logger.debug("getBalance(): token balance, token: "+token.toBase58()+" balance: "+balance.toString(10));
|
|
152
|
-
return balance;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* @inheritDoc
|
|
157
|
-
*/
|
|
158
|
-
isValidAddress(address: string): boolean {
|
|
159
|
-
return SolanaAddresses.isValidAddress(address);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* @inheritDoc
|
|
164
|
-
*/
|
|
165
|
-
normalizeAddress(address: string): string {
|
|
166
|
-
return address;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* @inheritDoc
|
|
171
|
-
*/
|
|
172
|
-
getNativeCurrencyAddress(): string {
|
|
173
|
-
return this.Tokens.getNativeCurrencyAddress().toString();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* @inheritDoc
|
|
178
|
-
*/
|
|
179
|
-
shouldGetNativeTokenDrop(tokenAddress: string): boolean {
|
|
180
|
-
// True for all the tokens, because the contracts don't support native SOL handling yet
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* @inheritDoc
|
|
186
|
-
*/
|
|
187
|
-
txsTransfer(signer: string, token: string, amount: bigint, dstAddress: string, feeRate?: string): Promise<SolanaTx[]> {
|
|
188
|
-
return this.Tokens.txsTransfer(new PublicKey(signer), new PublicKey(token), amount, new PublicKey(dstAddress), feeRate);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* @inheritDoc
|
|
193
|
-
*/
|
|
194
|
-
async transfer(
|
|
195
|
-
signer: SolanaSigner,
|
|
196
|
-
token: string,
|
|
197
|
-
amount: bigint,
|
|
198
|
-
dstAddress: string,
|
|
199
|
-
txOptions?: TransactionConfirmationOptions
|
|
200
|
-
): Promise<string> {
|
|
201
|
-
const txs = await this.Tokens.txsTransfer(signer.getPublicKey(), new PublicKey(token), amount, new PublicKey(dstAddress), txOptions?.feeRate);
|
|
202
|
-
const [txId] = await this.Transactions.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
|
|
203
|
-
return txId;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
////////////////////////////////////////////
|
|
208
|
-
//// Transactions
|
|
209
|
-
/**
|
|
210
|
-
* @inheritDoc
|
|
211
|
-
*/
|
|
212
|
-
sendAndConfirm(
|
|
213
|
-
signer: SolanaSigner,
|
|
214
|
-
txs: SolanaTx[],
|
|
215
|
-
waitForConfirmation?: boolean,
|
|
216
|
-
abortSignal?: AbortSignal,
|
|
217
|
-
parallel?: boolean,
|
|
218
|
-
onBeforePublish?: (txId: string, rawTx: string) => Promise<void>
|
|
219
|
-
): Promise<string[]> {
|
|
220
|
-
return this.Transactions.sendAndConfirm(signer, txs, waitForConfirmation, abortSignal, parallel, onBeforePublish);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* @inheritDoc
|
|
225
|
-
*/
|
|
226
|
-
sendSignedAndConfirm(
|
|
227
|
-
txs: SignedSolanaTx[],
|
|
228
|
-
waitForConfirmation?: boolean,
|
|
229
|
-
abortSignal?: AbortSignal,
|
|
230
|
-
parallel?: boolean,
|
|
231
|
-
onBeforePublish?: (txId: string, rawTx: string) => Promise<void>
|
|
232
|
-
): Promise<string[]> {
|
|
233
|
-
return this.Transactions.sendSignedAndConfirm(txs, waitForConfirmation, abortSignal, parallel, onBeforePublish);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* @inheritDoc
|
|
238
|
-
*/
|
|
239
|
-
async prepareTxs(txs: SolanaTx[]): Promise<SolanaTx[]> {
|
|
240
|
-
await this.Transactions.prepareTransactions(txs);
|
|
241
|
-
return txs;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* @inheritDoc
|
|
246
|
-
*/
|
|
247
|
-
serializeTx(tx: SolanaTx): Promise<string> {
|
|
248
|
-
return Promise.resolve(this.Transactions.serializeUnsignedTx(tx));
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* @inheritDoc
|
|
253
|
-
*/
|
|
254
|
-
deserializeTx(txData: string): Promise<SolanaTx> {
|
|
255
|
-
return Promise.resolve(this.Transactions.deserializeUnsignedTx(txData));
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* @inheritDoc
|
|
260
|
-
*/
|
|
261
|
-
serializeSignedTx(tx: Transaction): Promise<string> {
|
|
262
|
-
return Promise.resolve(this.Transactions.serializeSignedTx(tx));
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* @inheritDoc
|
|
267
|
-
*/
|
|
268
|
-
deserializeSignedTx(txData: string): Promise<Transaction> {
|
|
269
|
-
return Promise.resolve(this.Transactions.deserializeSignedTransaction(txData));
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* @inheritDoc
|
|
274
|
-
*/
|
|
275
|
-
getTxId(signedTX: SignedSolanaTx): Promise<string> {
|
|
276
|
-
return Promise.resolve(bs58.encode(signedTX.signature));
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* @inheritDoc
|
|
281
|
-
*/
|
|
282
|
-
getTxIdStatus(txId: string): Promise<"not_found" | "pending" | "success" | "reverted"> {
|
|
283
|
-
return this.Transactions.getTxIdStatus(txId);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* @inheritDoc
|
|
288
|
-
*/
|
|
289
|
-
getTxStatus(tx: string): Promise<"not_found" | "pending" | "success" | "reverted"> {
|
|
290
|
-
return this.Transactions.getTxStatus(tx);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* @inheritDoc
|
|
295
|
-
*/
|
|
296
|
-
async getFinalizedBlock(): Promise<{ height: number; blockHash: string }> {
|
|
297
|
-
const {block} = await this.Blocks.findLatestParsedBlock("finalized");
|
|
298
|
-
return {
|
|
299
|
-
height: block.blockHeight,
|
|
300
|
-
blockHash: block.blockhash
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
///////////////////////////////////
|
|
306
|
-
//// Callbacks & handlers
|
|
307
|
-
/**
|
|
308
|
-
* @inheritDoc
|
|
309
|
-
*/
|
|
310
|
-
offBeforeTxReplace(callback: (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => Promise<void>): boolean {
|
|
311
|
-
return true;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* @inheritDoc
|
|
316
|
-
*/
|
|
317
|
-
onBeforeTxReplace(callback: (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => Promise<void>): void {}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* @inheritDoc
|
|
321
|
-
*/
|
|
322
|
-
onBeforeTxSigned(callback: (tx: SolanaTx) => Promise<void>): void {
|
|
323
|
-
this.Transactions.onBeforeTxSigned(callback);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* @inheritDoc
|
|
328
|
-
*/
|
|
329
|
-
offBeforeTxSigned(callback: (tx: SolanaTx) => Promise<void>): boolean {
|
|
330
|
-
return this.Transactions.offBeforeTxSigned(callback);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Registers a low-level transaction sender override hook.
|
|
335
|
-
*
|
|
336
|
-
* @param callback Callback used for raw transaction publishing
|
|
337
|
-
*/
|
|
338
|
-
onSendTransaction(callback: (tx: Buffer, options?: SendOptions) => Promise<string>): void {
|
|
339
|
-
this.Transactions.onSendTransaction(callback);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Unregisters a previously registered transaction sender override hook.
|
|
344
|
-
*
|
|
345
|
-
* @param callback Previously registered callback
|
|
346
|
-
*/
|
|
347
|
-
offSendTransaction(callback: (tx: Buffer, options?: SendOptions) => Promise<string>): boolean {
|
|
348
|
-
return this.Transactions.offSendTransaction(callback);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* @inheritDoc
|
|
353
|
-
*/
|
|
354
|
-
isValidToken(tokenIdentifier: string): boolean {
|
|
355
|
-
try {
|
|
356
|
-
new PublicKey(tokenIdentifier);
|
|
357
|
-
return true;
|
|
358
|
-
} catch (e) {
|
|
359
|
-
return false;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* @inheritDoc
|
|
365
|
-
*/
|
|
366
|
-
randomAddress(): string {
|
|
367
|
-
return Keypair.generate().publicKey.toString();
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* @inheritDoc
|
|
372
|
-
*/
|
|
373
|
-
randomSigner(): SolanaSigner {
|
|
374
|
-
const keypair = Keypair.generate();
|
|
375
|
-
const wallet = new SolanaKeypairWallet(keypair);
|
|
376
|
-
return new SolanaSigner(wallet, keypair);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* @inheritDoc
|
|
381
|
-
*/
|
|
382
|
-
wrapSigner(signer: Wallet): Promise<SolanaSigner> {
|
|
383
|
-
return Promise.resolve(new SolanaSigner(signer));
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
async verifyNetwork(bitcoinNetwork: BitcoinNetwork): Promise<void> {
|
|
387
|
-
const genesisHash = await this._connection.getGenesisHash();
|
|
388
|
-
const result = CLUSTER_BY_GENESIS_HASH[genesisHash];
|
|
389
|
-
if(result==null) {
|
|
390
|
-
this.logger.warn(`verifyNetwork(): Unknown cluster detected, genesis hash: ${genesisHash}`);
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const deployment = SolanaChains[bitcoinNetwork];
|
|
395
|
-
if(deployment==null) {
|
|
396
|
-
this.logger.warn(`verifyNetwork(): No Solana deployment is defined for ${BitcoinNetwork[bitcoinNetwork]}, the RPC check is skipped.`);
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
if(deployment.clusterName!==result)
|
|
401
|
-
throw new Error(`Expected ${deployment.clusterName} Solana cluster for ${BitcoinNetwork[bitcoinNetwork]}, but got ${result}!`);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
}
|
|
1
|
+
import {Connection, Keypair, PublicKey, SendOptions, Transaction} from "@solana/web3.js";
|
|
2
|
+
import {SolanaFees} from "./modules/SolanaFees";
|
|
3
|
+
import {SolanaBlocks} from "./modules/SolanaBlocks";
|
|
4
|
+
import {SolanaSlots} from "./modules/SolanaSlots";
|
|
5
|
+
import {SolanaTokens} from "./modules/SolanaTokens";
|
|
6
|
+
import {SignedSolanaTx, SolanaTransactions, SolanaTx} from "./modules/SolanaTransactions";
|
|
7
|
+
import {SolanaSignatures} from "./modules/SolanaSignatures";
|
|
8
|
+
import {SolanaEvents} from "./modules/SolanaEvents";
|
|
9
|
+
import {getLogger} from "../../utils/Utils";
|
|
10
|
+
import {BitcoinNetwork, ChainInterface, TransactionConfirmationOptions} from "@atomiqlabs/base";
|
|
11
|
+
import {SolanaAddresses} from "./modules/SolanaAddresses";
|
|
12
|
+
import {SolanaSigner} from "../wallet/SolanaSigner";
|
|
13
|
+
import {Buffer} from "buffer";
|
|
14
|
+
import {SolanaKeypairWallet} from "../wallet/SolanaKeypairWallet";
|
|
15
|
+
import {Wallet} from "@coral-xyz/anchor/dist/cjs/provider";
|
|
16
|
+
import {SolanaChains} from "../SolanaChains";
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
import * as bs58 from "bs58";
|
|
19
|
+
|
|
20
|
+
const CLUSTER_BY_GENESIS_HASH: Record<string, "mainnet-beta" | "devnet" | "testnet"> = {
|
|
21
|
+
"5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d": "mainnet-beta",
|
|
22
|
+
"EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG": "devnet",
|
|
23
|
+
"4uhcVJyU9pJkvQyS88uRDiswHXSCkY3zQawwpjk2NsNY": "testnet",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Retry policy configuration for Solana RPC calls
|
|
28
|
+
* @category Chain Interface
|
|
29
|
+
*/
|
|
30
|
+
export type SolanaRetryPolicy = {
|
|
31
|
+
/**
|
|
32
|
+
* Maximum retries to be attempted
|
|
33
|
+
*/
|
|
34
|
+
maxRetries?: number,
|
|
35
|
+
/**
|
|
36
|
+
* Default delay between retries
|
|
37
|
+
*/
|
|
38
|
+
delay?: number,
|
|
39
|
+
/**
|
|
40
|
+
* Whether the delays should scale exponentially, i.e. 1 second, 2 seconds, 4 seconds, 8 seconds
|
|
41
|
+
*/
|
|
42
|
+
exponential?: boolean,
|
|
43
|
+
/**
|
|
44
|
+
* Interval between re-sending Solana transaction to the RPC
|
|
45
|
+
*/
|
|
46
|
+
transactionResendInterval?: number
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Main chain interface for interacting with Solana blockchain
|
|
51
|
+
* @category Chain Interface
|
|
52
|
+
*/
|
|
53
|
+
export class SolanaChainInterface implements ChainInterface<
|
|
54
|
+
SolanaTx,
|
|
55
|
+
SignedSolanaTx,
|
|
56
|
+
SolanaSigner,
|
|
57
|
+
"SOLANA",
|
|
58
|
+
Wallet
|
|
59
|
+
> {
|
|
60
|
+
/**
|
|
61
|
+
* @inheritDoc
|
|
62
|
+
*/
|
|
63
|
+
readonly chainId = "SOLANA";
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Average Solana slot time in milliseconds.
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
readonly _SLOT_TIME = 400;
|
|
70
|
+
/**
|
|
71
|
+
* Approximate number of recent slots for which a transaction remains valid.
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
readonly _TX_SLOT_VALIDITY = 151;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Underlying Solana web3.js connection.
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
80
|
+
readonly _connection: Connection;
|
|
81
|
+
/**
|
|
82
|
+
* Retry policy used by chain modules.
|
|
83
|
+
* @internal
|
|
84
|
+
*/
|
|
85
|
+
readonly _retryPolicy?: SolanaRetryPolicy;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Block-related read module.
|
|
89
|
+
*/
|
|
90
|
+
public readonly Blocks: SolanaBlocks;
|
|
91
|
+
/**
|
|
92
|
+
* Fee estimation and fee-rate module.
|
|
93
|
+
*/
|
|
94
|
+
public Fees: SolanaFees;
|
|
95
|
+
/**
|
|
96
|
+
* Slot-related read module.
|
|
97
|
+
*/
|
|
98
|
+
public readonly Slots: SolanaSlots;
|
|
99
|
+
/**
|
|
100
|
+
* Token operations module.
|
|
101
|
+
*/
|
|
102
|
+
public readonly Tokens: SolanaTokens;
|
|
103
|
+
/**
|
|
104
|
+
* Transaction send/confirm/serialization module.
|
|
105
|
+
*/
|
|
106
|
+
public readonly Transactions: SolanaTransactions;
|
|
107
|
+
/**
|
|
108
|
+
* Signature utilities module.
|
|
109
|
+
*/
|
|
110
|
+
public readonly Signatures: SolanaSignatures;
|
|
111
|
+
/**
|
|
112
|
+
* Event/log scanning module.
|
|
113
|
+
*/
|
|
114
|
+
public readonly Events: SolanaEvents;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @internal
|
|
118
|
+
*/
|
|
119
|
+
protected readonly logger = getLogger(this.constructor.name+": ");
|
|
120
|
+
|
|
121
|
+
constructor(
|
|
122
|
+
connection: Connection,
|
|
123
|
+
retryPolicy?: SolanaRetryPolicy,
|
|
124
|
+
solanaFeeEstimator: SolanaFees = new SolanaFees(connection)
|
|
125
|
+
) {
|
|
126
|
+
this._connection = connection;
|
|
127
|
+
this._retryPolicy = retryPolicy;
|
|
128
|
+
|
|
129
|
+
this.Blocks = new SolanaBlocks(this);
|
|
130
|
+
this.Fees = solanaFeeEstimator;
|
|
131
|
+
this.Slots = new SolanaSlots(this);
|
|
132
|
+
this.Tokens = new SolanaTokens(this);
|
|
133
|
+
this.Transactions = new SolanaTransactions(this);
|
|
134
|
+
this.Signatures = new SolanaSignatures(this);
|
|
135
|
+
this.Events = new SolanaEvents(this);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @inheritDoc
|
|
140
|
+
*/
|
|
141
|
+
async getBalance(signer: string, tokenAddress: string): Promise<bigint> {
|
|
142
|
+
const token = new PublicKey(tokenAddress);
|
|
143
|
+
const publicKey = new PublicKey(signer);
|
|
144
|
+
|
|
145
|
+
let { balance } = await this.Tokens.getTokenBalance(publicKey, token);
|
|
146
|
+
if(token.equals(SolanaTokens.WSOL_ADDRESS)) {
|
|
147
|
+
const accountRentExemptCost = 1000000n;
|
|
148
|
+
balance = balance - accountRentExemptCost;
|
|
149
|
+
if(balance < 0n) balance = 0n;
|
|
150
|
+
}
|
|
151
|
+
this.logger.debug("getBalance(): token balance, token: "+token.toBase58()+" balance: "+balance.toString(10));
|
|
152
|
+
return balance;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @inheritDoc
|
|
157
|
+
*/
|
|
158
|
+
isValidAddress(address: string): boolean {
|
|
159
|
+
return SolanaAddresses.isValidAddress(address);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @inheritDoc
|
|
164
|
+
*/
|
|
165
|
+
normalizeAddress(address: string): string {
|
|
166
|
+
return address;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @inheritDoc
|
|
171
|
+
*/
|
|
172
|
+
getNativeCurrencyAddress(): string {
|
|
173
|
+
return this.Tokens.getNativeCurrencyAddress().toString();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @inheritDoc
|
|
178
|
+
*/
|
|
179
|
+
shouldGetNativeTokenDrop(tokenAddress: string): boolean {
|
|
180
|
+
// True for all the tokens, because the contracts don't support native SOL handling yet
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @inheritDoc
|
|
186
|
+
*/
|
|
187
|
+
txsTransfer(signer: string, token: string, amount: bigint, dstAddress: string, feeRate?: string): Promise<SolanaTx[]> {
|
|
188
|
+
return this.Tokens.txsTransfer(new PublicKey(signer), new PublicKey(token), amount, new PublicKey(dstAddress), feeRate);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @inheritDoc
|
|
193
|
+
*/
|
|
194
|
+
async transfer(
|
|
195
|
+
signer: SolanaSigner,
|
|
196
|
+
token: string,
|
|
197
|
+
amount: bigint,
|
|
198
|
+
dstAddress: string,
|
|
199
|
+
txOptions?: TransactionConfirmationOptions
|
|
200
|
+
): Promise<string> {
|
|
201
|
+
const txs = await this.Tokens.txsTransfer(signer.getPublicKey(), new PublicKey(token), amount, new PublicKey(dstAddress), txOptions?.feeRate);
|
|
202
|
+
const [txId] = await this.Transactions.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
|
|
203
|
+
return txId;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
////////////////////////////////////////////
|
|
208
|
+
//// Transactions
|
|
209
|
+
/**
|
|
210
|
+
* @inheritDoc
|
|
211
|
+
*/
|
|
212
|
+
sendAndConfirm(
|
|
213
|
+
signer: SolanaSigner,
|
|
214
|
+
txs: SolanaTx[],
|
|
215
|
+
waitForConfirmation?: boolean,
|
|
216
|
+
abortSignal?: AbortSignal,
|
|
217
|
+
parallel?: boolean,
|
|
218
|
+
onBeforePublish?: (txId: string, rawTx: string) => Promise<void>
|
|
219
|
+
): Promise<string[]> {
|
|
220
|
+
return this.Transactions.sendAndConfirm(signer, txs, waitForConfirmation, abortSignal, parallel, onBeforePublish);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* @inheritDoc
|
|
225
|
+
*/
|
|
226
|
+
sendSignedAndConfirm(
|
|
227
|
+
txs: SignedSolanaTx[],
|
|
228
|
+
waitForConfirmation?: boolean,
|
|
229
|
+
abortSignal?: AbortSignal,
|
|
230
|
+
parallel?: boolean,
|
|
231
|
+
onBeforePublish?: (txId: string, rawTx: string) => Promise<void>
|
|
232
|
+
): Promise<string[]> {
|
|
233
|
+
return this.Transactions.sendSignedAndConfirm(txs, waitForConfirmation, abortSignal, parallel, onBeforePublish);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @inheritDoc
|
|
238
|
+
*/
|
|
239
|
+
async prepareTxs(txs: SolanaTx[]): Promise<SolanaTx[]> {
|
|
240
|
+
await this.Transactions.prepareTransactions(txs);
|
|
241
|
+
return txs;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* @inheritDoc
|
|
246
|
+
*/
|
|
247
|
+
serializeTx(tx: SolanaTx): Promise<string> {
|
|
248
|
+
return Promise.resolve(this.Transactions.serializeUnsignedTx(tx));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @inheritDoc
|
|
253
|
+
*/
|
|
254
|
+
deserializeTx(txData: string): Promise<SolanaTx> {
|
|
255
|
+
return Promise.resolve(this.Transactions.deserializeUnsignedTx(txData));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @inheritDoc
|
|
260
|
+
*/
|
|
261
|
+
serializeSignedTx(tx: Transaction): Promise<string> {
|
|
262
|
+
return Promise.resolve(this.Transactions.serializeSignedTx(tx));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @inheritDoc
|
|
267
|
+
*/
|
|
268
|
+
deserializeSignedTx(txData: string): Promise<Transaction> {
|
|
269
|
+
return Promise.resolve(this.Transactions.deserializeSignedTransaction(txData));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @inheritDoc
|
|
274
|
+
*/
|
|
275
|
+
getTxId(signedTX: SignedSolanaTx): Promise<string> {
|
|
276
|
+
return Promise.resolve(bs58.encode(signedTX.signature));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* @inheritDoc
|
|
281
|
+
*/
|
|
282
|
+
getTxIdStatus(txId: string): Promise<"not_found" | "pending" | "success" | "reverted"> {
|
|
283
|
+
return this.Transactions.getTxIdStatus(txId);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @inheritDoc
|
|
288
|
+
*/
|
|
289
|
+
getTxStatus(tx: string): Promise<"not_found" | "pending" | "success" | "reverted"> {
|
|
290
|
+
return this.Transactions.getTxStatus(tx);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* @inheritDoc
|
|
295
|
+
*/
|
|
296
|
+
async getFinalizedBlock(): Promise<{ height: number; blockHash: string }> {
|
|
297
|
+
const {block} = await this.Blocks.findLatestParsedBlock("finalized");
|
|
298
|
+
return {
|
|
299
|
+
height: block.blockHeight,
|
|
300
|
+
blockHash: block.blockhash
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
///////////////////////////////////
|
|
306
|
+
//// Callbacks & handlers
|
|
307
|
+
/**
|
|
308
|
+
* @inheritDoc
|
|
309
|
+
*/
|
|
310
|
+
offBeforeTxReplace(callback: (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => Promise<void>): boolean {
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* @inheritDoc
|
|
316
|
+
*/
|
|
317
|
+
onBeforeTxReplace(callback: (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => Promise<void>): void {}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* @inheritDoc
|
|
321
|
+
*/
|
|
322
|
+
onBeforeTxSigned(callback: (tx: SolanaTx) => Promise<void>): void {
|
|
323
|
+
this.Transactions.onBeforeTxSigned(callback);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* @inheritDoc
|
|
328
|
+
*/
|
|
329
|
+
offBeforeTxSigned(callback: (tx: SolanaTx) => Promise<void>): boolean {
|
|
330
|
+
return this.Transactions.offBeforeTxSigned(callback);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Registers a low-level transaction sender override hook.
|
|
335
|
+
*
|
|
336
|
+
* @param callback Callback used for raw transaction publishing
|
|
337
|
+
*/
|
|
338
|
+
onSendTransaction(callback: (tx: Buffer, options?: SendOptions) => Promise<string>): void {
|
|
339
|
+
this.Transactions.onSendTransaction(callback);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Unregisters a previously registered transaction sender override hook.
|
|
344
|
+
*
|
|
345
|
+
* @param callback Previously registered callback
|
|
346
|
+
*/
|
|
347
|
+
offSendTransaction(callback: (tx: Buffer, options?: SendOptions) => Promise<string>): boolean {
|
|
348
|
+
return this.Transactions.offSendTransaction(callback);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* @inheritDoc
|
|
353
|
+
*/
|
|
354
|
+
isValidToken(tokenIdentifier: string): boolean {
|
|
355
|
+
try {
|
|
356
|
+
new PublicKey(tokenIdentifier);
|
|
357
|
+
return true;
|
|
358
|
+
} catch (e) {
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* @inheritDoc
|
|
365
|
+
*/
|
|
366
|
+
randomAddress(): string {
|
|
367
|
+
return Keypair.generate().publicKey.toString();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* @inheritDoc
|
|
372
|
+
*/
|
|
373
|
+
randomSigner(): SolanaSigner {
|
|
374
|
+
const keypair = Keypair.generate();
|
|
375
|
+
const wallet = new SolanaKeypairWallet(keypair);
|
|
376
|
+
return new SolanaSigner(wallet, keypair);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* @inheritDoc
|
|
381
|
+
*/
|
|
382
|
+
wrapSigner(signer: Wallet): Promise<SolanaSigner> {
|
|
383
|
+
return Promise.resolve(new SolanaSigner(signer));
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
async verifyNetwork(bitcoinNetwork: BitcoinNetwork): Promise<void> {
|
|
387
|
+
const genesisHash = await this._connection.getGenesisHash();
|
|
388
|
+
const result = CLUSTER_BY_GENESIS_HASH[genesisHash];
|
|
389
|
+
if(result==null) {
|
|
390
|
+
this.logger.warn(`verifyNetwork(): Unknown cluster detected, genesis hash: ${genesisHash}`);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const deployment = SolanaChains[bitcoinNetwork];
|
|
395
|
+
if(deployment==null) {
|
|
396
|
+
this.logger.warn(`verifyNetwork(): No Solana deployment is defined for ${BitcoinNetwork[bitcoinNetwork]}, the RPC check is skipped.`);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if(deployment.clusterName!==result)
|
|
401
|
+
throw new Error(`Expected ${deployment.clusterName} Solana cluster for ${BitcoinNetwork[bitcoinNetwork]}, but got ${result}!`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
}
|