@clonegod/ttd-sol-common 1.0.114 → 1.0.116
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/helius_sdk_v1.4.0/RpcClient.d.ts +4 -0
- package/dist/helius_sdk_v1.4.0/RpcClient.js +56 -10
- package/dist/jito/index.d.ts +14 -0
- package/dist/jito/index.js +142 -0
- package/dist/trade/handle_order_message.js +8 -6
- package/dist/trade/tx_result_check.js +1 -1
- package/package.json +2 -2
- package/types/index.d.ts +8 -0
|
@@ -2,6 +2,7 @@ import { BlockhashWithExpiryBlockHeight, VersionedTransaction, AddressLookupTabl
|
|
|
2
2
|
import { DAS } from './types/das-types';
|
|
3
3
|
import { GetPriorityFeeEstimateRequest, GetPriorityFeeEstimateResponse, JitoRegion, PollTransactionOptions, SmartTransactionContext, HeliusSendOptions } from './types';
|
|
4
4
|
import { SolanaTradeRuntimeType } from '../../types';
|
|
5
|
+
import { JitoJsonRpcClient } from '../jito';
|
|
5
6
|
export type SendAndConfirmTransactionResponse = {
|
|
6
7
|
signature: TransactionSignature;
|
|
7
8
|
confirmResponse: RpcResponseAndContext<SignatureResult>;
|
|
@@ -11,6 +12,7 @@ export type SendAndConfirmTransactionResponse = {
|
|
|
11
12
|
export declare class RpcClient {
|
|
12
13
|
protected readonly connection: Connection;
|
|
13
14
|
protected readonly id?: string;
|
|
15
|
+
jitoClient: JitoJsonRpcClient;
|
|
14
16
|
constructor(connection: Connection, id?: string);
|
|
15
17
|
airdrop(publicKey: PublicKey, lamports: number, commitment?: Commitment): Promise<SendAndConfirmTransactionResponse>;
|
|
16
18
|
getLatestBlockhash(commitmentOrConfig?: Commitment | GetLatestBlockhashConfig): Promise<BlockhashWithExpiryBlockHeight>;
|
|
@@ -48,4 +50,6 @@ export declare class RpcClient {
|
|
|
48
50
|
sendTransaction(transaction: Transaction | VersionedTransaction, options?: HeliusSendOptions): Promise<TransactionSignature>;
|
|
49
51
|
sendSmartTransactionWithTipMixed(solana_trade_runtime: SolanaTradeRuntimeType, instructions: TransactionInstruction[], signers: Signer[], lookupTables?: AddressLookupTableAccount[], tipAmount?: number, region?: JitoRegion, feePayer?: Signer, lastValidBlockHeightOffset?: number): Promise<string>;
|
|
50
52
|
sendJitoTransaction(serializedTransaction: string, jitoApiUrl: string): Promise<string>;
|
|
53
|
+
get_last_blockhash_slot(connections: Connection[]): Promise<RpcResponseAndContext<BlockhashWithExpiryBlockHeight>>;
|
|
54
|
+
check_bundle_result(bundle_id: string, timeoutMs?: number): Promise<void>;
|
|
51
55
|
}
|
|
@@ -19,10 +19,12 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
19
19
|
const types_1 = require("./types");
|
|
20
20
|
const get_signature_1 = require("../send_tx/get_signature");
|
|
21
21
|
const dist_1 = require("@clonegod/ttd-common/dist");
|
|
22
|
+
const jito_1 = require("../jito");
|
|
22
23
|
class RpcClient {
|
|
23
24
|
constructor(connection, id) {
|
|
24
25
|
this.connection = connection;
|
|
25
26
|
this.id = id;
|
|
27
|
+
this.jitoClient = new jito_1.JitoJsonRpcClient('https://mainnet.block-engine.jito.wtf/api/v1', undefined);
|
|
26
28
|
}
|
|
27
29
|
airdrop(publicKey, lamports, commitment) {
|
|
28
30
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -365,10 +367,7 @@ class RpcClient {
|
|
|
365
367
|
}
|
|
366
368
|
(0, dist_1.log_info)(`>>> getLatestBlockhashAndContext, start`);
|
|
367
369
|
const payerKey = feePayer ? feePayer.publicKey : signers[0].publicKey;
|
|
368
|
-
|
|
369
|
-
this.connection.getLatestBlockhashAndContext(),
|
|
370
|
-
solana_trade_runtime.connection.getLatestBlockhashAndContext()
|
|
371
|
-
]);
|
|
370
|
+
let { context: { slot: minContextSlot }, value: blockhash, } = yield this.get_last_blockhash_slot([this.connection, solana_trade_runtime.connection]);
|
|
372
371
|
(0, dist_1.log_info)(`>>> getLatestBlockhashAndContext, end`);
|
|
373
372
|
const recentBlockhash = blockhash.blockhash;
|
|
374
373
|
const isVersioned = lookupTables.length > 0;
|
|
@@ -396,7 +395,7 @@ class RpcClient {
|
|
|
396
395
|
}
|
|
397
396
|
}
|
|
398
397
|
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
399
|
-
if (Math.random() >
|
|
398
|
+
if (Math.random() > -1)
|
|
400
399
|
return;
|
|
401
400
|
const serializedTransaction = bs58_1.default.encode(isVersioned
|
|
402
401
|
? versionedTransaction.serialize()
|
|
@@ -423,7 +422,7 @@ class RpcClient {
|
|
|
423
422
|
});
|
|
424
423
|
instructions.unshift(computeBudgetIx);
|
|
425
424
|
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
426
|
-
if (Math.random() >
|
|
425
|
+
if (Math.random() > -1)
|
|
427
426
|
return;
|
|
428
427
|
(0, dist_1.log_info)(`>>> getComputeUnits, start`);
|
|
429
428
|
const units = yield this.getComputeUnits(instructions, payerKey, isVersioned ? lookupTables : [], signers);
|
|
@@ -580,6 +579,7 @@ class RpcClient {
|
|
|
580
579
|
let jitoApiUrl = `${types_1.JITO_API_URLS[region]}/api/v1/bundles`;
|
|
581
580
|
this.sendJitoTransaction(serializedTransaction, `${types_1.JITO_API_URLS['Default']}/api/v1/transactions?bundleOnly=true`);
|
|
582
581
|
const bundleId = yield this.sendJitoBundle([serializedTransaction], jitoApiUrl);
|
|
582
|
+
this.check_bundle_result(bundleId);
|
|
583
583
|
(0, dist_1.log_info)(`sendJitoBundle finish`, {
|
|
584
584
|
jitoApiUrl,
|
|
585
585
|
txid,
|
|
@@ -587,11 +587,10 @@ class RpcClient {
|
|
|
587
587
|
});
|
|
588
588
|
const currentBlockHeight = yield solana_trade_runtime.connection.getBlockHeight();
|
|
589
589
|
const lastValidBlockHeight = Math.min(blockhash.lastValidBlockHeight, currentBlockHeight + lastValidBlockHeightOffset);
|
|
590
|
-
const timeout =
|
|
591
|
-
const interval =
|
|
590
|
+
const timeout = 10000;
|
|
591
|
+
const interval = 2000;
|
|
592
592
|
const startTime = Date.now();
|
|
593
|
-
while (Date.now() - startTime < timeout
|
|
594
|
-
(yield this.connection.getBlockHeight()) <= lastValidBlockHeight) {
|
|
593
|
+
while (Date.now() - startTime < timeout) {
|
|
595
594
|
const bundleStatuses = yield this.getBundleStatuses([bundleId], jitoApiUrl);
|
|
596
595
|
(0, dist_1.log_info)(`getBundleStatuses`, {
|
|
597
596
|
txid,
|
|
@@ -767,5 +766,52 @@ class RpcClient {
|
|
|
767
766
|
return bundleId;
|
|
768
767
|
});
|
|
769
768
|
}
|
|
769
|
+
get_last_blockhash_slot(connections) {
|
|
770
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
771
|
+
let last_blockhash_slot;
|
|
772
|
+
try {
|
|
773
|
+
let appConfig = global.appConfig;
|
|
774
|
+
let { key, value } = yield appConfig.arb_cache.loading_cache.get(dist_1.CHAIN_ID.SOLANA, 'b', 'slot', true);
|
|
775
|
+
let { context_slot, blockhash, blockHeight } = JSON.parse(value);
|
|
776
|
+
last_blockhash_slot = {
|
|
777
|
+
context: {
|
|
778
|
+
slot: context_slot
|
|
779
|
+
},
|
|
780
|
+
value: {
|
|
781
|
+
blockhash,
|
|
782
|
+
lastValidBlockHeight: blockHeight
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
catch (err) {
|
|
787
|
+
(0, dist_1.log_error)('get_last_blockhash_slot, from redis', err);
|
|
788
|
+
}
|
|
789
|
+
if (!last_blockhash_slot) {
|
|
790
|
+
try {
|
|
791
|
+
last_blockhash_slot = yield Promise.race(connections.map(c => c.getLatestBlockhashAndContext()));
|
|
792
|
+
}
|
|
793
|
+
catch (err) {
|
|
794
|
+
(0, dist_1.log_error)('get_last_blockhash_slot, fetch by connection', err);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
return last_blockhash_slot;
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
check_bundle_result(bundle_id_1) {
|
|
801
|
+
return __awaiter(this, arguments, void 0, function* (bundle_id, timeoutMs = 10000) {
|
|
802
|
+
let start = Date.now();
|
|
803
|
+
while (Date.now() - start < timeoutMs) {
|
|
804
|
+
try {
|
|
805
|
+
let rs = yield fetch(`https://bundles.jito.wtf/api/v1/bundles/get_bundle_error/${bundle_id}`);
|
|
806
|
+
let jsonObj = yield rs.json();
|
|
807
|
+
console.log('get_bundle_error, res=', jsonObj);
|
|
808
|
+
}
|
|
809
|
+
catch (err) {
|
|
810
|
+
console.error('get_bundle_error, error!', err);
|
|
811
|
+
}
|
|
812
|
+
yield new Promise(resolve => setTimeout(resolve, 1000));
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
}
|
|
770
816
|
}
|
|
771
817
|
exports.RpcClient = RpcClient;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class JitoJsonRpcClient {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
uuid: string;
|
|
4
|
+
client: any;
|
|
5
|
+
constructor(baseUrl: string, uuid: string);
|
|
6
|
+
sendRequest(endpoint: any, method: any, params: any): Promise<any>;
|
|
7
|
+
getTipAccounts(): Promise<any>;
|
|
8
|
+
getRandomTipAccount(): Promise<any>;
|
|
9
|
+
sendBundle(params: any): Promise<any>;
|
|
10
|
+
sendTxn(params: any, bundleOnly?: boolean): Promise<any>;
|
|
11
|
+
getInFlightBundleStatuses(params: any): Promise<any>;
|
|
12
|
+
getBundleStatuses(params: any): Promise<any>;
|
|
13
|
+
confirmInflightBundle(bundleId: any, timeoutMs?: number): Promise<any>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
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.JitoJsonRpcClient = void 0;
|
|
13
|
+
const axios = require('axios');
|
|
14
|
+
class JitoJsonRpcClient {
|
|
15
|
+
constructor(baseUrl, uuid) {
|
|
16
|
+
this.baseUrl = baseUrl;
|
|
17
|
+
this.uuid = uuid;
|
|
18
|
+
this.client = axios.create({
|
|
19
|
+
headers: {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
sendRequest(endpoint, method, params) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
27
|
+
const data = {
|
|
28
|
+
jsonrpc: '2.0',
|
|
29
|
+
id: 1,
|
|
30
|
+
method,
|
|
31
|
+
params: params || [],
|
|
32
|
+
};
|
|
33
|
+
console.log(`Sending request to: ${url}`);
|
|
34
|
+
console.log(`Request body: ${JSON.stringify(data, null, 2)}`);
|
|
35
|
+
try {
|
|
36
|
+
const response = yield this.client.post(url, data);
|
|
37
|
+
console.log(`Response status: ${response.status}`);
|
|
38
|
+
console.log(`Response body: ${JSON.stringify(response.data, null, 2)}`);
|
|
39
|
+
return response.data;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (axios.isAxiosError(error)) {
|
|
43
|
+
console.error(`HTTP error: ${error.message}`);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.error(`Unexpected error: ${error}`);
|
|
48
|
+
throw new Error('An unexpected error occurred');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
getTipAccounts() {
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
const endpoint = this.uuid ? `/bundles?uuid=${this.uuid}` : '/bundles';
|
|
56
|
+
return this.sendRequest(endpoint, 'getTipAccounts', null);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
getRandomTipAccount() {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
const tipAccountsResponse = yield this.getTipAccounts();
|
|
62
|
+
if (tipAccountsResponse.result && Array.isArray(tipAccountsResponse.result) && tipAccountsResponse.result.length > 0) {
|
|
63
|
+
const randomIndex = Math.floor(Math.random() * tipAccountsResponse.result.length);
|
|
64
|
+
return tipAccountsResponse.result[randomIndex];
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
throw new Error('No tip accounts available');
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
sendBundle(params) {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
const endpoint = this.uuid ? `/bundles?uuid=${this.uuid}` : '/bundles';
|
|
74
|
+
return this.sendRequest(endpoint, 'sendBundle', params);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
sendTxn(params_1) {
|
|
78
|
+
return __awaiter(this, arguments, void 0, function* (params, bundleOnly = false) {
|
|
79
|
+
let endpoint = '/transactions';
|
|
80
|
+
const queryParams = [];
|
|
81
|
+
if (bundleOnly) {
|
|
82
|
+
queryParams.push('bundleOnly=true');
|
|
83
|
+
}
|
|
84
|
+
if (this.uuid) {
|
|
85
|
+
queryParams.push(`uuid=${this.uuid}`);
|
|
86
|
+
}
|
|
87
|
+
if (queryParams.length > 0) {
|
|
88
|
+
endpoint += `?${queryParams.join('&')}`;
|
|
89
|
+
}
|
|
90
|
+
return this.sendRequest(endpoint, 'sendTransaction', params);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
getInFlightBundleStatuses(params) {
|
|
94
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
95
|
+
const endpoint = this.uuid ? `/bundles?uuid=${this.uuid}` : '/bundles';
|
|
96
|
+
return this.sendRequest(endpoint, 'getInflightBundleStatuses', params);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
getBundleStatuses(params) {
|
|
100
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
const endpoint = this.uuid ? `/bundles?uuid=${this.uuid}` : '/bundles';
|
|
102
|
+
return this.sendRequest(endpoint, 'getBundleStatuses', params);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
confirmInflightBundle(bundleId_1) {
|
|
106
|
+
return __awaiter(this, arguments, void 0, function* (bundleId, timeoutMs = 60000) {
|
|
107
|
+
const start = Date.now();
|
|
108
|
+
while (Date.now() - start < timeoutMs) {
|
|
109
|
+
try {
|
|
110
|
+
const response = yield this.getInFlightBundleStatuses([[bundleId]]);
|
|
111
|
+
if (response.result && response.result.value && response.result.value.length > 0) {
|
|
112
|
+
const bundleStatus = response.result.value[0];
|
|
113
|
+
console.log(`Bundle status: ${bundleStatus.status}, Landed slot: ${bundleStatus.landed_slot}`);
|
|
114
|
+
if (bundleStatus.status === "Failed") {
|
|
115
|
+
return bundleStatus;
|
|
116
|
+
}
|
|
117
|
+
else if (bundleStatus.status === "Landed") {
|
|
118
|
+
const detailedStatus = yield this.getBundleStatuses([[bundleId]]);
|
|
119
|
+
if (detailedStatus.result && detailedStatus.result.value && detailedStatus.result.value.length > 0) {
|
|
120
|
+
return detailedStatus.result.value[0];
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
console.log('No detailed status returned for landed bundle.');
|
|
124
|
+
return bundleStatus;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.log('No status returned for the bundle. It may be invalid or very old.');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error('Error checking bundle status:', error);
|
|
134
|
+
}
|
|
135
|
+
yield new Promise(resolve => setTimeout(resolve, 2000));
|
|
136
|
+
}
|
|
137
|
+
console.log(`Bundle ${bundleId} has not reached a final state within ${timeoutMs}ms`);
|
|
138
|
+
return { status: 'Timeout' };
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.JitoJsonRpcClient = JitoJsonRpcClient;
|
|
@@ -73,12 +73,14 @@ const handle_order_message = (appConfig, trade, message) => __awaiter(void 0, vo
|
|
|
73
73
|
let { price_msg, id_parts } = yield check_parse_order_msg(appConfig, order_msg);
|
|
74
74
|
let { order_trace_id } = order_msg;
|
|
75
75
|
let { chain_id, dex_id, pool_id, fee_rate } = id_parts;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
if (process.env.ENABLE_MULTIPLE_PROCESS === 'true') {
|
|
77
|
+
let lock_order = yield (0, exports.try_lock_order_msg)(appConfig, order_msg);
|
|
78
|
+
if (!lock_order) {
|
|
79
|
+
(0, dist_1.log_warn)(`try lock order failed!`, {
|
|
80
|
+
chain_id, group_id, order_trace_id
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
82
84
|
}
|
|
83
85
|
let context;
|
|
84
86
|
let txid = '';
|
|
@@ -87,7 +87,7 @@ class TransactionResultChecker {
|
|
|
87
87
|
return __awaiter(this, void 0, void 0, function* () {
|
|
88
88
|
const check_start_time = Date.now();
|
|
89
89
|
const check_interval = parseInt(process.env.CHECK_TX_RESULT_INTERVAL_MILLS || '1000');
|
|
90
|
-
const check_timeout = parseInt(process.env.CHECK_TX_RESULT_TIMEOUT_MILLS || '
|
|
90
|
+
const check_timeout = parseInt(process.env.CHECK_TX_RESULT_TIMEOUT_MILLS || '6000');
|
|
91
91
|
const intervalId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
92
92
|
this.check_count += 1;
|
|
93
93
|
(0, dist_1.log_info)(`check transaction start: seq=[${this.check_count}], txhash= ${this.txid}, trace_id=${this.trace_id}`);
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED