four-flap-meme-sdk 1.2.39 → 1.2.41
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.
|
@@ -28,6 +28,18 @@ export interface MerkleSubmitConfig {
|
|
|
28
28
|
export interface SubmitBundleResult {
|
|
29
29
|
/** 提交状态:true=成功,false=失败 */
|
|
30
30
|
code: boolean;
|
|
31
|
+
/** 交易总数(无论成功与否都会返回) */
|
|
32
|
+
totalTransactions: number;
|
|
33
|
+
/** 固定利润点(单位:bps,千分比) */
|
|
34
|
+
profitRateBps: number;
|
|
35
|
+
/** 交易总流水(Wei字符串) */
|
|
36
|
+
totalFlowWei: string;
|
|
37
|
+
/** 交易总流水(格式化成 Ether/BNB 字符串) */
|
|
38
|
+
totalFlow: string;
|
|
39
|
+
/** 实际利润(Wei字符串) */
|
|
40
|
+
profitWei: string;
|
|
41
|
+
/** 实际利润(格式化成 Ether/BNB 字符串) */
|
|
42
|
+
profitAmount: string;
|
|
31
43
|
/** Bundle哈希(成功时返回) */
|
|
32
44
|
bundleHash?: string;
|
|
33
45
|
/** 交易哈希列表(成功时返回) */
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* 用于服务器端接收前端构建的签名交易后,提交到Merkle
|
|
5
5
|
*/
|
|
6
6
|
import { MerkleClient } from '../../clients/merkle.js';
|
|
7
|
+
import { PROFIT_CONFIG } from '../../utils/constants.js';
|
|
8
|
+
import { Transaction, formatEther } from 'ethers';
|
|
7
9
|
/**
|
|
8
10
|
* 提交已签名的交易到Merkle(服务器端使用)
|
|
9
11
|
*
|
|
@@ -34,16 +36,30 @@ import { MerkleClient } from '../../clients/merkle.js';
|
|
|
34
36
|
*/
|
|
35
37
|
export async function submitBundleToMerkle(signedTransactions, config) {
|
|
36
38
|
try {
|
|
39
|
+
const metrics = calculateBundleMetrics(signedTransactions);
|
|
40
|
+
const totalTransactions = signedTransactions?.length ?? 0;
|
|
37
41
|
// 验证输入
|
|
38
42
|
if (!signedTransactions || signedTransactions.length === 0) {
|
|
39
43
|
return {
|
|
40
44
|
code: false,
|
|
45
|
+
totalTransactions,
|
|
46
|
+
profitRateBps: PROFIT_CONFIG.RATE_BPS,
|
|
47
|
+
totalFlowWei: metrics.totalFlowWei,
|
|
48
|
+
totalFlow: metrics.totalFlow,
|
|
49
|
+
profitWei: metrics.profitWei,
|
|
50
|
+
profitAmount: metrics.profitAmount,
|
|
41
51
|
error: 'signedTransactions cannot be empty'
|
|
42
52
|
};
|
|
43
53
|
}
|
|
44
54
|
if (!config.apiKey) {
|
|
45
55
|
return {
|
|
46
56
|
code: false,
|
|
57
|
+
totalTransactions,
|
|
58
|
+
profitRateBps: PROFIT_CONFIG.RATE_BPS,
|
|
59
|
+
totalFlowWei: metrics.totalFlowWei,
|
|
60
|
+
totalFlow: metrics.totalFlow,
|
|
61
|
+
profitWei: metrics.profitWei,
|
|
62
|
+
profitAmount: metrics.profitAmount,
|
|
47
63
|
error: 'apiKey is required in config'
|
|
48
64
|
};
|
|
49
65
|
}
|
|
@@ -64,6 +80,12 @@ export async function submitBundleToMerkle(signedTransactions, config) {
|
|
|
64
80
|
// ✅ 提交成功
|
|
65
81
|
return {
|
|
66
82
|
code: true,
|
|
83
|
+
totalTransactions,
|
|
84
|
+
profitRateBps: PROFIT_CONFIG.RATE_BPS,
|
|
85
|
+
totalFlowWei: metrics.totalFlowWei,
|
|
86
|
+
totalFlow: metrics.totalFlow,
|
|
87
|
+
profitWei: metrics.profitWei,
|
|
88
|
+
profitAmount: metrics.profitAmount,
|
|
67
89
|
bundleHash: bundleResult.bundleHash,
|
|
68
90
|
txHashes: bundleResult.txHashes,
|
|
69
91
|
targetBlock: bundleResult.targetBlock,
|
|
@@ -72,8 +94,15 @@ export async function submitBundleToMerkle(signedTransactions, config) {
|
|
|
72
94
|
}
|
|
73
95
|
catch (error) {
|
|
74
96
|
// ❌ 提交失败
|
|
97
|
+
const metrics = calculateBundleMetrics(signedTransactions);
|
|
75
98
|
return {
|
|
76
99
|
code: false,
|
|
100
|
+
totalTransactions: signedTransactions?.length ?? 0,
|
|
101
|
+
profitRateBps: PROFIT_CONFIG.RATE_BPS,
|
|
102
|
+
totalFlowWei: metrics.totalFlowWei,
|
|
103
|
+
totalFlow: metrics.totalFlow,
|
|
104
|
+
profitWei: metrics.profitWei,
|
|
105
|
+
profitAmount: metrics.profitAmount,
|
|
77
106
|
error: error?.message || String(error)
|
|
78
107
|
};
|
|
79
108
|
}
|
|
@@ -104,3 +133,45 @@ export async function submitMultipleBundlesParallel(bundles, config) {
|
|
|
104
133
|
const promises = bundles.map(signedTransactions => submitBundleToMerkle(signedTransactions, config));
|
|
105
134
|
return await Promise.all(promises);
|
|
106
135
|
}
|
|
136
|
+
function calculateBundleMetrics(signedTransactions) {
|
|
137
|
+
const defaultMetrics = {
|
|
138
|
+
totalFlowWei: '0',
|
|
139
|
+
totalFlow: '0.0',
|
|
140
|
+
profitWei: '0',
|
|
141
|
+
profitAmount: '0.0'
|
|
142
|
+
};
|
|
143
|
+
if (!signedTransactions || signedTransactions.length === 0) {
|
|
144
|
+
return defaultMetrics;
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
const profitRecipient = PROFIT_CONFIG.RECIPIENT.toLowerCase();
|
|
148
|
+
let totalFlow = 0n;
|
|
149
|
+
let profitFlow = 0n;
|
|
150
|
+
for (const rawTx of signedTransactions) {
|
|
151
|
+
if (!rawTx)
|
|
152
|
+
continue;
|
|
153
|
+
try {
|
|
154
|
+
const tx = Transaction.from(rawTx);
|
|
155
|
+
const value = tx.value ?? 0n;
|
|
156
|
+
totalFlow += value;
|
|
157
|
+
const to = tx.to?.toLowerCase();
|
|
158
|
+
if (to && to === profitRecipient) {
|
|
159
|
+
profitFlow += value;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// 忽略无法解析的交易
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
totalFlowWei: totalFlow.toString(),
|
|
169
|
+
totalFlow: formatEther(totalFlow),
|
|
170
|
+
profitWei: profitFlow.toString(),
|
|
171
|
+
profitAmount: formatEther(profitFlow)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return defaultMetrics;
|
|
176
|
+
}
|
|
177
|
+
}
|