@clonegod/ttd-sol-common 2.0.40 → 2.0.42

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.
@@ -3,6 +3,7 @@ import { Connection, Keypair } from "@solana/web3.js";
3
3
  export declare class SolanaTradeAppConfig extends AbstractTradeAppConfig {
4
4
  connection: Connection;
5
5
  keypair: Keypair;
6
+ private ws_client;
6
7
  constructor();
7
8
  init(): Promise<void>;
8
9
  subscribe_wallet_raw_txn_event(): void;
@@ -5,6 +5,7 @@ const dist_1 = require("@clonegod/ttd-core/dist");
5
5
  class SolanaTradeAppConfig extends dist_1.AbstractTradeAppConfig {
6
6
  constructor() {
7
7
  super();
8
+ this.ws_client = null;
8
9
  }
9
10
  async init() {
10
11
  await super.init();
@@ -12,6 +13,19 @@ class SolanaTradeAppConfig extends dist_1.AbstractTradeAppConfig {
12
13
  (0, dist_1.log_info)('SolanaTradeAppConfig init ...');
13
14
  }
14
15
  subscribe_wallet_raw_txn_event() {
16
+ if (this.is_already_subscribe_wallet_raw_txn) {
17
+ if (this.ws_client && this.ws_client.isConnected()) {
18
+ return;
19
+ }
20
+ else {
21
+ (0, dist_1.log_info)('subscribe_wallet_raw_txn_event was subscribed but connection lost, reconnecting...');
22
+ if (this.ws_client) {
23
+ this.ws_client.disconnect();
24
+ this.ws_client = null;
25
+ }
26
+ }
27
+ }
28
+ this.is_already_subscribe_wallet_raw_txn = true;
15
29
  const transactionHandler = async (messageStr) => {
16
30
  let messageObj = messageStr;
17
31
  if (typeof messageStr === 'string') {
@@ -22,9 +36,11 @@ class SolanaTradeAppConfig extends dist_1.AbstractTradeAppConfig {
22
36
  this.emit(dist_1.LOCAL_EVENT_NAME.EVENT_WALLET_TRANSACTION + '#' + tx_id, messageObj);
23
37
  };
24
38
  const ws_port = process.env.STREAM_WS_TRADE_PORT || 10002;
25
- const ws = new dist_1.WebSocketClient(`ws://127.0.0.1:${ws_port}`);
26
- ws.onMessage(transactionHandler);
27
- ws.connect();
39
+ const ws_url = `ws://127.0.0.1:${ws_port}`;
40
+ this.ws_client = new dist_1.WebSocketClient(ws_url);
41
+ this.ws_client.onMessage(transactionHandler);
42
+ this.ws_client.connect();
43
+ (0, dist_1.log_info)(`subscribe_wallet_raw_txn_event, WebSocket connecting to ${ws_url}`);
28
44
  }
29
45
  }
30
46
  exports.SolanaTradeAppConfig = SolanaTradeAppConfig;
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TransactionResultChecker = void 0;
4
4
  const dist_1 = require("@clonegod/ttd-core/dist");
5
5
  const web3_js_1 = require("@solana/web3.js");
6
- const tx_result_parse_1 = require("./tx_result_parse");
7
6
  const common_1 = require("../common");
7
+ const tx_result_parse_1 = require("./tx_result_parse");
8
8
  class TransactionResultChecker extends dist_1.AbstractTransactionResultCheck {
9
9
  constructor(env_args, event_emitter) {
10
10
  super(env_args, event_emitter);
@@ -36,23 +36,49 @@ class TransactionResultChecker extends dist_1.AbstractTransactionResultCheck {
36
36
  }
37
37
  on_subscibe_transaction() {
38
38
  this.event_emitter.once(dist_1.LOCAL_EVENT_NAME.EVENT_WALLET_TRANSACTION + '#' + this.txid, (message) => {
39
+ var _a, _b, _c;
39
40
  try {
40
41
  this.trade_result_already_processed = true;
41
42
  let messageObj = message;
42
43
  if (typeof message === 'string') {
43
44
  messageObj = JSON.parse(message);
44
45
  }
45
- const result = messageObj.params.result;
46
- const _txid = result.signature;
47
- const slot = result.slot;
48
- (0, dist_1.log_info)('check txid:', { _txid, txid: this.txid, slot });
49
- result.transaction.transaction.signatures = [_txid];
46
+ let result;
47
+ let _txid;
48
+ let slot;
49
+ let transactionData;
50
+ let meta;
51
+ let version;
52
+ if (messageObj.transaction && messageObj.transaction.signature) {
53
+ _txid = messageObj.transaction.signature;
54
+ slot = messageObj.slot;
55
+ transactionData = messageObj.transaction.transaction;
56
+ meta = messageObj.transaction.meta;
57
+ version = messageObj.transaction.version !== undefined ? messageObj.transaction.version : 0;
58
+ }
59
+ else if (messageObj.params && messageObj.params.result) {
60
+ result = messageObj.params.result;
61
+ _txid = result.signature;
62
+ slot = result.slot;
63
+ transactionData = (_a = result.transaction) === null || _a === void 0 ? void 0 : _a.transaction;
64
+ meta = (_b = result.transaction) === null || _b === void 0 ? void 0 : _b.meta;
65
+ version = ((_c = result.transaction) === null || _c === void 0 ? void 0 : _c.version) !== undefined ? result.transaction.version : 0;
66
+ }
67
+ else {
68
+ (0, dist_1.log_error)('Invalid message format: unrecognized structure', new Error(JSON.stringify(messageObj)));
69
+ return;
70
+ }
71
+ if (_txid !== this.txid) {
72
+ (0, dist_1.log_error)('[tx_result_check] txid mismatch!', new Error(JSON.stringify({ _txid, txid: this.txid, slot })));
73
+ return;
74
+ }
75
+ transactionData.signatures = [_txid];
50
76
  let tx_result = {
51
- slot,
52
- transaction: result.transaction.transaction,
53
- meta: result.transaction.meta,
54
- blockTime: Date.now() / 1000,
55
- version: result.transaction.version
77
+ slot: slot,
78
+ transaction: transactionData,
79
+ meta: meta || null,
80
+ blockTime: messageObj.blockTime || (Date.now() / 1000),
81
+ version: (typeof version === 'number' && version === 0) ? 0 : version
56
82
  };
57
83
  let swap_result = this.transactionParser.parse_transaction_data(tx_result, this.pool_info);
58
84
  let trade_result = this.map_swap_result_to_tx_result(swap_result);
@@ -67,7 +93,7 @@ class TransactionResultChecker extends dist_1.AbstractTransactionResultCheck {
67
93
  console.log('---------------------------------------------------->');
68
94
  }
69
95
  catch (err) {
70
- (0, dist_1.log_error)('parse geyser stream message error!', err);
96
+ (0, dist_1.log_error)('parse stream transaction message error!', err);
71
97
  return;
72
98
  }
73
99
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clonegod/ttd-sol-common",
3
- "version": "2.0.40",
3
+ "version": "2.0.42",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "types/index.d.ts",
@@ -7,6 +7,9 @@ export class SolanaTradeAppConfig extends AbstractTradeAppConfig {
7
7
  public connection: Connection;
8
8
  public keypair: Keypair;
9
9
 
10
+ // WebSocket 客户端实例,用于订阅交易结果
11
+ private ws_client: WebSocketClient | null = null;
12
+
10
13
  constructor() {
11
14
  super();
12
15
  }
@@ -19,6 +22,22 @@ export class SolanaTradeAppConfig extends AbstractTradeAppConfig {
19
22
 
20
23
  // 订阅 Wallet 在链上发生的tx data
21
24
  subscribe_wallet_raw_txn_event(): void {
25
+ // 检查是否已经订阅
26
+ if(this.is_already_subscribe_wallet_raw_txn) {
27
+ // 如果已订阅,检查连接状态
28
+ if(this.ws_client && this.ws_client.isConnected()) {
29
+ return;
30
+ } else {
31
+ // 连接已断开,需要重新连接
32
+ log_info('subscribe_wallet_raw_txn_event was subscribed but connection lost, reconnecting...');
33
+ if(this.ws_client) {
34
+ this.ws_client.disconnect();
35
+ this.ws_client = null;
36
+ }
37
+ }
38
+ }
39
+ this.is_already_subscribe_wallet_raw_txn = true;
40
+
22
41
  // 定义处理函数,便于后续移除
23
42
  const transactionHandler = async (messageStr: any) => {
24
43
  let messageObj = messageStr
@@ -34,9 +53,12 @@ export class SolanaTradeAppConfig extends AbstractTradeAppConfig {
34
53
  };
35
54
 
36
55
  const ws_port = process.env.STREAM_WS_TRADE_PORT || 10002;
37
- const ws = new WebSocketClient(`ws://127.0.0.1:${ws_port}`)
38
- ws.onMessage(transactionHandler);
39
- ws.connect();
56
+ const ws_url = `ws://127.0.0.1:${ws_port}`;
57
+ this.ws_client = new WebSocketClient(ws_url)
58
+ this.ws_client.onMessage(transactionHandler);
59
+ this.ws_client.connect();
60
+
61
+ log_info(`subscribe_wallet_raw_txn_event, WebSocket connecting to ${ws_url}`);
40
62
 
41
63
  // 不断开连接
42
64
  // setTimeout(() => { ws.disconnect(); }, 6000);
@@ -1,9 +1,9 @@
1
1
  import { OrderMessageType, PriceMessageType, StandardPoolInfoType, StandardSwapDetailType, TradeBroadcastType, TradeResultBalanceChangeType, TradeResultType, TradeTimeFlowType } from "@clonegod/ttd-core"
2
- import { AbstractTransactionResultCheck, getServerInfo, isEmpty, LOCAL_EVENT_NAME, LOG, log_debug, log_error, log_info, log_warn, TradeContext, TRANSACTION_STATE_FAILED, TRANSACTION_STATE_PROCESSING, TRANSACTION_STATE_SUCCESS } from "@clonegod/ttd-core/dist"
2
+ import { AbstractTransactionResultCheck, getServerInfo, isEmpty, LOCAL_EVENT_NAME, log_error, log_info, log_warn, TradeContext, TRANSACTION_STATE_FAILED, TRANSACTION_STATE_PROCESSING, TRANSACTION_STATE_SUCCESS } from "@clonegod/ttd-core/dist"
3
3
  import { Connection, ParsedTransactionWithMeta, PublicKey } from "@solana/web3.js"
4
4
  import { EventEmitter } from 'events'
5
- import { TransactionResultParser } from "./tx_result_parse"
6
5
  import { COMMITMENT_LEVEL } from "../common"
6
+ import { TransactionResultParser } from "./tx_result_parse"
7
7
 
8
8
 
9
9
 
@@ -88,20 +88,57 @@ export class TransactionResultChecker extends AbstractTransactionResultCheck {
88
88
  messageObj = JSON.parse(message)
89
89
  }
90
90
 
91
- const result = messageObj.params.result
92
- const _txid = result.signature // Extract the signature
93
- const slot = result.slot
94
- log_info('check txid:', { _txid, txid: this.txid, slot})
91
+ // 支持两种消息格式:
92
+ // 1. 原始格式 (decodedTransaction): { slot, transaction: { signature, index, transaction, meta, version } }
93
+ // 2. 转换后格式: { params: { result: { signature, slot, transaction: { transaction, meta, version } } } }
94
+
95
+ let result: any
96
+ let _txid: string
97
+ let slot: number
98
+ let transactionData: any
99
+ let meta: any
100
+ let version: number
101
+
102
+ // 检查是否为转换后的格式 (params.result)
103
+
104
+ // 基于 laser_stream 推送的 transaction 格式
105
+ if (messageObj.transaction && messageObj.transaction.signature) {
106
+ _txid = messageObj.transaction.signature
107
+ slot = messageObj.slot
108
+ transactionData = messageObj.transaction.transaction
109
+ meta = messageObj.transaction.meta
110
+ version = messageObj.transaction.version !== undefined ? messageObj.transaction.version : 0
111
+ }
112
+ // 基于 geyser ws 推送的 transaction 格式 ?
113
+ else if (messageObj.params && messageObj.params.result) {
114
+ result = messageObj.params.result
115
+ _txid = result.signature
116
+ slot = result.slot
117
+ transactionData = result.transaction?.transaction
118
+ meta = result.transaction?.meta
119
+ version = result.transaction?.version !== undefined ? result.transaction.version : 0
120
+ }
121
+ else {
122
+ log_error('Invalid message format: unrecognized structure', new Error(JSON.stringify(messageObj)))
123
+ return
124
+ }
95
125
 
96
- // set txid for parse
97
- result.transaction.transaction.signatures = [_txid]
126
+ if(_txid !== this.txid) {
127
+ log_error('[tx_result_check] txid mismatch!', new Error(JSON.stringify({ _txid, txid: this.txid, slot })))
128
+ return
129
+ }
98
130
 
99
- let tx_result:ParsedTransactionWithMeta = {
100
- slot,
101
- transaction: result.transaction.transaction,
102
- meta: result.transaction.meta,
103
- blockTime: Date.now() / 1000,
104
- version: result.transaction.version
131
+ // set txid for parse - 确保 signatures 数组存在
132
+ transactionData.signatures = [_txid]
133
+
134
+ // 构建 ParsedTransactionWithMeta 对象,确保所有属性都被正确复制
135
+ // version 字段类型为 TransactionVersion,通常是 0 或 'legacy'
136
+ let tx_result: ParsedTransactionWithMeta = {
137
+ slot: slot,
138
+ transaction: transactionData,
139
+ meta: meta || null,
140
+ blockTime: messageObj.blockTime || (Date.now() / 1000),
141
+ version: (typeof version === 'number' && version === 0) ? 0 : (version as any)
105
142
  }
106
143
 
107
144
  let swap_result = this.transactionParser.parse_transaction_data(tx_result, this.pool_info)
@@ -117,7 +154,7 @@ export class TransactionResultChecker extends AbstractTransactionResultCheck {
117
154
  console.dir(trade_result, { depth: 8 })
118
155
  console.log('---------------------------------------------------->')
119
156
  } catch (err) {
120
- log_error('parse geyser stream message error!', err)
157
+ log_error('parse stream transaction message error!', err)
121
158
  return
122
159
  }
123
160
  })