four-flap-meme-sdk 1.3.95 → 1.3.98

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.
@@ -44,6 +44,8 @@ export interface DirectRouterSignConfig {
44
44
  skipApprovalCheck?: boolean;
45
45
  /** 滑点(基点),默认 100 = 1% */
46
46
  slippageBps?: number;
47
+ /** BlockRazor 贿赂金额(BNB),仅 BSC 链有效,用于提高 bundle 打包优先级 */
48
+ bribeAmount?: number;
47
49
  }
48
50
  export interface DirectV2BuyParams {
49
51
  chain: 'BSC' | 'MONAD' | 'XLAYER';
@@ -16,6 +16,8 @@ import { PROFIT_CONFIG } from '../utils/constants.js';
16
16
  const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
17
17
  const DEFAULT_GAS_LIMIT = 300000;
18
18
  const DEADLINE_MINUTES = 20;
19
+ // ✅ BlockRazor Builder EOA 地址(用于贿赂,仅 BSC 链)
20
+ const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
19
21
  // ✅ Router ABI(用于 ERC20 → 原生代币报价)
20
22
  const QUOTE_ROUTER_ABI = [
21
23
  'function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)'
@@ -585,6 +587,33 @@ async function buildProfitTransaction(wallet, profitAmountWei, nonce, gasPrice,
585
587
  };
586
588
  return wallet.signTransaction(tx);
587
589
  }
590
+ /**
591
+ * 获取贿赂金额(wei)
592
+ * ✅ 仅 BSC 链支持贿赂
593
+ */
594
+ function getBribeAmount(config, chain) {
595
+ // 只有 BSC 链支持贿赂
596
+ if (chain.toUpperCase() !== 'BSC')
597
+ return 0n;
598
+ const bribeAmount = config.bribeAmount;
599
+ if (typeof bribeAmount !== 'number' || bribeAmount <= 0)
600
+ return 0n;
601
+ // 转换为 wei
602
+ return ethers.parseEther(String(bribeAmount));
603
+ }
604
+ /** 构建贿赂交易(向 BlockRazor Builder EOA 转账 BNB) */
605
+ async function buildBribeTransaction(wallet, bribeAmountWei, nonce, gasPrice, chainId, txType = 0) {
606
+ const tx = {
607
+ to: BLOCKRAZOR_BUILDER_EOA,
608
+ value: bribeAmountWei,
609
+ nonce,
610
+ gasLimit: 21000n,
611
+ gasPrice,
612
+ chainId,
613
+ type: txType,
614
+ };
615
+ return wallet.signTransaction(tx);
616
+ }
588
617
  // ============================================================================
589
618
  // V2 直接交易
590
619
  // ============================================================================
@@ -717,22 +746,34 @@ export async function directV2BatchBuy(params) {
717
746
  };
718
747
  }
719
748
  };
749
+ // ✅ 优化:选择金额最大的钱包支付贿赂和利润
750
+ const maxFlowIndex = findMaxFlowIndex(flowAmounts);
751
+ // ✅ 计算贿赂金额(仅 BSC 链)
752
+ const bribeWei = getBribeAmount(config, chain);
753
+ const hasBribe = bribeWei > 0n && wallets.length > 0;
754
+ // ✅ 计算 nonce 偏移:如果有贿赂交易,需要为金额最大的钱包预留 nonce
755
+ const nonceOffsets = wallets.map((_, i) => i === maxFlowIndex && hasBribe ? 1 : 0);
756
+ // ✅ 贿赂交易放在首位(提高 BlockRazor 打包优先级)
757
+ const bribeTxs = [];
758
+ if (hasBribe) {
759
+ const bribeTx = await buildBribeTransaction(wallets[maxFlowIndex], bribeWei, nonces[maxFlowIndex], // 使用原始 nonce
760
+ gasPrice, chainId, txType);
761
+ bribeTxs.push(bribeTx);
762
+ }
720
763
  // ✅ 优化:并行签名所有交易
721
- const signedTxs = await Promise.all(wallets.map(async (wallet, i) => {
764
+ const swapTxs = await Promise.all(wallets.map(async (wallet, i) => {
722
765
  const { txData, txValue } = buildTxData(wallet, flowAmounts[i]);
723
766
  return wallet.signTransaction({
724
767
  to: routerAddress,
725
768
  data: txData,
726
769
  value: txValue,
727
- nonce: nonces[i],
770
+ nonce: nonces[i] + nonceOffsets[i], // ✅ 考虑贿赂交易的 nonce 偏移
728
771
  gasLimit,
729
772
  gasPrice,
730
773
  chainId,
731
774
  type: txType,
732
775
  });
733
776
  }));
734
- // ✅ 优化:选择金额最大的钱包支付利润(和 core.ts 逻辑一致)
735
- const maxFlowIndex = findMaxFlowIndex(flowAmounts);
736
777
  let profitWei = calculateProfitAmount(totalFlowWei);
737
778
  // ✅ 修复:ERC20 交易时,将利润转换为原生代币
738
779
  if (!useNative && profitWei > 0n && quoteToken) {
@@ -744,11 +785,15 @@ export async function directV2BatchBuy(params) {
744
785
  profitWei = 0n; // 报价失败,跳过利润
745
786
  }
746
787
  }
788
+ // ✅ 利润交易
789
+ const profitTxs = [];
747
790
  if (profitWei > 0n) {
748
- const profitNonce = nonces[maxFlowIndex] + 1; // ✅ 使用金额最大的钱包
791
+ const profitNonce = nonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1; // ✅ 考虑贿赂交易的 nonce 偏移
749
792
  const profitTx = await buildProfitTransaction(wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType);
750
- signedTxs.push(profitTx);
793
+ profitTxs.push(profitTx);
751
794
  }
795
+ // ✅ 组装最终交易列表:贿赂 → 交易 → 利润
796
+ const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
752
797
  return {
753
798
  signedTransactions: signedTxs,
754
799
  metadata: {
@@ -855,23 +900,55 @@ export async function directV2BatchSell(params) {
855
900
  if (!config.skipApprovalCheck) {
856
901
  allowances = await Promise.all(wallets.map(w => tokenContract.allowance(w.address, routerAddress)));
857
902
  }
858
- // ✅ 优化:计算每个钱包的 nonce 偏移(是否需要授权)
903
+ // ✅ 先获取报价,确定哪个钱包输出最大(用于支付贿赂和利润)
904
+ const router = new Contract(routerAddress, V2_ROUTER_ABI, provider);
905
+ const quotePromises = wallets.map(async (_, i) => {
906
+ if (sellAmountsWei[i] <= 0n)
907
+ return sellAmountsWei[i];
908
+ try {
909
+ const amounts = await router.getAmountsOut(sellAmountsWei[i], path);
910
+ return amounts[amounts.length - 1];
911
+ }
912
+ catch {
913
+ return sellAmountsWei[i];
914
+ }
915
+ });
916
+ const outputEstimates = await Promise.all(quotePromises);
917
+ const maxOutputIndex = findMaxFlowIndex(outputEstimates);
918
+ // ✅ 计算贿赂金额(仅 BSC 链)
919
+ const bribeWei = getBribeAmount(config, chain);
920
+ const hasBribe = bribeWei > 0n && wallets.length > 0;
921
+ // ✅ 优化:计算每个钱包的 nonce 偏移(授权 + 贿赂)
859
922
  const currentNonceOffset = wallets.map((_, i) => {
860
- if (config.skipApprovalCheck)
861
- return 0;
862
- return allowances[i] < sellAmountsWei[i] ? 1 : 0;
923
+ let offset = 0;
924
+ // 贿赂交易偏移(只有 maxOutputIndex 钱包需要)
925
+ if (hasBribe && i === maxOutputIndex)
926
+ offset++;
927
+ // 授权交易偏移
928
+ if (!config.skipApprovalCheck && allowances[i] < sellAmountsWei[i])
929
+ offset++;
930
+ return offset;
863
931
  });
932
+ // ✅ 贿赂交易放在首位(提高 BlockRazor 打包优先级)
933
+ const bribeTxs = [];
934
+ if (hasBribe) {
935
+ const bribeTx = await buildBribeTransaction(wallets[maxOutputIndex], bribeWei, nonces[maxOutputIndex], // 使用原始 nonce
936
+ gasPrice, chainId, txType);
937
+ bribeTxs.push(bribeTx);
938
+ }
864
939
  // ✅ 优化:并行签名所有授权交易
865
940
  const approvalTxPromises = wallets.map(async (wallet, i) => {
866
941
  if (config.skipApprovalCheck || sellAmountsWei[i] <= 0n)
867
942
  return null;
868
943
  if (allowances[i] >= sellAmountsWei[i])
869
944
  return null;
945
+ // 授权交易的 nonce = 原始 nonce + 贿赂偏移
946
+ const approvalNonce = nonces[i] + (hasBribe && i === maxOutputIndex ? 1 : 0);
870
947
  return wallet.signTransaction({
871
948
  to: tokenAddress,
872
949
  data: approveIface.encodeFunctionData('approve', [routerAddress, ethers.MaxUint256]),
873
950
  value: 0n,
874
- nonce: nonces[i],
951
+ nonce: approvalNonce,
875
952
  gasLimit: 60000n,
876
953
  gasPrice,
877
954
  chainId,
@@ -895,35 +972,19 @@ export async function directV2BatchSell(params) {
895
972
  });
896
973
  });
897
974
  const sellTxResults = await Promise.all(sellTxPromises);
898
- // ✅ 优化:并行获取所有报价
899
- const router = new Contract(routerAddress, V2_ROUTER_ABI, provider);
900
- const quotePromises = wallets.map(async (_, i) => {
901
- if (sellAmountsWei[i] <= 0n)
902
- return sellAmountsWei[i];
903
- try {
904
- const amounts = await router.getAmountsOut(sellAmountsWei[i], path);
905
- return amounts[amounts.length - 1];
906
- }
907
- catch {
908
- return sellAmountsWei[i];
909
- }
910
- });
911
- const outputEstimates = await Promise.all(quotePromises);
912
975
  // ✅ 按顺序组装签名交易:先授权,后卖出
913
- const signedTxs = [];
976
+ const swapTxs = [];
914
977
  for (let i = 0; i < wallets.length; i++) {
915
978
  const approvalTx = approvalTxResults[i];
916
979
  const sellTx = sellTxResults[i];
917
980
  if (approvalTx)
918
- signedTxs.push(approvalTx);
981
+ swapTxs.push(approvalTx);
919
982
  if (sellTx) {
920
- signedTxs.push(sellTx);
983
+ swapTxs.push(sellTx);
921
984
  currentNonceOffset[i]++; // 更新 offset 供利润交易使用
922
985
  }
923
986
  }
924
987
  const totalOutputEstimate = outputEstimates.reduce((sum, o) => sum + o, 0n);
925
- // ✅ 优化:选择输出最大的钱包支付利润(和 core.ts 逻辑一致)
926
- const maxOutputIndex = findMaxFlowIndex(outputEstimates);
927
988
  let profitWei = calculateProfitAmount(totalOutputEstimate);
928
989
  // ✅ 修复:ERC20 输出时,将利润转换为原生代币
929
990
  if (!useNativeOutput && profitWei > 0n && quoteToken) {
@@ -935,11 +996,15 @@ export async function directV2BatchSell(params) {
935
996
  profitWei = 0n;
936
997
  }
937
998
  }
999
+ // ✅ 利润交易
1000
+ const profitTxs = [];
938
1001
  if (profitWei > 0n && wallets.length > 0) {
939
1002
  const profitTx = await buildProfitTransaction(wallets[maxOutputIndex], // ✅ 使用输出最大的钱包
940
1003
  profitWei, nonces[maxOutputIndex] + currentNonceOffset[maxOutputIndex], gasPrice, chainId, txType);
941
- signedTxs.push(profitTx);
1004
+ profitTxs.push(profitTx);
942
1005
  }
1006
+ // ✅ 组装最终交易列表:贿赂 → 授权+卖出 → 利润
1007
+ const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
943
1008
  return {
944
1009
  signedTransactions: signedTxs,
945
1010
  metadata: {
@@ -1031,22 +1096,33 @@ export async function directV3BatchBuy(params) {
1031
1096
  }
1032
1097
  }
1033
1098
  };
1099
+ // ✅ 优化:选择金额最大的钱包支付贿赂和利润
1100
+ const maxFlowIndex = findMaxFlowIndex(flowAmounts);
1101
+ // ✅ 计算贿赂金额(仅 BSC 链)
1102
+ const bribeWei = getBribeAmount(config, chain);
1103
+ const hasBribe = bribeWei > 0n && wallets.length > 0;
1104
+ // ✅ 计算 nonce 偏移
1105
+ const nonceOffsets = wallets.map((_, i) => i === maxFlowIndex && hasBribe ? 1 : 0);
1106
+ // ✅ 贿赂交易放在首位(提高 BlockRazor 打包优先级)
1107
+ const bribeTxs = [];
1108
+ if (hasBribe) {
1109
+ const bribeTx = await buildBribeTransaction(wallets[maxFlowIndex], bribeWei, nonces[maxFlowIndex], gasPrice, chainId, txType);
1110
+ bribeTxs.push(bribeTx);
1111
+ }
1034
1112
  // ✅ 优化:并行签名所有交易
1035
- const signedTxs = await Promise.all(wallets.map(async (wallet, i) => {
1113
+ const swapTxs = await Promise.all(wallets.map(async (wallet, i) => {
1036
1114
  const { txData, txValue } = buildV3BuyTxData(wallet, flowAmounts[i]);
1037
1115
  return wallet.signTransaction({
1038
1116
  to: routerAddress,
1039
1117
  data: txData,
1040
1118
  value: txValue,
1041
- nonce: nonces[i],
1119
+ nonce: nonces[i] + nonceOffsets[i],
1042
1120
  gasLimit,
1043
1121
  gasPrice,
1044
1122
  chainId,
1045
1123
  type: txType,
1046
1124
  });
1047
1125
  }));
1048
- // ✅ 优化:选择金额最大的钱包支付利润
1049
- const maxFlowIndex = findMaxFlowIndex(flowAmounts);
1050
1126
  let profitWei = calculateProfitAmount(totalFlowWei);
1051
1127
  // ✅ 修复:ERC20 交易时,将利润转换为原生代币
1052
1128
  if (!useNative && profitWei > 0n && quoteToken) {
@@ -1058,11 +1134,14 @@ export async function directV3BatchBuy(params) {
1058
1134
  profitWei = 0n;
1059
1135
  }
1060
1136
  }
1137
+ // ✅ 利润交易
1138
+ const profitTxs = [];
1061
1139
  if (profitWei > 0n) {
1062
- const profitTx = await buildProfitTransaction(wallets[maxFlowIndex], // 使用金额最大的钱包
1063
- profitWei, nonces[maxFlowIndex] + 1, gasPrice, chainId, txType);
1064
- signedTxs.push(profitTx);
1140
+ const profitTx = await buildProfitTransaction(wallets[maxFlowIndex], profitWei, nonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1, gasPrice, chainId, txType);
1141
+ profitTxs.push(profitTx);
1065
1142
  }
1143
+ // ✅ 组装最终交易列表:贿赂 → 交易 → 利润
1144
+ const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
1066
1145
  return {
1067
1146
  signedTransactions: signedTxs,
1068
1147
  metadata: {
@@ -1162,23 +1241,43 @@ export async function directV3BatchSell(params) {
1162
1241
  if (!config.skipApprovalCheck) {
1163
1242
  allowances = await Promise.all(wallets.map(w => tokenContract.allowance(w.address, routerAddress)));
1164
1243
  }
1165
- // ✅ 优化:计算每个钱包的 nonce 偏移
1244
+ // ✅ 先找出输出最大的钱包索引(用于支付贿赂和利润)
1245
+ // 对于 V3 卖出,使用卖出金额作为输出估计
1246
+ const maxOutputIndex = findMaxFlowIndex(sellAmountsWei);
1247
+ // ✅ 计算贿赂金额(仅 BSC 链)
1248
+ const bribeWei = getBribeAmount(config, chain);
1249
+ const hasBribe = bribeWei > 0n && wallets.length > 0;
1250
+ // ✅ 优化:计算每个钱包的 nonce 偏移(贿赂 + 授权)
1166
1251
  const currentNonceOffset = wallets.map((_, i) => {
1167
- if (config.skipApprovalCheck || sellAmountsWei[i] <= 0n)
1168
- return 0;
1169
- return allowances[i] < sellAmountsWei[i] ? 1 : 0;
1252
+ let offset = 0;
1253
+ // 贿赂交易偏移(只有 maxOutputIndex 钱包需要)
1254
+ if (hasBribe && i === maxOutputIndex)
1255
+ offset++;
1256
+ // 授权交易偏移
1257
+ if (!config.skipApprovalCheck && sellAmountsWei[i] > 0n && allowances[i] < sellAmountsWei[i])
1258
+ offset++;
1259
+ return offset;
1170
1260
  });
1261
+ // ✅ 贿赂交易放在首位(提高 BlockRazor 打包优先级)
1262
+ const bribeTxs = [];
1263
+ if (hasBribe) {
1264
+ const bribeTx = await buildBribeTransaction(wallets[maxOutputIndex], bribeWei, nonces[maxOutputIndex], // 使用原始 nonce
1265
+ gasPrice, chainId, txType);
1266
+ bribeTxs.push(bribeTx);
1267
+ }
1171
1268
  // ✅ 优化:并行签名所有授权交易
1172
1269
  const approvalTxPromises = wallets.map(async (wallet, i) => {
1173
1270
  if (config.skipApprovalCheck || sellAmountsWei[i] <= 0n)
1174
1271
  return null;
1175
1272
  if (allowances[i] >= sellAmountsWei[i])
1176
1273
  return null;
1274
+ // 授权交易的 nonce = 原始 nonce + 贿赂偏移
1275
+ const approvalNonce = nonces[i] + (hasBribe && i === maxOutputIndex ? 1 : 0);
1177
1276
  return wallet.signTransaction({
1178
1277
  to: tokenAddress,
1179
1278
  data: approveIface.encodeFunctionData('approve', [routerAddress, ethers.MaxUint256]),
1180
1279
  value: 0n,
1181
- nonce: nonces[i],
1280
+ nonce: approvalNonce,
1182
1281
  gasLimit: 60000n,
1183
1282
  gasPrice,
1184
1283
  chainId,
@@ -1203,15 +1302,15 @@ export async function directV3BatchSell(params) {
1203
1302
  });
1204
1303
  const sellTxResults = await Promise.all(sellTxPromises);
1205
1304
  // ✅ 按顺序组装签名交易:先授权,后卖出
1206
- const signedTxs = [];
1305
+ const swapTxs = [];
1207
1306
  const outputEstimates = [];
1208
1307
  for (let i = 0; i < wallets.length; i++) {
1209
1308
  const approvalTx = approvalTxResults[i];
1210
1309
  const sellTx = sellTxResults[i];
1211
1310
  if (approvalTx)
1212
- signedTxs.push(approvalTx);
1311
+ swapTxs.push(approvalTx);
1213
1312
  if (sellTx) {
1214
- signedTxs.push(sellTx);
1313
+ swapTxs.push(sellTx);
1215
1314
  outputEstimates.push(sellAmountsWei[i]);
1216
1315
  currentNonceOffset[i]++;
1217
1316
  }
@@ -1220,8 +1319,6 @@ export async function directV3BatchSell(params) {
1220
1319
  }
1221
1320
  }
1222
1321
  const totalOutputEstimate = outputEstimates.reduce((sum, o) => sum + o, 0n);
1223
- // ✅ 优化:选择输出最大的钱包支付利润
1224
- const maxOutputIndex = findMaxFlowIndex(outputEstimates);
1225
1322
  let profitWei = calculateProfitAmount(totalOutputEstimate);
1226
1323
  // ✅ 修复:ERC20 输出时,将利润转换为原生代币
1227
1324
  if (!useNativeOutput && profitWei > 0n && quoteToken) {
@@ -1233,11 +1330,15 @@ export async function directV3BatchSell(params) {
1233
1330
  profitWei = 0n;
1234
1331
  }
1235
1332
  }
1333
+ // ✅ 利润交易
1334
+ const profitTxs = [];
1236
1335
  if (profitWei > 0n && wallets.length > 0) {
1237
1336
  const profitTx = await buildProfitTransaction(wallets[maxOutputIndex], // ✅ 使用输出最大的钱包
1238
1337
  profitWei, nonces[maxOutputIndex] + currentNonceOffset[maxOutputIndex], gasPrice, chainId, txType);
1239
- signedTxs.push(profitTx);
1338
+ profitTxs.push(profitTx);
1240
1339
  }
1340
+ // ✅ 组装最终交易列表:贿赂 → 授权+卖出 → 利润
1341
+ const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
1241
1342
  return {
1242
1343
  signedTransactions: signedTxs,
1243
1344
  metadata: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.3.95",
3
+ "version": "1.3.98",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",