four-flap-meme-sdk 2.2.0 → 2.2.2

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.
Files changed (467) hide show
  1. package/README.en.md +6 -41
  2. package/README.md +0 -31
  3. package/README.zh-CN.md +6 -41
  4. package/dist/chains/bsc/four/approve-tokenmanager.d.ts +26 -1
  5. package/dist/chains/bsc/four/approve-tokenmanager.js +113 -1
  6. package/dist/chains/bsc/four/config.d.ts +67 -5
  7. package/dist/chains/bsc/four/config.js +114 -2
  8. package/dist/chains/bsc/four/core.d.ts +4 -1
  9. package/dist/chains/bsc/four/core.js +592 -1
  10. package/dist/chains/bsc/four/index.d.ts +6 -6
  11. package/dist/chains/bsc/four/index.js +6 -6
  12. package/dist/chains/bsc/four/internal.d.ts +46 -2
  13. package/dist/chains/bsc/four/internal.js +239 -2
  14. package/dist/chains/bsc/four/pancake-proxy.d.ts +28 -1
  15. package/dist/chains/bsc/four/pancake-proxy.js +687 -1
  16. package/dist/chains/bsc/four/private.d.ts +27 -1
  17. package/dist/chains/bsc/four/private.js +477 -1
  18. package/dist/chains/bsc/four/submit.d.ts +315 -2
  19. package/dist/chains/bsc/four/submit.js +752 -2
  20. package/dist/chains/bsc/four/swap-buy-first.d.ts +55 -2
  21. package/dist/chains/bsc/four/swap-buy-first.js +507 -2
  22. package/dist/chains/bsc/four/swap-internal.d.ts +3 -1
  23. package/dist/chains/bsc/four/swap-internal.js +18 -1
  24. package/dist/chains/bsc/four/swap.d.ts +144 -2
  25. package/dist/chains/bsc/four/swap.js +766 -2
  26. package/dist/chains/bsc/four/types.d.ts +476 -1
  27. package/dist/chains/bsc/four/utils.d.ts +18 -5
  28. package/dist/chains/bsc/four/utils.js +1552 -5
  29. package/dist/chains/bsc/pancake/bundle-buy-first.d.ts +91 -1
  30. package/dist/chains/bsc/pancake/bundle-buy-first.js +212 -97
  31. package/dist/chains/bsc/pancake/bundle-swap.d.ts +79 -1
  32. package/dist/chains/bsc/pancake/bundle-swap.js +726 -114
  33. package/dist/chains/bsc/pancake/index.d.ts +2 -4
  34. package/dist/chains/bsc/pancake/index.js +3 -1
  35. package/dist/chains/bsc/platforms/iro/factory.js +1 -3
  36. package/dist/chains/bsc/platforms/iro/index.d.ts +5 -5
  37. package/dist/chains/bsc/platforms/iro/index.js +3 -3
  38. package/dist/chains/bsc/platforms/iro/pool.js +10 -31
  39. package/dist/chains/bsc/platforms/iro/token.js +1 -4
  40. package/dist/chains/eni/batch-router/bundle-approve.js +3 -4
  41. package/dist/chains/eni/batch-router/transfer.js +25 -55
  42. package/dist/chains/eni/batch-router/utils.js +6 -32
  43. package/dist/chains/eni/bundler/sign.js +4 -4
  44. package/dist/chains/eni/bundler/submit.js +4 -1
  45. package/dist/chains/eni/constants.js +1 -1
  46. package/dist/chains/eni/index.d.ts +1 -2
  47. package/dist/chains/eni/index.js +0 -1
  48. package/dist/chains/eni/platforms/daoaas/create.js +2 -2
  49. package/dist/chains/eni/platforms/daoaas/index.d.ts +3 -3
  50. package/dist/chains/eni/platforms/daoaas/index.js +3 -3
  51. package/dist/chains/eni/platforms/daoaas/meta.js +4 -8
  52. package/dist/chains/eni/platforms/daoaas/portal-direct.js +44 -28
  53. package/dist/chains/eni/platforms/daoaas/portal.js +6 -10
  54. package/dist/chains/eni/platforms/dswap/liquidity.js +26 -58
  55. package/dist/chains/eni/platforms/fair-launch/index.d.ts +2 -2
  56. package/dist/chains/eni/platforms/fair-launch/index.js +1 -1
  57. package/dist/chains/eni/platforms/fair-launch/launcher.js +46 -87
  58. package/dist/chains/eni/platforms/fair-launch/pool.js +1 -4
  59. package/dist/chains/eni/platforms/fair-launch/presets.js +2 -2
  60. package/dist/chains/eni/platforms/iro/factory.js +1 -3
  61. package/dist/chains/eni/platforms/iro/index.d.ts +6 -6
  62. package/dist/chains/eni/platforms/iro/index.js +4 -4
  63. package/dist/chains/eni/platforms/iro/pool.js +26 -90
  64. package/dist/chains/eni/platforms/iro/token.js +31 -107
  65. package/dist/chains/eni/platforms/iro/whitelist.js +18 -6
  66. package/dist/chains/index.d.ts +0 -13
  67. package/dist/chains/index.js +0 -13
  68. package/dist/chains/xlayer/eip7702/bundle-approve.d.ts +26 -2
  69. package/dist/chains/xlayer/eip7702/bundle-approve.js +21 -11
  70. package/dist/chains/xlayer/eip7702/bundle-buy.d.ts +6 -2
  71. package/dist/chains/xlayer/eip7702/bundle-buy.js +51 -13
  72. package/dist/chains/xlayer/eip7702/bundle-create.js +59 -93
  73. package/dist/chains/xlayer/eip7702/bundle-sell.d.ts +6 -2
  74. package/dist/chains/xlayer/eip7702/bundle-sell.js +97 -26
  75. package/dist/chains/xlayer/eip7702/bundle-swap.d.ts +65 -3
  76. package/dist/chains/xlayer/eip7702/bundle-swap.js +245 -51
  77. package/dist/chains/xlayer/eip7702/constants.d.ts +16 -1
  78. package/dist/chains/xlayer/eip7702/constants.js +21 -3
  79. package/dist/chains/xlayer/eip7702/index.d.ts +46 -28
  80. package/dist/chains/xlayer/eip7702/index.js +81 -28
  81. package/dist/chains/xlayer/eip7702/multi-hop-transfer.d.ts +203 -2
  82. package/dist/chains/xlayer/eip7702/multi-hop-transfer.js +301 -58
  83. package/dist/chains/xlayer/eip7702/types.d.ts +0 -88
  84. package/dist/chains/xlayer/eip7702/utils.d.ts +3 -0
  85. package/dist/chains/xlayer/eip7702/utils.js +28 -23
  86. package/dist/chains/xlayer/eip7702/volume.d.ts +184 -6
  87. package/dist/chains/xlayer/eip7702/volume.js +158 -83
  88. package/dist/chains/xlayer/eoa/constants.js +1 -1
  89. package/dist/chains/xlayer/eoa/dex-helpers.js +5 -5
  90. package/dist/chains/xlayer/eoa/eoa-bundle-swap.d.ts +95 -1
  91. package/dist/chains/xlayer/eoa/eoa-bundle-swap.js +299 -66
  92. package/dist/chains/xlayer/eoa/eoa-wash-volume.d.ts +1 -1
  93. package/dist/chains/xlayer/eoa/eoa-wash-volume.js +23 -18
  94. package/dist/chains/xlayer/eoa/index.d.ts +6 -10
  95. package/dist/chains/xlayer/eoa/index.js +23 -8
  96. package/dist/chains/xlayer/eoa/portal-ops.js +2 -7
  97. package/dist/chains/xlayer/eoa/router-manager.js +3 -3
  98. package/dist/chains/xlayer/eoa/types.d.ts +2 -2
  99. package/dist/chains/xlayer/eoa/types.js +3 -1
  100. package/dist/chains/xlayer/index.d.ts +2 -3
  101. package/dist/chains/xlayer/index.js +7 -4
  102. package/dist/contracts/helper3.d.ts +5 -20
  103. package/dist/contracts/helper3.js +20 -56
  104. package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.d.ts +26 -1
  105. package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.js +113 -1
  106. package/dist/contracts/tm-bundle-merkle/config.d.ts +67 -5
  107. package/dist/contracts/tm-bundle-merkle/config.js +114 -2
  108. package/dist/contracts/tm-bundle-merkle/core.d.ts +4 -1
  109. package/dist/contracts/tm-bundle-merkle/core.js +591 -1
  110. package/dist/contracts/tm-bundle-merkle/index.d.ts +5 -5
  111. package/dist/contracts/tm-bundle-merkle/index.js +5 -5
  112. package/dist/contracts/tm-bundle-merkle/internal.d.ts +46 -2
  113. package/dist/contracts/tm-bundle-merkle/internal.js +238 -2
  114. package/dist/contracts/tm-bundle-merkle/pancake-proxy.d.ts +28 -1
  115. package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +686 -1
  116. package/dist/contracts/tm-bundle-merkle/private.d.ts +27 -1
  117. package/dist/contracts/tm-bundle-merkle/private.js +476 -1
  118. package/dist/contracts/tm-bundle-merkle/submit.d.ts +314 -3
  119. package/dist/contracts/tm-bundle-merkle/submit.js +928 -3
  120. package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +55 -2
  121. package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +506 -2
  122. package/dist/contracts/tm-bundle-merkle/swap-internal.d.ts +3 -1
  123. package/dist/contracts/tm-bundle-merkle/swap-internal.js +18 -1
  124. package/dist/contracts/tm-bundle-merkle/swap.d.ts +144 -2
  125. package/dist/contracts/tm-bundle-merkle/swap.js +764 -2
  126. package/dist/contracts/tm-bundle-merkle/types.d.ts +476 -1
  127. package/dist/contracts/tm-bundle-merkle/utils.d.ts +18 -6
  128. package/dist/contracts/tm-bundle-merkle/utils.js +1501 -6
  129. package/dist/contracts/tm-bundle.d.ts +51 -3
  130. package/dist/contracts/tm-bundle.js +177 -108
  131. package/dist/contracts/tm.d.ts +2 -3
  132. package/dist/contracts/tm.js +32 -37
  133. package/dist/contracts/tm1.js +4 -9
  134. package/dist/contracts/tm2.js +4 -9
  135. package/dist/dex/direct-router.d.ts +125 -3
  136. package/dist/dex/direct-router.js +666 -237
  137. package/dist/flows/create.d.ts +1 -2
  138. package/dist/flows/create.js +6 -6
  139. package/dist/index.d.ts +85 -20
  140. package/dist/index.js +215 -20
  141. package/dist/shared/abis/TaxToken.json +105 -0
  142. package/dist/shared/abis/TokenManager2.json +60 -0
  143. package/dist/shared/abis/common.d.ts +83 -2
  144. package/dist/shared/abis/common.js +252 -2
  145. package/dist/shared/abis/index.d.ts +6 -5
  146. package/dist/shared/abis/index.js +7 -5
  147. package/dist/shared/clients/blockrazor.js +25 -39
  148. package/dist/shared/clients/club48.d.ts +2 -2
  149. package/dist/shared/clients/club48.js +29 -34
  150. package/dist/shared/clients/emitservice.js +0 -2
  151. package/dist/shared/clients/four.d.ts +5 -5
  152. package/dist/shared/clients/four.js +17 -21
  153. package/dist/shared/clients/merkle.js +34 -27
  154. package/dist/shared/constants/addresses.d.ts +1 -1
  155. package/dist/shared/constants/addresses.js +2 -11
  156. package/dist/shared/constants/chains.d.ts +1 -1
  157. package/dist/shared/constants/chains.js +1 -1
  158. package/dist/shared/constants/gas.d.ts +1 -1
  159. package/dist/shared/constants/gas.js +6 -2
  160. package/dist/shared/constants/index.d.ts +0 -3
  161. package/dist/shared/constants/index.js +0 -1
  162. package/dist/shared/flap/abi.js +1 -1
  163. package/dist/shared/flap/constants.d.ts +2 -1
  164. package/dist/shared/flap/constants.js +3 -2
  165. package/dist/shared/flap/curve.js +0 -3
  166. package/dist/shared/flap/errors.d.ts +4 -1
  167. package/dist/shared/flap/errors.js +1 -20
  168. package/dist/shared/flap/index.d.ts +3 -3
  169. package/dist/shared/flap/index.js +3 -3
  170. package/dist/shared/flap/meta.d.ts +18 -16
  171. package/dist/shared/flap/meta.js +17 -12
  172. package/dist/shared/flap/permit.js +2 -5
  173. package/dist/shared/flap/pinata.d.ts +4 -11
  174. package/dist/shared/flap/pinata.js +16 -21
  175. package/dist/shared/flap/portal-bundle-merkle/config.d.ts +72 -3
  176. package/dist/shared/flap/portal-bundle-merkle/config.js +124 -4
  177. package/dist/shared/flap/portal-bundle-merkle/core.d.ts +4 -0
  178. package/dist/shared/flap/portal-bundle-merkle/core.js +172 -92
  179. package/dist/shared/flap/portal-bundle-merkle/create-to-dex.js +99 -106
  180. package/dist/shared/flap/portal-bundle-merkle/curve-to-dex.js +92 -100
  181. package/dist/shared/flap/portal-bundle-merkle/index.d.ts +7 -11
  182. package/dist/shared/flap/portal-bundle-merkle/index.js +7 -4
  183. package/dist/shared/flap/portal-bundle-merkle/pancake-proxy.js +68 -71
  184. package/dist/shared/flap/portal-bundle-merkle/private.js +114 -61
  185. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.d.ts +64 -1
  186. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.js +247 -66
  187. package/dist/shared/flap/portal-bundle-merkle/swap.d.ts +71 -2
  188. package/dist/shared/flap/portal-bundle-merkle/swap.js +410 -103
  189. package/dist/shared/flap/portal-bundle-merkle/types.d.ts +7 -73
  190. package/dist/shared/flap/portal-bundle-merkle/utils.d.ts +80 -1
  191. package/dist/shared/flap/portal-bundle-merkle/utils.js +265 -145
  192. package/dist/shared/flap/portal-bundle.js +56 -55
  193. package/dist/shared/flap/portal.d.ts +3 -1
  194. package/dist/shared/flap/portal.js +25 -32
  195. package/dist/shared/flap/vanity.d.ts +5 -1
  196. package/dist/shared/flap/vanity.js +17 -6
  197. package/dist/shared/flap/vault.d.ts +124 -17
  198. package/dist/shared/flap/vault.js +148 -67
  199. package/dist/shared/four/tax-token.d.ts +1 -1
  200. package/dist/shared/four/tax-token.js +7 -27
  201. package/dist/shared/index.d.ts +0 -6
  202. package/dist/shared/index.js +0 -4
  203. package/dist/utils/airdrop-sweep.d.ts +76 -4
  204. package/dist/utils/airdrop-sweep.js +54 -40
  205. package/dist/utils/bundle-helpers.d.ts +243 -9
  206. package/dist/utils/bundle-helpers.js +584 -10
  207. package/dist/utils/constants.d.ts +61 -5
  208. package/dist/utils/constants.js +80 -5
  209. package/dist/utils/contract-factory.d.ts +4 -2
  210. package/dist/utils/contract-factory.js +18 -25
  211. package/dist/utils/erc20.d.ts +89 -7
  212. package/dist/utils/erc20.js +125 -94
  213. package/dist/utils/errors.d.ts +1 -12
  214. package/dist/utils/errors.js +1 -60
  215. package/dist/utils/holders-maker.d.ts +138 -2
  216. package/dist/utils/holders-maker.js +661 -26
  217. package/dist/utils/lp-inspect.d.ts +112 -2
  218. package/dist/utils/lp-inspect.js +223 -73
  219. package/dist/utils/mpcExclusive.d.ts +5 -2
  220. package/dist/utils/mpcExclusive.js +3 -4
  221. package/dist/utils/private-sale.d.ts +58 -2
  222. package/dist/utils/private-sale.js +15 -4
  223. package/dist/utils/provider-factory.d.ts +0 -4
  224. package/dist/utils/provider-factory.js +0 -10
  225. package/dist/utils/quote-helpers.d.ts +45 -4
  226. package/dist/utils/quote-helpers.js +74 -17
  227. package/dist/utils/stealth-transfer.d.ts +28 -2
  228. package/dist/utils/stealth-transfer.js +15 -31
  229. package/dist/utils/swap-helpers.d.ts +15 -2
  230. package/dist/utils/swap-helpers.js +10 -5
  231. package/dist/utils/wallet.d.ts +25 -2
  232. package/dist/utils/wallet.js +8 -9
  233. package/package.json +4 -159
  234. package/dist/__tests__/subpath-exports.test.d.ts +0 -1
  235. package/dist/__tests__/subpath-exports.test.js +0 -64
  236. package/dist/abis/common.d.ts +0 -85
  237. package/dist/abis/common.js +0 -260
  238. package/dist/abis/contracts/TaxToken.json +0 -969
  239. package/dist/abis/contracts/TokenManager2.json +0 -136
  240. package/dist/abis/contracts/index.d.ts +0 -5
  241. package/dist/abis/contracts/index.js +0 -5
  242. package/dist/abis/flap/index.d.ts +0 -3
  243. package/dist/abis/flap/index.js +0 -3
  244. package/dist/abis/flap/portal-events.d.ts +0 -6
  245. package/dist/abis/flap/portal-events.js +0 -17
  246. package/dist/abis/flap/portal.d.ts +0 -6
  247. package/dist/abis/flap/portal.js +0 -37
  248. package/dist/abis/flap/vault.d.ts +0 -171
  249. package/dist/abis/flap/vault.js +0 -91
  250. package/dist/abis/index.d.ts +0 -8
  251. package/dist/abis/index.js +0 -11
  252. package/dist/bundle-core/__tests__/config-helpers.test.d.ts +0 -1
  253. package/dist/bundle-core/__tests__/config-helpers.test.js +0 -28
  254. package/dist/bundle-core/__tests__/facade-parity.test.d.ts +0 -1
  255. package/dist/bundle-core/__tests__/facade-parity.test.js +0 -33
  256. package/dist/bundle-core/__tests__/sign-context-helpers.test.d.ts +0 -1
  257. package/dist/bundle-core/__tests__/sign-context-helpers.test.js +0 -60
  258. package/dist/bundle-core/__tests__/sign-fixture.test.d.ts +0 -1
  259. package/dist/bundle-core/__tests__/sign-fixture.test.js +0 -220
  260. package/dist/bundle-core/__tests__/sign-fixtures.d.ts +0 -10
  261. package/dist/bundle-core/__tests__/sign-fixtures.js +0 -16
  262. package/dist/bundle-core/config-helpers.d.ts +0 -36
  263. package/dist/bundle-core/config-helpers.js +0 -57
  264. package/dist/bundle-core/errors.d.ts +0 -50
  265. package/dist/bundle-core/errors.js +0 -34
  266. package/dist/bundle-core/four-meme/approve-tokenmanager.d.ts +0 -7
  267. package/dist/bundle-core/four-meme/approve-tokenmanager.js +0 -99
  268. package/dist/bundle-core/four-meme/core-helpers.d.ts +0 -8
  269. package/dist/bundle-core/four-meme/core-helpers.js +0 -40
  270. package/dist/bundle-core/four-meme/core.d.ts +0 -4
  271. package/dist/bundle-core/four-meme/core.js +0 -515
  272. package/dist/bundle-core/four-meme/pancake-proxy.d.ts +0 -28
  273. package/dist/bundle-core/four-meme/pancake-proxy.js +0 -679
  274. package/dist/bundle-core/four-meme/private.d.ts +0 -27
  275. package/dist/bundle-core/four-meme/private.js +0 -465
  276. package/dist/bundle-core/four-meme/sign-context-helpers.d.ts +0 -2
  277. package/dist/bundle-core/four-meme/sign-context-helpers.js +0 -2
  278. package/dist/bundle-core/four-meme/swap-buy-first.d.ts +0 -8
  279. package/dist/bundle-core/four-meme/swap-buy-first.js +0 -493
  280. package/dist/bundle-core/four-meme/swap-hop-helpers.d.ts +0 -6
  281. package/dist/bundle-core/four-meme/swap-hop-helpers.js +0 -63
  282. package/dist/bundle-core/four-meme/swap-internal.d.ts +0 -3
  283. package/dist/bundle-core/four-meme/swap-internal.js +0 -18
  284. package/dist/bundle-core/four-meme/swap-sign-helpers.d.ts +0 -27
  285. package/dist/bundle-core/four-meme/swap-sign-helpers.js +0 -105
  286. package/dist/bundle-core/four-meme/swap.d.ts +0 -17
  287. package/dist/bundle-core/four-meme/swap.js +0 -505
  288. package/dist/bundle-core/four-meme/types/buy-first.d.ts +0 -50
  289. package/dist/bundle-core/four-meme/types/buy-first.js +0 -1
  290. package/dist/bundle-core/four-meme/types/core-flow.d.ts +0 -63
  291. package/dist/bundle-core/four-meme/types/core-flow.js +0 -1
  292. package/dist/bundle-core/four-meme/types/index.d.ts +0 -600
  293. package/dist/bundle-core/four-meme/types/index.js +0 -1
  294. package/dist/bundle-core/four-meme/types/swap-internal.d.ts +0 -19
  295. package/dist/bundle-core/four-meme/types/swap-internal.js +0 -1
  296. package/dist/bundle-core/four-meme/types.d.ts +0 -1
  297. package/dist/bundle-core/four-meme/types.js +0 -1
  298. package/dist/bundle-core/four-meme/utils-disperse.d.ts +0 -7
  299. package/dist/bundle-core/four-meme/utils-disperse.js +0 -396
  300. package/dist/bundle-core/four-meme/utils-pairwise.d.ts +0 -8
  301. package/dist/bundle-core/four-meme/utils-pairwise.js +0 -328
  302. package/dist/bundle-core/four-meme/utils-sweep.d.ts +0 -8
  303. package/dist/bundle-core/four-meme/utils-sweep.js +0 -744
  304. package/dist/bundle-core/index.d.ts +0 -8
  305. package/dist/bundle-core/index.js +0 -8
  306. package/dist/bundle-core/internal.d.ts +0 -21
  307. package/dist/bundle-core/internal.js +0 -182
  308. package/dist/bundle-core/sign-context-helpers.d.ts +0 -25
  309. package/dist/bundle-core/sign-context-helpers.js +0 -67
  310. package/dist/bundle-core/submit.d.ts +0 -293
  311. package/dist/bundle-core/submit.js +0 -727
  312. package/dist/bundle-core/types/index.d.ts +0 -8
  313. package/dist/bundle-core/types/index.js +0 -1
  314. package/dist/bundle-core/types.d.ts +0 -1
  315. package/dist/bundle-core/types.js +0 -1
  316. package/dist/chains/bsc/four/utils-disperse.d.ts +0 -1
  317. package/dist/chains/bsc/four/utils-disperse.js +0 -1
  318. package/dist/chains/bsc/four/utils-pairwise.d.ts +0 -1
  319. package/dist/chains/bsc/four/utils-pairwise.js +0 -1
  320. package/dist/chains/bsc/four/utils-sweep.d.ts +0 -1
  321. package/dist/chains/bsc/four/utils-sweep.js +0 -1
  322. package/dist/chains/bsc/iro.d.ts +0 -5
  323. package/dist/chains/bsc/iro.js +0 -4
  324. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.d.ts +0 -159
  325. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.js +0 -117
  326. package/dist/chains/bsc/pancake/bundle-swap-helpers.d.ts +0 -241
  327. package/dist/chains/bsc/pancake/bundle-swap-helpers.js +0 -565
  328. package/dist/chains/eni/flat-aliases.d.ts +0 -10
  329. package/dist/chains/eni/flat-aliases.js +0 -8
  330. package/dist/chains/eni/submit.d.ts +0 -43
  331. package/dist/chains/eni/submit.js +0 -286
  332. package/dist/chains/xlayer/eip7702/flat-aliases.d.ts +0 -13
  333. package/dist/chains/xlayer/eip7702/flat-aliases.js +0 -10
  334. package/dist/chains/xlayer/eip7702/multi-hop-transfer-helpers.d.ts +0 -79
  335. package/dist/chains/xlayer/eip7702/multi-hop-transfer-helpers.js +0 -1
  336. package/dist/chains/xlayer/eip7702/transfer-context-helpers.d.ts +0 -26
  337. package/dist/chains/xlayer/eip7702/transfer-context-helpers.js +0 -57
  338. package/dist/chains/xlayer/eip7702/volume-helpers.d.ts +0 -148
  339. package/dist/chains/xlayer/eip7702/volume-helpers.js +0 -48
  340. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.d.ts +0 -126
  341. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.js +0 -228
  342. package/dist/contracts/tm-bundle-helpers.d.ts +0 -88
  343. package/dist/contracts/tm-bundle-helpers.js +0 -72
  344. package/dist/contracts/tm-bundle-merkle/utils-disperse.d.ts +0 -1
  345. package/dist/contracts/tm-bundle-merkle/utils-disperse.js +0 -1
  346. package/dist/contracts/tm-bundle-merkle/utils-pairwise.d.ts +0 -1
  347. package/dist/contracts/tm-bundle-merkle/utils-pairwise.js +0 -1
  348. package/dist/contracts/tm-bundle-merkle/utils-sweep.d.ts +0 -1
  349. package/dist/contracts/tm-bundle-merkle/utils-sweep.js +0 -1
  350. package/dist/dex/direct-router-helpers.d.ts +0 -264
  351. package/dist/dex/direct-router-helpers.js +0 -539
  352. package/dist/dex/types.d.ts +0 -81
  353. package/dist/dex/types.js +0 -1
  354. package/dist/exports/root-bundle-and-tooling.d.ts +0 -27
  355. package/dist/exports/root-bundle-and-tooling.js +0 -30
  356. package/dist/exports/root-eni-and-bsc-iro.d.ts +0 -26
  357. package/dist/exports/root-eni-and-bsc-iro.js +0 -66
  358. package/dist/exports/root-foundations.d.ts +0 -35
  359. package/dist/exports/root-foundations.js +0 -70
  360. package/dist/exports/root-swap-dex-and-xlayer.d.ts +0 -30
  361. package/dist/exports/root-swap-dex-and-xlayer.js +0 -78
  362. package/dist/flap/index.d.ts +0 -10
  363. package/dist/flap/index.js +0 -8
  364. package/dist/flows/index.d.ts +0 -1
  365. package/dist/flows/index.js +0 -1
  366. package/dist/merkle/index.d.ts +0 -12
  367. package/dist/merkle/index.js +0 -11
  368. package/dist/shared/clients/index.d.ts +0 -8
  369. package/dist/shared/clients/index.js +0 -8
  370. package/dist/shared/constants/quote.d.ts +0 -30
  371. package/dist/shared/constants/quote.js +0 -37
  372. package/dist/shared/flap/portal-bundle-merkle/core-helpers.d.ts +0 -32
  373. package/dist/shared/flap/portal-bundle-merkle/core-helpers.js +0 -83
  374. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.d.ts +0 -125
  375. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.js +0 -113
  376. package/dist/shared/flap/portal-bundle-merkle/swap-helpers.d.ts +0 -149
  377. package/dist/shared/flap/portal-bundle-merkle/swap-helpers.js +0 -259
  378. package/dist/shared/foundation/dex/v3-path.d.ts +0 -6
  379. package/dist/shared/foundation/dex/v3-path.js +0 -35
  380. package/dist/shared/foundation/gas/bundle-gas.d.ts +0 -39
  381. package/dist/shared/foundation/gas/bundle-gas.js +0 -93
  382. package/dist/shared/foundation/gas/profit-hop.d.ts +0 -20
  383. package/dist/shared/foundation/gas/profit-hop.js +0 -72
  384. package/dist/shared/foundation/index.d.ts +0 -13
  385. package/dist/shared/foundation/index.js +0 -12
  386. package/dist/shared/foundation/nonce/nonce-manager.d.ts +0 -17
  387. package/dist/shared/foundation/nonce/nonce-manager.js +0 -180
  388. package/dist/shared/foundation/normalize-unknown.d.ts +0 -9
  389. package/dist/shared/foundation/normalize-unknown.js +0 -29
  390. package/dist/shared/foundation/sdk-logger.d.ts +0 -13
  391. package/dist/shared/foundation/sdk-logger.js +0 -12
  392. package/dist/shared/foundation/tx/build-request.d.ts +0 -17
  393. package/dist/shared/foundation/tx/build-request.js +0 -25
  394. package/dist/shared/foundation/tx/sign-batch.d.ts +0 -5
  395. package/dist/shared/foundation/tx/sign-batch.js +0 -26
  396. package/dist/shared/foundation/tx/wallet-sign-patch.d.ts +0 -1
  397. package/dist/shared/foundation/tx/wallet-sign-patch.js +0 -18
  398. package/dist/shared/foundation/types/airdrop-sweep.d.ts +0 -79
  399. package/dist/shared/foundation/types/airdrop-sweep.js +0 -1
  400. package/dist/shared/foundation/types/erc20.d.ts +0 -65
  401. package/dist/shared/foundation/types/erc20.js +0 -1
  402. package/dist/shared/foundation/types/holders-maker.d.ts +0 -64
  403. package/dist/shared/foundation/types/holders-maker.js +0 -1
  404. package/dist/shared/foundation/types/index.d.ts +0 -7
  405. package/dist/shared/foundation/types/index.js +0 -1
  406. package/dist/shared/foundation/types/lp-inspect.d.ts +0 -102
  407. package/dist/shared/foundation/types/lp-inspect.js +0 -1
  408. package/dist/shared/foundation/types/multicall.d.ts +0 -5
  409. package/dist/shared/foundation/types/multicall.js +0 -1
  410. package/dist/shared/foundation/types/private-sale.d.ts +0 -35
  411. package/dist/shared/foundation/types/private-sale.js +0 -1
  412. package/dist/shared/foundation/types/quote-helpers.d.ts +0 -17
  413. package/dist/shared/foundation/types/quote-helpers.js +0 -1
  414. package/dist/types/errors.d.ts +0 -27
  415. package/dist/types/errors.js +0 -34
  416. package/dist/utils/holders-maker/addresses.d.ts +0 -12
  417. package/dist/utils/holders-maker/addresses.js +0 -15
  418. package/dist/utils/holders-maker/buy-tx.d.ts +0 -44
  419. package/dist/utils/holders-maker/buy-tx.js +0 -278
  420. package/dist/utils/holders-maker/constants.d.ts +0 -6
  421. package/dist/utils/holders-maker/constants.js +0 -7
  422. package/dist/utils/holders-maker/disperse.d.ts +0 -18
  423. package/dist/utils/holders-maker/disperse.js +0 -90
  424. package/dist/utils/holders-maker/routing.d.ts +0 -4
  425. package/dist/utils/holders-maker/routing.js +0 -45
  426. package/dist/utils/holders-maker/transfer-tx.d.ts +0 -4
  427. package/dist/utils/holders-maker/transfer-tx.js +0 -67
  428. package/dist/utils/holders-maker-helpers.d.ts +0 -9
  429. package/dist/utils/holders-maker-helpers.js +0 -9
  430. package/dist/utils/hop-chains.d.ts +0 -35
  431. package/dist/utils/hop-chains.js +0 -215
  432. package/dist/utils/lp-inspect-helpers.d.ts +0 -9
  433. package/dist/utils/lp-inspect-helpers.js +0 -109
  434. package/dist/utils/types/airdrop-sweep.d.ts +0 -1
  435. package/dist/utils/types/airdrop-sweep.js +0 -1
  436. package/dist/utils/types/contract-factory.d.ts +0 -1
  437. package/dist/utils/types/contract-factory.js +0 -1
  438. package/dist/utils/types/erc20.d.ts +0 -1
  439. package/dist/utils/types/erc20.js +0 -1
  440. package/dist/utils/types/errors.d.ts +0 -1
  441. package/dist/utils/types/errors.js +0 -1
  442. package/dist/utils/types/holders-maker.d.ts +0 -1
  443. package/dist/utils/types/holders-maker.js +0 -1
  444. package/dist/utils/types/hop-chains.d.ts +0 -8
  445. package/dist/utils/types/hop-chains.js +0 -1
  446. package/dist/utils/types/index.d.ts +0 -13
  447. package/dist/utils/types/index.js +0 -1
  448. package/dist/utils/types/lp-inspect.d.ts +0 -1
  449. package/dist/utils/types/lp-inspect.js +0 -1
  450. package/dist/utils/types/mpc-exclusive.d.ts +0 -5
  451. package/dist/utils/types/mpc-exclusive.js +0 -1
  452. package/dist/utils/types/private-sale.d.ts +0 -1
  453. package/dist/utils/types/private-sale.js +0 -1
  454. package/dist/utils/types/quote-helpers.d.ts +0 -1
  455. package/dist/utils/types/quote-helpers.js +0 -1
  456. package/dist/utils/types/stealth-transfer.d.ts +0 -44
  457. package/dist/utils/types/stealth-transfer.js +0 -1
  458. package/dist/utils/types/wallet.d.ts +0 -25
  459. package/dist/utils/types/wallet.js +0 -1
  460. package/dist/vanity/index.d.ts +0 -5
  461. package/dist/vanity/index.js +0 -5
  462. package/src/abis/contracts/TaxToken.json +0 -969
  463. package/src/abis/contracts/TokenManager.json +0 -836
  464. package/src/abis/contracts/TokenManager2.json +0 -136
  465. package/src/abis/contracts/TokenManagerHelper3.json +0 -993
  466. /package/dist/{abis/contracts → shared/abis}/TokenManager.json +0 -0
  467. /package/dist/{abis/contracts → shared/abis}/TokenManagerHelper3.json +0 -0
@@ -1,15 +1,592 @@
1
+ // ==================== 多跳转账常量(使用统一常量) ====================
2
+ import { GAS_LIMITS, CHAINS } from '../../../shared/constants/index.js';
3
+ const NATIVE_TRANSFER_GAS_LIMIT = GAS_LIMITS.NATIVE_TRANSFER;
4
+ const ERC20_TRANSFER_GAS_LIMIT_HOP = GAS_LIMITS.ERC20_TRANSFER;
5
+ const BRIBE_GAS_LIMIT = GAS_LIMITS.BRIBE;
1
6
  /**
2
- * bundle-swap - 主函数
7
+ * 生成分发多跳路径
8
+ */
9
+ function generateDisperseHopPaths(targetAddresses, hopCount, provider) {
10
+ if (hopCount <= 0) {
11
+ return targetAddresses.map(addr => ({
12
+ targetAddress: addr,
13
+ hopWallets: [],
14
+ hopWalletsInfo: []
15
+ }));
16
+ }
17
+ return targetAddresses.map(targetAddress => {
18
+ const hopWalletsInfo = generateWallets(hopCount);
19
+ const hopWallets = hopWalletsInfo.map(w => new Wallet(w.privateKey, provider));
20
+ return { targetAddress, hopWallets, hopWalletsInfo };
21
+ });
22
+ }
23
+ /**
24
+ * 构建原生代币多跳转账链
25
+ */
26
+ async function buildNativeHopChain(payer, path, finalAmount, gasPrice, chainId, txType, payerNonce) {
27
+ const signedTxs = [];
28
+ const hopCount = path.hopWallets.length;
29
+ if (hopCount === 0) {
30
+ const tx = {
31
+ to: path.targetAddress,
32
+ value: finalAmount,
33
+ nonce: payerNonce,
34
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
35
+ chainId,
36
+ type: txType
37
+ };
38
+ if (txType === 2) {
39
+ tx.maxFeePerGas = gasPrice;
40
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
41
+ }
42
+ else {
43
+ tx.gasPrice = gasPrice;
44
+ }
45
+ signedTxs.push(await payer.signTransaction(tx));
46
+ return signedTxs;
47
+ }
48
+ const hopGasCost = NATIVE_TRANSFER_GAS_LIMIT * gasPrice;
49
+ // 计算每跳需要的金额
50
+ const amountsPerHop = [];
51
+ for (let i = 0; i < hopCount; i++) {
52
+ const remainingHops = hopCount - i;
53
+ amountsPerHop.push(finalAmount + hopGasCost * BigInt(remainingHops));
54
+ }
55
+ // payer → hop1
56
+ const firstTx = {
57
+ to: path.hopWallets[0].address,
58
+ value: amountsPerHop[0],
59
+ nonce: payerNonce,
60
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
61
+ chainId,
62
+ type: txType
63
+ };
64
+ if (txType === 2) {
65
+ firstTx.maxFeePerGas = gasPrice;
66
+ firstTx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
67
+ }
68
+ else {
69
+ firstTx.gasPrice = gasPrice;
70
+ }
71
+ signedTxs.push(await payer.signTransaction(firstTx));
72
+ // hop1 → hop2 → ... → target
73
+ for (let i = 0; i < hopCount; i++) {
74
+ const fromWallet = path.hopWallets[i];
75
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
76
+ const amount = i === hopCount - 1 ? finalAmount : amountsPerHop[i + 1];
77
+ const tx = {
78
+ to: toAddress,
79
+ value: amount,
80
+ nonce: 0,
81
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
82
+ chainId,
83
+ type: txType
84
+ };
85
+ if (txType === 2) {
86
+ tx.maxFeePerGas = gasPrice;
87
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
88
+ }
89
+ else {
90
+ tx.gasPrice = gasPrice;
91
+ }
92
+ signedTxs.push(await fromWallet.signTransaction(tx));
93
+ }
94
+ return signedTxs;
95
+ }
96
+ /**
97
+ * 构建 ERC20 多跳转账链(需要配合 BNB 多跳使用)
98
+ */
99
+ async function buildERC20HopChain(payer, path, erc20Address, erc20Amount, gasPrice, chainId, txType, payerNonce) {
100
+ const signedTxs = [];
101
+ const hopCount = path.hopWallets.length;
102
+ const erc20Interface = new ethers.Interface(ERC20_ABI);
103
+ if (hopCount === 0) {
104
+ const data = erc20Interface.encodeFunctionData('transfer', [path.targetAddress, erc20Amount]);
105
+ const tx = {
106
+ to: erc20Address,
107
+ data,
108
+ value: 0n,
109
+ nonce: payerNonce,
110
+ gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
111
+ chainId,
112
+ type: txType
113
+ };
114
+ if (txType === 2) {
115
+ tx.maxFeePerGas = gasPrice;
116
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
117
+ }
118
+ else {
119
+ tx.gasPrice = gasPrice;
120
+ }
121
+ signedTxs.push(await payer.signTransaction(tx));
122
+ return signedTxs;
123
+ }
124
+ // payer → hop1
125
+ const firstData = erc20Interface.encodeFunctionData('transfer', [path.hopWallets[0].address, erc20Amount]);
126
+ const firstTx = {
127
+ to: erc20Address,
128
+ data: firstData,
129
+ value: 0n,
130
+ nonce: payerNonce,
131
+ gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
132
+ chainId,
133
+ type: txType
134
+ };
135
+ if (txType === 2) {
136
+ firstTx.maxFeePerGas = gasPrice;
137
+ firstTx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
138
+ }
139
+ else {
140
+ firstTx.gasPrice = gasPrice;
141
+ }
142
+ signedTxs.push(await payer.signTransaction(firstTx));
143
+ // hop1 → hop2 → ... → target (nonce=1,nonce=0 用于 BNB 转发)
144
+ for (let i = 0; i < hopCount; i++) {
145
+ const fromWallet = path.hopWallets[i];
146
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
147
+ const data = erc20Interface.encodeFunctionData('transfer', [toAddress, erc20Amount]);
148
+ const tx = {
149
+ to: erc20Address,
150
+ data,
151
+ value: 0n,
152
+ nonce: 1, // nonce=0 已用于 BNB 转发
153
+ gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
154
+ chainId,
155
+ type: txType
156
+ };
157
+ if (txType === 2) {
158
+ tx.maxFeePerGas = gasPrice;
159
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
160
+ }
161
+ else {
162
+ tx.gasPrice = gasPrice;
163
+ }
164
+ signedTxs.push(await fromWallet.signTransaction(tx));
165
+ }
166
+ return signedTxs;
167
+ }
168
+ /**
169
+ * 构建 BNB 多跳转账链(为 ERC20 中间钱包预留 gas)
170
+ */
171
+ async function buildBNBHopChainForERC20(payer, path, finalGasAmount, gasPrice, chainId, txType, payerNonce) {
172
+ const signedTxs = [];
173
+ const hopCount = path.hopWallets.length;
174
+ if (hopCount === 0) {
175
+ // 无多跳时不需要转 gas
176
+ return signedTxs;
177
+ }
178
+ const hopGasCost = NATIVE_TRANSFER_GAS_LIMIT * gasPrice;
179
+ const erc20GasCost = ERC20_TRANSFER_GAS_LIMIT_HOP * gasPrice;
180
+ // 每个中间钱包需要: BNB 转发 gas + ERC20 转发 gas
181
+ const gasPerHop = hopGasCost + erc20GasCost * 2n; // 2倍安全系数
182
+ // 计算每跳需要的金额
183
+ const amountsPerHop = [];
184
+ for (let i = 0; i < hopCount; i++) {
185
+ const remainingHops = hopCount - i;
186
+ amountsPerHop.push(finalGasAmount + gasPerHop * BigInt(remainingHops));
187
+ }
188
+ // payer → hop1
189
+ const firstTx = {
190
+ to: path.hopWallets[0].address,
191
+ value: amountsPerHop[0],
192
+ nonce: payerNonce,
193
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
194
+ chainId,
195
+ type: txType
196
+ };
197
+ if (txType === 2) {
198
+ firstTx.maxFeePerGas = gasPrice;
199
+ firstTx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
200
+ }
201
+ else {
202
+ firstTx.gasPrice = gasPrice;
203
+ }
204
+ signedTxs.push(await payer.signTransaction(firstTx));
205
+ // hop1 → hop2 → ... → target (nonce=0)
206
+ for (let i = 0; i < hopCount; i++) {
207
+ const fromWallet = path.hopWallets[i];
208
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
209
+ const amount = i === hopCount - 1 ? finalGasAmount : amountsPerHop[i + 1];
210
+ const tx = {
211
+ to: toAddress,
212
+ value: amount,
213
+ nonce: 0,
214
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
215
+ chainId,
216
+ type: txType
217
+ };
218
+ if (txType === 2) {
219
+ tx.maxFeePerGas = gasPrice;
220
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
221
+ }
222
+ else {
223
+ tx.gasPrice = gasPrice;
224
+ }
225
+ signedTxs.push(await fromWallet.signTransaction(tx));
226
+ }
227
+ return signedTxs;
228
+ }
229
+ // ==================== 工具函数 ====================
230
+ function createPancakeContext(config) {
231
+ const chainId = config.chainId ?? 56;
232
+ const provider = new ethers.JsonRpcProvider(config.rpcUrl, {
233
+ chainId,
234
+ name: 'BSC'
235
+ });
236
+ return { chainId, provider };
237
+ }
238
+ async function quoteSellOutput({ routeParams, sellAmountWei, provider, v2RouterAddress }) {
239
+ console.log(`[quoteSellOutput] 开始报价, routeType=${routeParams.routeType}, sellAmount=${sellAmountWei} wei`);
240
+ // ==================== V2 报价 ====================
241
+ if (routeParams.routeType === 'v2') {
242
+ const { v2Path } = routeParams;
243
+ const tokenIn = v2Path[0];
244
+ const tokenOut = v2Path[v2Path.length - 1];
245
+ console.log(`[quoteSellOutput] V2 路径: ${v2Path.join(' → ')}`);
246
+ const result = await quoteV2(provider, tokenIn, tokenOut, sellAmountWei, 'BSC', v2RouterAddress);
247
+ if (result.amountOut > 0n) {
248
+ console.log(`[quoteSellOutput] V2 报价成功: ${ethers.formatEther(result.amountOut)} BNB`);
249
+ return { estimatedBNBOut: result.amountOut };
250
+ }
251
+ throw new Error('V2 报价失败: 所有路径均无效');
252
+ }
253
+ // ==================== V3 单跳报价 ====================
254
+ if (routeParams.routeType === 'v3-single') {
255
+ const params = routeParams;
256
+ console.log(`[quoteSellOutput] V3 单跳: ${params.v3TokenIn} → ${params.v3TokenOut}, fee=${params.v3Fee}`);
257
+ // ✅ 只用 V3 报价,不 fallback 到 V2
258
+ const result = await quoteV3(provider, params.v3TokenIn, params.v3TokenOut, sellAmountWei, 'BSC', params.v3Fee);
259
+ if (result.amountOut > 0n) {
260
+ console.log(`[quoteSellOutput] V3 报价成功 (fee=${result.fee}): ${ethers.formatEther(result.amountOut)} BNB`);
261
+ return { estimatedBNBOut: result.amountOut };
262
+ }
263
+ // ❌ V3 报价失败时不再 fallback 到 V2,因为价格可能差异很大
264
+ throw new Error(`V3 单跳报价失败: tokenIn=${params.v3TokenIn}, tokenOut=${params.v3TokenOut}, fee=${params.v3Fee}`);
265
+ }
266
+ // ==================== V3 多跳报价 ====================
267
+ if (routeParams.routeType === 'v3-multi') {
268
+ const params = routeParams;
269
+ console.log(`[quoteSellOutput] V3 多跳: LPs=${params.v3LpAddresses?.join(', ')}`);
270
+ // ✅ V3 多跳:只用 V3 报价,不 fallback 到 V2
271
+ if (params.v3LpAddresses && params.v3LpAddresses.length > 0) {
272
+ const tokenIn = params.v3ExactTokenIn;
273
+ const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
274
+ const result = await quoteV3(provider, tokenIn, WBNB, sellAmountWei, 'BSC');
275
+ if (result.amountOut > 0n) {
276
+ console.log(`[quoteSellOutput] V3 多跳报价成功: ${ethers.formatEther(result.amountOut)} BNB`);
277
+ return { estimatedBNBOut: result.amountOut };
278
+ }
279
+ }
280
+ // ❌ V3 多跳报价失败时不再 fallback 到 V2,因为价格可能差异很大
281
+ throw new Error(`V3 多跳报价失败: LPs=${params.v3LpAddresses?.join(', ')}, tokenIn=${params.v3ExactTokenIn}`);
282
+ }
283
+ throw new Error(`不支持的路由类型: ${routeParams.routeType}`);
284
+ }
285
+ async function buildSwapTransactions({ routeParams, sellAmountWei, buyAmountBNB, buyer, seller, tokenAddress, useNativeToken = true, v2RouterAddress }) {
286
+ const deadline = getDeadline();
287
+ const buyValue = useNativeToken ? buyAmountBNB + FLAT_FEE : 0n;
288
+ if (routeParams.routeType === 'v2') {
289
+ const { v2Path } = routeParams;
290
+ const reversePath = [...v2Path].reverse();
291
+ const routerAddr = v2RouterAddress || PANCAKE_V2_ROUTER_ADDRESS;
292
+ const v2RouterSeller = new Contract(routerAddr, PANCAKE_V2_ROUTER_ABI, seller);
293
+ const v2RouterBuyer = new Contract(routerAddr, PANCAKE_V2_ROUTER_ABI, buyer);
294
+ let sellUnsigned;
295
+ let buyUnsigned;
296
+ if (useNativeToken) {
297
+ // ✅ 原生代币模式(BNB)
298
+ // 卖出:Token → WBNB → BNB
299
+ sellUnsigned = await v2RouterSeller.swapExactTokensForETHSupportingFeeOnTransferTokens.populateTransaction(sellAmountWei, 0n, v2Path, seller.address, deadline);
300
+ // 买入:BNB → WBNB → Token
301
+ buyUnsigned = await v2RouterBuyer.swapExactETHForTokensSupportingFeeOnTransferTokens.populateTransaction(0n, reversePath, buyer.address, deadline, { value: buyValue });
302
+ }
303
+ else {
304
+ // ✅ ERC20 模式(如 USDT)
305
+ // 卖出:Token → USDT
306
+ sellUnsigned = await v2RouterSeller.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(sellAmountWei, 0n, v2Path, seller.address, deadline);
307
+ // 买入:USDT → Token
308
+ buyUnsigned = await v2RouterBuyer.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(buyAmountBNB, // USDT 数量
309
+ 0n, reversePath, buyer.address, deadline);
310
+ }
311
+ return { sellUnsigned, buyUnsigned };
312
+ }
313
+ if (routeParams.routeType === 'v3-single') {
314
+ const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
315
+ const v3RouterIface = new ethers.Interface(PANCAKE_V3_ROUTER_ABI);
316
+ const v3RouterSeller = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, seller);
317
+ const v3RouterBuyer = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, buyer);
318
+ // 卖出:Token → WBNB,需要 unwrapWETH9
319
+ const sellSwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
320
+ tokenIn: v3TokenIn,
321
+ tokenOut: v3TokenOut,
322
+ fee: v3Fee,
323
+ recipient: PANCAKE_V3_ROUTER_ADDRESS, // 先发给 Router
324
+ amountIn: sellAmountWei,
325
+ amountOutMinimum: 0n,
326
+ sqrtPriceLimitX96: 0n
327
+ }]);
328
+ const sellUnwrapData = v3RouterIface.encodeFunctionData('unwrapWETH9', [0n, seller.address]);
329
+ const sellUnsigned = await v3RouterSeller.multicall.populateTransaction(deadline, [sellSwapData, sellUnwrapData]);
330
+ // 买入:WBNB → Token
331
+ const buySwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
332
+ tokenIn: v3TokenOut,
333
+ tokenOut: v3TokenIn,
334
+ fee: v3Fee,
335
+ recipient: buyer.address,
336
+ amountIn: buyAmountBNB,
337
+ amountOutMinimum: 0n,
338
+ sqrtPriceLimitX96: 0n
339
+ }]);
340
+ const buyUnsigned = await v3RouterBuyer.multicall.populateTransaction(deadline, [buySwapData], { value: buyValue });
341
+ return { sellUnsigned, buyUnsigned };
342
+ }
343
+ // V3 多跳暂不支持官方合约
344
+ throw new Error('V3 多跳路由暂不支持官方合约,请使用 V2 路由或 V3 单跳');
345
+ }
346
+ async function calculateBuyerBudget({ buyer, quotedBNBOut, reserveGasBNB, useNativeToken = true, quoteToken, quoteTokenDecimals = 18, provider }) {
347
+ const reserveGas = ethers.parseEther((reserveGasBNB ?? 0.0005).toString());
348
+ // ✅ 已移除滑点保护:直接使用报价金额
349
+ const buyAmountBNB = quotedBNBOut;
350
+ // ✅ 根据是否使用原生代币获取不同的余额
351
+ let buyerBalance;
352
+ if (useNativeToken) {
353
+ buyerBalance = await buyer.provider.getBalance(buyer.address);
354
+ const requiredBalance = buyAmountBNB + FLAT_FEE + reserveGas;
355
+ if (buyerBalance < requiredBalance) {
356
+ throw new Error(`买方余额不足: 需要 ${ethers.formatEther(requiredBalance)} BNB, 实际 ${ethers.formatEther(buyerBalance)} BNB`);
357
+ }
358
+ return { buyerBalance, reserveGas, requiredBalance, buyAmountBNB, useNativeToken };
359
+ }
360
+ else {
361
+ // ERC20 代币余额
362
+ const erc20 = new Contract(quoteToken, ERC20_BALANCE_OF_ABI, provider || buyer.provider);
363
+ buyerBalance = await erc20.balanceOf(buyer.address);
364
+ const requiredBalance = buyAmountBNB + FLAT_FEE; // ERC20 不需要预留 Gas 在代币余额中
365
+ if (buyerBalance < requiredBalance) {
366
+ throw new Error(`买方代币余额不足: 需要 ${ethers.formatUnits(requiredBalance, quoteTokenDecimals)}, 实际 ${ethers.formatUnits(buyerBalance, quoteTokenDecimals)}`);
367
+ }
368
+ // ✅ ERC20 购买时,还需要检查买方是否有足够 BNB 支付 Gas
369
+ const buyerBnbBalance = await buyer.provider.getBalance(buyer.address);
370
+ if (buyerBnbBalance < reserveGas) {
371
+ throw new Error(`买方 BNB 余额不足 (用于支付 Gas): 需要 ${ethers.formatEther(reserveGas)} BNB, 实际 ${ethers.formatEther(buyerBnbBalance)} BNB`);
372
+ }
373
+ return { buyerBalance, reserveGas, requiredBalance, buyAmountBNB, useNativeToken };
374
+ }
375
+ }
376
+ /**
377
+ * ✅ 从前端传入的 startNonces 构建 NoncePlan(用于性能优化)
378
+ * 顺序:[sellerBaseNonce, buyerNonce]
379
+ */
380
+ function buildNoncePlanFromNonces(startNonces, sameAddress, approvalExists, profitNeeded, needBribeTx) {
381
+ if (sameAddress) {
382
+ let idx = 0;
383
+ const bribeNonce = needBribeTx ? startNonces[0] + idx++ : undefined;
384
+ if (approvalExists)
385
+ idx++;
386
+ const sellerNonce = startNonces[0] + idx++;
387
+ const buyerNonce = startNonces[0] + idx++;
388
+ const profitNonce = profitNeeded ? startNonces[0] + idx : undefined;
389
+ return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
390
+ }
391
+ let sellerIdx = 0;
392
+ const bribeNonce = needBribeTx ? startNonces[0] + sellerIdx++ : undefined;
393
+ if (approvalExists)
394
+ sellerIdx++;
395
+ const sellerNonce = startNonces[0] + sellerIdx++;
396
+ const profitNonce = profitNeeded ? startNonces[0] + sellerIdx : undefined;
397
+ const buyerNonce = startNonces[1];
398
+ return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
399
+ }
400
+ /**
401
+ * ✅ 规划 nonce
402
+ * 交易顺序:贿赂 → 授权 → 卖出 → 买入 → 利润
403
+ * 贿赂和利润由卖方发送
404
+ */
405
+ async function planNonces({ seller, buyer, sameAddress, approvalExists, profitNeeded, needBribeTx, nonceManager }) {
406
+ if (sameAddress) {
407
+ // 同一地址:贿赂(可选) + 授权(可选) + 卖出 + 买入 + 利润(可选)
408
+ const txCount = countTruthy([needBribeTx, approvalExists, true, true, profitNeeded]);
409
+ const nonces = await nonceManager.getNextNonceBatch(buyer, txCount);
410
+ let idx = 0;
411
+ const bribeNonce = needBribeTx ? nonces[idx++] : undefined;
412
+ if (approvalExists)
413
+ idx++;
414
+ const sellerNonce = nonces[idx++];
415
+ const buyerNonce = nonces[idx++];
416
+ const profitNonce = profitNeeded ? nonces[idx] : undefined;
417
+ return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
418
+ }
419
+ if (needBribeTx || approvalExists || profitNeeded) {
420
+ // 卖方需要多个 nonce:贿赂(可选) + 授权(可选) + 卖出 + 利润(可选)
421
+ const sellerTxCount = countTruthy([needBribeTx, approvalExists, true, profitNeeded]);
422
+ // ✅ 并行获取 seller 和 buyer 的 nonce
423
+ const [sellerNonces, buyerNonce] = await Promise.all([
424
+ nonceManager.getNextNonceBatch(seller, sellerTxCount),
425
+ nonceManager.getNextNonce(buyer)
426
+ ]);
427
+ let idx = 0;
428
+ const bribeNonce = needBribeTx ? sellerNonces[idx++] : undefined;
429
+ if (approvalExists)
430
+ idx++;
431
+ const sellerNonce = sellerNonces[idx++];
432
+ const profitNonce = profitNeeded ? sellerNonces[idx] : undefined;
433
+ return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
434
+ }
435
+ // ✅ 并行获取 seller 和 buyer 的 nonce
436
+ const [sellerNonce, buyerNonce] = await Promise.all([
437
+ nonceManager.getNextNonce(seller),
438
+ nonceManager.getNextNonce(buyer)
439
+ ]);
440
+ return { sellerNonce, buyerNonce };
441
+ }
442
+ /**
443
+ * 根据 userType 计算利润率
444
+ */
445
+ function getProfitRateBps(userType) {
446
+ if (userType === 'v0') {
447
+ return PROFIT_CONFIG.RATE_BPS_V0; // 0.06%
448
+ }
449
+ else if (userType === 'v1') {
450
+ return PROFIT_CONFIG.RATE_BPS_V1; // 0.05%
451
+ }
452
+ return PROFIT_CONFIG.RATE_BPS_V0; // 默认 0.06%
453
+ }
454
+ function calculateProfitAmount(estimatedBNBOut, userType) {
455
+ if (estimatedBNBOut <= 0n) {
456
+ return 0n;
457
+ }
458
+ const rateBps = getProfitRateBps(userType);
459
+ return (estimatedBNBOut * BigInt(rateBps)) / 10000n;
460
+ }
461
+ /**
462
+ * ✅ 获取 ERC20 代币 → 原生代币(BNB)的报价
463
+ * 用于将 ERC20 利润转换为 BNB
464
+ * 使用共享的报价函数
465
+ */
466
+ async function getERC20ToNativeQuote(provider, tokenAddress, tokenAmount, version = 'v2', fee) {
467
+ if (tokenAmount <= 0n)
468
+ return 0n;
469
+ const tokenLower = tokenAddress.toLowerCase();
470
+ const wbnbLower = WBNB_ADDRESS.toLowerCase();
471
+ // 如果代币本身就是 WBNB,直接返回
472
+ if (tokenLower === wbnbLower) {
473
+ return tokenAmount;
474
+ }
475
+ // 使用共享的报价函数
476
+ if (version === 'v3') {
477
+ const result = await quoteV3(provider, tokenAddress, WBNB_ADDRESS, tokenAmount, 'BSC', fee);
478
+ if (result.amountOut > 0n) {
479
+ console.log(`[getERC20ToNativeQuote] V3 报价成功: ${ethers.formatEther(result.amountOut)} BNB`);
480
+ return result.amountOut;
481
+ }
482
+ console.warn(`[getERC20ToNativeQuote] V3 报价失败`);
483
+ return 0n;
484
+ }
485
+ // V2 报价
486
+ const result = await quoteV2(provider, tokenAddress, WBNB_ADDRESS, tokenAmount, 'BSC');
487
+ if (result.amountOut > 0n) {
488
+ console.log(`[getERC20ToNativeQuote] V2 报价成功: ${ethers.formatEther(result.amountOut)} BNB`);
489
+ return result.amountOut;
490
+ }
491
+ console.warn(`[getERC20ToNativeQuote] V2 报价失败`);
492
+ return 0n;
493
+ }
494
+ async function validateFinalBalances({ sameAddress, buyerBalance, buyAmountBNB, reserveGas, gasLimit, gasPrice, useNativeToken = true, quoteTokenDecimals = 18, provider, buyerAddress }) {
495
+ const gasCost = gasLimit * gasPrice;
496
+ if (sameAddress) {
497
+ // 同一地址:需要足够的余额支付两笔交易
498
+ if (useNativeToken) {
499
+ const requiredCombined = buyAmountBNB + FLAT_FEE * 2n + gasCost * 2n;
500
+ if (buyerBalance < requiredCombined) {
501
+ throw new Error(`账户余额不足:\n - 需要: ${ethers.formatEther(requiredCombined)} BNB(含两笔Gas与两笔手续费)\n - 实际: ${ethers.formatEther(buyerBalance)} BNB`);
502
+ }
503
+ }
504
+ else {
505
+ // ERC20:检查代币余额 + BNB Gas 余额
506
+ const requiredToken = buyAmountBNB + FLAT_FEE * 2n;
507
+ if (buyerBalance < requiredToken) {
508
+ throw new Error(`账户代币余额不足:\n - 需要: ${ethers.formatUnits(requiredToken, quoteTokenDecimals)}\n - 实际: ${ethers.formatUnits(buyerBalance, quoteTokenDecimals)}`);
509
+ }
510
+ // 检查 BNB Gas
511
+ if (provider && buyerAddress) {
512
+ const bnbBalance = await provider.getBalance(buyerAddress);
513
+ const requiredGas = gasCost * 2n;
514
+ if (bnbBalance < requiredGas) {
515
+ throw new Error(`账户 BNB 余额不足 (用于支付 Gas):\n - 需要: ${ethers.formatEther(requiredGas)} BNB\n - 实际: ${ethers.formatEther(bnbBalance)} BNB`);
516
+ }
517
+ }
518
+ }
519
+ return;
520
+ }
521
+ // 不同地址
522
+ if (useNativeToken) {
523
+ const requiredBuyer = buyAmountBNB + FLAT_FEE + reserveGas;
524
+ if (buyerBalance < requiredBuyer) {
525
+ throw new Error(`买方余额不足:\n - 需要: ${ethers.formatEther(requiredBuyer)} BNB\n - 实际: ${ethers.formatEther(buyerBalance)} BNB`);
526
+ }
527
+ }
528
+ // ERC20 余额已在 calculateBuyerBudget 中检查过
529
+ }
530
+ function countTruthy(values) {
531
+ return values.filter(Boolean).length;
532
+ }
533
+ /**
534
+ * PancakeSwap V2/V3 通用捆绑换手(Merkle Bundle)
535
+ *
536
+ * 功能:钱包A卖出代币 → 钱包B买入相同数量 → 原子执行
537
+ * 适用于所有已迁移到外盘的代币(不区分Four/Flap)
3
538
  */
4
- import { GAS_LIMITS, CHAINS, getProfitRecipient } from '../../../shared/constants/index.js';
5
539
  import { ethers, Contract, Wallet } from 'ethers';
6
540
  import { calculateSellAmount } from '../../../utils/swap-helpers.js';
7
- import { NonceManager, getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT, } from '../../../utils/bundle-helpers.js';
8
- import { ADDRESSES, BLOCKRAZOR_BUILDER_EOA } from '../../../shared/constants/index.js';
9
- import { ERC20_ABI } from '../../../abis/common.js';
10
- import { BRIBE_GAS_LIMIT, ERC20_BALANCE_OF_ABI, FLAT_FEE, NATIVE_TRANSFER_GAS_LIMIT, PANCAKE_V2_ROUTER_ABI, PANCAKE_V2_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, PANCAKE_V3_ROUTER_ADDRESS, ZERO_ADDRESS, buildBNBHopChainForERC20, buildERC20HopChain, buildNativeHopChain, buildNoncePlanFromNonces, buildSwapTransactions, calculateBuyerBudget, calculateProfitAmount, createPancakeContext, generateDisperseHopPaths, getERC20ToNativeQuote, getGasLimit, getGasPrice, planNonces, quoteSellOutput, validateFinalBalances, } from './bundle-swap-helpers.js';
541
+ import { NonceManager, getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../../utils/bundle-helpers.js';
542
+ import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA } from '../../../utils/constants.js';
543
+ import { quoteV2, quoteV3 } from '../../../utils/quote-helpers.js';
544
+ import { V2_ROUTER_ABI, V3_ROUTER02_ABI, ERC20_BALANCE_ABI, ERC20_ABI } from '../../../shared/abis/common.js';
545
+ import { generateWallets } from '../../../utils/wallet.js';
546
+ /**
547
+ * 获取 Gas Limit
548
+ */
549
+ function getGasLimit(config, defaultGas = 800000) {
550
+ if (config.gasLimit !== undefined) {
551
+ return typeof config.gasLimit === 'bigint' ? config.gasLimit : BigInt(config.gasLimit);
552
+ }
553
+ const multiplier = config.gasLimitMultiplier ?? 1.0;
554
+ const calculatedGas = Math.ceil(defaultGas * multiplier);
555
+ return BigInt(calculatedGas);
556
+ }
557
+ async function getGasPrice(provider, config) {
558
+ const feeData = await provider.getFeeData();
559
+ let gasPrice = feeData.gasPrice || ethers.parseUnits('3', 'gwei');
560
+ if (config.minGasPriceGwei) {
561
+ const minGas = ethers.parseUnits(config.minGasPriceGwei.toString(), 'gwei');
562
+ if (gasPrice < minGas)
563
+ gasPrice = minGas;
564
+ }
565
+ if (config.maxGasPriceGwei) {
566
+ const maxGas = ethers.parseUnits(config.maxGasPriceGwei.toString(), 'gwei');
567
+ if (gasPrice > maxGas)
568
+ gasPrice = maxGas;
569
+ }
570
+ return gasPrice;
571
+ }
572
+ // ✅ ABI 别名(从公共模块导入)
573
+ const PANCAKE_V2_ROUTER_ABI = V2_ROUTER_ABI;
574
+ const PANCAKE_V3_ROUTER_ABI = V3_ROUTER02_ABI;
575
+ const ERC20_BALANCE_OF_ABI = ERC20_BALANCE_ABI;
576
+ // ✅ 使用官方 PancakeSwap Router 地址
577
+ const PANCAKE_V2_ROUTER_ADDRESS = ADDRESSES.BSC.PancakeV2Router;
578
+ const PANCAKE_V3_ROUTER_ADDRESS = ADDRESSES.BSC.PancakeV3Router;
579
+ // 常量
580
+ const FLAT_FEE = 0n;
581
+ const WBNB_ADDRESS = ADDRESSES.BSC.WBNB;
582
+ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
583
+ // ✅ ERC20_BALANCE_OF_ABI 已在文件开头定义
584
+ /**
585
+ * PancakeSwap捆绑换手(V2/V3通用)
586
+ * ✅ 支持 quoteToken:传入 USDT 等地址时,卖出得到该代币,买入使用该代币
587
+ */
11
588
  export async function pancakeBundleSwapMerkle(params) {
12
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces, // ✅ 可选:前端预获取的 nonces
589
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
13
590
  } = params;
14
591
  // ✅ 判断是否使用原生代币(BNB)或 ERC20 代币(如 USDT)
15
592
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
@@ -24,14 +601,14 @@ export async function pancakeBundleSwapMerkle(params) {
24
601
  // ✅ 并行获取 gasPrice 和卖出数量
25
602
  const [gasPrice, sellAmountResult] = await Promise.all([
26
603
  getGasPrice(context.provider, config),
27
- calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage),
604
+ calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage)
28
605
  ]);
29
606
  const { amount: sellAmountWei, decimals } = sellAmountResult;
30
607
  const quoteResult = await quoteSellOutput({
31
608
  routeParams,
32
609
  sellAmountWei,
33
610
  provider: context.provider,
34
- v2RouterAddress: config.v2RouterAddress,
611
+ v2RouterAddress: config.v2RouterAddress
35
612
  });
36
613
  const buyerBudget = await calculateBuyerBudget({
37
614
  buyer,
@@ -40,7 +617,7 @@ export async function pancakeBundleSwapMerkle(params) {
40
617
  useNativeToken,
41
618
  quoteToken,
42
619
  quoteTokenDecimals,
43
- provider: context.provider,
620
+ provider: context.provider
44
621
  });
45
622
  const swapUnsigned = await buildSwapTransactions({
46
623
  routeParams,
@@ -50,7 +627,7 @@ export async function pancakeBundleSwapMerkle(params) {
50
627
  seller,
51
628
  tokenAddress,
52
629
  useNativeToken,
53
- v2RouterAddress: config.v2RouterAddress,
630
+ v2RouterAddress: config.v2RouterAddress
54
631
  });
55
632
  // ✅ 修复:利润计算应基于 BNB 数量,不是 ERC20 数量
56
633
  // 如果输出是原生代币(BNB),直接使用报价结果
@@ -71,7 +648,9 @@ export async function pancakeBundleSwapMerkle(params) {
71
648
  // ERC20→BNB 报价完成
72
649
  }
73
650
  // ✅ 获取贿赂金额
74
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0 ? ethers.parseEther(String(config.bribeAmount)) : 0n;
651
+ const bribeAmount = config.bribeAmount && config.bribeAmount > 0
652
+ ? ethers.parseEther(String(config.bribeAmount))
653
+ : 0n;
75
654
  const needBribeTx = bribeAmount > 0n;
76
655
  // ✅ 使用共享的 NonceManager 规划 nonce
77
656
  // 如果前端传入了 startNonces,直接使用(性能优化)
@@ -84,54 +663,48 @@ export async function pancakeBundleSwapMerkle(params) {
84
663
  approvalExists: false, // ✅ 已移除授权
85
664
  profitNeeded: profitAmount > 0n,
86
665
  needBribeTx,
87
- nonceManager,
666
+ nonceManager
88
667
  });
89
668
  // ✅ 并行签名所有交易
90
669
  const signPromises = [];
91
670
  // 贿赂交易
92
671
  if (needBribeTx && noncePlan.bribeNonce !== undefined) {
93
- signPromises.push(seller
94
- .signTransaction({
672
+ signPromises.push(seller.signTransaction({
95
673
  to: BLOCKRAZOR_BUILDER_EOA,
96
674
  value: bribeAmount,
97
675
  nonce: noncePlan.bribeNonce,
98
676
  gasPrice,
99
677
  gasLimit: BRIBE_GAS_LIMIT,
100
678
  chainId: context.chainId,
101
- type: txType,
102
- })
103
- .then((tx) => ({ type: 'bribe', tx })));
679
+ type: txType
680
+ }).then(tx => ({ type: 'bribe', tx })));
104
681
  }
105
682
  // 卖出交易
106
- signPromises.push(seller
107
- .signTransaction({
683
+ signPromises.push(seller.signTransaction({
108
684
  ...swapUnsigned.sellUnsigned,
109
685
  from: seller.address,
110
686
  nonce: noncePlan.sellerNonce,
111
687
  gasLimit: finalGasLimit,
112
688
  gasPrice,
113
689
  chainId: context.chainId,
114
- type: txType,
115
- })
116
- .then((tx) => ({ type: 'sell', tx })));
690
+ type: txType
691
+ }).then(tx => ({ type: 'sell', tx })));
117
692
  // 买入交易
118
- signPromises.push(buyer
119
- .signTransaction({
693
+ signPromises.push(buyer.signTransaction({
120
694
  ...swapUnsigned.buyUnsigned,
121
695
  from: buyer.address,
122
696
  nonce: noncePlan.buyerNonce,
123
697
  gasLimit: finalGasLimit,
124
698
  gasPrice,
125
699
  chainId: context.chainId,
126
- type: txType,
127
- })
128
- .then((tx) => ({ type: 'buy', tx })));
700
+ type: txType
701
+ }).then(tx => ({ type: 'buy', tx })));
129
702
  // ✅ 并行执行所有签名
130
703
  const signedResults = await Promise.all(signPromises);
131
704
  // 按类型提取结果
132
- const bribeTx = signedResults.find((r) => r.type === 'bribe')?.tx || null;
133
- const signedSell = signedResults.find((r) => r.type === 'sell').tx;
134
- const signedBuy = signedResults.find((r) => r.type === 'buy').tx;
705
+ const bribeTx = signedResults.find(r => r.type === 'bribe')?.tx || null;
706
+ const signedSell = signedResults.find(r => r.type === 'sell').tx;
707
+ const signedBuy = signedResults.find(r => r.type === 'buy').tx;
135
708
  nonceManager.clearTemp();
136
709
  validateFinalBalances({
137
710
  sameAddress,
@@ -143,7 +716,7 @@ export async function pancakeBundleSwapMerkle(params) {
143
716
  useNativeToken,
144
717
  quoteTokenDecimals,
145
718
  provider: context.provider,
146
- buyerAddress: buyer.address,
719
+ buyerAddress: buyer.address
147
720
  });
148
721
  // ✅ 组装顺序:贿赂 → 卖出 → 买入
149
722
  const signedTransactions = [];
@@ -157,12 +730,12 @@ export async function pancakeBundleSwapMerkle(params) {
157
730
  provider: context.provider,
158
731
  payerWallet: seller,
159
732
  profitAmount,
160
- profitRecipient: getProfitRecipient(),
733
+ profitRecipient: PROFIT_CONFIG.RECIPIENT,
161
734
  hopCount: PROFIT_HOP_COUNT,
162
735
  gasPrice,
163
736
  chainId: context.chainId,
164
737
  txType,
165
- startNonce: noncePlan.profitNonce,
738
+ startNonce: noncePlan.profitNonce
166
739
  });
167
740
  signedTransactions.push(...profitHopResult.signedTransactions);
168
741
  profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
@@ -177,8 +750,8 @@ export async function pancakeBundleSwapMerkle(params) {
177
750
  buyAmount: useNativeToken
178
751
  ? ethers.formatEther(buyerBudget.buyAmountBNB)
179
752
  : ethers.formatUnits(buyerBudget.buyAmountBNB, quoteTokenDecimals),
180
- profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined,
181
- },
753
+ profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined
754
+ }
182
755
  };
183
756
  }
184
757
  /**
@@ -190,7 +763,7 @@ export async function pancakeBundleSwapMerkle(params) {
190
763
  * 交易顺序:[授权(可选)] → [卖出] → [买入1, 买入2, ..., 买入N] → [利润]
191
764
  */
192
765
  export async function pancakeBatchSwapMerkle(params) {
193
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces, // ✅ 可选:前端预获取的 nonces
766
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
194
767
  } = params;
195
768
  // ✅ 校验买方数量(最多 24 个)
196
769
  const MAX_BUYERS = 24;
@@ -203,7 +776,7 @@ export async function pancakeBatchSwapMerkle(params) {
203
776
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
204
777
  const context = createPancakeContext(config);
205
778
  const seller = new Wallet(sellerPrivateKey, context.provider);
206
- const buyers = buyerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
779
+ const buyers = buyerPrivateKeys.map(pk => new Wallet(pk, context.provider));
207
780
  // ✅ 创建共享资源
208
781
  const nonceManager = new NonceManager(context.provider);
209
782
  const finalGasLimit = getGasLimit(config);
@@ -211,14 +784,14 @@ export async function pancakeBatchSwapMerkle(params) {
211
784
  // ✅ 并行获取 gasPrice 和卖出数量
212
785
  const [gasPrice, sellAmountResult] = await Promise.all([
213
786
  getGasPrice(context.provider, config),
214
- calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage),
787
+ calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage)
215
788
  ]);
216
789
  const { amount: sellAmountWei, decimals } = sellAmountResult;
217
790
  const quoteResult = await quoteSellOutput({
218
791
  routeParams,
219
792
  sellAmountWei,
220
793
  provider: context.provider,
221
- v2RouterAddress: config.v2RouterAddress,
794
+ v2RouterAddress: config.v2RouterAddress
222
795
  });
223
796
  const estimatedBNBOut = quoteResult.estimatedBNBOut;
224
797
  // ✅ 计算每个买方的买入金额(已移除滑点保护:直接使用报价金额)
@@ -226,12 +799,14 @@ export async function pancakeBatchSwapMerkle(params) {
226
799
  const totalBuyAmount = estimatedBNBOut;
227
800
  if (buyerAmounts && buyerAmounts.length === buyers.length) {
228
801
  // 方式1:使用指定的买入金额(USDT)
229
- buyAmountsWei = buyerAmounts.map((amt) => useNativeToken ? ethers.parseEther(amt) : ethers.parseUnits(amt, quoteTokenDecimals));
802
+ buyAmountsWei = buyerAmounts.map(amt => useNativeToken
803
+ ? ethers.parseEther(amt)
804
+ : ethers.parseUnits(amt, quoteTokenDecimals));
230
805
  }
231
806
  else if (params.buyerRatios && params.buyerRatios.length === buyers.length) {
232
807
  // ✅ 方式2:按比例分配卖出所得
233
808
  // buyerRatios 如 [0.3, 0.5, 0.2] 表示第一个买方分 30%,第二个 50%,第三个 20%
234
- buyAmountsWei = params.buyerRatios.map((ratio) => {
809
+ buyAmountsWei = params.buyerRatios.map((ratio, index) => {
235
810
  // 按比例计算每个买方的金额
236
811
  const amount = (totalBuyAmount * BigInt(Math.round(ratio * 10000))) / 10000n;
237
812
  return amount;
@@ -281,17 +856,15 @@ export async function pancakeBatchSwapMerkle(params) {
281
856
  else if (routeParams.routeType === 'v3-single') {
282
857
  const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
283
858
  const v3RouterSeller = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, seller);
284
- const sellSwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [
285
- {
859
+ const sellSwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
286
860
  tokenIn: v3TokenIn,
287
861
  tokenOut: v3TokenOut,
288
862
  fee: v3Fee,
289
863
  recipient: useNativeToken ? PANCAKE_V3_ROUTER_ADDRESS : seller.address,
290
864
  amountIn: sellAmountWei,
291
865
  amountOutMinimum: 0n,
292
- sqrtPriceLimitX96: 0n,
293
- },
294
- ]);
866
+ sqrtPriceLimitX96: 0n
867
+ }]);
295
868
  if (useNativeToken) {
296
869
  // 原生代币:需要 unwrap WBNB
297
870
  const sellUnwrapData = v3RouterIface.encodeFunctionData('unwrapWETH9', [0n, seller.address]);
@@ -324,17 +897,15 @@ export async function pancakeBatchSwapMerkle(params) {
324
897
  else if (routeParams.routeType === 'v3-single') {
325
898
  const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
326
899
  const v3RouterBuyer = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, buyer);
327
- const buySwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [
328
- {
900
+ const buySwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
329
901
  tokenIn: v3TokenOut,
330
902
  tokenOut: v3TokenIn,
331
903
  fee: v3Fee,
332
904
  recipient: buyer.address,
333
905
  amountIn: buyAmount,
334
906
  amountOutMinimum: 0n,
335
- sqrtPriceLimitX96: 0n,
336
- },
337
- ]);
907
+ sqrtPriceLimitX96: 0n
908
+ }]);
338
909
  return await v3RouterBuyer.multicall.populateTransaction(deadline, [buySwapData], { value: buyValue });
339
910
  }
340
911
  else {
@@ -342,14 +913,16 @@ export async function pancakeBatchSwapMerkle(params) {
342
913
  }
343
914
  }));
344
915
  // ✅ 获取贿赂金额
345
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0 ? ethers.parseEther(String(config.bribeAmount)) : 0n;
916
+ const bribeAmount = config.bribeAmount && config.bribeAmount > 0
917
+ ? ethers.parseEther(String(config.bribeAmount))
918
+ : 0n;
346
919
  // ✅ 规划 Nonce(贿赂和利润都由卖方发送)
347
920
  // 卖方: [贿赂(可选)] → [卖出] → [利润(可选)]
348
921
  let bribeNonce;
349
922
  let sellNonce;
350
923
  let buyerNonces;
351
924
  // ✅ 如果前端传入了 startNonces,直接使用(性能优化)
352
- if (startNonces && startNonces.length >= 1 + buyers.length) {
925
+ if (startNonces && startNonces.length >= (1 + buyers.length)) {
353
926
  let sellerIdx = 0;
354
927
  if (bribeAmount > 0n) {
355
928
  bribeNonce = startNonces[0] + sellerIdx++;
@@ -362,7 +935,7 @@ export async function pancakeBatchSwapMerkle(params) {
362
935
  bribeNonce = await nonceManager.getNextNonce(seller);
363
936
  }
364
937
  sellNonce = await nonceManager.getNextNonce(seller);
365
- buyerNonces = await Promise.all(buyers.map((buyer) => nonceManager.getNextNonce(buyer)));
938
+ buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
366
939
  }
367
940
  // ✅ 贿赂交易放在首位(由卖方发送)
368
941
  let bribeTx = null;
@@ -374,7 +947,7 @@ export async function pancakeBatchSwapMerkle(params) {
374
947
  gasPrice,
375
948
  gasLimit: BRIBE_GAS_LIMIT,
376
949
  chainId: context.chainId,
377
- type: txType,
950
+ type: txType
378
951
  });
379
952
  }
380
953
  // ✅ 修复:利润计算应基于 BNB 数量,不是 ERC20 数量
@@ -392,9 +965,7 @@ export async function pancakeBatchSwapMerkle(params) {
392
965
  }
393
966
  // 计算利润 nonce
394
967
  const profitNonce = profitAmount > 0n
395
- ? startNonces && startNonces.length >= 1
396
- ? sellNonce + 1
397
- : await nonceManager.getNextNonce(seller)
968
+ ? (startNonces && startNonces.length >= 1 ? sellNonce + 1 : await nonceManager.getNextNonce(seller))
398
969
  : undefined;
399
970
  nonceManager.clearTemp();
400
971
  // ✅ 并行签名所有交易
@@ -406,7 +977,7 @@ export async function pancakeBatchSwapMerkle(params) {
406
977
  gasLimit: finalGasLimit,
407
978
  gasPrice,
408
979
  chainId: context.chainId,
409
- type: txType,
980
+ type: txType
410
981
  });
411
982
  // 2. 并行签名所有买入交易
412
983
  const signedBuyPromises = buyers.map((buyer, i) => buyer.signTransaction({
@@ -416,10 +987,13 @@ export async function pancakeBatchSwapMerkle(params) {
416
987
  gasLimit: finalGasLimit,
417
988
  gasPrice,
418
989
  chainId: context.chainId,
419
- type: txType,
990
+ type: txType
420
991
  }));
421
992
  // 3. 等待所有签名完成
422
- const [signedSell, ...signedBuys] = await Promise.all([signedSellPromise, ...signedBuyPromises]);
993
+ const [signedSell, ...signedBuys] = await Promise.all([
994
+ signedSellPromise,
995
+ ...signedBuyPromises
996
+ ]);
423
997
  // 4. 按顺序组装交易数组:贿赂 → 卖出 → 买入
424
998
  const signedTransactions = [];
425
999
  if (bribeTx)
@@ -433,12 +1007,12 @@ export async function pancakeBatchSwapMerkle(params) {
433
1007
  provider: context.provider,
434
1008
  payerWallet: seller,
435
1009
  profitAmount,
436
- profitRecipient: getProfitRecipient(),
1010
+ profitRecipient: PROFIT_CONFIG.RECIPIENT,
437
1011
  hopCount: PROFIT_HOP_COUNT,
438
1012
  gasPrice,
439
1013
  chainId: context.chainId,
440
1014
  txType,
441
- startNonce: profitNonce,
1015
+ startNonce: profitNonce
442
1016
  });
443
1017
  signedTransactions.push(...profitHopResult.signedTransactions);
444
1018
  profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
@@ -448,11 +1022,13 @@ export async function pancakeBatchSwapMerkle(params) {
448
1022
  profitHopWallets, // ✅ 导出利润多跳钱包
449
1023
  metadata: {
450
1024
  sellerAddress: seller.address,
451
- buyerAddresses: buyers.map((b) => b.address),
1025
+ buyerAddresses: buyers.map(b => b.address),
452
1026
  sellAmount: ethers.formatUnits(sellAmountWei, decimals),
453
- buyAmounts: buyAmountsWei.map((amt) => useNativeToken ? ethers.formatEther(amt) : ethers.formatUnits(amt, quoteTokenDecimals)),
454
- profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined,
455
- },
1027
+ buyAmounts: buyAmountsWei.map(amt => useNativeToken
1028
+ ? ethers.formatEther(amt)
1029
+ : ethers.formatUnits(amt, quoteTokenDecimals)),
1030
+ profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined
1031
+ }
456
1032
  };
457
1033
  }
458
1034
  /**
@@ -471,7 +1047,7 @@ export async function pancakeBatchSwapMerkle(params) {
471
1047
  */
472
1048
  export async function pancakeQuickBatchSwapMerkle(params) {
473
1049
  const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, disperseHopCount = 0, // ✅ 转账多跳数(默认0=直接转账)
474
- startNonces, // ✅ 可选:前端预获取的 nonces
1050
+ startNonces // ✅ 可选:前端预获取的 nonces
475
1051
  } = params;
476
1052
  // ✅ 判断是否使用原生代币
477
1053
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
@@ -498,6 +1074,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
498
1074
  MAX_BUYERS = Math.floor(maxTxs / (2 * disperseHopCount + 3));
499
1075
  }
500
1076
  MAX_BUYERS = Math.max(1, MAX_BUYERS); // 至少1个
1077
+ console.log(`[pancakeQuickBatchSwapMerkle] 多跳数: ${disperseHopCount}, 最大买方数: ${MAX_BUYERS}`);
501
1078
  if (buyerPrivateKeys.length === 0) {
502
1079
  throw new Error('至少需要一个买方钱包');
503
1080
  }
@@ -517,7 +1094,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
517
1094
  }
518
1095
  const context = createPancakeContext(config);
519
1096
  const seller = new Wallet(sellerPrivateKey, context.provider);
520
- const buyers = buyerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
1097
+ const buyers = buyerPrivateKeys.map(pk => new Wallet(pk, context.provider));
521
1098
  // ✅ 校验卖出路径输出代币是否匹配
522
1099
  let sellOutputToken;
523
1100
  if (routeParams.routeType === 'v2') {
@@ -557,16 +1134,30 @@ export async function pancakeQuickBatchSwapMerkle(params) {
557
1134
  // ✅ 并行获取 gasPrice 和卖出数量
558
1135
  const [gasPrice, sellAmountResult] = await Promise.all([
559
1136
  getGasPrice(context.provider, config),
560
- calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage),
1137
+ calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage)
561
1138
  ]);
562
1139
  const { amount: sellAmountWei, decimals } = sellAmountResult;
1140
+ // ✅ 调试日志
1141
+ console.log(`[pancakeQuickBatchSwapMerkle] 模式: ${useNativeToken ? 'BNB' : 'ERC20'}`);
1142
+ console.log(`[pancakeQuickBatchSwapMerkle] 卖出数量: ${ethers.formatUnits(sellAmountWei, decimals)}`);
1143
+ console.log(`[pancakeQuickBatchSwapMerkle] routeParams:`, JSON.stringify({
1144
+ routeType: routeParams.routeType,
1145
+ v2Path: routeParams.v2Path,
1146
+ v3TokenIn: routeParams.v3TokenIn,
1147
+ v3TokenOut: routeParams.v3TokenOut,
1148
+ v3Fee: routeParams.v3Fee
1149
+ }));
563
1150
  const quoteResult = await quoteSellOutput({
564
1151
  routeParams,
565
1152
  sellAmountWei,
566
1153
  provider: context.provider,
567
- v2RouterAddress: config.v2RouterAddress,
1154
+ v2RouterAddress: config.v2RouterAddress
568
1155
  });
569
1156
  const estimatedOutput = quoteResult.estimatedBNBOut;
1157
+ const outputFormatted = useNativeToken
1158
+ ? ethers.formatEther(estimatedOutput)
1159
+ : ethers.formatUnits(estimatedOutput, quoteTokenDecimals);
1160
+ console.log(`[pancakeQuickBatchSwapMerkle] 预估卖出所得: ${outputFormatted} ${useNativeToken ? 'BNB' : 'ERC20'}`);
570
1161
  // ✅ 计算利润(万分之六)
571
1162
  let profitAmount;
572
1163
  if (useNativeToken) {
@@ -578,13 +1169,16 @@ export async function pancakeQuickBatchSwapMerkle(params) {
578
1169
  const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
579
1170
  const estimatedBNBValue = await getERC20ToNativeQuote(context.provider, quoteToken, estimatedOutput, version, fee);
580
1171
  profitAmount = calculateProfitAmount(estimatedBNBValue, config.userType);
1172
+ console.log(`[pancakeQuickBatchSwapMerkle] ERC20→BNB 报价: ${outputFormatted} → ${ethers.formatEther(estimatedBNBValue)} BNB`);
581
1173
  }
582
1174
  const distributableAmount = estimatedOutput - (useNativeToken ? profitAmount : 0n);
583
1175
  // ✅ 计算每个买方分到的金额
584
1176
  let transferAmountsWei;
585
1177
  if (buyerAmounts && buyerAmounts.length === buyers.length) {
586
1178
  // 数量模式
587
- transferAmountsWei = buyerAmounts.map((amt) => useNativeToken ? ethers.parseEther(amt) : ethers.parseUnits(amt, quoteTokenDecimals));
1179
+ transferAmountsWei = buyerAmounts.map(amt => useNativeToken
1180
+ ? ethers.parseEther(amt)
1181
+ : ethers.parseUnits(amt, quoteTokenDecimals));
588
1182
  const totalTransfer = transferAmountsWei.reduce((a, b) => a + b, 0n);
589
1183
  if (totalTransfer > distributableAmount) {
590
1184
  const formatted = useNativeToken
@@ -595,7 +1189,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
595
1189
  }
596
1190
  else if (buyerRatios && buyerRatios.length === buyers.length) {
597
1191
  // 比例模式
598
- transferAmountsWei = buyerRatios.map((ratio) => {
1192
+ transferAmountsWei = buyerRatios.map(ratio => {
599
1193
  return (distributableAmount * BigInt(Math.round(ratio * 10000))) / 10000n;
600
1194
  });
601
1195
  }
@@ -603,22 +1197,22 @@ export async function pancakeQuickBatchSwapMerkle(params) {
603
1197
  throw new Error('必须提供 buyerRatios 或 buyerAmounts');
604
1198
  }
605
1199
  // ✅ 获取贿赂金额
606
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0 ? ethers.parseEther(String(config.bribeAmount)) : 0n;
1200
+ const bribeAmount = config.bribeAmount && config.bribeAmount > 0
1201
+ ? ethers.parseEther(String(config.bribeAmount))
1202
+ : 0n;
607
1203
  // ✅ 验证主钱包余额
608
1204
  const sellerBalance = await seller.provider.getBalance(seller.address);
609
1205
  let sellerGasCost;
610
1206
  let sellerRequired;
611
1207
  if (useNativeToken) {
612
1208
  // BNB 模式:贿赂(BRIBE) + 卖出(gasLimit) + N个原生转账(BRIBE each) + 利润(BRIBE)
613
- sellerGasCost =
614
- gasPrice * (BRIBE_GAS_LIMIT + finalGasLimit + BRIBE_GAS_LIMIT * BigInt(buyers.length) + BRIBE_GAS_LIMIT);
1209
+ sellerGasCost = gasPrice * (BRIBE_GAS_LIMIT + finalGasLimit + BRIBE_GAS_LIMIT * BigInt(buyers.length) + BRIBE_GAS_LIMIT);
615
1210
  sellerRequired = bribeAmount + sellerGasCost;
616
1211
  }
617
1212
  else {
618
1213
  // ERC20 模式:子钱包已预留 BNB,不需要主钱包转 Gas
619
1214
  // 卖方 Gas: 贿赂(BRIBE) + 卖出(gasLimit) + N个ERC20转账(65000 each) + 利润(BRIBE)
620
- sellerGasCost =
621
- gasPrice * (BRIBE_GAS_LIMIT + finalGasLimit + ERC20_TRANSFER_GAS * BigInt(buyers.length) + BRIBE_GAS_LIMIT);
1215
+ sellerGasCost = gasPrice * (BRIBE_GAS_LIMIT + finalGasLimit + ERC20_TRANSFER_GAS * BigInt(buyers.length) + BRIBE_GAS_LIMIT);
622
1216
  sellerRequired = bribeAmount + sellerGasCost;
623
1217
  }
624
1218
  if (sellerBalance < sellerRequired) {
@@ -626,7 +1220,9 @@ export async function pancakeQuickBatchSwapMerkle(params) {
626
1220
  }
627
1221
  // ==================== 规划 Nonce ====================
628
1222
  // ✅ 如果前端传入了 startNonces,直接使用(性能优化)
629
- let sellerNonce = startNonces && startNonces.length > 0 ? startNonces[0] : await nonceManager.getNextNonce(seller);
1223
+ let sellerNonce = startNonces && startNonces.length > 0
1224
+ ? startNonces[0]
1225
+ : await nonceManager.getNextNonce(seller);
630
1226
  const deadline = Math.floor(Date.now() / 1000) + 600;
631
1227
  // ==================== 1. 贿赂交易 ====================
632
1228
  let bribeTx = null;
@@ -638,8 +1234,9 @@ export async function pancakeQuickBatchSwapMerkle(params) {
638
1234
  gasPrice,
639
1235
  gasLimit: BRIBE_GAS_LIMIT,
640
1236
  chainId: context.chainId,
641
- type: txType,
1237
+ type: txType
642
1238
  });
1239
+ console.log(`[pancakeQuickBatchSwapMerkle] 贿赂交易已签名`);
643
1240
  }
644
1241
  // ==================== 2. 卖出交易 ====================
645
1242
  const v3RouterIface2 = new ethers.Interface(PANCAKE_V3_ROUTER_ABI);
@@ -660,17 +1257,15 @@ export async function pancakeQuickBatchSwapMerkle(params) {
660
1257
  else if (routeParams.routeType === 'v3-single') {
661
1258
  const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
662
1259
  const v3RouterSeller = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, seller);
663
- const sellSwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [
664
- {
1260
+ const sellSwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [{
665
1261
  tokenIn: v3TokenIn,
666
1262
  tokenOut: v3TokenOut,
667
1263
  fee: v3Fee,
668
1264
  recipient: useNativeToken ? PANCAKE_V3_ROUTER_ADDRESS : seller.address,
669
1265
  amountIn: sellAmountWei,
670
1266
  amountOutMinimum: 0n,
671
- sqrtPriceLimitX96: 0n,
672
- },
673
- ]);
1267
+ sqrtPriceLimitX96: 0n
1268
+ }]);
674
1269
  if (useNativeToken) {
675
1270
  // 原生代币:需要 unwrap WBNB
676
1271
  const sellUnwrapData = v3RouterIface2.encodeFunctionData('unwrapWETH9', [0n, seller.address]);
@@ -691,18 +1286,19 @@ export async function pancakeQuickBatchSwapMerkle(params) {
691
1286
  gasLimit: finalGasLimit,
692
1287
  gasPrice,
693
1288
  chainId: context.chainId,
694
- type: txType,
1289
+ type: txType
695
1290
  });
1291
+ console.log(`[pancakeQuickBatchSwapMerkle] 卖出交易已签名`);
696
1292
  // ==================== 3. 转账交易(支持多跳)====================
697
1293
  const buyerGasCost = gasPrice * finalGasLimit;
698
1294
  // ✅ 生成多跳路径
699
- const hopPaths = generateDisperseHopPaths(buyers.map((b) => b.address), disperseHopCount, context.provider);
1295
+ const hopPaths = generateDisperseHopPaths(buyers.map(b => b.address), disperseHopCount, context.provider);
700
1296
  // 收集所有中间钱包信息
701
1297
  const allHopWallets = [];
702
- hopPaths.forEach((path) => {
1298
+ hopPaths.forEach(path => {
703
1299
  allHopWallets.push(...path.hopWalletsInfo);
704
1300
  });
705
- let transferTxs;
1301
+ let transferTxs = [];
706
1302
  if (disperseHopCount === 0) {
707
1303
  // ✅ 无多跳:直接转账
708
1304
  const transferNonces = buyers.map((_, i) => sellerNonce + i);
@@ -717,14 +1313,17 @@ export async function pancakeQuickBatchSwapMerkle(params) {
717
1313
  gasPrice,
718
1314
  gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
719
1315
  chainId: context.chainId,
720
- type: txType,
1316
+ type: txType
721
1317
  });
722
1318
  }));
723
1319
  }
724
1320
  else {
725
1321
  const erc20Interface = new ethers.Interface(ERC20_ABI);
726
1322
  transferTxs = await Promise.all(buyers.map((buyer, i) => {
727
- const transferData = erc20Interface.encodeFunctionData('transfer', [buyer.address, transferAmountsWei[i]]);
1323
+ const transferData = erc20Interface.encodeFunctionData('transfer', [
1324
+ buyer.address,
1325
+ transferAmountsWei[i]
1326
+ ]);
728
1327
  return seller.signTransaction({
729
1328
  to: quoteToken,
730
1329
  data: transferData,
@@ -733,7 +1332,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
733
1332
  gasPrice,
734
1333
  gasLimit: ERC20_TRANSFER_GAS,
735
1334
  chainId: context.chainId,
736
- type: txType,
1335
+ type: txType
737
1336
  });
738
1337
  }));
739
1338
  }
@@ -773,11 +1372,12 @@ export async function pancakeQuickBatchSwapMerkle(params) {
773
1372
  transferTxs = [...bnbTxs, ...erc20Txs];
774
1373
  }
775
1374
  }
1375
+ console.log(`[pancakeQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名 (多跳数=${disperseHopCount})`);
776
1376
  // ==================== 4. 买入交易 ====================
777
1377
  // ✅ 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
778
1378
  const buyerNonces = startNonces && startNonces.length > 1
779
1379
  ? startNonces.slice(1)
780
- : await Promise.all(buyers.map((buyer) => nonceManager.getNextNonce(buyer)));
1380
+ : await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
781
1381
  const signedBuys = await Promise.all(buyers.map(async (buyer, i) => {
782
1382
  const buyAmount = transferAmountsWei[i];
783
1383
  // ✅ ERC20 模式:value = 0(通过代币授权支付)
@@ -797,17 +1397,15 @@ export async function pancakeQuickBatchSwapMerkle(params) {
797
1397
  else if (routeParams.routeType === 'v3-single') {
798
1398
  const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
799
1399
  const v3RouterBuyer = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, buyer);
800
- const buySwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [
801
- {
1400
+ const buySwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [{
802
1401
  tokenIn: v3TokenOut,
803
1402
  tokenOut: v3TokenIn,
804
1403
  fee: v3Fee,
805
1404
  recipient: buyer.address,
806
1405
  amountIn: buyAmount,
807
1406
  amountOutMinimum: 0n,
808
- sqrtPriceLimitX96: 0n,
809
- },
810
- ]);
1407
+ sqrtPriceLimitX96: 0n
1408
+ }]);
811
1409
  buyUnsigned = await v3RouterBuyer.multicall.populateTransaction(deadline, [buySwapData], { value: buyValue });
812
1410
  }
813
1411
  else {
@@ -820,9 +1418,10 @@ export async function pancakeQuickBatchSwapMerkle(params) {
820
1418
  gasLimit: finalGasLimit,
821
1419
  gasPrice,
822
1420
  chainId: context.chainId,
823
- type: txType,
1421
+ type: txType
824
1422
  });
825
1423
  }));
1424
+ console.log(`[pancakeQuickBatchSwapMerkle] ${signedBuys.length} 笔买入交易已签名`);
826
1425
  nonceManager.clearTemp();
827
1426
  // ==================== 组装交易数组 ====================
828
1427
  // BNB 模式:贿赂 → 卖出 → 转账 → 买入 → 利润多跳
@@ -840,33 +1439,41 @@ export async function pancakeQuickBatchSwapMerkle(params) {
840
1439
  provider: context.provider,
841
1440
  payerWallet: seller,
842
1441
  profitAmount,
843
- profitRecipient: getProfitRecipient(),
1442
+ profitRecipient: PROFIT_CONFIG.RECIPIENT,
844
1443
  hopCount: PROFIT_HOP_COUNT,
845
1444
  gasPrice,
846
1445
  chainId: context.chainId,
847
1446
  txType,
848
- startNonce: sellerNonce++,
1447
+ startNonce: sellerNonce++
849
1448
  });
850
1449
  signedTransactions.push(...profitHopResult.signedTransactions);
851
1450
  profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
852
1451
  // 多跳交易已签名
853
1452
  }
1453
+ console.log(`[pancakeQuickBatchSwapMerkle] 交易组装完成: ${signedTransactions.length} 笔`);
1454
+ console.log(` - 贿赂: ${bribeTx ? 1 : 0}`);
1455
+ console.log(` - 卖出: 1`);
1456
+ console.log(` - 转账: ${transferTxs.length}`);
1457
+ console.log(` - 买入: ${signedBuys.length}`);
1458
+ const outputUnit = useNativeToken ? 'BNB' : 'ERC20';
854
1459
  return {
855
1460
  signedTransactions,
856
1461
  disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅ 返回转账多跳钱包
857
1462
  profitHopWallets, // ✅ 返回利润多跳钱包
858
1463
  metadata: {
859
1464
  sellerAddress: seller.address,
860
- buyerAddresses: buyers.map((b) => b.address),
1465
+ buyerAddresses: buyers.map(b => b.address),
861
1466
  sellAmount: ethers.formatUnits(sellAmountWei, decimals),
862
1467
  estimatedOutput: useNativeToken
863
1468
  ? ethers.formatEther(estimatedOutput)
864
1469
  : ethers.formatUnits(estimatedOutput, quoteTokenDecimals),
865
- transferAmounts: transferAmountsWei.map((amt) => useNativeToken ? ethers.formatEther(amt) : ethers.formatUnits(amt, quoteTokenDecimals)),
1470
+ transferAmounts: transferAmountsWei.map(amt => useNativeToken
1471
+ ? ethers.formatEther(amt)
1472
+ : ethers.formatUnits(amt, quoteTokenDecimals)),
866
1473
  profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined,
867
1474
  useNativeToken,
868
- disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined, // ✅ 返回多跳数
869
- },
1475
+ disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined // ✅ 返回多跳数
1476
+ }
870
1477
  };
871
1478
  }
872
1479
  /**
@@ -877,7 +1484,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
877
1484
  * - ✅ 正确处理 nonce:同一钱包在多轮中使用时 nonce 自动递增
878
1485
  */
879
1486
  export async function pancakeCrossSwapMerkle(params) {
880
- const { sellerPrivateKeys, sellAmounts, buyerPrivateKeys, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, buyersPerSell, disperseHopCount = 0, } = params;
1487
+ const { sellerPrivateKeys, sellAmounts, buyerPrivateKeys, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, buyersPerSell, disperseHopCount = 0 } = params;
881
1488
  if (sellerPrivateKeys.length === 0) {
882
1489
  throw new Error('至少需要一个卖方');
883
1490
  }
@@ -891,8 +1498,8 @@ export async function pancakeCrossSwapMerkle(params) {
891
1498
  const context = createPancakeContext(config);
892
1499
  const nonceManager = new NonceManager(context.provider);
893
1500
  // ✅ 预先获取所有钱包的初始 nonce
894
- const allSellerWallets = sellerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
895
- const allBuyerWallets = buyerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
1501
+ const allSellerWallets = sellerPrivateKeys.map(pk => new Wallet(pk, context.provider));
1502
+ const allBuyerWallets = buyerPrivateKeys.map(pk => new Wallet(pk, context.provider));
896
1503
  // 使用 Map 去重(同一私钥可能出现多次)
897
1504
  const addressToNonce = new Map();
898
1505
  // 获取所有卖方 nonce
@@ -909,6 +1516,7 @@ export async function pancakeCrossSwapMerkle(params) {
909
1516
  addressToNonce.set(wallet.address, nonce);
910
1517
  }
911
1518
  }
1519
+ console.log(`[pancakeCrossSwapMerkle] 初始化完成: ${sellerPrivateKeys.length} 卖方, ${buyerPrivateKeys.length} 买方`);
912
1520
  const allSigned = [];
913
1521
  const allDisperse = [];
914
1522
  const allProfit = [];
@@ -919,7 +1527,9 @@ export async function pancakeCrossSwapMerkle(params) {
919
1527
  // 判断是否使用原生代币
920
1528
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
921
1529
  // 获取贿赂金额
922
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0 ? ethers.parseEther(String(config.bribeAmount)) : 0n;
1530
+ const bribeAmount = config.bribeAmount && config.bribeAmount > 0
1531
+ ? ethers.parseEther(String(config.bribeAmount))
1532
+ : 0n;
923
1533
  const hasBribe = bribeAmount > 0n;
924
1534
  for (let i = 0; i < sellerPrivateKeys.length; i++) {
925
1535
  const sellerPk = sellerPrivateKeys[i];
@@ -937,7 +1547,7 @@ export async function pancakeCrossSwapMerkle(params) {
937
1547
  // ✅ 获取卖方当前 nonce
938
1548
  const sellerNonce = addressToNonce.get(sellerWallet.address);
939
1549
  // ✅ 获取并更新买方 nonces(每个买方本轮需要 1 个 nonce)
940
- const roundBuyerNonces = roundBuyerWallets.map((w) => {
1550
+ const roundBuyerNonces = roundBuyerWallets.map(w => {
941
1551
  const nonce = addressToNonce.get(w.address);
942
1552
  addressToNonce.set(w.address, nonce + 1); // 每个买方用 1 个 nonce
943
1553
  return nonce;
@@ -977,10 +1587,11 @@ export async function pancakeCrossSwapMerkle(params) {
977
1587
  quoteToken,
978
1588
  quoteTokenDecimals,
979
1589
  disperseHopCount,
980
- startNonces, // ✅ 传入预计算的 nonces
1590
+ startNonces // ✅ 传入预计算的 nonces
981
1591
  });
982
1592
  // ✅ 更新卖方 nonce(使用精确计算的值)
983
1593
  addressToNonce.set(sellerWallet.address, sellerNonce + sellerNonceConsumed);
1594
+ console.log(`[pancakeCrossSwapMerkle] 轮次 ${i + 1}: 卖方=${sellerWallet.address.slice(0, 10)}..., 买方=${roundBuyerPks.length}, 交易=${res.signedTransactions.length}`);
984
1595
  // 累积签名与中间钱包
985
1596
  allSigned.push(...res.signedTransactions);
986
1597
  if (res.disperseHopWallets)
@@ -991,14 +1602,15 @@ export async function pancakeCrossSwapMerkle(params) {
991
1602
  sellerAddress: res.metadata?.sellerAddress || '',
992
1603
  buyerAddresses: res.metadata?.buyerAddresses || roundBuyerPks.map(() => ''),
993
1604
  sellAmount,
994
- bundleHash: undefined,
1605
+ bundleHash: undefined
995
1606
  });
996
1607
  }
997
1608
  nonceManager.clearTemp();
1609
+ console.log(`[pancakeCrossSwapMerkle] 完成: ${rounds.length} 轮, ${allSigned.length} 笔交易`);
998
1610
  return {
999
1611
  signedTransactions: allSigned,
1000
1612
  rounds,
1001
1613
  disperseHopWallets: allDisperse.length > 0 ? allDisperse : undefined,
1002
- profitHopWallets: allProfit.length > 0 ? allProfit : undefined,
1614
+ profitHopWallets: allProfit.length > 0 ? allProfit : undefined
1003
1615
  };
1004
1616
  }