@clonegod/ttd-sol-common 1.0.33 → 1.0.35

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.
@@ -0,0 +1,10 @@
1
+ export declare const MAX_GAS_FEE: number;
2
+ export declare const ONE_MILLION = 1000000;
3
+ export declare enum COMMITMENT_LEVEL {
4
+ PROCESSED = "processed",
5
+ CONFIRMED = "confirmed",
6
+ _FINALIZED = "finalized"
7
+ }
8
+ export declare enum LOCAL_EVENT_NAME {
9
+ EVENT_POOL_ACCOUNT_CHANGE = "EVENT_POOL_ACCOUNT_CHANGE"
10
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LOCAL_EVENT_NAME = exports.COMMITMENT_LEVEL = exports.ONE_MILLION = exports.MAX_GAS_FEE = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ exports.MAX_GAS_FEE = web3_js_1.LAMPORTS_PER_SOL / 1000;
6
+ exports.ONE_MILLION = 1000000;
7
+ var COMMITMENT_LEVEL;
8
+ (function (COMMITMENT_LEVEL) {
9
+ COMMITMENT_LEVEL["PROCESSED"] = "processed";
10
+ COMMITMENT_LEVEL["CONFIRMED"] = "confirmed";
11
+ COMMITMENT_LEVEL["_FINALIZED"] = "finalized";
12
+ })(COMMITMENT_LEVEL || (exports.COMMITMENT_LEVEL = COMMITMENT_LEVEL = {}));
13
+ var LOCAL_EVENT_NAME;
14
+ (function (LOCAL_EVENT_NAME) {
15
+ LOCAL_EVENT_NAME["EVENT_POOL_ACCOUNT_CHANGE"] = "EVENT_POOL_ACCOUNT_CHANGE";
16
+ })(LOCAL_EVENT_NAME || (exports.LOCAL_EVENT_NAME = LOCAL_EVENT_NAME = {}));
@@ -0,0 +1,22 @@
1
+ import { OrderMessageType, PriceMessageType, StandardPoolInfoType, TradeRuntimeType } from "@clonegod/ttd-common";
2
+ import { CHAIN_ID, DEX_ID } from "@clonegod/ttd-common/dist";
3
+ import { Connection } from "@solana/web3.js";
4
+ import { SolanaTradeRuntimeType } from "../../types";
5
+ export declare class TradeContext {
6
+ connection: Connection;
7
+ trade_runtime: TradeRuntimeType;
8
+ solana_trade_runtime: SolanaTradeRuntimeType;
9
+ price_msg: PriceMessageType;
10
+ order_msg: OrderMessageType;
11
+ order_trace_id: string;
12
+ group_id: string;
13
+ chain_id: CHAIN_ID;
14
+ dex_id: DEX_ID;
15
+ pool_id: string;
16
+ fee_rate: string;
17
+ pool_info: StandardPoolInfoType;
18
+ aToB: boolean;
19
+ slippage_bps: number;
20
+ constructor(price_msg: PriceMessageType, order_msg: OrderMessageType);
21
+ init(trade_runtime: TradeRuntimeType): Promise<void>;
22
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TradeContext = void 0;
13
+ const dist_1 = require("@clonegod/ttd-common/dist");
14
+ const send_tx_1 = require("../send_tx");
15
+ class TradeContext {
16
+ constructor(price_msg, order_msg) {
17
+ this.price_msg = price_msg;
18
+ this.order_msg = order_msg;
19
+ this.order_trace_id = order_msg.order_trace_id;
20
+ }
21
+ init(trade_runtime) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ this.trade_runtime = trade_runtime;
24
+ let { group_id, unique_orderbook_id } = this.order_msg;
25
+ this.group_id = group_id;
26
+ let unique_orderbook_id_obj = (0, dist_1.parse_unique_orderbook_id)(unique_orderbook_id);
27
+ this.chain_id = dist_1.CHAIN_ID[unique_orderbook_id_obj.chain_id];
28
+ this.dex_id = dist_1.DEX_ID[unique_orderbook_id_obj.dex_id];
29
+ this.pool_id = unique_orderbook_id_obj.pool_id;
30
+ this.fee_rate = unique_orderbook_id_obj.fee_rate;
31
+ this.pool_info = this.trade_runtime.pair_dex.pool_info_list.find(e => e.pool_address === this.pool_id);
32
+ if (!this.pool_info) {
33
+ throw new Error(`Not found pool_info! pool_id=${this.pool_id}, pool_info_list=${JSON.stringify(this.trade_runtime.pair_dex.pool_info_list)}`);
34
+ }
35
+ this.slippage_bps = Math.min(100, Math.max(30, this.trade_runtime.settings.slippage_bps));
36
+ this.aToB = this.pool_info.is_reverse_token ? !this.order_msg.aToB : this.order_msg.aToB;
37
+ this.solana_trade_runtime = (0, send_tx_1.create_solana_trade_runtime)(this.connection, this.trade_runtime, this.pool_info);
38
+ });
39
+ }
40
+ }
41
+ exports.TradeContext = TradeContext;
@@ -0,0 +1,2 @@
1
+ export * from './constants';
2
+ export * from './context';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./constants"), exports);
18
+ __exportStar(require("./context"), exports);
@@ -0,0 +1,31 @@
1
+ import { StandardTokenInfoType, TradeRuntimeType } from "@clonegod/ttd-common";
2
+ import { Connection } from "@solana/web3.js";
3
+ export interface StandardSwapDetailType {
4
+ success: boolean;
5
+ error_code: string;
6
+ wallet: string;
7
+ txid: string;
8
+ block_time: number;
9
+ block_number: number;
10
+ pool_address: string;
11
+ tokenA: TokenBalChangeType;
12
+ tokenB: TokenBalChangeType;
13
+ tx_price: string;
14
+ gas_fee: GasFeeType;
15
+ }
16
+ export interface TokenBalChangeType extends StandardTokenInfoType {
17
+ pre_bal: number;
18
+ post_bal: number;
19
+ change: string;
20
+ }
21
+ export interface GasFeeType {
22
+ base_fee: number;
23
+ priority_fee: number;
24
+ total_fee: number;
25
+ }
26
+ export interface SolanaTradeRuntimeType extends TradeRuntimeType {
27
+ connection: Connection;
28
+ priority_fee: number;
29
+ cu_price: number;
30
+ cu_limit: number;
31
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ /// <reference types="node" />
2
+ import { StandardPoolInfoType } from "@clonegod/ttd-common";
3
+ import EventEmitter from "events";
4
+ export declare const subscribe_pool_change_by_geyser: (geyser_ws_url: string, pool_list: StandardPoolInfoType[], eventEmitter: EventEmitter) => Promise<void>;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.subscribe_pool_change_by_geyser = void 0;
16
+ const dist_1 = require("@clonegod/ttd-common/dist");
17
+ const ws_1 = __importDefault(require("ws"));
18
+ const constants_1 = require("../common/constants");
19
+ const subscribe_pool_change_by_geyser = (geyser_ws_url, pool_list, eventEmitter) => __awaiter(void 0, void 0, void 0, function* () {
20
+ if ((0, dist_1.isEmpty)(geyser_ws_url)) {
21
+ (0, dist_1.log_warn)(`geyser_ws_url is empty, cann't subscribe`);
22
+ return;
23
+ }
24
+ if ((0, dist_1.isEmpty)(pool_list)) {
25
+ (0, dist_1.log_warn)(`pool_list is empty, nothing to subscribe`);
26
+ return;
27
+ }
28
+ yield (0, dist_1.sleep)(1000);
29
+ var ws_client = new ws_1.default(geyser_ws_url);
30
+ function subscribe_account_change(ws_client, pool) {
31
+ (0, dist_1.log_info)(`subscribe: ${pool.pool_name} -> ${pool.pool_address}`);
32
+ const request = {
33
+ jsonrpc: '2.0',
34
+ id: 420,
35
+ method: 'accountSubscribe',
36
+ params: [
37
+ pool.pool_address,
38
+ {
39
+ encoding: 'jsonParsed',
40
+ commitment: constants_1.COMMITMENT_LEVEL.PROCESSED,
41
+ },
42
+ ],
43
+ };
44
+ ws_client.send(JSON.stringify(request));
45
+ }
46
+ ws_client.on('open', function open() {
47
+ (0, dist_1.log_info)(`WebSocket is open`);
48
+ pool_list.forEach((pool) => {
49
+ subscribe_account_change(ws_client, pool);
50
+ });
51
+ });
52
+ ws_client.on('message', function incoming(data) {
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ (0, dist_1.log_info)(`Received Geyser Message`);
55
+ let messageStr = '';
56
+ try {
57
+ messageStr = data.toString('utf8');
58
+ if (dist_1.LOG.trace) {
59
+ (0, dist_1.log_trace)(`Received msg:`, messageStr);
60
+ }
61
+ if (messageStr == '{}') {
62
+ (0, dist_1.log_info)(`receive empty message, something wrong! exit ...`);
63
+ ws_client.close();
64
+ }
65
+ const messageObj = JSON.parse(messageStr);
66
+ if (messageObj['id']) {
67
+ (0, dist_1.log_info)(`accountSubscribe success!`, messageStr);
68
+ return;
69
+ }
70
+ else {
71
+ const res_data = messageObj['params']['result']['value']['data'];
72
+ let data_buff = Buffer.from(res_data[0], res_data[1]);
73
+ eventEmitter.emit(constants_1.LOCAL_EVENT_NAME.EVENT_POOL_ACCOUNT_CHANGE, data_buff);
74
+ }
75
+ }
76
+ catch (err) {
77
+ (0, dist_1.log_error)(`Failed to parse JSON: ${messageStr}`, err);
78
+ ws_client.close();
79
+ }
80
+ });
81
+ });
82
+ ws_client.on('error', function error(err) {
83
+ (0, dist_1.log_error)(`WebSocket error:`, err);
84
+ ws_client.close();
85
+ });
86
+ ws_client.on('close', function close() {
87
+ return __awaiter(this, void 0, void 0, function* () {
88
+ (0, dist_1.log_warn)(`Socket is closed. Reconnect will be attempted in few seconds`);
89
+ (0, exports.subscribe_pool_change_by_geyser)(geyser_ws_url, pool_list, eventEmitter);
90
+ });
91
+ });
92
+ });
93
+ exports.subscribe_pool_change_by_geyser = subscribe_pool_change_by_geyser;
@@ -3,7 +3,7 @@
3
3
  import { BlockhashWithExpiryBlockHeight, VersionedTransaction, AddressLookupTableAccount, Transaction, TransactionInstruction, TransactionSignature, Commitment, PublicKey, AccountInfo, GetLatestBlockhashConfig, RpcResponseAndContext, SignatureResult, Blockhash, Connection, ParsedAccountData, SendOptions, Signer, SerializeConfig } from '@solana/web3.js';
4
4
  import { DAS } from './types/das-types';
5
5
  import { GetPriorityFeeEstimateRequest, GetPriorityFeeEstimateResponse, JitoRegion, PollTransactionOptions, SmartTransactionContext, HeliusSendOptions } from './types';
6
- import { SolanaTradeRuntimeType } from '../context';
6
+ import { SolanaTradeRuntimeType } from '../../types';
7
7
  export type SendAndConfirmTransactionResponse = {
8
8
  signature: TransactionSignature;
9
9
  confirmResponse: RpcResponseAndContext<SignatureResult>;
@@ -17,7 +17,7 @@ const web3_js_1 = require("@solana/web3.js");
17
17
  const bs58_1 = __importDefault(require("bs58"));
18
18
  const axios_1 = __importDefault(require("axios"));
19
19
  const types_1 = require("./types");
20
- const get_signature_1 = require("../get_signature");
20
+ const get_signature_1 = require("../send_tx/get_signature");
21
21
  const dist_1 = require("@clonegod/ttd-common/dist");
22
22
  class RpcClient {
23
23
  constructor(connection, id) {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export * from './constants';
2
- export * from './context';
3
- export * from './strategy_util';
1
+ export * from './common';
2
+ export * from './config';
4
3
  export * from './helius_geyser_ws';
5
- export * from './send_transaction';
4
+ export * from './send_tx';
5
+ export * from './trade';
package/dist/index.js CHANGED
@@ -14,8 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./constants"), exports);
18
- __exportStar(require("./context"), exports);
19
- __exportStar(require("./strategy_util"), exports);
17
+ __exportStar(require("./common"), exports);
18
+ __exportStar(require("./config"), exports);
20
19
  __exportStar(require("./helius_geyser_ws"), exports);
21
- __exportStar(require("./send_transaction"), exports);
20
+ __exportStar(require("./send_tx"), exports);
21
+ __exportStar(require("./trade"), exports);
@@ -0,0 +1,2 @@
1
+ import { Transaction, VersionedTransaction } from '@solana/web3.js';
2
+ export declare function getSignature(transaction: Transaction | VersionedTransaction): string;
@@ -0,0 +1,15 @@
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.getSignature = void 0;
7
+ const bs58_1 = __importDefault(require("bs58"));
8
+ function getSignature(transaction) {
9
+ const signature = 'signature' in transaction ? transaction.signature : transaction.signatures[0];
10
+ if (!signature) {
11
+ throw new Error('Missing transaction signature, the transaction was not signed by the fee payer');
12
+ }
13
+ return bs58_1.default.encode(signature);
14
+ }
15
+ exports.getSignature = getSignature;
@@ -0,0 +1,3 @@
1
+ export * from './get_signature';
2
+ export * from './send_transaction';
3
+ export * from './strategy_util';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./get_signature"), exports);
18
+ __exportStar(require("./send_transaction"), exports);
19
+ __exportStar(require("./strategy_util"), exports);
@@ -0,0 +1,14 @@
1
+ import { SendOptions, Signer, TransactionInstruction } from "@solana/web3.js";
2
+ import { Helius } from "../helius_sdk_v1.4.0";
3
+ import { SolanaTradeRuntimeType } from '../../types';
4
+ export declare class HeliusClient {
5
+ signers: Signer[];
6
+ sendOptions: SendOptions;
7
+ cluster: string;
8
+ helius_mainnet: Helius;
9
+ helius_staked: Helius;
10
+ constructor(signers: Signer[]);
11
+ send_transaction(solana_trade_runtime: SolanaTradeRuntimeType, instructions: TransactionInstruction[]): Promise<string>;
12
+ private send_smart_transaction;
13
+ private send_transaction_by_jito;
14
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.HeliusClient = void 0;
13
+ const dist_1 = require("@clonegod/ttd-common/dist");
14
+ const helius_sdk_v1_4_0_1 = require("../helius_sdk_v1.4.0");
15
+ const strategy_util_1 = require("./strategy_util");
16
+ class HeliusClient {
17
+ constructor(signers) {
18
+ this.cluster = 'mainnet-beta';
19
+ this.signers = signers;
20
+ this.sendOptions = {
21
+ skipPreflight: true,
22
+ maxRetries: 0
23
+ };
24
+ let helius_api_key = process.env.HELIUS_API_KEY;
25
+ let helius_mainnet_endpoint = `https://mainnet.helius-rpc.com/?api-key=${helius_api_key}`;
26
+ let helius_staked_endpoint = `https://staked.helius-rpc.com?api-key=${helius_api_key}`;
27
+ this.helius_mainnet = new helius_sdk_v1_4_0_1.Helius('', this.cluster, 'helius-sdk', helius_mainnet_endpoint);
28
+ this.helius_staked = new helius_sdk_v1_4_0_1.Helius('', this.cluster, 'helius-sdk', helius_staked_endpoint);
29
+ }
30
+ send_transaction(solana_trade_runtime, instructions) {
31
+ return __awaiter(this, void 0, void 0, function* () {
32
+ let txid = '';
33
+ let { broadcast_type, speed } = solana_trade_runtime.settings.strategy;
34
+ if (broadcast_type === 'rpc') {
35
+ let use_staked_endpint = speed === 'turbo' || speed === 'ultra';
36
+ txid = yield this.send_smart_transaction(solana_trade_runtime, instructions, use_staked_endpint);
37
+ }
38
+ else if (broadcast_type === 'jito') {
39
+ txid = yield this.send_transaction_by_jito(solana_trade_runtime, instructions);
40
+ }
41
+ else {
42
+ throw new Error(`Not support broadcast_type: ${broadcast_type}`);
43
+ }
44
+ return txid;
45
+ });
46
+ }
47
+ send_smart_transaction(solana_trade_runtime, instructions, use_staked_endpint) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ (0, dist_1.log_info)(`send_smart_transaction, start`);
50
+ let start_time = Date.now();
51
+ let rpc = use_staked_endpint ? this.helius_staked.rpc : this.helius_mainnet.rpc;
52
+ let txid = yield rpc.sendSmartTransaction(solana_trade_runtime, instructions, this.signers, [], this.sendOptions);
53
+ (0, dist_1.log_info)(`send_smart_transaction, end`, {
54
+ txid,
55
+ use_staked_endpint,
56
+ take_time: Date.now() - start_time
57
+ });
58
+ return txid;
59
+ });
60
+ }
61
+ send_transaction_by_jito(solana_trade_runtime, instructions) {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ (0, dist_1.log_info)(`send_transaction_by_jito, start`);
64
+ let start_time = Date.now();
65
+ let tipAmount = solana_trade_runtime.priority_fee;
66
+ let jito_region = (0, strategy_util_1.get_jito_region)();
67
+ let rpc = this.helius_mainnet.rpc;
68
+ let txid = yield rpc.sendSmartTransactionWithTip(solana_trade_runtime, instructions, this.signers, [], tipAmount, jito_region);
69
+ (0, dist_1.log_info)(`send_transaction_by_jito, end`, {
70
+ tipAmount,
71
+ jito_region,
72
+ txid,
73
+ take_time: Date.now() - start_time
74
+ });
75
+ return txid;
76
+ });
77
+ }
78
+ }
79
+ exports.HeliusClient = HeliusClient;
@@ -0,0 +1,7 @@
1
+ import { StandardPoolInfoType, TradeRuntimeType, TradeStrategyType } from "@clonegod/ttd-common";
2
+ import { JitoRegion } from "../helius_sdk_v1.4.0";
3
+ import { Connection } from "@solana/web3.js";
4
+ import { SolanaTradeRuntimeType } from "../../types";
5
+ export declare function create_solana_trade_runtime(connection: Connection, trade_runtime: TradeRuntimeType, pool_info: StandardPoolInfoType): SolanaTradeRuntimeType;
6
+ export declare function calculate_gas_fee(trade_strategy: TradeStrategyType): number;
7
+ export declare function get_jito_region(): JitoRegion;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.get_jito_region = exports.calculate_gas_fee = exports.create_solana_trade_runtime = void 0;
4
+ const dist_1 = require("@clonegod/ttd-common/dist");
5
+ const constants_1 = require("../common/constants");
6
+ function create_solana_trade_runtime(connection, trade_runtime, pool_info) {
7
+ let trade_strategy = trade_runtime.settings.strategy;
8
+ let { cu_limit } = pool_info;
9
+ if (isNaN(cu_limit) || cu_limit < 50000) {
10
+ cu_limit = 50000;
11
+ }
12
+ let priority_fee = calculate_gas_fee(trade_strategy);
13
+ let cu_price = Math.ceil(priority_fee * constants_1.ONE_MILLION / cu_limit);
14
+ (0, dist_1.log_info)(`trade_strategy & gas`, {
15
+ trade_strategy,
16
+ priority_fee,
17
+ cu_limit,
18
+ cu_price
19
+ });
20
+ let solana_trade_runtime = Object.assign(Object.assign({}, trade_runtime), { connection,
21
+ priority_fee,
22
+ cu_limit,
23
+ cu_price });
24
+ return solana_trade_runtime;
25
+ }
26
+ exports.create_solana_trade_runtime = create_solana_trade_runtime;
27
+ function calculate_gas_fee(trade_strategy) {
28
+ let { speed, fee_mode, fee_exact, fee_max_cap, } = trade_strategy;
29
+ let gas_fee = 1000;
30
+ switch (fee_mode) {
31
+ case "exact":
32
+ gas_fee = get_excat_fee_by_speed(speed, fee_exact);
33
+ break;
34
+ case "max_cap":
35
+ gas_fee = get_dynamic_fee_by_speed(speed, 50000, fee_max_cap);
36
+ break;
37
+ default:
38
+ throw new Error(`Not support fee_mode: ${fee_mode}`);
39
+ }
40
+ return gas_fee;
41
+ }
42
+ exports.calculate_gas_fee = calculate_gas_fee;
43
+ function get_excat_fee_by_speed(speed, fee_exact) {
44
+ let factor = 1;
45
+ if (speed === 'fast') {
46
+ factor = 1;
47
+ }
48
+ if (speed === 'turbo') {
49
+ factor = 2;
50
+ }
51
+ if (speed === 'ultra') {
52
+ factor = 5;
53
+ }
54
+ return fee_exact * factor;
55
+ }
56
+ function get_dynamic_fee_by_speed(speed, estimate_priority_fee, fee_max_cap) {
57
+ let factor = 1;
58
+ if (speed === 'fast') {
59
+ factor = 1;
60
+ }
61
+ if (speed === 'turbo') {
62
+ factor = 2;
63
+ }
64
+ if (speed === 'ultra') {
65
+ factor = 5;
66
+ }
67
+ return Math.min(estimate_priority_fee * factor, fee_max_cap);
68
+ }
69
+ function get_jito_region() {
70
+ let jito_region;
71
+ let server_info = (0, dist_1.getServerInfo)();
72
+ switch (server_info.region) {
73
+ case 'fra':
74
+ jito_region = 'Frankfurt';
75
+ break;
76
+ case 'virginia':
77
+ jito_region = 'NY';
78
+ break;
79
+ case 'jp':
80
+ jito_region = 'Tokyo';
81
+ break;
82
+ default:
83
+ jito_region = 'Default';
84
+ }
85
+ (0, dist_1.log_debug)(`get_jito_region`, {
86
+ server_info,
87
+ jito_region
88
+ });
89
+ return jito_region;
90
+ }
91
+ exports.get_jito_region = get_jito_region;
@@ -0,0 +1,6 @@
1
+ import { StandardPoolInfoType } from "@clonegod/ttd-common";
2
+ import { TradeContext } from "../common/context";
3
+ export declare abstract class AbastrcatTrade {
4
+ abstract init(pool_list: StandardPoolInfoType[]): void;
5
+ abstract execute(context: TradeContext): Promise<string>;
6
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbastrcatTrade = void 0;
4
+ class AbastrcatTrade {
5
+ }
6
+ exports.AbastrcatTrade = AbastrcatTrade;
@@ -0,0 +1,4 @@
1
+ import { AppConfig } from "../config";
2
+ import { AbastrcatTrade } from "./abstract_trade";
3
+ export declare const try_lock_order_msg: (appConfig: AppConfig, order_msg: any) => Promise<boolean>;
4
+ export declare const handle_order_message: (appConfig: AppConfig, trade: AbastrcatTrade, message: string) => Promise<void>;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.handle_order_message = exports.try_lock_order_msg = void 0;
13
+ const dist_1 = require("@clonegod/ttd-common/dist");
14
+ const common_1 = require("../common");
15
+ const tx_result_check_1 = require("./tx_result_check");
16
+ const check_parse_order_msg = (appConfig, order_msg) => __awaiter(void 0, void 0, void 0, function* () {
17
+ let { unique_orderbook_id, price_id, group_id, unique_order_msg_id } = order_msg;
18
+ const runtime_group_id = appConfig.trade_runtime.group.id;
19
+ if (group_id !== runtime_group_id) {
20
+ throw new Error(`group_id not match!!! ${(0, dist_1.to_json_str)({ group_id, runtime_group_id })}`);
21
+ }
22
+ if ((0, dist_1.isEmpty)(unique_order_msg_id)) {
23
+ throw new Error(`unique_order_msg_id is empty or null! unique_order_msg_id=${unique_order_msg_id}`);
24
+ }
25
+ let price_msg = yield appConfig.arb_cache.get_price_message(price_id);
26
+ if ((0, dist_1.isEmpty)(price_msg)) {
27
+ throw new Error(`price_msg not found in the cache! price_id=${price_id}`);
28
+ }
29
+ let id_parts = (0, dist_1.parse_unique_orderbook_id)(unique_orderbook_id);
30
+ if (id_parts.dex_id != price_msg.dex_id ||
31
+ id_parts.pool_id != price_msg.pool_id) {
32
+ (0, dist_1.log_warn)(`check data: order_msg VS price_msg, not match!!!`, {
33
+ order_msg,
34
+ uinique_orderbook: id_parts,
35
+ price_msg,
36
+ });
37
+ }
38
+ return {
39
+ price_msg,
40
+ id_parts
41
+ };
42
+ });
43
+ const try_lock_order_msg = (appConfig, order_msg) => __awaiter(void 0, void 0, void 0, function* () {
44
+ let { chain_id, group_id, price_id, order_trace_id } = order_msg;
45
+ let lock_order_key = (0, dist_1.format_order_lock_key)(chain_id, group_id, price_id, order_trace_id);
46
+ (0, dist_1.log_info)(`try_lock_order_msg, key=${lock_order_key}`);
47
+ let is_lock_success = yield appConfig.arb_cache.redis_cmd.set_nx(lock_order_key, '');
48
+ if (is_lock_success) {
49
+ (0, dist_1.log_info)(`try_lock_order_msg, key=${lock_order_key}, success`);
50
+ appConfig.arb_cache.redis_cmd.expire(lock_order_key, 60)
51
+ .then(res => (0, dist_1.log_trace)(`expire lock: key=${lock_order_key}, success`))
52
+ .catch(err => (0, dist_1.log_error)(`expire lock: key=${lock_order_key}, error!`, err));
53
+ }
54
+ else {
55
+ (0, dist_1.log_info)(`try_lock_order_msg, key=${lock_order_key}, acquire lock failed!`);
56
+ }
57
+ return is_lock_success;
58
+ });
59
+ exports.try_lock_order_msg = try_lock_order_msg;
60
+ const handle_order_message = (appConfig, trade, message) => __awaiter(void 0, void 0, void 0, function* () {
61
+ (0, dist_1.new_line)(3);
62
+ (0, dist_1.log_info)(`handle_order_message, on message: `, message);
63
+ setTimeout(() => {
64
+ console.log(`=================================================================================`);
65
+ console.log(`| NEW ORDER MESSAGE |`);
66
+ console.log(`=================================================================================`);
67
+ }, 0);
68
+ let order_event_message = JSON.parse(message);
69
+ if (dist_1.LOG.debug) {
70
+ (0, dist_1.log_debug)(`order_event_msg`, order_event_message);
71
+ }
72
+ let { event_time, event_type, group_id, data: order_msg } = order_event_message;
73
+ let { price_msg, id_parts } = yield check_parse_order_msg(appConfig, order_msg);
74
+ let { order_trace_id } = order_msg;
75
+ let { chain_id, dex_id, pool_id, fee_rate } = id_parts;
76
+ let lock_order = yield (0, exports.try_lock_order_msg)(appConfig, order_msg);
77
+ if (!lock_order) {
78
+ (0, dist_1.log_warn)(`try lock order failed!`, {
79
+ chain_id, group_id, order_trace_id
80
+ });
81
+ return;
82
+ }
83
+ let context;
84
+ let txid = '';
85
+ let order_submit_result;
86
+ try {
87
+ let { env_args, trade_runtime } = appConfig;
88
+ context = new common_1.TradeContext(price_msg, order_msg);
89
+ yield context.init(trade_runtime);
90
+ txid = yield trade.execute(context);
91
+ order_msg.order_submit_time = Date.now();
92
+ order_submit_result = {
93
+ success: true,
94
+ msg: 'SUCCESS',
95
+ txid
96
+ };
97
+ new tx_result_check_1.TransactionResultChecker(env_args, appConfig, context, txid).init_tx_status().check();
98
+ }
99
+ catch (err) {
100
+ (0, dist_1.log_error)(`handle_order_message error!`, err);
101
+ order_submit_result = {
102
+ success: false,
103
+ msg: (err === null || err === void 0 ? void 0 : err.message) || 'FAILED',
104
+ txid
105
+ };
106
+ }
107
+ finally {
108
+ appConfig.arb_cache.cache_order_message(Object.assign(Object.assign({}, order_msg), { order_submit_result })).then(res => {
109
+ (0, dist_1.log_info)(`cache order submit result, success`, { order_msg, order_submit_result, res });
110
+ }).catch(err => {
111
+ (0, dist_1.log_warn)('cache order submit result, error!', { order_msg, order_submit_result, err });
112
+ console.log(err);
113
+ });
114
+ }
115
+ });
116
+ exports.handle_order_message = handle_order_message;
@@ -0,0 +1,4 @@
1
+ export * from './abstract_trade';
2
+ export * from './tx_result_check';
3
+ export * from './tx_result_parse';
4
+ export * from './handle_order_message';
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./abstract_trade"), exports);
18
+ __exportStar(require("./tx_result_check"), exports);
19
+ __exportStar(require("./tx_result_parse"), exports);
20
+ __exportStar(require("./handle_order_message"), exports);
@@ -0,0 +1,27 @@
1
+ /// <reference types="node" />
2
+ import { OrderMessageType, PriceMessageType, StandardPoolInfoType, TradeResultType } from "@clonegod/ttd-common";
3
+ import { Connection, PublicKey } from "@solana/web3.js";
4
+ import { EventEmitter } from 'events';
5
+ import { StandardSwapDetailType } from "../../types";
6
+ import { TradeContext } from "../common/context";
7
+ import { TransactionResultParser } from "./tx_result_parse";
8
+ export declare class TransactionResultChecker {
9
+ env_args: any;
10
+ event_emitter: EventEmitter;
11
+ connection: Connection;
12
+ wallet: PublicKey;
13
+ context: TradeContext;
14
+ group_id: string;
15
+ txid: string;
16
+ trace_id: string;
17
+ price_msg: PriceMessageType;
18
+ order_msg: OrderMessageType;
19
+ pool_info: StandardPoolInfoType;
20
+ check_count: number;
21
+ transactionParser: TransactionResultParser;
22
+ constructor(env_args: any, event_emitter: EventEmitter, context: TradeContext, txid: string);
23
+ init_tx_status(): this;
24
+ check(): Promise<void>;
25
+ check_tx_result_interval(): Promise<void>;
26
+ map_swap_result_to_tx_result(swap_result: StandardSwapDetailType): TradeResultType;
27
+ }
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TransactionResultChecker = void 0;
13
+ const dist_1 = require("@clonegod/ttd-common/dist");
14
+ const web3_js_1 = require("@solana/web3.js");
15
+ const constants_1 = require("../common/constants");
16
+ const tx_result_parse_1 = require("./tx_result_parse");
17
+ class TransactionResultChecker {
18
+ constructor(env_args, event_emitter, context, txid) {
19
+ this.env_args = env_args;
20
+ this.event_emitter = event_emitter;
21
+ this.context = context;
22
+ this.group_id = context.group_id;
23
+ this.connection = context.solana_trade_runtime.connection;
24
+ this.wallet = new web3_js_1.PublicKey(context.trade_runtime.wallet.public_key);
25
+ this.txid = txid;
26
+ this.price_msg = context.price_msg;
27
+ this.order_msg = context.order_msg;
28
+ this.pool_info = context.pool_info;
29
+ this.trace_id = context.order_msg.order_trace_id;
30
+ this.check_count = 0;
31
+ this.transactionParser = new tx_result_parse_1.TransactionResultParser(this.env_args, this.wallet, this.event_emitter);
32
+ }
33
+ init_tx_status() {
34
+ let empty_trade_result = JSON.parse(JSON.stringify({
35
+ group_id: this.context.group_id,
36
+ txid: this.txid
37
+ }));
38
+ this.event_emitter.emit(dist_1.TRANSACTION_STATE_PROCESSING, empty_trade_result);
39
+ return this;
40
+ }
41
+ check() {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ this.check_tx_result_interval();
44
+ });
45
+ }
46
+ check_tx_result_interval() {
47
+ return __awaiter(this, void 0, void 0, function* () {
48
+ const check_start_time = Date.now();
49
+ const check_interval = 1000;
50
+ const check_timeout = 30 * 1000;
51
+ const intervalId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
52
+ this.check_count += 1;
53
+ (0, dist_1.log_info)(`check transaction start: seq=[${this.check_count}], txhash= ${this.txid}, trace_id=${this.trace_id}`);
54
+ try {
55
+ if (Date.now() - check_start_time < check_timeout) {
56
+ let tx_info = yield this.connection.getParsedTransaction(this.txid, {
57
+ commitment: constants_1.COMMITMENT_LEVEL.CONFIRMED,
58
+ maxSupportedTransactionVersion: 0,
59
+ });
60
+ if ((0, dist_1.isEmpty)(tx_info)) {
61
+ return;
62
+ }
63
+ clearInterval(intervalId);
64
+ let swap_result = this.transactionParser.parse_transaction_data(tx_info, this.pool_info);
65
+ let trade_result = this.map_swap_result_to_tx_result(swap_result);
66
+ if (trade_result.success) {
67
+ this.event_emitter.emit(dist_1.TRANSACTION_STATE_SUCCESS, trade_result);
68
+ }
69
+ else {
70
+ this.event_emitter.emit(dist_1.TRANSACTION_STATE_FAILED, trade_result);
71
+ }
72
+ setTimeout(() => {
73
+ console.log('<====================================================');
74
+ console.dir(trade_result, { depth: 8 });
75
+ console.log('====================================================>');
76
+ }, 0);
77
+ }
78
+ else {
79
+ clearInterval(intervalId);
80
+ }
81
+ }
82
+ catch (err) {
83
+ (0, dist_1.log_error)('parse transaction error!', err);
84
+ }
85
+ }), check_interval);
86
+ });
87
+ }
88
+ map_swap_result_to_tx_result(swap_result) {
89
+ let { success, error_code, wallet, block_number, block_time: order_block_time, txid, tx_price, tokenA, tokenB, gas_fee } = swap_result;
90
+ let { pool_name, is_reverse_token } = this.pool_info;
91
+ let { chain_id, dex_id, unique_orderbook_id, pair, price_id, time: quote_time, ask, bid } = this.price_msg;
92
+ let { group_id, unique_order_msg_id, order_send_time, order_recv_time, order_submit_time, aToB } = this.order_msg;
93
+ let order_price = aToB ? bid.price : ask.price;
94
+ let server_info = (0, dist_1.getServerInfo)();
95
+ let total_order_time = (order_block_time + 500) - order_recv_time;
96
+ let order_end_time = Date.now();
97
+ let start_time = order_recv_time;
98
+ let end_time = order_end_time;
99
+ let total_time = total_order_time;
100
+ let time = {
101
+ block_time: quote_time.block_time,
102
+ stream_time: quote_time.stream_time,
103
+ quote_start_time: quote_time.quote_start_time,
104
+ quote_end_time: quote_time.quote_end_time,
105
+ price_time: quote_time.price_time,
106
+ total_quote_time: quote_time.total_quote_time,
107
+ order_send_time,
108
+ order_recv_time,
109
+ order_submit_time,
110
+ order_block_time,
111
+ total_order_time,
112
+ order_end_time,
113
+ };
114
+ let broadcast = [];
115
+ let trade_strategy = this.context.solana_trade_runtime.settings.strategy;
116
+ let send_type = trade_strategy.broadcast_type;
117
+ if (send_type === 'rpc') {
118
+ send_type = trade_strategy.speed === 'fast' ? 'mainnet' : 'mainnet-premium';
119
+ }
120
+ broadcast.push({
121
+ rpc: {
122
+ read: 'qn',
123
+ write: 'qn'
124
+ },
125
+ type: send_type,
126
+ fee: gas_fee
127
+ });
128
+ let trade_balance_change = {
129
+ tokenA: {
130
+ symbol: tokenA.symbol,
131
+ address: tokenA.address,
132
+ pre_bal: tokenA.pre_bal,
133
+ post_bal: tokenA.post_bal,
134
+ change: Number(tokenA.change),
135
+ decimals: tokenA.decimals,
136
+ },
137
+ tokenB: {
138
+ symbol: tokenB.symbol,
139
+ address: tokenB.address,
140
+ pre_bal: tokenB.pre_bal,
141
+ post_bal: tokenB.post_bal,
142
+ change: Number(tokenB.change),
143
+ decimals: tokenB.decimals,
144
+ },
145
+ };
146
+ if (is_reverse_token) {
147
+ let { tokenA, tokenB } = trade_balance_change;
148
+ trade_balance_change.tokenA = tokenB;
149
+ trade_balance_change.tokenB = tokenA;
150
+ }
151
+ let trade_extra_info = {
152
+ time,
153
+ broadcast,
154
+ server_info,
155
+ };
156
+ const trade_result = {
157
+ success,
158
+ error_code,
159
+ start_time,
160
+ end_time,
161
+ total_time,
162
+ group_id,
163
+ wallet,
164
+ chain_id,
165
+ pair,
166
+ dex_id,
167
+ txid,
168
+ unique_orderbook_id,
169
+ unique_order_msg_id,
170
+ order_price,
171
+ aToB,
172
+ tx_price,
173
+ balance: trade_balance_change,
174
+ execution: trade_extra_info,
175
+ };
176
+ return trade_result;
177
+ }
178
+ }
179
+ exports.TransactionResultChecker = TransactionResultChecker;
@@ -0,0 +1,14 @@
1
+ /// <reference types="node" />
2
+ import { StandardPoolInfoType } from '@clonegod/ttd-common';
3
+ import { ParsedTransactionWithMeta, PublicKey, TokenBalance } from '@solana/web3.js';
4
+ import { EventEmitter } from 'events';
5
+ import { StandardSwapDetailType } from '../../types';
6
+ export declare class TransactionResultParser {
7
+ env_args: any;
8
+ event_emitter: EventEmitter;
9
+ wallet_pubkey: PublicKey;
10
+ constructor(env_args: any, wallet_pubkey: PublicKey, event_emitter: EventEmitter);
11
+ parse_transaction_data(txData: ParsedTransactionWithMeta, pool_info: StandardPoolInfoType): StandardSwapDetailType;
12
+ getTokenBalance(owner: string, mint: string, tokenBalances: TokenBalance[]): number;
13
+ }
14
+ export declare const parse_tx_failed_error_code: (dex_id_list: string[], tx_failed_error_msg: string) => string;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parse_tx_failed_error_code = exports.TransactionResultParser = void 0;
4
+ const dist_1 = require("@clonegod/ttd-common/dist");
5
+ class TransactionResultParser {
6
+ constructor(env_args, wallet_pubkey, event_emitter) {
7
+ this.env_args = env_args;
8
+ this.wallet_pubkey = wallet_pubkey;
9
+ this.event_emitter = event_emitter;
10
+ }
11
+ parse_transaction_data(txData, pool_info) {
12
+ let success = true;
13
+ let error_code = '';
14
+ let { blockTime, meta, transaction, slot } = txData;
15
+ if (meta.err) {
16
+ success = false;
17
+ error_code = (0, exports.parse_tx_failed_error_code)(this.env_args.dex_id_list, JSON.stringify({
18
+ txid: transaction.signatures,
19
+ err: meta.err,
20
+ logMessages: meta.logMessages
21
+ }));
22
+ }
23
+ const { pool_address, tokenA, tokenB, is_reverse_token } = pool_info;
24
+ let txid = transaction.signatures[0];
25
+ const owner = this.wallet_pubkey.toBase58();
26
+ const { preTokenBalances, postTokenBalances, preBalances, postBalances } = meta;
27
+ const tokenA_PreBalance = this.getTokenBalance(owner, tokenA.address, preTokenBalances);
28
+ const tokenA_PostBalance = this.getTokenBalance(owner, tokenA.address, postTokenBalances);
29
+ const tokenB_PreBalance = this.getTokenBalance(owner, tokenB.address, preTokenBalances);
30
+ const tokenB_PostBalance = this.getTokenBalance(owner, tokenB.address, postTokenBalances);
31
+ blockTime = blockTime * 1000 || 0;
32
+ const tokenAChange = Number((tokenA_PostBalance - tokenA_PreBalance).toFixed(tokenA.decimals));
33
+ const tokenBChange = Number((tokenB_PostBalance - tokenB_PreBalance).toFixed(tokenB.decimals));
34
+ let price = "";
35
+ if (success) {
36
+ if (is_reverse_token) {
37
+ price = Math.abs(tokenAChange / tokenBChange).toFixed(tokenA.decimals);
38
+ }
39
+ else {
40
+ price = Math.abs(tokenBChange / tokenAChange).toFixed(tokenB.decimals);
41
+ }
42
+ }
43
+ const base_fee = 5000;
44
+ const total_fee = preBalances[0] - postBalances[0];
45
+ const priority_fee = total_fee - base_fee;
46
+ let gas_fee = {
47
+ base_fee,
48
+ priority_fee,
49
+ total_fee
50
+ };
51
+ const tradeResult = {
52
+ success,
53
+ error_code,
54
+ wallet: owner,
55
+ block_time: blockTime,
56
+ block_number: slot,
57
+ txid,
58
+ pool_address,
59
+ tokenA: Object.assign(Object.assign({}, tokenA), { pre_bal: tokenA_PreBalance, post_bal: tokenA_PostBalance, change: tokenAChange.toString() }),
60
+ tokenB: Object.assign(Object.assign({}, tokenB), { pre_bal: tokenB_PreBalance, post_bal: tokenB_PostBalance, change: tokenBChange.toString() }),
61
+ tx_price: price,
62
+ gas_fee
63
+ };
64
+ return tradeResult;
65
+ }
66
+ getTokenBalance(owner, mint, tokenBalances) {
67
+ var _a, _b;
68
+ const balance = (_b = (_a = tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.find((e) => e.owner === owner && e.mint == mint)) === null || _a === void 0 ? void 0 : _a.uiTokenAmount) === null || _b === void 0 ? void 0 : _b.uiAmount;
69
+ if (typeof balance !== 'undefined' && balance !== null) {
70
+ return balance;
71
+ }
72
+ return 0;
73
+ }
74
+ }
75
+ exports.TransactionResultParser = TransactionResultParser;
76
+ const parse_tx_failed_error_code = (dex_id_list, tx_failed_error_msg) => {
77
+ (0, dist_1.log_info)(`parse_tx_failed_error_code`, {
78
+ dex_id_list,
79
+ tx_failed_error_msg
80
+ });
81
+ let err_code = "";
82
+ if (dex_id_list.includes(dist_1.DEX_ID.RAYDIUM_AMM)) {
83
+ err_code = parse_raydium_failure(tx_failed_error_msg);
84
+ }
85
+ else if (dex_id_list.includes(dist_1.DEX_ID.ORCA_CLMM)) {
86
+ err_code = parse_orca_failure(tx_failed_error_msg);
87
+ }
88
+ if (!err_code) {
89
+ err_code = dist_1.TradeErrorCodeType.UNKOWN;
90
+ }
91
+ return err_code;
92
+ };
93
+ exports.parse_tx_failed_error_code = parse_tx_failed_error_code;
94
+ function parse_raydium_failure(error_msg) {
95
+ if (error_msg.includes('0x28')) {
96
+ return dist_1.TradeErrorCodeType.InsufficientFunds;
97
+ }
98
+ if (error_msg.includes('0x1e') || error_msg.includes('exceeds desired slippage limit')) {
99
+ return dist_1.TradeErrorCodeType.AmountOutBelowMinimum;
100
+ }
101
+ return null;
102
+ }
103
+ function parse_orca_failure(error_msg) {
104
+ if (error_msg.includes('0x1]') || error_msg.includes('insufficient funds')) {
105
+ return dist_1.TradeErrorCodeType.InsufficientFunds;
106
+ }
107
+ if (error_msg.includes('0x1794') || error_msg.includes('below minimum threshold')) {
108
+ return dist_1.TradeErrorCodeType.AmountOutBelowMinimum;
109
+ }
110
+ if (error_msg.includes('0xbc4') || error_msg.includes('expected this account to be already initialized')) {
111
+ return dist_1.TradeErrorCodeType.AccountNotInitialized;
112
+ }
113
+ if (error_msg.includes('0x1787') || error_msg.includes('Invalid tick array sequence')) {
114
+ return dist_1.TradeErrorCodeType.InvalidTickArraySequence;
115
+ }
116
+ return null;
117
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clonegod/ttd-sol-common",
3
- "version": "1.0.33",
3
+ "version": "1.0.35",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "types/index.d.ts",
@@ -13,7 +13,8 @@
13
13
  "push": "npm run build && npm publish"
14
14
  },
15
15
  "dependencies": {
16
- "@clonegod/ttd-common": "1.0.135",
16
+ "@clonegod/ttd-common": "1.0.146",
17
+ "@solana/web3.js": "1.91.6",
17
18
  "@irys/sdk": "^0.2.10",
18
19
  "@metaplex-foundation/mpl-token-metadata": "^2.5.2",
19
20
  "axios": "^1.2.3",
package/types/index.d.ts CHANGED
@@ -1,23 +1,53 @@
1
- import { TradeRuntimeType, TradeStrategyType } from "@clonegod/ttd-common";
2
- import { SendOptions, Signer, TransactionInstruction } from "@solana/web3.js";
3
- import { Helius, JitoRegion } from "./helius_sdk_v1.4.0";
4
- import { _Context } from "./context";
5
- export declare class HeliusClient {
6
- signers: Signer[];
7
- sendOptions: SendOptions;
8
- cluster: string;
9
- helius_mainnet: Helius;
10
- helius_staked: Helius;
11
- _context: _Context;
12
- constructor(signers: Signer[]);
13
- send_transaction(trade_runtime: TradeRuntimeType, instructions: TransactionInstruction[]): Promise<string>;
14
- private send_smart_transaction;
15
- private send_transaction_by_jito;
16
- get_jito_region(): JitoRegion;
17
- get_gas_fee(trade_strategy: TradeStrategyType): number;
18
- get_excat_fee_by_speed(speed: string, fee_exact: number): number;
19
- get_dynamic_fee_by_speed(speed: string, estimate_priority_fee: number, fee_max_cap: number): number;
1
+ import { StandardTokenInfoType, TradeRuntimeType } from "@clonegod/ttd-common";
2
+ import { Connection } from "@solana/web3.js";
3
+
4
+ export interface StandardSwapDetailType {
5
+ success: boolean
6
+ error_code: string
7
+
8
+ wallet: string,
9
+ txid: string,
10
+ block_time: number
11
+ block_number: number
12
+
13
+ pool_address: string
14
+ tokenA: TokenBalChangeType
15
+ tokenB: TokenBalChangeType
16
+ tx_price: string
17
+
18
+ gas_fee: GasFeeType
19
+ }
20
+
21
+
22
+
23
+ export interface TokenBalChangeType extends StandardTokenInfoType {
24
+ pre_bal: number
25
+ post_bal: number
26
+ change: string
27
+ }
28
+
29
+
30
+
31
+ export interface GasFeeType {
32
+ base_fee: number
33
+ priority_fee: number
34
+ total_fee: number
20
35
  }
21
36
 
22
37
 
23
38
 
39
+ export interface SolanaTradeRuntimeType extends TradeRuntimeType {
40
+ // common connection
41
+ connection: Connection
42
+
43
+ // priority fee
44
+ priority_fee: number
45
+
46
+ // Compute Budget: SetComputeUnitPrice
47
+ cu_price: number
48
+
49
+ // Compute Budget: SetComputeUnitLimit
50
+ cu_limit: number
51
+ }
52
+
53
+