@clonegod/ttd-sol-common 1.0.113 → 1.0.115
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 +55 -7
- package/dist/jito/index.d.ts +14 -0
- package/dist/jito/index.js +142 -0
- package/dist/quote/to_price_message.d.ts +1 -1
- package/dist/quote/to_price_message.js +3 -2
- package/package.json +3 -3
- 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,7 +587,7 @@ 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 =
|
|
590
|
+
const timeout = 10000;
|
|
591
591
|
const interval = 5000;
|
|
592
592
|
const startTime = Date.now();
|
|
593
593
|
while (Date.now() - startTime < timeout ||
|
|
@@ -767,5 +767,53 @@ class RpcClient {
|
|
|
767
767
|
return bundleId;
|
|
768
768
|
});
|
|
769
769
|
}
|
|
770
|
+
get_last_blockhash_slot(connections) {
|
|
771
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
772
|
+
let last_blockhash_slot;
|
|
773
|
+
try {
|
|
774
|
+
let appConfig = global.appConfig;
|
|
775
|
+
let { key, value } = yield appConfig.arb_cache.loading_cache.get(dist_1.CHAIN_ID.SOLANA, 'b', 'slot', true);
|
|
776
|
+
let { context_slot, blockhash, blockHeight } = JSON.parse(value);
|
|
777
|
+
last_blockhash_slot = {
|
|
778
|
+
context: {
|
|
779
|
+
slot: context_slot
|
|
780
|
+
},
|
|
781
|
+
value: {
|
|
782
|
+
blockhash,
|
|
783
|
+
lastValidBlockHeight: blockHeight
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
catch (err) {
|
|
788
|
+
(0, dist_1.log_error)('get_last_blockhash_slot, from redis', err);
|
|
789
|
+
}
|
|
790
|
+
if (!last_blockhash_slot) {
|
|
791
|
+
try {
|
|
792
|
+
last_blockhash_slot = yield Promise.race(connections.map(c => c.getLatestBlockhashAndContext()));
|
|
793
|
+
}
|
|
794
|
+
catch (err) {
|
|
795
|
+
(0, dist_1.log_error)('get_last_blockhash_slot, fetch by connection', err);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
return last_blockhash_slot;
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
check_bundle_result(bundle_id_1) {
|
|
802
|
+
return __awaiter(this, arguments, void 0, function* (bundle_id, timeoutMs = 3000) {
|
|
803
|
+
this.jitoClient.confirmInflightBundle(bundle_id, timeoutMs);
|
|
804
|
+
let start = Date.now();
|
|
805
|
+
while (Date.now() - start < timeoutMs) {
|
|
806
|
+
try {
|
|
807
|
+
let rs = yield fetch(`https://bundles.jito.wtf/api/v1/bundles/get_bundle_error/${bundle_id}`);
|
|
808
|
+
let jsonObj = yield rs.json();
|
|
809
|
+
console.log('get_bundle_error, res=', jsonObj);
|
|
810
|
+
}
|
|
811
|
+
catch (err) {
|
|
812
|
+
console.error('get_bundle_error, error!', err);
|
|
813
|
+
}
|
|
814
|
+
yield new Promise(resolve => setTimeout(resolve, 500));
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
}
|
|
770
818
|
}
|
|
771
819
|
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;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PriceMessageType, QuoteTimeInfoType, StandardPoolInfoType } from '@clonegod/ttd-common';
|
|
2
2
|
import { AppConfig } from '../appconfig';
|
|
3
3
|
export declare const get_quote_token_decimals: (pool_info: StandardPoolInfoType) => number;
|
|
4
|
-
export declare function to_price_message(appConfig: AppConfig, quote_amount_usd: number, tx_price: number, quote_ask_price: number, quote_bid_price: number, pool_info: StandardPoolInfoType, time: QuoteTimeInfoType): Promise<PriceMessageType>;
|
|
4
|
+
export declare function to_price_message(appConfig: AppConfig, quote_amount_usd: number, tx_price: number, quote_ask_price: number, quote_bid_price: number, pool_info: StandardPoolInfoType, time: QuoteTimeInfoType, slot?: string): Promise<PriceMessageType>;
|
|
5
5
|
export declare function normalize_pair_name(priceMessage: PriceMessageType): void;
|
|
@@ -30,7 +30,7 @@ const get_quote_token_decimals = (pool_info) => {
|
|
|
30
30
|
return decimals;
|
|
31
31
|
};
|
|
32
32
|
exports.get_quote_token_decimals = get_quote_token_decimals;
|
|
33
|
-
function to_price_message(appConfig, quote_amount_usd, tx_price, quote_ask_price, quote_bid_price, pool_info, time) {
|
|
33
|
+
function to_price_message(appConfig, quote_amount_usd, tx_price, quote_ask_price, quote_bid_price, pool_info, time, slot) {
|
|
34
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
35
|
let { pool_address, tokenA, tokenB } = pool_info;
|
|
36
36
|
let { dex_id, pool_name, fee_rate, is_reverse_token } = yield appConfig.arb_cache.get_one_pool_info(pool_address);
|
|
@@ -78,7 +78,8 @@ function to_price_message(appConfig, quote_amount_usd, tx_price, quote_ask_price
|
|
|
78
78
|
price: bid_price,
|
|
79
79
|
quantity: quote_amount_usd
|
|
80
80
|
},
|
|
81
|
-
time
|
|
81
|
+
time,
|
|
82
|
+
slot
|
|
82
83
|
};
|
|
83
84
|
normalize_pair_name(price_message);
|
|
84
85
|
return price_message;
|
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.115",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
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.164",
|
|
17
17
|
"@irys/sdk": "^0.2.10",
|
|
18
18
|
"@metaplex-foundation/mpl-token-metadata": "^2.5.2",
|
|
19
19
|
"@solana/web3.js": "1.91.6",
|
|
@@ -30,4 +30,4 @@
|
|
|
30
30
|
"publishConfig": {
|
|
31
31
|
"access": "public"
|
|
32
32
|
}
|
|
33
|
-
}
|
|
33
|
+
}
|
package/types/index.d.ts
CHANGED