@clonegod/ttd-bsc-common 3.1.64 → 3.1.65
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/quote/index.d.ts +1 -0
- package/dist/quote/index.js +1 -0
- package/dist/quote/preload_token_prices.d.ts +2 -0
- package/dist/quote/preload_token_prices.js +36 -0
- package/dist/quote/verify/quote_price_verify.d.ts +1 -0
- package/dist/quote/verify/quote_price_verify.js +70 -27
- package/package.json +2 -2
package/dist/quote/index.d.ts
CHANGED
package/dist/quote/index.js
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.preloadTokenPrices = preloadTokenPrices;
|
|
4
|
+
const ttd_core_1 = require("@clonegod/ttd-core");
|
|
5
|
+
async function preloadTokenPrices(pool_list, label = 'Quote') {
|
|
6
|
+
if (!pool_list || pool_list.length === 0)
|
|
7
|
+
return;
|
|
8
|
+
const addrSet = new Set();
|
|
9
|
+
for (const pool of pool_list) {
|
|
10
|
+
if (pool.tokenA?.address)
|
|
11
|
+
addrSet.add(pool.tokenA.address.toLowerCase());
|
|
12
|
+
if (pool.tokenB?.address)
|
|
13
|
+
addrSet.add(pool.tokenB.address.toLowerCase());
|
|
14
|
+
}
|
|
15
|
+
const addresses = Array.from(addrSet);
|
|
16
|
+
if (addresses.length === 0)
|
|
17
|
+
return;
|
|
18
|
+
try {
|
|
19
|
+
const priceMap = await (0, ttd_core_1.get_bsc_token_price_info)(addresses, { source: 'force_fetch' });
|
|
20
|
+
const got = [];
|
|
21
|
+
const miss = [];
|
|
22
|
+
for (const a of addresses) {
|
|
23
|
+
if (priceMap.get(a)?.price)
|
|
24
|
+
got.push(a);
|
|
25
|
+
else
|
|
26
|
+
miss.push(a);
|
|
27
|
+
}
|
|
28
|
+
(0, ttd_core_1.log_info)(`[${label}] preloadTokenPrices done, total=${addresses.length}, got=${got.length}, miss=${miss.length}`);
|
|
29
|
+
if (miss.length > 0) {
|
|
30
|
+
(0, ttd_core_1.log_warn)(`[${label}] preloadTokenPrices missing: ${miss.join(', ')}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
(0, ttd_core_1.log_warn)(`[${label}] preloadTokenPrices error (non-fatal): ${err.message}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -21,5 +21,6 @@ export declare class QuotePriceVerify {
|
|
|
21
21
|
private get enabled();
|
|
22
22
|
cacheQuote(poolAddress: string, priceId: string, source: string, askPrice: number, bidPrice: number, blockNumber: number, quoteAmountUsd: number, token0PriceUsd?: number, token1PriceUsd?: number): void;
|
|
23
23
|
checkSwap(params: CheckSwapParams): void;
|
|
24
|
+
private deriveSwapDirection;
|
|
24
25
|
private compareAndLog;
|
|
25
26
|
}
|
|
@@ -13,10 +13,21 @@ class QuotePriceVerify {
|
|
|
13
13
|
cacheQuote(poolAddress, priceId, source, askPrice, bidPrice, blockNumber, quoteAmountUsd, token0PriceUsd = 0, token1PriceUsd = 0) {
|
|
14
14
|
if (!this.enabled)
|
|
15
15
|
return;
|
|
16
|
-
|
|
16
|
+
if (!source)
|
|
17
|
+
return;
|
|
18
|
+
let sourceMap = this.quoteCache.get(poolAddress);
|
|
19
|
+
if (!sourceMap) {
|
|
20
|
+
sourceMap = new Map();
|
|
21
|
+
this.quoteCache.set(poolAddress, sourceMap);
|
|
22
|
+
}
|
|
23
|
+
const existing = sourceMap.get(source);
|
|
24
|
+
const verifiedReferenceBlock = (existing && existing.referenceBlock === blockNumber)
|
|
25
|
+
? existing.verifiedReferenceBlock
|
|
26
|
+
: 0;
|
|
27
|
+
sourceMap.set(source, {
|
|
17
28
|
priceId, source, askPrice, bidPrice,
|
|
18
29
|
referenceBlock: blockNumber,
|
|
19
|
-
verifiedReferenceBlock
|
|
30
|
+
verifiedReferenceBlock,
|
|
20
31
|
quoteAmountUsd,
|
|
21
32
|
token0PriceUsd, token1PriceUsd,
|
|
22
33
|
});
|
|
@@ -24,43 +35,74 @@ class QuotePriceVerify {
|
|
|
24
35
|
checkSwap(params) {
|
|
25
36
|
if (!this.enabled)
|
|
26
37
|
return;
|
|
27
|
-
const { poolAddress,
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
const { poolAddress, blockNumber, txHash, poolInfo, token0Address } = params;
|
|
39
|
+
const sourceMap = this.quoteCache.get(poolAddress);
|
|
40
|
+
if (!sourceMap || sourceMap.size === 0)
|
|
41
|
+
return;
|
|
42
|
+
const swapData = this.deriveSwapDirection(params);
|
|
43
|
+
if (!swapData)
|
|
31
44
|
return;
|
|
32
|
-
|
|
45
|
+
const direction = (0, trade_direction_1.resolveTradeDirection)(poolInfo, true);
|
|
46
|
+
const inputIsQuoteToken = swapData.inputTokenAddress.toLowerCase() === direction.quoteToken.address.toLowerCase();
|
|
47
|
+
const isBuy = inputIsQuoteToken;
|
|
48
|
+
const execPriceStr = (0, trade_direction_1.calculateStandardPrice)(swapData.inputAmountUi, swapData.outputAmountUi, isBuy);
|
|
49
|
+
const execPrice = Number(execPriceStr);
|
|
50
|
+
if (execPrice <= 0)
|
|
33
51
|
return;
|
|
34
|
-
|
|
52
|
+
const verifiable = [];
|
|
53
|
+
for (const [source, cached] of sourceMap) {
|
|
54
|
+
if (blockNumber <= cached.referenceBlock)
|
|
55
|
+
continue;
|
|
56
|
+
if (cached.verifiedReferenceBlock === cached.referenceBlock)
|
|
57
|
+
continue;
|
|
58
|
+
const refPrice = isBuy ? cached.askPrice : cached.bidPrice;
|
|
59
|
+
if (refPrice <= 0)
|
|
60
|
+
continue;
|
|
61
|
+
cached.verifiedReferenceBlock = cached.referenceBlock;
|
|
62
|
+
const diff_bps = (refPrice - execPrice) / refPrice * 10000;
|
|
63
|
+
verifiable.push({ source, cached, refPrice, diff_bps });
|
|
64
|
+
}
|
|
65
|
+
if (verifiable.length === 0)
|
|
35
66
|
return;
|
|
36
|
-
cached.
|
|
67
|
+
verifiable.sort((a, b) => b.cached.referenceBlock - a.cached.referenceBlock);
|
|
68
|
+
const primary = verifiable[0];
|
|
69
|
+
const sources = {};
|
|
70
|
+
for (const r of verifiable) {
|
|
71
|
+
sources[r.source] = {
|
|
72
|
+
ask: r.cached.askPrice,
|
|
73
|
+
bid: r.cached.bidPrice,
|
|
74
|
+
diff_bps: parseFloat(r.diff_bps.toFixed(1)),
|
|
75
|
+
quote_block: r.cached.referenceBlock,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
this.compareAndLog(poolAddress, params.poolName, poolInfo, primary.cached, swapData.inputTokenAddress, swapData.outputTokenAddress, swapData.inputAmountUi, swapData.outputAmountUi, primary.cached.token0PriceUsd, primary.cached.token1PriceUsd, token0Address, blockNumber, txHash, sources);
|
|
79
|
+
}
|
|
80
|
+
deriveSwapDirection(params) {
|
|
81
|
+
const { amount0, amount1, token0Address, token1Address, token0Decimals, token1Decimals } = params;
|
|
37
82
|
const sign = params.swapperDeltaConvention ? -1n : 1n;
|
|
38
83
|
const amt0 = BigInt(amount0) * sign;
|
|
39
84
|
const amt1 = BigInt(amount1) * sign;
|
|
40
85
|
if (amt0 === 0n && amt1 === 0n)
|
|
41
|
-
return;
|
|
42
|
-
let inputTokenAddress;
|
|
43
|
-
let outputTokenAddress;
|
|
44
|
-
let inputAmountUi;
|
|
45
|
-
let outputAmountUi;
|
|
86
|
+
return null;
|
|
46
87
|
if (amt0 > 0n && amt1 < 0n) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
88
|
+
return {
|
|
89
|
+
inputTokenAddress: token0Address,
|
|
90
|
+
outputTokenAddress: token1Address,
|
|
91
|
+
inputAmountUi: Number(amt0) / Math.pow(10, token0Decimals),
|
|
92
|
+
outputAmountUi: Number(-amt1) / Math.pow(10, token1Decimals),
|
|
93
|
+
};
|
|
51
94
|
}
|
|
52
95
|
else if (amt0 < 0n && amt1 > 0n) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return;
|
|
96
|
+
return {
|
|
97
|
+
inputTokenAddress: token1Address,
|
|
98
|
+
outputTokenAddress: token0Address,
|
|
99
|
+
inputAmountUi: Number(amt1) / Math.pow(10, token1Decimals),
|
|
100
|
+
outputAmountUi: Number(-amt0) / Math.pow(10, token0Decimals),
|
|
101
|
+
};
|
|
60
102
|
}
|
|
61
|
-
|
|
103
|
+
return null;
|
|
62
104
|
}
|
|
63
|
-
compareAndLog(poolAddress, poolName, poolInfo, cached, inputTokenAddress, outputTokenAddress, inputAmountUi, outputAmountUi, token0PriceUsd, token1PriceUsd, token0Address, swapBlockNumber, txHash) {
|
|
105
|
+
compareAndLog(poolAddress, poolName, poolInfo, cached, inputTokenAddress, outputTokenAddress, inputAmountUi, outputAmountUi, token0PriceUsd, token1PriceUsd, token0Address, swapBlockNumber, txHash, sources) {
|
|
64
106
|
if (inputAmountUi <= 0 || outputAmountUi <= 0)
|
|
65
107
|
return;
|
|
66
108
|
let swapUsd = 0;
|
|
@@ -121,6 +163,7 @@ class QuotePriceVerify {
|
|
|
121
163
|
output_symbol: isBuy ? baseToken.symbol : quoteToken.symbol,
|
|
122
164
|
status,
|
|
123
165
|
time: Date.now(),
|
|
166
|
+
sources: sources || undefined,
|
|
124
167
|
});
|
|
125
168
|
}
|
|
126
169
|
catch (_) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clonegod/ttd-bsc-common",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.65",
|
|
4
4
|
"description": "BSC common library",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"push": "npm run build && npm publish"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@clonegod/ttd-core": "3.1.
|
|
17
|
+
"@clonegod/ttd-core": "3.1.55",
|
|
18
18
|
"axios": "1.15.0",
|
|
19
19
|
"dotenv": "^16.4.7",
|
|
20
20
|
"ethers": "^5.8.0",
|