four-flap-meme-sdk 2.2.2 → 2.2.4

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