sol-parser-sdk-nodejs 0.3.0 → 0.4.4
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/.env.example +24 -0
- package/README.md +100 -352
- package/README_CN.md +107 -253
- package/dist/accounts/mod.d.ts +3 -0
- package/dist/accounts/mod.js +18 -1
- package/dist/accounts/pumpfun.d.ts +6 -0
- package/dist/accounts/pumpfun.js +157 -0
- package/dist/accounts/rpc_wallet.d.ts +5 -0
- package/dist/accounts/rpc_wallet.js +18 -0
- package/dist/accounts/rust_aliases.d.ts +10 -0
- package/dist/accounts/rust_aliases.js +21 -0
- package/dist/accounts/wallet_resolve.d.ts +1 -0
- package/dist/accounts/wallet_resolve.js +28 -0
- package/dist/common/constants.d.ts +10 -0
- package/dist/common/constants.js +13 -0
- package/dist/core/account_dispatcher_rpc.js +26 -5
- package/dist/core/account_fill_meteora.d.ts +4 -2
- package/dist/core/account_fill_meteora.js +5 -2
- package/dist/core/account_fill_pumpfun.js +17 -0
- package/dist/core/account_pubkey_cache.d.ts +12 -0
- package/dist/core/account_pubkey_cache.js +26 -0
- package/dist/core/clock.d.ts +6 -0
- package/dist/core/clock.js +13 -0
- package/dist/core/dex_event.d.ts +172 -44
- package/dist/core/metadata.d.ts +1 -0
- package/dist/core/pumpfun_fee_enrich.d.ts +4 -0
- package/dist/core/pumpfun_fee_enrich.js +80 -0
- package/dist/core/unified_parser.d.ts +2 -2
- package/dist/core/unified_parser.js +8 -6
- package/dist/grpc/client.d.ts +32 -1
- package/dist/grpc/client.js +400 -64
- package/dist/grpc/event_parser.d.ts +6 -0
- package/dist/grpc/event_parser.js +15 -0
- package/dist/grpc/geyser_connect.d.ts +30 -0
- package/dist/grpc/geyser_connect.js +40 -0
- package/dist/grpc/log_instr_dedup.d.ts +2 -0
- package/dist/grpc/log_instr_dedup.js +330 -0
- package/dist/grpc/order_buffer.d.ts +27 -0
- package/dist/grpc/order_buffer.js +166 -0
- package/dist/grpc/program_ids.d.ts +26 -0
- package/dist/grpc/program_ids.js +55 -0
- package/dist/grpc/rpc_to_grpc.d.ts +18 -0
- package/dist/grpc/rpc_to_grpc.js +127 -0
- package/dist/grpc/subscribe_builder.d.ts +13 -0
- package/dist/grpc/subscribe_builder.js +66 -0
- package/dist/grpc/transaction_meta.d.ts +29 -0
- package/dist/grpc/transaction_meta.js +208 -0
- package/dist/grpc/types.d.ts +57 -2
- package/dist/grpc/types.js +199 -7
- package/dist/grpc/yellowstone_parse.d.ts +8 -1
- package/dist/grpc/yellowstone_parse.js +27 -11
- package/dist/index.d.ts +39 -8
- package/dist/index.js +184 -2
- package/dist/instr/bonk_ix.d.ts +4 -1
- package/dist/instr/bonk_ix.js +106 -27
- package/dist/instr/meteora_damm_ix.d.ts +4 -2
- package/dist/instr/meteora_damm_ix.js +248 -13
- package/dist/instr/mod.d.ts +1 -0
- package/dist/instr/mod.js +16 -3
- package/dist/instr/orca_whirlpool_ix.d.ts +4 -1
- package/dist/instr/orca_whirlpool_ix.js +45 -16
- package/dist/instr/program_ids.d.ts +7 -13
- package/dist/instr/program_ids.js +20 -15
- package/dist/instr/pump_fees_ix.d.ts +2 -0
- package/dist/instr/pump_fees_ix.js +166 -0
- package/dist/instr/pumpfun_ix.js +57 -0
- package/dist/instr/pumpswap_ix.d.ts +1 -1
- package/dist/instr/pumpswap_ix.js +78 -57
- package/dist/instr/raydium_amm_v4_ix.d.ts +1 -1
- package/dist/instr/raydium_amm_v4_ix.js +94 -28
- package/dist/instr/raydium_clmm_ix.d.ts +1 -1
- package/dist/instr/raydium_clmm_ix.js +84 -30
- package/dist/instr/raydium_cpmm_ix.d.ts +1 -1
- package/dist/instr/raydium_cpmm_ix.js +46 -12
- package/dist/instr/rust_aliases.d.ts +8 -0
- package/dist/instr/rust_aliases.js +16 -0
- package/dist/instr/utils.d.ts +1 -1
- package/dist/instr/utils.js +2 -1
- package/dist/logs/discriminator_lut.d.ts +19 -0
- package/dist/logs/discriminator_lut.js +62 -0
- package/dist/logs/meteora_damm.d.ts +3 -4
- package/dist/logs/meteora_damm.js +3 -369
- package/dist/logs/optimized_matcher.d.ts +2 -2
- package/dist/logs/optimized_matcher.js +123 -23
- package/dist/logs/program_log_discriminators.d.ts +10 -0
- package/dist/logs/program_log_discriminators.js +10 -0
- package/dist/logs/pump.d.ts +2 -0
- package/dist/logs/pump.js +51 -4
- package/dist/logs/pump_fees.d.ts +23 -0
- package/dist/logs/pump_fees.js +364 -0
- package/dist/logs/rust_aliases.d.ts +6 -0
- package/dist/logs/rust_aliases.js +13 -0
- package/dist/rpc_parser.d.ts +1 -0
- package/dist/rpc_parser.js +4 -1
- package/dist/rpc_transaction.d.ts +2 -0
- package/dist/rpc_transaction.js +14 -6
- package/dist/shredstream/alt_lookup.d.ts +9 -0
- package/dist/shredstream/alt_lookup.js +70 -0
- package/dist/shredstream/client.d.ts +62 -0
- package/dist/shredstream/client.js +399 -0
- package/dist/shredstream/config.d.ts +30 -0
- package/dist/shredstream/config.js +34 -0
- package/dist/shredstream/entries_decode.d.ts +28 -0
- package/dist/shredstream/entries_decode.js +251 -0
- package/dist/shredstream/index.d.ts +17 -0
- package/dist/shredstream/index.js +33 -0
- package/dist/shredstream/instruction_parse.d.ts +34 -0
- package/dist/shredstream/instruction_parse.js +49 -0
- package/dist/shredstream/proto_types.d.ts +9 -0
- package/dist/shredstream/proto_types.js +2 -0
- package/dist/shredstream/shredstream.proto +15 -0
- package/dist/shredstream/wire_to_shred_tx.d.ts +2 -0
- package/dist/shredstream/wire_to_shred_tx.js +59 -0
- package/package.json +28 -11
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.convert_rpc_to_grpc = void 0;
|
|
7
|
+
exports.convertRpcToGrpc = convertRpcToGrpc;
|
|
8
|
+
/**
|
|
9
|
+
* 将 `@solana/web3.js` 的 `VersionedTransactionResponse` 转为 Yellowstone `Transaction` + `TransactionStatusMeta`,
|
|
10
|
+
* 与 Rust `rpc_parser::convert_rpc_to_grpc` 字段取舍一致(token balances / rewards 置空,err 置空等)。
|
|
11
|
+
*/
|
|
12
|
+
const bs58_1 = __importDefault(require("bs58"));
|
|
13
|
+
const rpc_invoke_map_js_1 = require("../core/rpc_invoke_map.js");
|
|
14
|
+
function toYCompiled(ix) {
|
|
15
|
+
const accounts = "accountKeyIndexes" in ix ? ix.accountKeyIndexes : ix.accounts;
|
|
16
|
+
return {
|
|
17
|
+
programIdIndex: ix.programIdIndex,
|
|
18
|
+
accounts: Uint8Array.from(accounts),
|
|
19
|
+
data: (0, rpc_invoke_map_js_1.decodeIxData)(ix.data),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function toYInnerInstruction(ix) {
|
|
23
|
+
const stackHeight = ix.stackHeight;
|
|
24
|
+
return {
|
|
25
|
+
programIdIndex: ix.programIdIndex,
|
|
26
|
+
accounts: Uint8Array.from(ix.accounts),
|
|
27
|
+
data: (0, rpc_invoke_map_js_1.decodeIxData)(ix.data),
|
|
28
|
+
...(stackHeight !== undefined ? { stackHeight } : {}),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function legacyMessageToYellowstone(msg) {
|
|
32
|
+
return {
|
|
33
|
+
header: {
|
|
34
|
+
numRequiredSignatures: msg.header.numRequiredSignatures,
|
|
35
|
+
numReadonlySignedAccounts: msg.header.numReadonlySignedAccounts,
|
|
36
|
+
numReadonlyUnsignedAccounts: msg.header.numReadonlyUnsignedAccounts,
|
|
37
|
+
},
|
|
38
|
+
accountKeys: msg.accountKeys.map((k) => new Uint8Array(k.toBytes())),
|
|
39
|
+
recentBlockhash: new Uint8Array(bs58_1.default.decode(msg.recentBlockhash)),
|
|
40
|
+
instructions: msg.compiledInstructions.map(toYCompiled),
|
|
41
|
+
versioned: false,
|
|
42
|
+
addressTableLookups: [],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function v0MessageToYellowstone(msg) {
|
|
46
|
+
const lookups = msg.addressTableLookups.map((l) => ({
|
|
47
|
+
accountKey: new Uint8Array(l.accountKey.toBytes()),
|
|
48
|
+
writableIndexes: l.writableIndexes instanceof Uint8Array ? l.writableIndexes : Uint8Array.from(l.writableIndexes),
|
|
49
|
+
readonlyIndexes: l.readonlyIndexes instanceof Uint8Array ? l.readonlyIndexes : Uint8Array.from(l.readonlyIndexes),
|
|
50
|
+
}));
|
|
51
|
+
return {
|
|
52
|
+
header: {
|
|
53
|
+
numRequiredSignatures: msg.header.numRequiredSignatures,
|
|
54
|
+
numReadonlySignedAccounts: msg.header.numReadonlySignedAccounts,
|
|
55
|
+
numReadonlyUnsignedAccounts: msg.header.numReadonlyUnsignedAccounts,
|
|
56
|
+
},
|
|
57
|
+
accountKeys: msg.staticAccountKeys.map((k) => new Uint8Array(k.toBytes())),
|
|
58
|
+
recentBlockhash: new Uint8Array(bs58_1.default.decode(msg.recentBlockhash)),
|
|
59
|
+
instructions: msg.compiledInstructions.map(toYCompiled),
|
|
60
|
+
versioned: true,
|
|
61
|
+
addressTableLookups: lookups,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function metaToYellowstone(meta) {
|
|
65
|
+
const innerGroups = meta.innerInstructions;
|
|
66
|
+
const innerInstructions = [];
|
|
67
|
+
if (innerGroups) {
|
|
68
|
+
for (const g of innerGroups) {
|
|
69
|
+
innerInstructions.push({
|
|
70
|
+
index: g.index,
|
|
71
|
+
instructions: g.instructions.map(toYInnerInstruction),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const loaded = meta.loadedAddresses;
|
|
76
|
+
const loadedWritable = loaded?.writable.map((k) => new Uint8Array(k.toBytes())) ?? [];
|
|
77
|
+
const loadedReadonly = loaded?.readonly.map((k) => new Uint8Array(k.toBytes())) ?? [];
|
|
78
|
+
const logs = meta.logMessages ?? [];
|
|
79
|
+
return {
|
|
80
|
+
err: undefined,
|
|
81
|
+
fee: String(meta.fee),
|
|
82
|
+
preBalances: meta.preBalances.map(String),
|
|
83
|
+
postBalances: meta.postBalances.map(String),
|
|
84
|
+
innerInstructions,
|
|
85
|
+
innerInstructionsNone: innerGroups == null,
|
|
86
|
+
logMessages: [...logs],
|
|
87
|
+
logMessagesNone: logs.length === 0,
|
|
88
|
+
preTokenBalances: [],
|
|
89
|
+
postTokenBalances: [],
|
|
90
|
+
rewards: [],
|
|
91
|
+
loadedWritableAddresses: loadedWritable,
|
|
92
|
+
loadedReadonlyAddresses: loadedReadonly,
|
|
93
|
+
returnData: undefined,
|
|
94
|
+
returnDataNone: true,
|
|
95
|
+
computeUnitsConsumed: meta.computeUnitsConsumed !== undefined ? String(meta.computeUnitsConsumed) : undefined,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 与 Rust `convert_rpc_to_grpc` 对齐:输入为 RPC `getTransaction` 的 **非 jsonParsed**、已编译 message 的响应。
|
|
100
|
+
*/
|
|
101
|
+
function convertRpcToGrpc(tx) {
|
|
102
|
+
const msg = tx.transaction?.message;
|
|
103
|
+
if (!msg || !(0, rpc_invoke_map_js_1.isCompiledVersionedMessage)(msg)) {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
error: {
|
|
107
|
+
kind: "ConversionError",
|
|
108
|
+
message: "交易 message 非编译形态(例如 jsonParsed)。请使用默认编码的 getTransaction 响应后再转换。",
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const meta = tx.meta;
|
|
113
|
+
if (meta == null) {
|
|
114
|
+
return {
|
|
115
|
+
ok: false,
|
|
116
|
+
error: { kind: "MissingField", field: "meta" },
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const yMsg = msg.version === "legacy" ? legacyMessageToYellowstone(msg) : v0MessageToYellowstone(msg);
|
|
120
|
+
const transaction = {
|
|
121
|
+
signatures: tx.transaction.signatures.map((s) => new Uint8Array(bs58_1.default.decode(s))),
|
|
122
|
+
message: yMsg,
|
|
123
|
+
};
|
|
124
|
+
return { ok: true, meta: metaToYellowstone(meta), transaction };
|
|
125
|
+
}
|
|
126
|
+
/** Rust 蛇形命名 */
|
|
127
|
+
exports.convert_rpc_to_grpc = convertRpcToGrpc;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yellowstone `SubscribeRequest` 构造(与 Rust `grpc/subscribe_builder` 对齐)。
|
|
3
|
+
*/
|
|
4
|
+
import type { SubscribeRequest } from "@triton-one/yellowstone-grpc";
|
|
5
|
+
import { CommitmentLevel } from "@triton-one/yellowstone-grpc";
|
|
6
|
+
import type { AccountFilter, TransactionFilter } from "./types.js";
|
|
7
|
+
export declare function buildSubscribeRequest(txFilters: TransactionFilter[], accFilters: AccountFilter[]): SubscribeRequest;
|
|
8
|
+
export declare function buildSubscribeRequestWithCommitment(txFilters: TransactionFilter[], accFilters: AccountFilter[], commitment: CommitmentLevel): SubscribeRequest;
|
|
9
|
+
export declare function buildSubscribeTransactionFiltersNamed(namedTxFilters: readonly {
|
|
10
|
+
name: string;
|
|
11
|
+
filter: TransactionFilter;
|
|
12
|
+
}[], accFilters: AccountFilter[], commitment: CommitmentLevel): SubscribeRequest;
|
|
13
|
+
export { CommitmentLevel };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CommitmentLevel = void 0;
|
|
4
|
+
exports.buildSubscribeRequest = buildSubscribeRequest;
|
|
5
|
+
exports.buildSubscribeRequestWithCommitment = buildSubscribeRequestWithCommitment;
|
|
6
|
+
exports.buildSubscribeTransactionFiltersNamed = buildSubscribeTransactionFiltersNamed;
|
|
7
|
+
const yellowstone_grpc_1 = require("@triton-one/yellowstone-grpc");
|
|
8
|
+
Object.defineProperty(exports, "CommitmentLevel", { enumerable: true, get: function () { return yellowstone_grpc_1.CommitmentLevel; } });
|
|
9
|
+
function txFilterToProto(f) {
|
|
10
|
+
return {
|
|
11
|
+
vote: false,
|
|
12
|
+
failed: false,
|
|
13
|
+
signature: undefined,
|
|
14
|
+
accountInclude: f.account_include,
|
|
15
|
+
accountExclude: f.account_exclude,
|
|
16
|
+
accountRequired: f.account_required,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function accFilterToProto(f) {
|
|
20
|
+
return {
|
|
21
|
+
account: f.account,
|
|
22
|
+
owner: f.owner,
|
|
23
|
+
filters: f.filters,
|
|
24
|
+
nonemptyTxnSignature: undefined,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function finalize(transactions, accounts, commitment) {
|
|
28
|
+
return {
|
|
29
|
+
slots: {},
|
|
30
|
+
accounts,
|
|
31
|
+
transactions,
|
|
32
|
+
transactionsStatus: {},
|
|
33
|
+
blocks: {},
|
|
34
|
+
blocksMeta: {},
|
|
35
|
+
entry: {},
|
|
36
|
+
commitment,
|
|
37
|
+
accountsDataSlice: [],
|
|
38
|
+
ping: undefined,
|
|
39
|
+
fromSlot: undefined,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function buildSubscribeRequest(txFilters, accFilters) {
|
|
43
|
+
return buildSubscribeRequestWithCommitment(txFilters, accFilters, yellowstone_grpc_1.CommitmentLevel.PROCESSED);
|
|
44
|
+
}
|
|
45
|
+
function buildSubscribeRequestWithCommitment(txFilters, accFilters, commitment) {
|
|
46
|
+
const transactions = {};
|
|
47
|
+
txFilters.forEach((f, i) => {
|
|
48
|
+
transactions[`tx_${i}`] = txFilterToProto(f);
|
|
49
|
+
});
|
|
50
|
+
const accounts = {};
|
|
51
|
+
accFilters.forEach((f, i) => {
|
|
52
|
+
accounts[`acc_${i}`] = accFilterToProto(f);
|
|
53
|
+
});
|
|
54
|
+
return finalize(transactions, accounts, commitment);
|
|
55
|
+
}
|
|
56
|
+
function buildSubscribeTransactionFiltersNamed(namedTxFilters, accFilters, commitment) {
|
|
57
|
+
const transactions = {};
|
|
58
|
+
for (const { name, filter } of namedTxFilters) {
|
|
59
|
+
transactions[name] = txFilterToProto(filter);
|
|
60
|
+
}
|
|
61
|
+
const accounts = {};
|
|
62
|
+
accFilters.forEach((f, i) => {
|
|
63
|
+
accounts[`acc_${i}`] = accFilterToProto(f);
|
|
64
|
+
});
|
|
65
|
+
return finalize(transactions, accounts, commitment);
|
|
66
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TokenBalance, Transaction, TransactionStatusMeta } from "@triton-one/yellowstone-grpc/dist/grpc/solana-storage.js";
|
|
2
|
+
/** 32 字节公钥 → Base58(无效长度返回 `null`) */
|
|
3
|
+
export declare function pubkeyBytesToBs58(bytes: Uint8Array): string | null;
|
|
4
|
+
/**
|
|
5
|
+
* 消息静态 `accountKeys` + meta 中 `loadedWritableAddresses` / `loadedReadonlyAddresses`,
|
|
6
|
+
* 顺序与 `preBalances` / `postBalances` 对齐。
|
|
7
|
+
*/
|
|
8
|
+
export declare function collectAccountKeysBs58(tx: Transaction, meta: TransactionStatusMeta): string[] | null;
|
|
9
|
+
/** 每个账户索引的 lamports 变化(post − pre) */
|
|
10
|
+
export declare function lamportBalanceDeltas(meta: TransactionStatusMeta): bigint[];
|
|
11
|
+
/**
|
|
12
|
+
* 启发式原生 SOL:对 `watchedBs58` 中出现的账户,若 lamports 净减少 ≥ `minOutflowLamports`,
|
|
13
|
+
* 再与其它索引配对,要求对方 delta ≥ `minOutflowLamports/2`。
|
|
14
|
+
*/
|
|
15
|
+
export declare function heuristicSolCounterpartiesForWatchedKeys(accountKeysBs58: string[], lamportDeltas: bigint[], watchedBs58: Set<string>, minOutflowLamports: bigint): [string, string][];
|
|
16
|
+
/** `TokenBalance.uiTokenAmount.amount` → 原始整数;解析失败为 `0n` */
|
|
17
|
+
export declare function tokenBalanceRawAmount(t: TokenBalance): bigint;
|
|
18
|
+
/**
|
|
19
|
+
* SPL:当 `watchOwnerBs58` 在某 mint 上余额净减少 ≥ `minWatchDecreaseRaw` 时,
|
|
20
|
+
* 找同 mint 下余额增加的其它 owner,返回 `(watch_owner, counterparty_owner)`。
|
|
21
|
+
*/
|
|
22
|
+
export declare function splTokenCounterpartyByOwner(meta: TransactionStatusMeta, watchOwnerBs58: string, minWatchDecreaseRaw: bigint): [string, string][];
|
|
23
|
+
/**
|
|
24
|
+
* 汇总监控地址在一笔交易中的转出对手方(原生 SOL 启发式 + SPL token balance 启发式)。
|
|
25
|
+
* 若账户 key 与 balance 数组长度不一致则返回 `null`。
|
|
26
|
+
*/
|
|
27
|
+
export declare function collectWatchTransferCounterpartyPairs(tx: Transaction, meta: TransactionStatusMeta, watchedBs58: string[], minNativeOutflowLamports: bigint, splMinWatchDecreaseRaw: bigint): [string, string][] | null;
|
|
28
|
+
/** Yellowstone 交易签名原始字节(64)→ Base58 签名字符串;长度非 64 返回 `null` */
|
|
29
|
+
export declare function tryYellowstoneSignature(sig: Uint8Array): string | null;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.pubkeyBytesToBs58 = pubkeyBytesToBs58;
|
|
7
|
+
exports.collectAccountKeysBs58 = collectAccountKeysBs58;
|
|
8
|
+
exports.lamportBalanceDeltas = lamportBalanceDeltas;
|
|
9
|
+
exports.heuristicSolCounterpartiesForWatchedKeys = heuristicSolCounterpartiesForWatchedKeys;
|
|
10
|
+
exports.tokenBalanceRawAmount = tokenBalanceRawAmount;
|
|
11
|
+
exports.splTokenCounterpartyByOwner = splTokenCounterpartyByOwner;
|
|
12
|
+
exports.collectWatchTransferCounterpartyPairs = collectWatchTransferCounterpartyPairs;
|
|
13
|
+
exports.tryYellowstoneSignature = tryYellowstoneSignature;
|
|
14
|
+
/**
|
|
15
|
+
* Yellowstone `Transaction` / `TransactionStatusMeta` 通用工具(与 Rust `grpc/transaction_meta` 对齐)。
|
|
16
|
+
* 不依赖 DEX 日志解析,用于 mentions 订阅后的 SOL/SPL 转账启发式分析等。
|
|
17
|
+
*/
|
|
18
|
+
const bs58_1 = __importDefault(require("bs58"));
|
|
19
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
20
|
+
/** 32 字节公钥 → Base58(无效长度返回 `null`) */
|
|
21
|
+
function pubkeyBytesToBs58(bytes) {
|
|
22
|
+
if (bytes.length !== 32)
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
return new web3_js_1.PublicKey(bytes).toBase58();
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 消息静态 `accountKeys` + meta 中 `loadedWritableAddresses` / `loadedReadonlyAddresses`,
|
|
33
|
+
* 顺序与 `preBalances` / `postBalances` 对齐。
|
|
34
|
+
*/
|
|
35
|
+
function collectAccountKeysBs58(tx, meta) {
|
|
36
|
+
const msg = tx.message;
|
|
37
|
+
if (!msg)
|
|
38
|
+
return null;
|
|
39
|
+
const keys = [];
|
|
40
|
+
for (const b of msg.accountKeys) {
|
|
41
|
+
const s = pubkeyBytesToBs58(b);
|
|
42
|
+
if (!s)
|
|
43
|
+
continue;
|
|
44
|
+
keys.push(s);
|
|
45
|
+
}
|
|
46
|
+
for (const b of meta.loadedWritableAddresses) {
|
|
47
|
+
const s = pubkeyBytesToBs58(b);
|
|
48
|
+
if (!s)
|
|
49
|
+
continue;
|
|
50
|
+
keys.push(s);
|
|
51
|
+
}
|
|
52
|
+
for (const b of meta.loadedReadonlyAddresses) {
|
|
53
|
+
const s = pubkeyBytesToBs58(b);
|
|
54
|
+
if (!s)
|
|
55
|
+
continue;
|
|
56
|
+
keys.push(s);
|
|
57
|
+
}
|
|
58
|
+
return keys;
|
|
59
|
+
}
|
|
60
|
+
/** 每个账户索引的 lamports 变化(post − pre) */
|
|
61
|
+
function lamportBalanceDeltas(meta) {
|
|
62
|
+
const n = Math.min(meta.preBalances.length, meta.postBalances.length);
|
|
63
|
+
const out = [];
|
|
64
|
+
for (let i = 0; i < n; i++) {
|
|
65
|
+
out.push(BigInt(meta.postBalances[i] ?? "0") - BigInt(meta.preBalances[i] ?? "0"));
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 启发式原生 SOL:对 `watchedBs58` 中出现的账户,若 lamports 净减少 ≥ `minOutflowLamports`,
|
|
71
|
+
* 再与其它索引配对,要求对方 delta ≥ `minOutflowLamports/2`。
|
|
72
|
+
*/
|
|
73
|
+
function heuristicSolCounterpartiesForWatchedKeys(accountKeysBs58, lamportDeltas, watchedBs58, minOutflowLamports) {
|
|
74
|
+
const minL = minOutflowLamports;
|
|
75
|
+
const half = minL / 2n;
|
|
76
|
+
const pairs = [];
|
|
77
|
+
for (let i = 0; i < accountKeysBs58.length; i++) {
|
|
78
|
+
const key = accountKeysBs58[i];
|
|
79
|
+
if (!watchedBs58.has(key))
|
|
80
|
+
continue;
|
|
81
|
+
const d = lamportDeltas[i] ?? 0n;
|
|
82
|
+
if (d >= -minL)
|
|
83
|
+
continue;
|
|
84
|
+
for (let j = 0; j < lamportDeltas.length; j++) {
|
|
85
|
+
if (i === j)
|
|
86
|
+
continue;
|
|
87
|
+
const dj = lamportDeltas[j] ?? 0n;
|
|
88
|
+
if (dj <= half)
|
|
89
|
+
continue;
|
|
90
|
+
pairs.push([key, accountKeysBs58[j]]);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return pairs;
|
|
94
|
+
}
|
|
95
|
+
/** `TokenBalance.uiTokenAmount.amount` → 原始整数;解析失败为 `0n` */
|
|
96
|
+
function tokenBalanceRawAmount(t) {
|
|
97
|
+
const a = t.uiTokenAmount?.amount;
|
|
98
|
+
if (a === undefined || a === "")
|
|
99
|
+
return 0n;
|
|
100
|
+
try {
|
|
101
|
+
return BigInt(a);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return 0n;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function mapKey(mint, owner) {
|
|
108
|
+
return `${mint}\0${owner}`;
|
|
109
|
+
}
|
|
110
|
+
function parseMapKey(k) {
|
|
111
|
+
const i = k.indexOf("\0");
|
|
112
|
+
if (i <= 0)
|
|
113
|
+
return null;
|
|
114
|
+
return { mint: k.slice(0, i), owner: k.slice(i + 1) };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* SPL:当 `watchOwnerBs58` 在某 mint 上余额净减少 ≥ `minWatchDecreaseRaw` 时,
|
|
118
|
+
* 找同 mint 下余额增加的其它 owner,返回 `(watch_owner, counterparty_owner)`。
|
|
119
|
+
*/
|
|
120
|
+
function splTokenCounterpartyByOwner(meta, watchOwnerBs58, minWatchDecreaseRaw) {
|
|
121
|
+
const pre = meta.preTokenBalances ?? [];
|
|
122
|
+
const post = meta.postTokenBalances ?? [];
|
|
123
|
+
const preM = new Map();
|
|
124
|
+
for (const b of pre) {
|
|
125
|
+
if (!b.owner)
|
|
126
|
+
continue;
|
|
127
|
+
const k = mapKey(b.mint, b.owner);
|
|
128
|
+
preM.set(k, (preM.get(k) ?? 0n) + tokenBalanceRawAmount(b));
|
|
129
|
+
}
|
|
130
|
+
const postM = new Map();
|
|
131
|
+
for (const b of post) {
|
|
132
|
+
if (!b.owner)
|
|
133
|
+
continue;
|
|
134
|
+
const k = mapKey(b.mint, b.owner);
|
|
135
|
+
postM.set(k, (postM.get(k) ?? 0n) + tokenBalanceRawAmount(b));
|
|
136
|
+
}
|
|
137
|
+
const mints = new Set();
|
|
138
|
+
for (const k of preM.keys()) {
|
|
139
|
+
const p = parseMapKey(k);
|
|
140
|
+
if (p && p.owner === watchOwnerBs58)
|
|
141
|
+
mints.add(p.mint);
|
|
142
|
+
}
|
|
143
|
+
for (const k of postM.keys()) {
|
|
144
|
+
const p = parseMapKey(k);
|
|
145
|
+
if (p && p.owner === watchOwnerBs58)
|
|
146
|
+
mints.add(p.mint);
|
|
147
|
+
}
|
|
148
|
+
const out = [];
|
|
149
|
+
const minL = minWatchDecreaseRaw > 0n ? minWatchDecreaseRaw : 1n;
|
|
150
|
+
for (const mint of mints) {
|
|
151
|
+
const wPre = preM.get(mapKey(mint, watchOwnerBs58)) ?? 0n;
|
|
152
|
+
const wPost = postM.get(mapKey(mint, watchOwnerBs58)) ?? 0n;
|
|
153
|
+
const lost = wPre > wPost ? wPre - wPost : 0n;
|
|
154
|
+
if (lost < minL)
|
|
155
|
+
continue;
|
|
156
|
+
for (const [k, po] of postM) {
|
|
157
|
+
const parsed = parseMapKey(k);
|
|
158
|
+
if (!parsed || parsed.mint !== mint || parsed.owner === watchOwnerBs58)
|
|
159
|
+
continue;
|
|
160
|
+
const pr = preM.get(k) ?? 0n;
|
|
161
|
+
if (po > pr) {
|
|
162
|
+
out.push([watchOwnerBs58, parsed.owner]);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
out.sort((a, b) => a[1].localeCompare(b[1]));
|
|
167
|
+
const dedup = [];
|
|
168
|
+
for (const p of out) {
|
|
169
|
+
const prev = dedup[dedup.length - 1];
|
|
170
|
+
if (prev && prev[0] === p[0] && prev[1] === p[1])
|
|
171
|
+
continue;
|
|
172
|
+
dedup.push(p);
|
|
173
|
+
}
|
|
174
|
+
return dedup;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* 汇总监控地址在一笔交易中的转出对手方(原生 SOL 启发式 + SPL token balance 启发式)。
|
|
178
|
+
* 若账户 key 与 balance 数组长度不一致则返回 `null`。
|
|
179
|
+
*/
|
|
180
|
+
function collectWatchTransferCounterpartyPairs(tx, meta, watchedBs58, minNativeOutflowLamports, splMinWatchDecreaseRaw) {
|
|
181
|
+
const keys = collectAccountKeysBs58(tx, meta);
|
|
182
|
+
if (!keys)
|
|
183
|
+
return null;
|
|
184
|
+
const n = keys.length;
|
|
185
|
+
if (meta.preBalances.length !== n || meta.postBalances.length !== n)
|
|
186
|
+
return null;
|
|
187
|
+
const deltas = lamportBalanceDeltas(meta);
|
|
188
|
+
const watchedH = new Set(watchedBs58);
|
|
189
|
+
const pairs = heuristicSolCounterpartiesForWatchedKeys(keys, deltas, watchedH, minNativeOutflowLamports);
|
|
190
|
+
for (const w of watchedBs58) {
|
|
191
|
+
pairs.push(...splTokenCounterpartyByOwner(meta, w, splMinWatchDecreaseRaw));
|
|
192
|
+
}
|
|
193
|
+
pairs.sort((a, b) => a[1].localeCompare(b[1]));
|
|
194
|
+
const dedup = [];
|
|
195
|
+
for (const p of pairs) {
|
|
196
|
+
const prev = dedup[dedup.length - 1];
|
|
197
|
+
if (prev && prev[0] === p[0] && prev[1] === p[1])
|
|
198
|
+
continue;
|
|
199
|
+
dedup.push(p);
|
|
200
|
+
}
|
|
201
|
+
return dedup;
|
|
202
|
+
}
|
|
203
|
+
/** Yellowstone 交易签名原始字节(64)→ Base58 签名字符串;长度非 64 返回 `null` */
|
|
204
|
+
function tryYellowstoneSignature(sig) {
|
|
205
|
+
if (sig.length !== 64)
|
|
206
|
+
return null;
|
|
207
|
+
return bs58_1.default.encode(sig);
|
|
208
|
+
}
|
package/dist/grpc/types.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import type { SubscribeRequestFilterAccountsFilter } from "@triton-one/yellowstone-grpc";
|
|
1
2
|
/** gRPC 订阅顺序模式 */
|
|
2
3
|
export type OrderMode = "Unordered" | "Ordered" | "StreamingOrdered" | "MicroBatch";
|
|
4
|
+
/** 与 Rust `grpc::types::Protocol` 一致 */
|
|
5
|
+
export type Protocol = "PumpFun" | "PumpSwap" | "Bonk" | "RaydiumCpmm" | "RaydiumClmm" | "RaydiumAmmV4" | "MeteoraDammV2";
|
|
3
6
|
export type SlotStatus = "Processed" | "Confirmed" | "Finalized" | "FirstShredReceived" | "Completed" | "CreatedBank" | "Dead";
|
|
4
7
|
export interface SubscribeUpdateAccountInfo {
|
|
5
8
|
pubkey: Uint8Array;
|
|
@@ -70,11 +73,18 @@ export interface SubscribeUpdate {
|
|
|
70
73
|
blockMeta?: SubscribeUpdateBlockMeta;
|
|
71
74
|
ping?: SubscribeUpdatePing;
|
|
72
75
|
pong?: SubscribeUpdatePong;
|
|
76
|
+
/** Yellowstone SubscribeUpdate.created_at, Unix timestamp in microseconds. */
|
|
77
|
+
createdAtUs?: number;
|
|
73
78
|
}
|
|
74
79
|
export interface SubscribeCallbacks {
|
|
75
80
|
onUpdate?: (update: SubscribeUpdate) => void;
|
|
76
81
|
onError?: (err: Error) => void;
|
|
77
82
|
onEnd?: () => void;
|
|
83
|
+
/**
|
|
84
|
+
* 是否在流断开后自动重连(指数退避,与 Rust `subscribe_dex_events` 一致)。
|
|
85
|
+
* 默认 `true`。为 `false` 时保持单次连接的旧行为。
|
|
86
|
+
*/
|
|
87
|
+
autoReconnect?: boolean;
|
|
78
88
|
}
|
|
79
89
|
export interface ClientConfig {
|
|
80
90
|
enable_metrics: boolean;
|
|
@@ -91,15 +101,56 @@ export interface ClientConfig {
|
|
|
91
101
|
order_timeout_ms: number;
|
|
92
102
|
micro_batch_us: number;
|
|
93
103
|
}
|
|
104
|
+
/** 与 Rust `grpc::config` 中 `StreamingConfig` 别名(即 `ClientConfig`)一致 */
|
|
105
|
+
export type StreamingConfig = ClientConfig;
|
|
94
106
|
export declare function defaultClientConfig(): ClientConfig;
|
|
107
|
+
/** 与 Rust `ClientConfig::low_latency` 一致 */
|
|
108
|
+
export declare function lowLatencyClientConfig(): ClientConfig;
|
|
109
|
+
/** 与 Rust `ClientConfig::high_throughput` 一致 */
|
|
110
|
+
export declare function highThroughputClientConfig(): ClientConfig;
|
|
95
111
|
export interface TransactionFilter {
|
|
96
112
|
account_include: string[];
|
|
97
113
|
account_exclude: string[];
|
|
98
114
|
account_required: string[];
|
|
99
115
|
}
|
|
100
116
|
export declare function newTransactionFilter(): TransactionFilter;
|
|
117
|
+
/** 与 Rust `TransactionFilter::from_program_ids` 一致 */
|
|
118
|
+
export declare function transactionFilterFromProgramIds(programIds: string[]): TransactionFilter;
|
|
119
|
+
/** 与 Rust `grpc::AccountFilter` 一致(Yellowstone 账户订阅) */
|
|
120
|
+
export interface AccountFilter {
|
|
121
|
+
account: string[];
|
|
122
|
+
owner: string[];
|
|
123
|
+
filters: SubscribeRequestFilterAccountsFilter[];
|
|
124
|
+
}
|
|
125
|
+
/** 与 Rust `grpc::types::AccountFilterMemcmp` / `AccountFilterData` 一致(文档与扩展用) */
|
|
126
|
+
export interface AccountFilterMemcmp {
|
|
127
|
+
offset: number;
|
|
128
|
+
bytes: Uint8Array;
|
|
129
|
+
}
|
|
130
|
+
export interface AccountFilterData {
|
|
131
|
+
memcmp?: AccountFilterMemcmp;
|
|
132
|
+
datasize?: number;
|
|
133
|
+
}
|
|
134
|
+
export declare function newAccountFilter(): AccountFilter;
|
|
135
|
+
/** 与 Rust `grpc::types::SlotFilter` 一致 */
|
|
136
|
+
export interface SlotFilter {
|
|
137
|
+
min_slot?: number;
|
|
138
|
+
max_slot?: number;
|
|
139
|
+
}
|
|
140
|
+
export declare function newSlotFilter(): SlotFilter;
|
|
141
|
+
export declare function slotFilterMinSlot(filter: SlotFilter, slot: number): SlotFilter;
|
|
142
|
+
export declare function slotFilterMaxSlot(filter: SlotFilter, slot: number): SlotFilter;
|
|
143
|
+
/** 与 Rust `AccountFilter::from_program_owners` 一致 */
|
|
144
|
+
export declare function accountFilterFromProgramOwners(programIds: string[]): AccountFilter;
|
|
145
|
+
/**
|
|
146
|
+
* 构造 memcmp 账户过滤器(与 Rust `account_filter_memcmp` 一致)。
|
|
147
|
+
* ATA 常在 offset 0 放 mint;PumpSwap 池子等常在 offset 32。
|
|
148
|
+
*/
|
|
149
|
+
export declare function accountFilterMemcmp(offset: number, bytes: Uint8Array): SubscribeRequestFilterAccountsFilter;
|
|
101
150
|
/** 事件类型过滤标签 */
|
|
102
|
-
export type EventType = "BlockMeta" | "PumpFunTrade" | "PumpFunBuy" | "PumpFunSell" | "PumpFunBuyExactSolIn" | "PumpFunCreate" | "PumpFunCreateV2" | "PumpFunComplete" | "PumpFunMigrate" | "PumpSwapTrade" | "PumpSwapBuy" | "PumpSwapSell" | "PumpSwapCreatePool" | "PumpSwapLiquidityAdded" | "PumpSwapLiquidityRemoved" | "RaydiumClmmSwap" | "RaydiumClmmIncreaseLiquidity" | "RaydiumClmmDecreaseLiquidity" | "RaydiumClmmCreatePool" | "RaydiumClmmOpenPosition" | "RaydiumClmmOpenPositionWithTokenExtNft" | "RaydiumClmmClosePosition" | "RaydiumClmmCollectFee" | "RaydiumCpmmSwap" | "RaydiumCpmmDeposit" | "RaydiumCpmmWithdraw" | "RaydiumCpmmInitialize" | "RaydiumAmmV4Swap" | "RaydiumAmmV4Deposit" | "RaydiumAmmV4Withdraw" | "RaydiumAmmV4WithdrawPnl" | "RaydiumAmmV4Initialize2" | "OrcaWhirlpoolSwap" | "OrcaWhirlpoolLiquidityIncreased" | "OrcaWhirlpoolLiquidityDecreased" | "OrcaWhirlpoolPoolInitialized" | "MeteoraPoolsSwap" | "MeteoraPoolsAddLiquidity" | "MeteoraPoolsRemoveLiquidity" | "MeteoraPoolsBootstrapLiquidity" | "MeteoraPoolsPoolCreated" | "MeteoraPoolsSetPoolFees" | "MeteoraDammV2Swap" | "MeteoraDammV2AddLiquidity" | "MeteoraDammV2RemoveLiquidity" | "
|
|
151
|
+
export type EventType = "BlockMeta" | "PumpFunTrade" | "PumpFunBuy" | "PumpFunSell" | "PumpFunBuyExactSolIn" | "PumpFunCreate" | "PumpFunCreateV2" | "PumpFunComplete" | "PumpFunMigrate" | "PumpFeesCreateFeeSharingConfig" | "PumpFeesInitializeFeeConfig" | "PumpFeesResetFeeSharingConfig" | "PumpFeesRevokeFeeSharingAuthority" | "PumpFeesTransferFeeSharingAuthority" | "PumpFeesUpdateAdmin" | "PumpFeesUpdateFeeConfig" | "PumpFeesUpdateFeeShares" | "PumpFeesUpsertFeeTiers" | "PumpFunMigrateBondingCurveCreator" | "PumpSwapTrade" | "PumpSwapBuy" | "PumpSwapSell" | "PumpSwapCreatePool" | "PumpSwapLiquidityAdded" | "PumpSwapLiquidityRemoved" | "RaydiumClmmSwap" | "RaydiumClmmIncreaseLiquidity" | "RaydiumClmmDecreaseLiquidity" | "RaydiumClmmCreatePool" | "RaydiumClmmOpenPosition" | "RaydiumClmmOpenPositionWithTokenExtNft" | "RaydiumClmmClosePosition" | "RaydiumClmmCollectFee" | "RaydiumCpmmSwap" | "RaydiumCpmmDeposit" | "RaydiumCpmmWithdraw" | "RaydiumCpmmInitialize" | "RaydiumAmmV4Swap" | "RaydiumAmmV4Deposit" | "RaydiumAmmV4Withdraw" | "RaydiumAmmV4WithdrawPnl" | "RaydiumAmmV4Initialize2" | "OrcaWhirlpoolSwap" | "OrcaWhirlpoolLiquidityIncreased" | "OrcaWhirlpoolLiquidityDecreased" | "OrcaWhirlpoolPoolInitialized" | "MeteoraPoolsSwap" | "MeteoraPoolsAddLiquidity" | "MeteoraPoolsRemoveLiquidity" | "MeteoraPoolsBootstrapLiquidity" | "MeteoraPoolsPoolCreated" | "MeteoraPoolsSetPoolFees" | "MeteoraDammV2Swap" | "MeteoraDammV2AddLiquidity" | "MeteoraDammV2RemoveLiquidity" | "MeteoraDammV2RemoveAllLiquidity" | "MeteoraDammV2CreatePosition" | "MeteoraDammV2InitializePool" | "MeteoraDammV2ClosePosition" | "MeteoraDlmmSwap" | "MeteoraDlmmAddLiquidity" | "MeteoraDlmmRemoveLiquidity" | "MeteoraDlmmInitializePool" | "MeteoraDlmmInitializeBinArray" | "MeteoraDlmmCreatePosition" | "MeteoraDlmmClosePosition" | "MeteoraDlmmClaimFee" | "BonkTrade" | "BonkPoolCreate" | "BonkMigrateAmm" | "TokenAccount" | "TokenInfo" | "NonceAccount" | "AccountPumpFunGlobal" | "AccountPumpSwapGlobalConfig" | "AccountPumpSwapPool";
|
|
152
|
+
/** 与 Rust `grpc::EventType`(由 `StreamingEventType` 导出)一致 */
|
|
153
|
+
export type StreamingEventType = EventType;
|
|
103
154
|
/** 所有事件类型列表 */
|
|
104
155
|
export declare const ALL_EVENT_TYPES: EventType[];
|
|
105
156
|
export interface EventTypeFilter {
|
|
@@ -111,6 +162,8 @@ export declare function eventTypeFilterIncludeOnly(types: EventType[]): EventTyp
|
|
|
111
162
|
export declare function eventTypeFilterExclude(types: EventType[]): EventTypeFilter;
|
|
112
163
|
/** 过滤器是否包含 PumpFun 相关类型 */
|
|
113
164
|
export declare function eventTypeFilterIncludesPumpfun(filter: EventTypeFilter): boolean;
|
|
165
|
+
/** 过滤器是否包含 Pump Fees (`pfeeUx...`) 相关类型 */
|
|
166
|
+
export declare function eventTypeFilterIncludesPumpFees(filter: EventTypeFilter): boolean;
|
|
114
167
|
/** 过滤器是否包含 PumpSwap 相关类型 */
|
|
115
168
|
export declare function eventTypeFilterIncludesPumpswap(filter: EventTypeFilter): boolean;
|
|
116
169
|
/** 过滤器是否包含 Meteora DAMM V2 相关类型 */
|
|
@@ -123,8 +176,10 @@ export declare function eventTypeFilterIncludesRaydiumCpmm(filter: EventTypeFilt
|
|
|
123
176
|
export declare function eventTypeFilterIncludesRaydiumAmmV4(filter: EventTypeFilter): boolean;
|
|
124
177
|
/** 过滤器是否包含 Orca Whirlpool 相关类型 */
|
|
125
178
|
export declare function eventTypeFilterIncludesOrcaWhirlpool(filter: EventTypeFilter): boolean;
|
|
126
|
-
/** 过滤器是否包含 Bonk Launchpad
|
|
179
|
+
/** 过滤器是否包含 Bonk Launchpad 相关类型(与 Rust `includes_raydium_launchpad` / Bonk 集合一致) */
|
|
127
180
|
export declare function eventTypeFilterIncludesBonk(filter: EventTypeFilter): boolean;
|
|
181
|
+
/** 与 Rust `EventTypeFilter::includes_raydium_launchpad` 同名语义 */
|
|
182
|
+
export declare function eventTypeFilterIncludesRaydiumLaunchpad(filter: EventTypeFilter): boolean;
|
|
128
183
|
/**
|
|
129
184
|
* `parseInstructionUnified` 前置白名单:仅当 `include_only` 与下列指令相关类型有交集时才解析指令。
|
|
130
185
|
* 若白名单中不含下列任一类型,则整条指令解析入口返回 null。
|