@atomiqlabs/chain-solana 12.0.13 → 12.0.15
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/dist/index.d.ts +29 -29
- package/dist/index.js +45 -45
- package/dist/solana/SolanaChainType.d.ts +11 -11
- package/dist/solana/SolanaChainType.js +2 -2
- package/dist/solana/SolanaChains.d.ts +20 -20
- package/dist/solana/SolanaChains.js +25 -25
- package/dist/solana/SolanaInitializer.d.ts +18 -18
- package/dist/solana/SolanaInitializer.js +63 -63
- package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +228 -228
- package/dist/solana/btcrelay/SolanaBtcRelay.js +441 -441
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.d.ts +29 -29
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.js +34 -34
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.d.ts +46 -46
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.js +78 -78
- package/dist/solana/btcrelay/program/programIdl.json +671 -671
- package/dist/solana/chain/SolanaAction.d.ts +26 -26
- package/dist/solana/chain/SolanaAction.js +86 -86
- package/dist/solana/chain/SolanaChainInterface.d.ts +65 -65
- package/dist/solana/chain/SolanaChainInterface.js +125 -125
- 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 +28 -28
- package/dist/solana/chain/modules/SolanaBlocks.js +72 -72
- package/dist/solana/chain/modules/SolanaEvents.d.ts +68 -68
- package/dist/solana/chain/modules/SolanaEvents.js +238 -225
- package/dist/solana/chain/modules/SolanaFees.d.ts +121 -121
- package/dist/solana/chain/modules/SolanaFees.js +379 -379
- package/dist/solana/chain/modules/SolanaSignatures.d.ts +23 -23
- package/dist/solana/chain/modules/SolanaSignatures.js +39 -39
- package/dist/solana/chain/modules/SolanaSlots.d.ts +31 -31
- package/dist/solana/chain/modules/SolanaSlots.js +68 -68
- package/dist/solana/chain/modules/SolanaTokens.d.ts +136 -136
- package/dist/solana/chain/modules/SolanaTokens.js +248 -248
- package/dist/solana/chain/modules/SolanaTransactions.d.ts +124 -124
- package/dist/solana/chain/modules/SolanaTransactions.js +323 -323
- package/dist/solana/events/SolanaChainEvents.d.ts +88 -88
- package/dist/solana/events/SolanaChainEvents.js +256 -256
- package/dist/solana/events/SolanaChainEventsBrowser.d.ts +75 -75
- package/dist/solana/events/SolanaChainEventsBrowser.js +172 -172
- package/dist/solana/program/SolanaProgramBase.d.ts +40 -40
- package/dist/solana/program/SolanaProgramBase.js +43 -43
- 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 +114 -114
- package/dist/solana/swaps/SolanaSwapData.d.ts +71 -71
- package/dist/solana/swaps/SolanaSwapData.js +292 -292
- package/dist/solana/swaps/SolanaSwapModule.d.ts +10 -10
- package/dist/solana/swaps/SolanaSwapModule.js +11 -11
- package/dist/solana/swaps/SolanaSwapProgram.d.ts +224 -224
- package/dist/solana/swaps/SolanaSwapProgram.js +570 -570
- package/dist/solana/swaps/SwapTypeEnum.d.ts +11 -11
- package/dist/solana/swaps/SwapTypeEnum.js +42 -42
- package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +94 -94
- package/dist/solana/swaps/modules/SolanaDataAccount.js +231 -231
- package/dist/solana/swaps/modules/SolanaLpVault.d.ts +71 -71
- package/dist/solana/swaps/modules/SolanaLpVault.js +173 -173
- package/dist/solana/swaps/modules/SwapClaim.d.ts +129 -129
- package/dist/solana/swaps/modules/SwapClaim.js +291 -291
- package/dist/solana/swaps/modules/SwapInit.d.ts +217 -217
- package/dist/solana/swaps/modules/SwapInit.js +519 -519
- package/dist/solana/swaps/modules/SwapRefund.d.ts +82 -82
- package/dist/solana/swaps/modules/SwapRefund.js +262 -262
- 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/wallet/SolanaKeypairWallet.d.ts +9 -9
- package/dist/solana/wallet/SolanaKeypairWallet.js +33 -33
- package/dist/solana/wallet/SolanaSigner.d.ts +11 -11
- package/dist/solana/wallet/SolanaSigner.js +17 -17
- package/dist/utils/Utils.d.ts +53 -53
- package/dist/utils/Utils.js +170 -170
- package/package.json +41 -41
- package/src/index.ts +36 -36
- package/src/solana/SolanaChainType.ts +27 -27
- package/src/solana/SolanaChains.ts +23 -23
- package/src/solana/SolanaInitializer.ts +102 -102
- package/src/solana/btcrelay/SolanaBtcRelay.ts +589 -589
- package/src/solana/btcrelay/headers/SolanaBtcHeader.ts +57 -57
- package/src/solana/btcrelay/headers/SolanaBtcStoredHeader.ts +102 -102
- package/src/solana/btcrelay/program/programIdl.json +670 -670
- package/src/solana/chain/SolanaAction.ts +108 -108
- package/src/solana/chain/SolanaChainInterface.ts +192 -192
- package/src/solana/chain/SolanaModule.ts +20 -20
- package/src/solana/chain/modules/SolanaAddresses.ts +20 -20
- package/src/solana/chain/modules/SolanaBlocks.ts +78 -78
- package/src/solana/chain/modules/SolanaEvents.ts +270 -256
- package/src/solana/chain/modules/SolanaFees.ts +450 -450
- package/src/solana/chain/modules/SolanaSignatures.ts +39 -39
- package/src/solana/chain/modules/SolanaSlots.ts +82 -82
- package/src/solana/chain/modules/SolanaTokens.ts +307 -307
- package/src/solana/chain/modules/SolanaTransactions.ts +365 -365
- package/src/solana/events/SolanaChainEvents.ts +299 -299
- package/src/solana/events/SolanaChainEventsBrowser.ts +209 -209
- package/src/solana/program/SolanaProgramBase.ts +79 -79
- package/src/solana/program/SolanaProgramModule.ts +15 -15
- package/src/solana/program/modules/SolanaProgramEvents.ts +155 -155
- package/src/solana/swaps/SolanaSwapData.ts +430 -430
- package/src/solana/swaps/SolanaSwapModule.ts +16 -16
- package/src/solana/swaps/SolanaSwapProgram.ts +854 -854
- package/src/solana/swaps/SwapTypeEnum.ts +29 -29
- package/src/solana/swaps/modules/SolanaDataAccount.ts +307 -307
- package/src/solana/swaps/modules/SolanaLpVault.ts +215 -215
- package/src/solana/swaps/modules/SwapClaim.ts +389 -389
- package/src/solana/swaps/modules/SwapInit.ts +663 -663
- package/src/solana/swaps/modules/SwapRefund.ts +323 -323
- package/src/solana/swaps/programIdl.json +944 -944
- package/src/solana/swaps/programTypes.ts +1885 -1885
- package/src/solana/wallet/SolanaKeypairWallet.ts +36 -36
- package/src/solana/wallet/SolanaSigner.ts +24 -24
- package/src/utils/Utils.ts +180 -180
|
@@ -1,257 +1,271 @@
|
|
|
1
|
-
import {SolanaModule} from "../SolanaModule";
|
|
2
|
-
import {ConfirmedSignatureInfo, ParsedTransactionWithMeta, PublicKey} from "@solana/web3.js";
|
|
3
|
-
import {sign} from "tweetnacl";
|
|
4
|
-
import {ProgramEvent} from "../../program/modules/SolanaProgramEvents";
|
|
5
|
-
import {tryWithRetries} from "../../../utils/Utils";
|
|
6
|
-
|
|
7
|
-
export class SolanaEvents extends SolanaModule {
|
|
8
|
-
|
|
9
|
-
public readonly LOG_FETCH_LIMIT = 500;
|
|
10
|
-
|
|
11
|
-
private usingHeliusTFA: "yes" | "no" | "auto" = "auto";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Gets the signatures for a given topicKey public key, if lastProcessedSignature is specified, it fetches only
|
|
15
|
-
* the signatures before this signature
|
|
16
|
-
*
|
|
17
|
-
* @param topicKey
|
|
18
|
-
* @param logFetchLimit
|
|
19
|
-
* @param lastProcessedSignature
|
|
20
|
-
* @private
|
|
21
|
-
*/
|
|
22
|
-
private getSignatures(topicKey: PublicKey, logFetchLimit: number, lastProcessedSignature?: string): Promise<ConfirmedSignatureInfo[]> {
|
|
23
|
-
if(lastProcessedSignature==null) {
|
|
24
|
-
return this.connection.getSignaturesForAddress(topicKey, {
|
|
25
|
-
limit: logFetchLimit,
|
|
26
|
-
}, "confirmed");
|
|
27
|
-
} else {
|
|
28
|
-
return this.connection.getSignaturesForAddress(topicKey, {
|
|
29
|
-
before: lastProcessedSignature,
|
|
30
|
-
limit: logFetchLimit
|
|
31
|
-
}, "confirmed");
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Implements Helius getTransactionsForAddress RPC API
|
|
37
|
-
*
|
|
38
|
-
* @param account
|
|
39
|
-
* @param options
|
|
40
|
-
* @param commitment
|
|
41
|
-
*/
|
|
42
|
-
async getTransactionsForAddress(
|
|
43
|
-
account: PublicKey,
|
|
44
|
-
options?: {
|
|
45
|
-
paginationToken?: string,
|
|
46
|
-
filters?: {
|
|
47
|
-
slot?: {gte?: number, lte?: number, gt?: number, lt?: number},
|
|
48
|
-
blockTime?: {gte?: number, lte?: number, gt?: number, lt?: number, eq?: number},
|
|
49
|
-
signature?: {gte?: number, lte?: number, gt?: number, lt?: number, eq?: number},
|
|
50
|
-
status?: "succeeded" | "failed" | "any"
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
commitment?: "finalized" | "confirmed" | "processed"
|
|
54
|
-
): Promise<{
|
|
55
|
-
data: ParsedTransactionWithMeta[],
|
|
56
|
-
paginationToken?: string
|
|
57
|
-
}> {
|
|
58
|
-
const limit = 100;
|
|
59
|
-
|
|
60
|
-
//Try to use getPriorityFeeEstimate api of Helius
|
|
61
|
-
const response = await (this.connection as any)._rpcRequest("getTransactionsForAddress", [
|
|
62
|
-
account.toString(),
|
|
63
|
-
{
|
|
64
|
-
...options,
|
|
65
|
-
transactionDetails: "full",
|
|
66
|
-
sortOrder: "desc",
|
|
67
|
-
limit,
|
|
68
|
-
commitment: commitment ?? "confirmed",
|
|
69
|
-
encoding: "jsonParsed",
|
|
70
|
-
maxSupportedTransactionVersion: 0
|
|
71
|
-
}
|
|
72
|
-
]).catch(e => {
|
|
73
|
-
//Catching not supported errors
|
|
74
|
-
if(e.message!=null && (e.message.includes("-32601") || e.message.includes("-32600") || e.message.includes("-32403"))) {
|
|
75
|
-
return {
|
|
76
|
-
error: {
|
|
77
|
-
code: -32601,
|
|
78
|
-
message: e.message
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
throw e;
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
if(response.error!=null) {
|
|
86
|
-
//Catching not supported errors
|
|
87
|
-
if(response.error.code!==-32601 && response.error.code!==-32600 && response.error.code!==-32403) throw new Error(response.error.message);
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
data: response.result.data.map(val => {
|
|
93
|
-
return {
|
|
94
|
-
...val, //slot, blockTime, version
|
|
95
|
-
meta: val.meta==null ? undefined : {
|
|
96
|
-
//ParsedTransactionMeta
|
|
97
|
-
...val.meta,
|
|
98
|
-
innerInstructions: val.meta.innerInstructions==null ? undefined : val.meta.innerInstructions.map(innerIx => ({
|
|
99
|
-
//ParsedInnerInstruction
|
|
100
|
-
...innerIx, //index
|
|
101
|
-
instructions: innerIx.instructions.map(ix => {
|
|
102
|
-
if(ix.program!=null && ix.programId!=null) {
|
|
103
|
-
return {
|
|
104
|
-
//ParsedInstruction
|
|
105
|
-
...ix,
|
|
106
|
-
programId: new PublicKey(ix.programId)
|
|
107
|
-
}
|
|
108
|
-
} else {
|
|
109
|
-
return {
|
|
110
|
-
//PartiallyDecodedInstruction
|
|
111
|
-
data: ix.data,
|
|
112
|
-
programId: new PublicKey(ix.programId),
|
|
113
|
-
accounts: ix.accounts.map(pubkey => new PublicKey(pubkey))
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
})),
|
|
118
|
-
loadedAddresses: val.meta.loadedAddresses==null ? undefined : {
|
|
119
|
-
writable: val.meta.loadedAddresses.writable.map(pubkey => new PublicKey(pubkey)),
|
|
120
|
-
readonly: val.meta.loadedAddresses.readonly.map(pubkey => new PublicKey(pubkey)),
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
transaction: {
|
|
124
|
-
//ParsedTransaction
|
|
125
|
-
...val.transaction, //signatures
|
|
126
|
-
message: {
|
|
127
|
-
//ParsedMessage
|
|
128
|
-
...val.transaction.message, //recentBlockhash
|
|
129
|
-
accountKeys: val.transaction.message.accountKeys.map(accountKey => ({
|
|
130
|
-
//ParsedMessageAccount
|
|
131
|
-
...accountKey,
|
|
132
|
-
pubkey: new PublicKey(accountKey.pubkey)
|
|
133
|
-
})),
|
|
134
|
-
instructions: val.transaction.message.instructions.map(ix => {
|
|
135
|
-
if(ix.program!=null && ix.programId!=null) {
|
|
136
|
-
return {
|
|
137
|
-
//ParsedInstruction
|
|
138
|
-
...ix,
|
|
139
|
-
programId: new PublicKey(ix.programId)
|
|
140
|
-
}
|
|
141
|
-
} else {
|
|
142
|
-
return {
|
|
143
|
-
//PartiallyDecodedInstruction
|
|
144
|
-
data: ix.data,
|
|
145
|
-
programId: new PublicKey(ix.programId),
|
|
146
|
-
accounts: ix.accounts.map(pubkey => new PublicKey(pubkey))
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}),
|
|
150
|
-
addressTableLookups: val.transaction.message.addressTableLookups==null ? undefined : val.transaction.message.addressTableLookups.map(addressTableLookup => ({
|
|
151
|
-
//ParsedAddressTableLookup
|
|
152
|
-
...addressTableLookup,
|
|
153
|
-
accountKey: new PublicKey(addressTableLookup.accountKey)
|
|
154
|
-
}))
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}),
|
|
159
|
-
paginationToken: response.result.
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
private async _findInTxsTFA<T>(
|
|
164
|
-
topicKey: PublicKey,
|
|
165
|
-
processor: (data: {signatures?: ConfirmedSignatureInfo[], txs?: ParsedTransactionWithMeta[]}) => Promise<T>,
|
|
166
|
-
abortSignal?: AbortSignal,
|
|
167
|
-
startBlockheight?: number
|
|
168
|
-
): Promise<T> {
|
|
169
|
-
let paginationToken: string;
|
|
170
|
-
let txs: ParsedTransactionWithMeta[] = null;
|
|
171
|
-
while(txs==null || txs.length>0) {
|
|
172
|
-
let filters = startBlockheight!=null ? {
|
|
173
|
-
slot: {gte: startBlockheight}
|
|
174
|
-
} : {};
|
|
175
|
-
const tfaResult = await tryWithRetries(
|
|
176
|
-
() => this.getTransactionsForAddress(topicKey, {
|
|
177
|
-
paginationToken,
|
|
178
|
-
filters: {
|
|
179
|
-
...filters,
|
|
180
|
-
status: "succeeded"
|
|
181
|
-
}
|
|
182
|
-
}, "confirmed"),
|
|
183
|
-
undefined, undefined, abortSignal
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
if(tfaResult==null) {
|
|
187
|
-
//Not supported
|
|
188
|
-
return undefined;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
txs = tfaResult.data;
|
|
192
|
-
paginationToken = tfaResult.paginationToken;
|
|
193
|
-
|
|
194
|
-
if(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
1
|
+
import {SolanaModule} from "../SolanaModule";
|
|
2
|
+
import {ConfirmedSignatureInfo, ParsedTransactionWithMeta, PublicKey} from "@solana/web3.js";
|
|
3
|
+
import {sign} from "tweetnacl";
|
|
4
|
+
import {ProgramEvent} from "../../program/modules/SolanaProgramEvents";
|
|
5
|
+
import {tryWithRetries} from "../../../utils/Utils";
|
|
6
|
+
|
|
7
|
+
export class SolanaEvents extends SolanaModule {
|
|
8
|
+
|
|
9
|
+
public readonly LOG_FETCH_LIMIT = 500;
|
|
10
|
+
|
|
11
|
+
private usingHeliusTFA: "yes" | "no" | "auto" = "auto";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Gets the signatures for a given topicKey public key, if lastProcessedSignature is specified, it fetches only
|
|
15
|
+
* the signatures before this signature
|
|
16
|
+
*
|
|
17
|
+
* @param topicKey
|
|
18
|
+
* @param logFetchLimit
|
|
19
|
+
* @param lastProcessedSignature
|
|
20
|
+
* @private
|
|
21
|
+
*/
|
|
22
|
+
private getSignatures(topicKey: PublicKey, logFetchLimit: number, lastProcessedSignature?: string): Promise<ConfirmedSignatureInfo[]> {
|
|
23
|
+
if(lastProcessedSignature==null) {
|
|
24
|
+
return this.connection.getSignaturesForAddress(topicKey, {
|
|
25
|
+
limit: logFetchLimit,
|
|
26
|
+
}, "confirmed");
|
|
27
|
+
} else {
|
|
28
|
+
return this.connection.getSignaturesForAddress(topicKey, {
|
|
29
|
+
before: lastProcessedSignature,
|
|
30
|
+
limit: logFetchLimit
|
|
31
|
+
}, "confirmed");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Implements Helius getTransactionsForAddress RPC API
|
|
37
|
+
*
|
|
38
|
+
* @param account
|
|
39
|
+
* @param options
|
|
40
|
+
* @param commitment
|
|
41
|
+
*/
|
|
42
|
+
async getTransactionsForAddress(
|
|
43
|
+
account: PublicKey,
|
|
44
|
+
options?: {
|
|
45
|
+
paginationToken?: string,
|
|
46
|
+
filters?: {
|
|
47
|
+
slot?: {gte?: number, lte?: number, gt?: number, lt?: number},
|
|
48
|
+
blockTime?: {gte?: number, lte?: number, gt?: number, lt?: number, eq?: number},
|
|
49
|
+
signature?: {gte?: number, lte?: number, gt?: number, lt?: number, eq?: number},
|
|
50
|
+
status?: "succeeded" | "failed" | "any"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
commitment?: "finalized" | "confirmed" | "processed"
|
|
54
|
+
): Promise<{
|
|
55
|
+
data: ParsedTransactionWithMeta[],
|
|
56
|
+
paginationToken?: string
|
|
57
|
+
}> {
|
|
58
|
+
const limit = 100;
|
|
59
|
+
|
|
60
|
+
//Try to use getPriorityFeeEstimate api of Helius
|
|
61
|
+
const response = await (this.connection as any)._rpcRequest("getTransactionsForAddress", [
|
|
62
|
+
account.toString(),
|
|
63
|
+
{
|
|
64
|
+
...options,
|
|
65
|
+
transactionDetails: "full",
|
|
66
|
+
sortOrder: "desc",
|
|
67
|
+
limit,
|
|
68
|
+
commitment: commitment ?? "confirmed",
|
|
69
|
+
encoding: "jsonParsed",
|
|
70
|
+
maxSupportedTransactionVersion: 0
|
|
71
|
+
}
|
|
72
|
+
]).catch(e => {
|
|
73
|
+
//Catching not supported errors
|
|
74
|
+
if(e.message!=null && (e.message.includes("-32601") || e.message.includes("-32600") || e.message.includes("-32403"))) {
|
|
75
|
+
return {
|
|
76
|
+
error: {
|
|
77
|
+
code: -32601,
|
|
78
|
+
message: e.message
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
throw e;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if(response.error!=null) {
|
|
86
|
+
//Catching not supported errors
|
|
87
|
+
if(response.error.code!==-32601 && response.error.code!==-32600 && response.error.code!==-32403) throw new Error(response.error.message);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
data: response.result.data.map(val => {
|
|
93
|
+
return {
|
|
94
|
+
...val, //slot, blockTime, version
|
|
95
|
+
meta: val.meta==null ? undefined : {
|
|
96
|
+
//ParsedTransactionMeta
|
|
97
|
+
...val.meta,
|
|
98
|
+
innerInstructions: val.meta.innerInstructions==null ? undefined : val.meta.innerInstructions.map(innerIx => ({
|
|
99
|
+
//ParsedInnerInstruction
|
|
100
|
+
...innerIx, //index
|
|
101
|
+
instructions: innerIx.instructions.map(ix => {
|
|
102
|
+
if(ix.program!=null && ix.programId!=null) {
|
|
103
|
+
return {
|
|
104
|
+
//ParsedInstruction
|
|
105
|
+
...ix,
|
|
106
|
+
programId: new PublicKey(ix.programId)
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
return {
|
|
110
|
+
//PartiallyDecodedInstruction
|
|
111
|
+
data: ix.data,
|
|
112
|
+
programId: new PublicKey(ix.programId),
|
|
113
|
+
accounts: ix.accounts.map(pubkey => new PublicKey(pubkey))
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
})),
|
|
118
|
+
loadedAddresses: val.meta.loadedAddresses==null ? undefined : {
|
|
119
|
+
writable: val.meta.loadedAddresses.writable.map(pubkey => new PublicKey(pubkey)),
|
|
120
|
+
readonly: val.meta.loadedAddresses.readonly.map(pubkey => new PublicKey(pubkey)),
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
transaction: {
|
|
124
|
+
//ParsedTransaction
|
|
125
|
+
...val.transaction, //signatures
|
|
126
|
+
message: {
|
|
127
|
+
//ParsedMessage
|
|
128
|
+
...val.transaction.message, //recentBlockhash
|
|
129
|
+
accountKeys: val.transaction.message.accountKeys.map(accountKey => ({
|
|
130
|
+
//ParsedMessageAccount
|
|
131
|
+
...accountKey,
|
|
132
|
+
pubkey: new PublicKey(accountKey.pubkey)
|
|
133
|
+
})),
|
|
134
|
+
instructions: val.transaction.message.instructions.map(ix => {
|
|
135
|
+
if(ix.program!=null && ix.programId!=null) {
|
|
136
|
+
return {
|
|
137
|
+
//ParsedInstruction
|
|
138
|
+
...ix,
|
|
139
|
+
programId: new PublicKey(ix.programId)
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
return {
|
|
143
|
+
//PartiallyDecodedInstruction
|
|
144
|
+
data: ix.data,
|
|
145
|
+
programId: new PublicKey(ix.programId),
|
|
146
|
+
accounts: ix.accounts.map(pubkey => new PublicKey(pubkey))
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}),
|
|
150
|
+
addressTableLookups: val.transaction.message.addressTableLookups==null ? undefined : val.transaction.message.addressTableLookups.map(addressTableLookup => ({
|
|
151
|
+
//ParsedAddressTableLookup
|
|
152
|
+
...addressTableLookup,
|
|
153
|
+
accountKey: new PublicKey(addressTableLookup.accountKey)
|
|
154
|
+
}))
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}),
|
|
159
|
+
paginationToken: response.result.paginationToken
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private async _findInTxsTFA<T>(
|
|
164
|
+
topicKey: PublicKey,
|
|
165
|
+
processor: (data: {signatures?: ConfirmedSignatureInfo[], txs?: ParsedTransactionWithMeta[]}) => Promise<T>,
|
|
166
|
+
abortSignal?: AbortSignal,
|
|
167
|
+
startBlockheight?: number
|
|
168
|
+
): Promise<T> {
|
|
169
|
+
let paginationToken: string;
|
|
170
|
+
let txs: ParsedTransactionWithMeta[] = null;
|
|
171
|
+
while(txs==null || txs.length>0) {
|
|
172
|
+
let filters = startBlockheight!=null ? {
|
|
173
|
+
slot: {gte: startBlockheight}
|
|
174
|
+
} : {};
|
|
175
|
+
const tfaResult = await tryWithRetries(
|
|
176
|
+
() => this.getTransactionsForAddress(topicKey, {
|
|
177
|
+
paginationToken,
|
|
178
|
+
filters: {
|
|
179
|
+
...filters,
|
|
180
|
+
status: "succeeded"
|
|
181
|
+
}
|
|
182
|
+
}, "confirmed"),
|
|
183
|
+
undefined, undefined, abortSignal
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
if(tfaResult==null) {
|
|
187
|
+
//Not supported
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
txs = tfaResult.data;
|
|
192
|
+
paginationToken = tfaResult.paginationToken;
|
|
193
|
+
|
|
194
|
+
if(txs.length===0) {
|
|
195
|
+
this.logger.debug(`_findInTxsTFA(): Got ${txs.length} txns (empty response), paginationToken: ${paginationToken}`);
|
|
196
|
+
} else {
|
|
197
|
+
this.logger.debug(`_findInTxsTFA(): Got ${txs.length} txns (${txs[0].transaction.signatures[0]}..${txs[txs.length-1].transaction.signatures[0]}), paginationToken: ${paginationToken}`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if(abortSignal!=null) abortSignal.throwIfAborted();
|
|
201
|
+
const result: T = await processor({txs});
|
|
202
|
+
if(result!=null) return result;
|
|
203
|
+
if(paginationToken==null) break;
|
|
204
|
+
}
|
|
205
|
+
return null;
|
|
206
|
+
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Runs a search backwards in time, processing transaction signatures for a specific topic public key
|
|
211
|
+
*
|
|
212
|
+
* @param topicKey
|
|
213
|
+
* @param processor called for every batch of returned signatures, should return a value if the correct signature
|
|
214
|
+
* was found, or null if the search should continue
|
|
215
|
+
* @param abortSignal
|
|
216
|
+
* @param logFetchLimit
|
|
217
|
+
* @param startBlockheight
|
|
218
|
+
*/
|
|
219
|
+
private async _findInSignatures<T>(
|
|
220
|
+
topicKey: PublicKey,
|
|
221
|
+
processor: (data: {signatures?: ConfirmedSignatureInfo[], txs?: ParsedTransactionWithMeta[]}) => Promise<T>,
|
|
222
|
+
abortSignal?: AbortSignal,
|
|
223
|
+
logFetchLimit?: number,
|
|
224
|
+
startBlockheight?: number
|
|
225
|
+
): Promise<T> {
|
|
226
|
+
if(logFetchLimit==null || logFetchLimit>this.LOG_FETCH_LIMIT) logFetchLimit = this.LOG_FETCH_LIMIT;
|
|
227
|
+
let signatures: ConfirmedSignatureInfo[] = null;
|
|
228
|
+
while(signatures==null || signatures.length>0) {
|
|
229
|
+
signatures = await this.getSignatures(topicKey, logFetchLimit, signatures!=null ? signatures[signatures.length-1].signature : null);
|
|
230
|
+
if(startBlockheight!=null) {
|
|
231
|
+
const endIndex = signatures.findIndex(val => val.slot < startBlockheight);
|
|
232
|
+
if(endIndex===0) return null;
|
|
233
|
+
if(endIndex!==-1) signatures = signatures.slice(0, endIndex - 1);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if(signatures.length===0) {
|
|
237
|
+
this.logger.debug(`_findInSignatures(): Got ${signatures.length} txns (empty response)`);
|
|
238
|
+
} else {
|
|
239
|
+
this.logger.debug(`_findInSignatures(): Got ${signatures.length} txns (${signatures[0].signature}..${signatures[signatures.length-1].signature})`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if(abortSignal!=null) abortSignal.throwIfAborted();
|
|
243
|
+
const result: T = await processor({signatures});
|
|
244
|
+
if(result!=null) return result;
|
|
245
|
+
if(signatures.length<logFetchLimit) break;
|
|
246
|
+
}
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
public async findInSignatures<T>(
|
|
251
|
+
topicKey: PublicKey,
|
|
252
|
+
processor: (data: {signatures?: ConfirmedSignatureInfo[], txs?: ParsedTransactionWithMeta[]}) => Promise<T>,
|
|
253
|
+
abortSignal?: AbortSignal,
|
|
254
|
+
logFetchLimit?: number,
|
|
255
|
+
startBlockheight?: number
|
|
256
|
+
) {
|
|
257
|
+
if(this.usingHeliusTFA!=="no") {
|
|
258
|
+
//Attempt to use Helius's gTFA
|
|
259
|
+
const result = await this._findInTxsTFA(topicKey, processor, abortSignal, startBlockheight);
|
|
260
|
+
if(result!==undefined) return result;
|
|
261
|
+
|
|
262
|
+
//Not supported
|
|
263
|
+
if(this.usingHeliusTFA==="yes") throw new Error("Helius gTFA is not supported with current provider!");
|
|
264
|
+
//If set to auto, we can manually set to "no"
|
|
265
|
+
this.usingHeliusTFA = "no";
|
|
266
|
+
this.logger.warn("findInSignatures(): Helius gTFA is not supported, switching back to using gSFA!")
|
|
267
|
+
}
|
|
268
|
+
return await this._findInSignatures(topicKey, processor, abortSignal, logFetchLimit, startBlockheight);
|
|
269
|
+
}
|
|
270
|
+
|
|
257
271
|
}
|