@clonegod/ttd-sol-common 1.0.32 → 1.0.34
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/dist/common/constants.d.ts +10 -0
- package/dist/common/constants.js +16 -0
- package/dist/common/context.d.ts +22 -0
- package/dist/common/context.js +41 -0
- package/dist/common/index.d.ts +3 -0
- package/dist/common/index.js +19 -0
- package/dist/common/types.d.ts +31 -0
- package/dist/common/types.js +2 -0
- package/dist/helius_geyser_ws/index.d.ts +4 -0
- package/dist/helius_geyser_ws/index.js +93 -0
- package/dist/helius_sdk_v1.4.0/RpcClient.d.ts +1 -1
- package/dist/helius_sdk_v1.4.0/RpcClient.js +8 -8
- package/dist/index.d.ts +3 -4
- package/dist/index.js +3 -4
- package/dist/send_tx/get_signature.d.ts +2 -0
- package/dist/send_tx/get_signature.js +15 -0
- package/dist/send_tx/index.d.ts +3 -0
- package/dist/send_tx/index.js +19 -0
- package/dist/send_tx/send_transaction.d.ts +14 -0
- package/dist/send_tx/send_transaction.js +79 -0
- package/dist/send_tx/strategy_util.d.ts +7 -0
- package/dist/send_tx/strategy_util.js +91 -0
- package/dist/trade/abstract_trade.d.ts +4 -0
- package/dist/trade/abstract_trade.js +6 -0
- package/dist/trade/index.d.ts +3 -0
- package/dist/trade/index.js +19 -0
- package/dist/trade/tx_result_check.d.ts +27 -0
- package/dist/trade/tx_result_check.js +179 -0
- package/dist/trade/tx_result_parse.d.ts +14 -0
- package/dist/trade/tx_result_parse.js +117 -0
- package/package.json +3 -2
|
@@ -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,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("./constants"), exports);
|
|
18
|
+
__exportStar(require("./context"), exports);
|
|
19
|
+
__exportStar(require("./types"), 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,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 '../
|
|
6
|
+
import { SolanaTradeRuntimeType } from '../common';
|
|
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) {
|
|
@@ -363,14 +363,14 @@ class RpcClient {
|
|
|
363
363
|
if (existingComputeBudgetInstructions.length > 0) {
|
|
364
364
|
throw new Error('Cannot provide instructions that set the compute unit price and/or limit');
|
|
365
365
|
}
|
|
366
|
-
(0, dist_1.
|
|
366
|
+
(0, dist_1.log_info)(`>>> getLatestBlockhashAndContext, start`);
|
|
367
367
|
const payerKey = feePayer ? feePayer.publicKey : signers[0].publicKey;
|
|
368
368
|
const { context: { slot: minContextSlot }, value: blockhash, } = yield Promise.race([
|
|
369
369
|
this.connection.getLatestBlockhashAndContext(),
|
|
370
370
|
solana_trade_runtime.connection.getLatestBlockhashAndContext()
|
|
371
371
|
]);
|
|
372
|
+
(0, dist_1.log_info)(`>>> getLatestBlockhashAndContext, end`);
|
|
372
373
|
const recentBlockhash = blockhash.blockhash;
|
|
373
|
-
(0, dist_1.log_debug)(`>>> getLatestBlockhashAndContext, end`);
|
|
374
374
|
const isVersioned = lookupTables.length > 0;
|
|
375
375
|
let legacyTransaction = null;
|
|
376
376
|
let versionedTransaction = null;
|
|
@@ -401,7 +401,7 @@ class RpcClient {
|
|
|
401
401
|
const serializedTransaction = bs58_1.default.encode(isVersioned
|
|
402
402
|
? versionedTransaction.serialize()
|
|
403
403
|
: legacyTransaction.serialize(serializeOptions));
|
|
404
|
-
(0, dist_1.
|
|
404
|
+
(0, dist_1.log_info)(`>>> getPriorityFeeEstimate, start`);
|
|
405
405
|
const priorityFeeEstimateResponse = yield this.getPriorityFeeEstimate({
|
|
406
406
|
transaction: serializedTransaction,
|
|
407
407
|
options: {
|
|
@@ -409,7 +409,7 @@ class RpcClient {
|
|
|
409
409
|
},
|
|
410
410
|
});
|
|
411
411
|
const { priorityFeeEstimate } = priorityFeeEstimateResponse;
|
|
412
|
-
(0, dist_1.
|
|
412
|
+
(0, dist_1.log_info)(`>>> getPriorityFeeEstimate, end. priorityFeeEstimate=${priorityFeeEstimate}`);
|
|
413
413
|
if (!priorityFeeEstimate) {
|
|
414
414
|
throw new Error('Priority fee estimate not available');
|
|
415
415
|
}
|
|
@@ -425,9 +425,9 @@ class RpcClient {
|
|
|
425
425
|
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
426
426
|
if (Math.random() > 0.15)
|
|
427
427
|
return;
|
|
428
|
-
(0, dist_1.
|
|
428
|
+
(0, dist_1.log_info)(`>>> getComputeUnits, start`);
|
|
429
429
|
const units = yield this.getComputeUnits(instructions, payerKey, isVersioned ? lookupTables : [], signers);
|
|
430
|
-
(0, dist_1.
|
|
430
|
+
(0, dist_1.log_info)(`>>> getComputeUnits, end. ComputeUnits=${units}`);
|
|
431
431
|
if (!units) {
|
|
432
432
|
throw new Error(`Error fetching compute units for the instructions provided`);
|
|
433
433
|
}
|
|
@@ -476,7 +476,7 @@ class RpcClient {
|
|
|
476
476
|
throw new Error('expiryBlockOffset must be a positive integer');
|
|
477
477
|
try {
|
|
478
478
|
const { transaction, blockhash, minContextSlot } = yield this.createSmartTransaction(solana_trade_runtime, instructions, signers, lookupTables, sendOptions.feePayer);
|
|
479
|
-
(0, dist_1.
|
|
479
|
+
(0, dist_1.log_info)(`>>> createSmartTransaction, end`);
|
|
480
480
|
let txid = (0, get_signature_1.getSignature)(transaction);
|
|
481
481
|
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
482
482
|
const commitment = (sendOptions === null || sendOptions === void 0 ? void 0 : sendOptions.preflightCommitment) || 'confirmed';
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -14,8 +14,7 @@ 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("./
|
|
18
|
-
__exportStar(require("./context"), exports);
|
|
19
|
-
__exportStar(require("./strategy_util"), exports);
|
|
17
|
+
__exportStar(require("./common"), exports);
|
|
20
18
|
__exportStar(require("./helius_geyser_ws"), exports);
|
|
21
|
-
__exportStar(require("./
|
|
19
|
+
__exportStar(require("./send_tx"), exports);
|
|
20
|
+
__exportStar(require("./trade"), exports);
|
|
@@ -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,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 '../common/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 "../common/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,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("./abstract_trade"), exports);
|
|
18
|
+
__exportStar(require("./tx_result_check"), exports);
|
|
19
|
+
__exportStar(require("./tx_result_parse"), 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 { TradeContext } from "../common/context";
|
|
6
|
+
import { StandardSwapDetailType } from "../common/types";
|
|
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 '../common/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.
|
|
3
|
+
"version": "1.0.34",
|
|
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.
|
|
16
|
+
"@clonegod/ttd-common": "1.0.145",
|
|
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",
|