four-flap-meme-sdk 1.9.49 → 2.1.0

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 (567) 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.js +34 -0
  5. package/dist/abis/common.js +74 -68
  6. package/dist/abis/flap/vault.js +9 -7
  7. package/dist/abis/index.d.ts +3 -4
  8. package/dist/abis/index.js +3 -4
  9. package/dist/bundle-core/__tests__/config-helpers.test.js +28 -0
  10. package/dist/bundle-core/__tests__/facade-parity.test.js +33 -0
  11. package/dist/bundle-core/__tests__/sign-context-helpers.test.js +60 -0
  12. package/dist/bundle-core/__tests__/sign-fixture.test.js +220 -0
  13. package/dist/bundle-core/__tests__/sign-fixtures.d.ts +10 -0
  14. package/dist/bundle-core/__tests__/sign-fixtures.js +16 -0
  15. package/dist/bundle-core/config-helpers.d.ts +36 -0
  16. package/dist/bundle-core/config-helpers.js +57 -0
  17. package/dist/bundle-core/errors.d.ts +50 -0
  18. package/dist/bundle-core/errors.js +34 -0
  19. package/dist/bundle-core/four-meme/approve-tokenmanager.d.ts +7 -0
  20. package/dist/bundle-core/four-meme/approve-tokenmanager.js +99 -0
  21. package/dist/bundle-core/four-meme/core-helpers.d.ts +8 -0
  22. package/dist/bundle-core/four-meme/core-helpers.js +40 -0
  23. package/dist/bundle-core/four-meme/core.d.ts +4 -0
  24. package/dist/bundle-core/four-meme/core.js +515 -0
  25. package/dist/bundle-core/four-meme/pancake-proxy.d.ts +28 -0
  26. package/dist/{shared 2/flap/portal-bundle-merkle/pancake-proxy.js → bundle-core/four-meme/pancake-proxy.js} +277 -299
  27. package/dist/bundle-core/four-meme/private.d.ts +27 -0
  28. package/dist/bundle-core/four-meme/private.js +465 -0
  29. package/dist/bundle-core/four-meme/sign-context-helpers.d.ts +2 -0
  30. package/dist/bundle-core/four-meme/sign-context-helpers.js +2 -0
  31. package/dist/bundle-core/four-meme/swap-buy-first.d.ts +8 -0
  32. package/dist/bundle-core/four-meme/swap-buy-first.js +493 -0
  33. package/dist/bundle-core/four-meme/swap-hop-helpers.d.ts +6 -0
  34. package/dist/bundle-core/four-meme/swap-hop-helpers.js +63 -0
  35. package/dist/bundle-core/four-meme/swap-internal.d.ts +3 -0
  36. package/dist/bundle-core/four-meme/swap-internal.js +18 -0
  37. package/dist/bundle-core/four-meme/swap-sign-helpers.d.ts +27 -0
  38. package/dist/bundle-core/four-meme/swap-sign-helpers.js +105 -0
  39. package/dist/bundle-core/four-meme/swap.d.ts +17 -0
  40. package/dist/{chains/bsc/four/swap/index.js → bundle-core/four-meme/swap.js} +84 -408
  41. package/dist/bundle-core/four-meme/types/buy-first.d.ts +50 -0
  42. package/dist/bundle-core/four-meme/types/core-flow.d.ts +63 -0
  43. package/dist/bundle-core/four-meme/types/index.d.ts +600 -0
  44. package/dist/bundle-core/four-meme/types/swap-internal.d.ts +19 -0
  45. package/dist/bundle-core/four-meme/types.d.ts +1 -0
  46. package/dist/bundle-core/four-meme/utils-disperse.d.ts +7 -0
  47. package/dist/bundle-core/four-meme/utils-disperse.js +396 -0
  48. package/dist/bundle-core/four-meme/utils-pairwise.d.ts +8 -0
  49. package/dist/bundle-core/four-meme/utils-pairwise.js +328 -0
  50. package/dist/bundle-core/four-meme/utils-sweep.d.ts +8 -0
  51. package/dist/bundle-core/four-meme/utils-sweep.js +744 -0
  52. package/dist/bundle-core/index.d.ts +8 -0
  53. package/dist/bundle-core/index.js +8 -0
  54. package/dist/bundle-core/internal.d.ts +21 -0
  55. package/dist/bundle-core/internal.js +182 -0
  56. package/dist/bundle-core/sign-context-helpers.d.ts +25 -0
  57. package/dist/bundle-core/sign-context-helpers.js +67 -0
  58. package/dist/bundle-core/submit.d.ts +293 -0
  59. package/dist/bundle-core/submit.js +727 -0
  60. package/dist/bundle-core/types/index.d.ts +8 -0
  61. package/dist/bundle-core/types.d.ts +1 -0
  62. package/dist/chains/bsc/four/approve-tokenmanager.d.ts +1 -26
  63. package/dist/chains/bsc/four/approve-tokenmanager.js +1 -116
  64. package/dist/chains/bsc/four/config.d.ts +5 -70
  65. package/dist/chains/bsc/four/config.js +2 -115
  66. package/dist/chains/bsc/four/core.d.ts +1 -4
  67. package/dist/chains/bsc/four/core.js +1 -589
  68. package/dist/chains/bsc/four/index.d.ts +6 -6
  69. package/dist/chains/bsc/four/index.js +6 -6
  70. package/dist/chains/bsc/four/internal.d.ts +2 -50
  71. package/dist/chains/bsc/four/internal.js +2 -237
  72. package/dist/chains/bsc/four/pancake-proxy.d.ts +1 -28
  73. package/dist/chains/bsc/four/pancake-proxy.js +1 -688
  74. package/dist/chains/bsc/four/private.d.ts +1 -27
  75. package/dist/chains/bsc/four/private.js +1 -477
  76. package/dist/chains/bsc/four/submit.d.ts +2 -315
  77. package/dist/chains/bsc/four/submit.js +2 -746
  78. package/dist/chains/bsc/four/swap-buy-first.d.ts +2 -55
  79. package/dist/chains/bsc/four/swap-buy-first.js +2 -506
  80. package/dist/chains/bsc/four/swap-internal.d.ts +1 -3
  81. package/dist/chains/bsc/four/swap-internal.js +1 -18
  82. package/dist/chains/bsc/four/swap.d.ts +2 -144
  83. package/dist/chains/bsc/four/swap.js +2 -760
  84. package/dist/chains/bsc/four/types.d.ts +1 -476
  85. package/dist/chains/bsc/four/utils-disperse.d.ts +1 -0
  86. package/dist/chains/bsc/four/utils-disperse.js +1 -0
  87. package/dist/chains/bsc/four/utils-pairwise.d.ts +1 -0
  88. package/dist/chains/bsc/four/utils-pairwise.js +1 -0
  89. package/dist/chains/bsc/four/utils-sweep.d.ts +1 -0
  90. package/dist/chains/bsc/four/utils-sweep.js +1 -0
  91. package/dist/chains/bsc/four/utils.d.ts +5 -18
  92. package/dist/chains/bsc/four/utils.js +5 -1534
  93. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.d.ts +159 -0
  94. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.js +117 -0
  95. package/dist/chains/bsc/pancake/bundle-buy-first.d.ts +1 -91
  96. package/dist/chains/bsc/pancake/bundle-buy-first.js +97 -207
  97. package/dist/chains/bsc/pancake/bundle-swap-helpers.d.ts +241 -0
  98. package/dist/chains/bsc/pancake/{bundle-swap/helpers.js → bundle-swap-helpers.js} +63 -70
  99. package/dist/chains/bsc/pancake/bundle-swap.d.ts +1 -79
  100. package/dist/chains/bsc/pancake/bundle-swap.js +111 -686
  101. package/dist/chains/bsc/pancake/index.d.ts +4 -2
  102. package/dist/chains/bsc/pancake/index.js +1 -3
  103. package/dist/chains/bsc/platforms/iro/factory.js +3 -1
  104. package/dist/chains/bsc/platforms/iro/index.d.ts +5 -5
  105. package/dist/chains/bsc/platforms/iro/index.js +3 -3
  106. package/dist/chains/bsc/platforms/iro/pool.js +31 -10
  107. package/dist/chains/bsc/platforms/iro/token.js +4 -1
  108. package/dist/chains/eni/batch-router/bundle-approve.js +4 -3
  109. package/dist/chains/eni/batch-router/transfer.js +54 -23
  110. package/dist/chains/eni/batch-router/utils.js +32 -6
  111. package/dist/chains/eni/bundler/sign.js +4 -4
  112. package/dist/chains/eni/bundler/submit.js +1 -4
  113. package/dist/chains/eni/constants.js +1 -1
  114. package/dist/chains/eni/index.d.ts +1 -1
  115. package/dist/chains/eni/platforms/daoaas/create.js +2 -2
  116. package/dist/chains/eni/platforms/daoaas/index.d.ts +3 -3
  117. package/dist/chains/eni/platforms/daoaas/index.js +3 -3
  118. package/dist/chains/eni/platforms/daoaas/meta.js +8 -4
  119. package/dist/chains/eni/platforms/daoaas/portal-direct.js +28 -43
  120. package/dist/chains/eni/platforms/daoaas/portal.js +10 -6
  121. package/dist/chains/eni/platforms/dswap/liquidity.js +58 -26
  122. package/dist/chains/eni/platforms/fair-launch/index.d.ts +2 -2
  123. package/dist/chains/eni/platforms/fair-launch/index.js +1 -1
  124. package/dist/chains/eni/platforms/fair-launch/launcher.js +87 -47
  125. package/dist/chains/eni/platforms/fair-launch/pool.js +4 -1
  126. package/dist/chains/eni/platforms/fair-launch/presets.js +2 -2
  127. package/dist/chains/eni/platforms/iro/factory.js +3 -1
  128. package/dist/chains/eni/platforms/iro/index.d.ts +6 -6
  129. package/dist/chains/eni/platforms/iro/index.js +4 -4
  130. package/dist/chains/eni/platforms/iro/pool.js +90 -26
  131. package/dist/chains/eni/platforms/iro/token.js +107 -31
  132. package/dist/chains/eni/platforms/iro/whitelist.js +6 -18
  133. package/dist/chains/eni/submit.js +5 -13
  134. package/dist/chains/index.d.ts +13 -0
  135. package/dist/chains/index.js +13 -0
  136. package/dist/chains/xlayer/eip7702/bundle-approve.d.ts +2 -26
  137. package/dist/chains/xlayer/eip7702/bundle-approve.js +11 -20
  138. package/dist/chains/xlayer/eip7702/bundle-buy.d.ts +2 -6
  139. package/dist/chains/xlayer/eip7702/bundle-buy.js +13 -51
  140. package/dist/chains/xlayer/eip7702/bundle-create.js +93 -56
  141. package/dist/chains/xlayer/eip7702/bundle-sell.d.ts +2 -6
  142. package/dist/chains/xlayer/eip7702/bundle-sell.js +26 -74
  143. package/dist/chains/xlayer/eip7702/bundle-swap.d.ts +3 -65
  144. package/dist/chains/xlayer/eip7702/bundle-swap.js +51 -68
  145. package/dist/chains/xlayer/eip7702/constants.d.ts +1 -16
  146. package/dist/chains/xlayer/eip7702/constants.js +3 -21
  147. package/dist/chains/xlayer/eip7702/index.d.ts +29 -46
  148. package/dist/chains/xlayer/eip7702/index.js +27 -81
  149. package/dist/chains/xlayer/eip7702/{multi-hop-transfer/types.d.ts → multi-hop-transfer-helpers.d.ts} +17 -23
  150. package/dist/chains/xlayer/eip7702/multi-hop-transfer.d.ts +2 -203
  151. package/dist/chains/xlayer/eip7702/multi-hop-transfer.js +58 -291
  152. package/dist/chains/xlayer/eip7702/transfer-context-helpers.d.ts +26 -0
  153. package/dist/chains/xlayer/eip7702/transfer-context-helpers.js +57 -0
  154. package/dist/chains/xlayer/eip7702/types.d.ts +88 -0
  155. package/dist/chains/xlayer/eip7702/utils.d.ts +0 -3
  156. package/dist/chains/xlayer/eip7702/utils.js +23 -28
  157. package/dist/chains/xlayer/eip7702/{volume/types.d.ts → volume-helpers.d.ts} +41 -17
  158. package/dist/chains/xlayer/eip7702/volume-helpers.js +48 -0
  159. package/dist/chains/xlayer/eip7702/volume.d.ts +6 -184
  160. package/dist/chains/xlayer/eip7702/volume.js +83 -158
  161. package/dist/chains/xlayer/eoa/constants.js +1 -1
  162. package/dist/chains/xlayer/eoa/dex-helpers.js +5 -5
  163. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.d.ts +126 -0
  164. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.js +228 -0
  165. package/dist/chains/xlayer/eoa/eoa-bundle-swap.d.ts +1 -95
  166. package/dist/chains/xlayer/eoa/eoa-bundle-swap.js +64 -276
  167. package/dist/chains/xlayer/eoa/eoa-wash-volume.d.ts +1 -1
  168. package/dist/chains/xlayer/eoa/eoa-wash-volume.js +14 -14
  169. package/dist/chains/xlayer/eoa/index.d.ts +10 -6
  170. package/dist/chains/xlayer/eoa/index.js +8 -23
  171. package/dist/chains/xlayer/eoa/portal-ops.js +7 -2
  172. package/dist/chains/xlayer/eoa/router-manager.js +3 -3
  173. package/dist/chains/xlayer/eoa/types.d.ts +2 -2
  174. package/dist/chains/xlayer/eoa/types.js +1 -3
  175. package/dist/contracts/helper3.d.ts +20 -17
  176. package/dist/contracts/helper3.js +56 -20
  177. package/dist/contracts/tm-bundle-helpers.d.ts +88 -0
  178. package/dist/contracts/tm-bundle-helpers.js +72 -0
  179. package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.d.ts +1 -26
  180. package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.js +1 -117
  181. package/dist/contracts/tm-bundle-merkle/config.d.ts +5 -70
  182. package/dist/contracts/tm-bundle-merkle/config.js +2 -115
  183. package/dist/contracts/tm-bundle-merkle/core.d.ts +1 -4
  184. package/dist/contracts/tm-bundle-merkle/core.js +1 -588
  185. package/dist/contracts/tm-bundle-merkle/index.d.ts +5 -5
  186. package/dist/contracts/tm-bundle-merkle/index.js +5 -5
  187. package/dist/contracts/tm-bundle-merkle/internal.d.ts +2 -50
  188. package/dist/contracts/tm-bundle-merkle/internal.js +2 -236
  189. package/dist/contracts/tm-bundle-merkle/pancake-proxy.d.ts +1 -28
  190. package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +1 -687
  191. package/dist/contracts/tm-bundle-merkle/private.d.ts +1 -27
  192. package/dist/contracts/tm-bundle-merkle/private.js +1 -476
  193. package/dist/contracts/tm-bundle-merkle/submit.d.ts +3 -314
  194. package/dist/contracts/tm-bundle-merkle/submit.js +3 -919
  195. package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +2 -55
  196. package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +2 -505
  197. package/dist/contracts/tm-bundle-merkle/swap-internal.d.ts +1 -3
  198. package/dist/contracts/tm-bundle-merkle/swap-internal.js +1 -18
  199. package/dist/contracts/tm-bundle-merkle/swap.d.ts +2 -144
  200. package/dist/contracts/tm-bundle-merkle/swap.js +2 -757
  201. package/dist/contracts/tm-bundle-merkle/types.d.ts +1 -476
  202. package/dist/contracts/tm-bundle-merkle/utils-disperse.d.ts +1 -0
  203. package/dist/contracts/tm-bundle-merkle/utils-disperse.js +1 -0
  204. package/dist/contracts/tm-bundle-merkle/utils-pairwise.d.ts +1 -0
  205. package/dist/contracts/tm-bundle-merkle/utils-pairwise.js +1 -0
  206. package/dist/contracts/tm-bundle-merkle/utils-sweep.d.ts +1 -0
  207. package/dist/contracts/tm-bundle-merkle/utils-sweep.js +1 -0
  208. package/dist/contracts/tm-bundle-merkle/utils.d.ts +5 -6
  209. package/dist/contracts/tm-bundle-merkle/utils.js +5 -6
  210. package/dist/contracts/tm-bundle.d.ts +3 -51
  211. package/dist/contracts/tm-bundle.js +102 -142
  212. package/dist/contracts/tm.d.ts +3 -2
  213. package/dist/contracts/tm.js +36 -32
  214. package/dist/contracts/tm1.js +9 -4
  215. package/dist/contracts/tm2.js +9 -4
  216. package/dist/dex/direct-router-helpers.d.ts +264 -0
  217. package/dist/dex/direct-router-helpers.js +539 -0
  218. package/dist/dex/direct-router.d.ts +3 -125
  219. package/dist/dex/direct-router.js +237 -652
  220. package/dist/dex/{direct-router/types.d.ts → types.d.ts} +1 -1
  221. package/dist/exports/root-bundle-and-tooling.d.ts +27 -0
  222. package/dist/exports/root-bundle-and-tooling.js +30 -0
  223. package/dist/exports/root-eni-and-bsc-iro.d.ts +26 -0
  224. package/dist/exports/root-eni-and-bsc-iro.js +66 -0
  225. package/dist/exports/root-foundations.d.ts +35 -0
  226. package/dist/exports/root-foundations.js +70 -0
  227. package/dist/exports/root-swap-dex-and-xlayer.d.ts +30 -0
  228. package/dist/exports/root-swap-dex-and-xlayer.js +78 -0
  229. package/dist/flap/index.d.ts +10 -0
  230. package/dist/flap/index.js +8 -0
  231. package/dist/flows/create.d.ts +2 -2
  232. package/dist/flows/create.js +6 -6
  233. package/dist/flows/index.d.ts +1 -0
  234. package/dist/flows/index.js +1 -0
  235. package/dist/index.d.ts +20 -91
  236. package/dist/index.js +20 -215
  237. package/dist/shared/abis/common.d.ts +2 -83
  238. package/dist/shared/abis/common.js +2 -252
  239. package/dist/shared/abis/index.d.ts +5 -6
  240. package/dist/shared/abis/index.js +5 -7
  241. package/dist/shared/clients/blockrazor.js +41 -24
  242. package/dist/shared/clients/club48.js +30 -26
  243. package/dist/shared/clients/emitservice.js +2 -0
  244. package/dist/shared/clients/four.js +23 -18
  245. package/dist/shared/clients/index.d.ts +8 -0
  246. package/dist/shared/clients/index.js +8 -0
  247. package/dist/shared/clients/merkle.js +26 -30
  248. package/dist/shared/constants/addresses.d.ts +1 -1
  249. package/dist/shared/constants/addresses.js +11 -2
  250. package/dist/shared/constants/chains.d.ts +1 -1
  251. package/dist/shared/constants/chains.js +1 -1
  252. package/dist/shared/constants/gas.d.ts +1 -1
  253. package/dist/shared/constants/gas.js +2 -6
  254. package/dist/shared/constants/index.d.ts +3 -0
  255. package/dist/shared/constants/index.js +1 -0
  256. package/dist/shared/constants/quote.d.ts +30 -0
  257. package/dist/shared/constants/quote.js +37 -0
  258. package/dist/shared/flap/abi.js +1 -1
  259. package/dist/shared/flap/constants.d.ts +1 -1
  260. package/dist/shared/flap/constants.js +2 -2
  261. package/dist/shared/flap/curve.js +3 -0
  262. package/dist/shared/flap/errors.d.ts +1 -4
  263. package/dist/shared/flap/errors.js +21 -3
  264. package/dist/shared/flap/index.d.ts +2 -2
  265. package/dist/shared/flap/index.js +2 -2
  266. package/dist/shared/flap/meta.d.ts +16 -18
  267. package/dist/shared/flap/meta.js +14 -26
  268. package/dist/shared/flap/permit.js +6 -5
  269. package/dist/shared/flap/pinata.d.ts +9 -2
  270. package/dist/shared/flap/pinata.js +20 -18
  271. package/dist/shared/flap/portal-bundle-merkle/config.d.ts +3 -72
  272. package/dist/shared/flap/portal-bundle-merkle/config.js +4 -124
  273. package/dist/shared/flap/portal-bundle-merkle/core-helpers.d.ts +32 -0
  274. package/dist/shared/flap/portal-bundle-merkle/core-helpers.js +83 -0
  275. package/dist/shared/flap/portal-bundle-merkle/core.d.ts +0 -4
  276. package/dist/shared/flap/portal-bundle-merkle/core.js +66 -156
  277. package/dist/shared/flap/portal-bundle-merkle/create-to-dex.js +81 -86
  278. package/dist/shared/flap/portal-bundle-merkle/curve-to-dex.js +100 -92
  279. package/dist/shared/flap/portal-bundle-merkle/index.d.ts +11 -7
  280. package/dist/shared/flap/portal-bundle-merkle/index.js +4 -7
  281. package/dist/shared/flap/portal-bundle-merkle/pancake-proxy.js +71 -68
  282. package/dist/shared/flap/portal-bundle-merkle/private.js +61 -114
  283. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.d.ts +125 -0
  284. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.js +113 -0
  285. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.d.ts +1 -64
  286. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.js +66 -247
  287. package/dist/shared/flap/portal-bundle-merkle/swap-helpers.d.ts +149 -0
  288. package/dist/shared/flap/portal-bundle-merkle/swap-helpers.js +259 -0
  289. package/dist/shared/flap/portal-bundle-merkle/swap.d.ts +2 -71
  290. package/dist/shared/flap/portal-bundle-merkle/swap.js +103 -410
  291. package/dist/shared/flap/portal-bundle-merkle/types.d.ts +73 -3
  292. package/dist/shared/flap/portal-bundle-merkle/utils.d.ts +1 -80
  293. package/dist/shared/flap/portal-bundle-merkle/utils.js +145 -265
  294. package/dist/shared/flap/portal-bundle.js +54 -42
  295. package/dist/shared/flap/portal.js +32 -10
  296. package/dist/shared/flap/vanity.js +4 -7
  297. package/dist/shared/flap/vault.d.ts +1 -1
  298. package/dist/shared/flap/vault.js +54 -48
  299. package/dist/shared/foundation/dex/v3-path.d.ts +6 -0
  300. package/dist/shared/foundation/dex/v3-path.js +35 -0
  301. package/dist/shared/foundation/gas/bundle-gas.d.ts +39 -0
  302. package/dist/shared/foundation/gas/bundle-gas.js +93 -0
  303. package/dist/shared/foundation/gas/profit-hop.d.ts +20 -0
  304. package/dist/shared/foundation/gas/profit-hop.js +72 -0
  305. package/dist/shared/foundation/index.d.ts +13 -0
  306. package/dist/shared/foundation/index.js +12 -0
  307. package/dist/shared/foundation/nonce/nonce-manager.d.ts +17 -0
  308. package/dist/shared/foundation/nonce/nonce-manager.js +180 -0
  309. package/dist/shared/foundation/normalize-unknown.d.ts +9 -0
  310. package/dist/shared/foundation/normalize-unknown.js +29 -0
  311. package/dist/shared/foundation/sdk-logger.d.ts +13 -0
  312. package/dist/shared/foundation/sdk-logger.js +12 -0
  313. package/dist/shared/foundation/tx/build-request.d.ts +17 -0
  314. package/dist/shared/foundation/tx/build-request.js +25 -0
  315. package/dist/shared/foundation/tx/sign-batch.d.ts +5 -0
  316. package/dist/shared/foundation/tx/sign-batch.js +26 -0
  317. package/dist/shared/foundation/tx/wallet-sign-patch.js +18 -0
  318. package/dist/shared/foundation/types/airdrop-sweep.d.ts +79 -0
  319. package/dist/{utils/erc20/types.d.ts → shared/foundation/types/erc20.d.ts} +7 -19
  320. package/dist/{utils/holders-maker/types.d.ts → shared/foundation/types/holders-maker.d.ts} +4 -12
  321. package/dist/shared/foundation/types/index.d.ts +7 -0
  322. package/dist/{utils/lp-inspect/types.d.ts → shared/foundation/types/lp-inspect.d.ts} +4 -2
  323. package/dist/shared/foundation/types/multicall.d.ts +5 -0
  324. package/dist/shared/foundation/types/multicall.js +1 -0
  325. package/dist/shared/foundation/types/private-sale.d.ts +35 -0
  326. package/dist/shared/foundation/types/private-sale.js +1 -0
  327. package/dist/{utils/quote-helpers/types.d.ts → shared/foundation/types/quote-helpers.d.ts} +1 -0
  328. package/dist/shared/foundation/types/quote-helpers.js +1 -0
  329. package/dist/shared/four/tax-token.d.ts +1 -1
  330. package/dist/shared/four/tax-token.js +27 -7
  331. package/dist/shared/index.d.ts +6 -0
  332. package/dist/shared/index.js +4 -0
  333. package/dist/utils/airdrop-sweep.d.ts +4 -76
  334. package/dist/utils/airdrop-sweep.js +38 -52
  335. package/dist/utils/bundle-helpers.d.ts +9 -243
  336. package/dist/utils/bundle-helpers.js +10 -584
  337. package/dist/utils/constants.d.ts +5 -61
  338. package/dist/utils/constants.js +5 -80
  339. package/dist/utils/contract-factory.d.ts +2 -4
  340. package/dist/utils/contract-factory.js +25 -18
  341. package/dist/utils/erc20.d.ts +8 -90
  342. package/dist/utils/erc20.js +94 -153
  343. package/dist/utils/errors.d.ts +10 -22
  344. package/dist/utils/errors.js +61 -79
  345. package/dist/utils/holders-maker/addresses.d.ts +12 -0
  346. package/dist/utils/holders-maker/addresses.js +15 -0
  347. package/dist/utils/holders-maker/buy-tx.d.ts +44 -0
  348. package/dist/utils/holders-maker/buy-tx.js +278 -0
  349. package/dist/utils/holders-maker/constants.d.ts +6 -0
  350. package/dist/utils/holders-maker/constants.js +7 -0
  351. package/dist/utils/holders-maker/disperse.d.ts +18 -0
  352. package/dist/utils/holders-maker/disperse.js +90 -0
  353. package/dist/utils/holders-maker/routing.d.ts +4 -0
  354. package/dist/utils/holders-maker/routing.js +45 -0
  355. package/dist/utils/holders-maker/transfer-tx.d.ts +4 -0
  356. package/dist/utils/holders-maker/transfer-tx.js +67 -0
  357. package/dist/utils/holders-maker-helpers.d.ts +9 -0
  358. package/dist/utils/holders-maker-helpers.js +9 -0
  359. package/dist/utils/holders-maker.d.ts +2 -138
  360. package/dist/utils/holders-maker.js +23 -651
  361. package/dist/utils/hop-chains.d.ts +35 -0
  362. package/dist/utils/hop-chains.js +215 -0
  363. package/dist/utils/lp-inspect-helpers.d.ts +9 -0
  364. package/dist/utils/lp-inspect-helpers.js +109 -0
  365. package/dist/utils/lp-inspect.d.ts +2 -112
  366. package/dist/utils/lp-inspect.js +63 -195
  367. package/dist/utils/mpcExclusive.d.ts +2 -5
  368. package/dist/utils/mpcExclusive.js +4 -3
  369. package/dist/utils/private-sale.d.ts +2 -58
  370. package/dist/utils/private-sale.js +2 -7
  371. package/dist/utils/provider-factory.d.ts +4 -0
  372. package/dist/utils/provider-factory.js +10 -0
  373. package/dist/utils/quote-helpers.d.ts +4 -45
  374. package/dist/utils/quote-helpers.js +15 -65
  375. package/dist/utils/stealth-transfer.d.ts +2 -28
  376. package/dist/utils/stealth-transfer.js +30 -14
  377. package/dist/utils/swap-helpers.d.ts +0 -3
  378. package/dist/utils/swap-helpers.js +6 -9
  379. package/dist/utils/types/airdrop-sweep.d.ts +1 -0
  380. package/dist/utils/types/airdrop-sweep.js +1 -0
  381. package/dist/utils/types/contract-factory.d.ts +1 -0
  382. package/dist/utils/types/contract-factory.js +1 -0
  383. package/dist/utils/types/erc20.d.ts +1 -0
  384. package/dist/utils/types/erc20.js +1 -0
  385. package/dist/utils/types/errors.d.ts +1 -0
  386. package/dist/utils/types/errors.js +1 -0
  387. package/dist/utils/types/holders-maker.d.ts +1 -0
  388. package/dist/utils/types/holders-maker.js +1 -0
  389. package/dist/utils/types/hop-chains.d.ts +8 -0
  390. package/dist/utils/types/hop-chains.js +1 -0
  391. package/dist/utils/types/index.d.ts +13 -0
  392. package/dist/utils/types/index.js +1 -0
  393. package/dist/utils/types/lp-inspect.d.ts +1 -0
  394. package/dist/utils/types/lp-inspect.js +1 -0
  395. package/dist/utils/types/mpc-exclusive.d.ts +5 -0
  396. package/dist/utils/types/mpc-exclusive.js +1 -0
  397. package/dist/utils/types/private-sale.d.ts +1 -0
  398. package/dist/utils/types/private-sale.js +1 -0
  399. package/dist/utils/types/quote-helpers.d.ts +1 -0
  400. package/dist/utils/types/quote-helpers.js +1 -0
  401. package/dist/utils/types/stealth-transfer.d.ts +44 -0
  402. package/dist/utils/types/stealth-transfer.js +1 -0
  403. package/dist/utils/types/wallet.d.ts +25 -0
  404. package/dist/utils/types/wallet.js +1 -0
  405. package/dist/utils/wallet.d.ts +2 -25
  406. package/dist/utils/wallet.js +9 -10
  407. package/package.json +120 -2
  408. package/src/abis/contracts/TaxToken.json +969 -0
  409. package/src/abis/contracts/TokenManager.json +836 -0
  410. package/src/abis/contracts/TokenManager2.json +136 -0
  411. package/src/abis/contracts/TokenManagerHelper3.json +993 -0
  412. package/dist/chains/bsc/four/submit/blockrazor.d.ts +0 -18
  413. package/dist/chains/bsc/four/submit/blockrazor.js +0 -86
  414. package/dist/chains/bsc/four/submit/direct.d.ts +0 -66
  415. package/dist/chains/bsc/four/submit/direct.js +0 -452
  416. package/dist/chains/bsc/four/submit/helpers.d.ts +0 -18
  417. package/dist/chains/bsc/four/submit/helpers.js +0 -57
  418. package/dist/chains/bsc/four/submit/index.d.ts +0 -12
  419. package/dist/chains/bsc/four/submit/index.js +0 -11
  420. package/dist/chains/bsc/four/submit/merkle.d.ts +0 -18
  421. package/dist/chains/bsc/four/submit/merkle.js +0 -74
  422. package/dist/chains/bsc/four/submit/types.d.ts +0 -143
  423. package/dist/chains/bsc/four/swap/index.d.ts +0 -32
  424. package/dist/chains/bsc/four/swap/types.d.ts +0 -70
  425. package/dist/chains/bsc/four/utils/index.d.ts +0 -20
  426. package/dist/chains/bsc/four/utils/index.js +0 -1558
  427. package/dist/chains/bsc/pancake/bundle-buy-first/index.d.ts +0 -8
  428. package/dist/chains/bsc/pancake/bundle-buy-first/index.js +0 -907
  429. package/dist/chains/bsc/pancake/bundle-buy-first/types.d.ts +0 -73
  430. package/dist/chains/bsc/pancake/bundle-swap/helpers.d.ts +0 -102
  431. package/dist/chains/bsc/pancake/bundle-swap/index.d.ts +0 -50
  432. package/dist/chains/bsc/pancake/bundle-swap/index.js +0 -1066
  433. package/dist/chains/bsc/pancake/bundle-swap/types.d.ts +0 -202
  434. package/dist/chains/bsc/pancake/bundle-swap/types.js +0 -3
  435. package/dist/chains/xlayer/eip7702/bundle-swap/index.d.ts +0 -72
  436. package/dist/chains/xlayer/eip7702/bundle-swap/index.js +0 -921
  437. package/dist/chains/xlayer/eip7702/bundle-swap/types.d.ts +0 -65
  438. package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.d.ts +0 -128
  439. package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.js +0 -857
  440. package/dist/chains/xlayer/eip7702/volume/index.d.ts +0 -96
  441. package/dist/chains/xlayer/eip7702/volume/index.js +0 -793
  442. package/dist/dex/direct-router/index.d.ts +0 -70
  443. package/dist/dex/direct-router/index.js +0 -1410
  444. package/dist/shared/abis/TaxToken.json +0 -969
  445. package/dist/shared/abis/TokenManager.json +0 -836
  446. package/dist/shared/abis/TokenManager2.json +0 -136
  447. package/dist/shared/abis/TokenManagerHelper3.json +0 -993
  448. package/dist/shared/flap/__tests__/curve.test.js +0 -85
  449. package/dist/shared/flap/portal/index.d.ts +0 -12
  450. package/dist/shared/flap/portal/index.js +0 -11
  451. package/dist/shared/flap/portal/portal.d.ts +0 -47
  452. package/dist/shared/flap/portal/portal.js +0 -218
  453. package/dist/shared/flap/portal/types.d.ts +0 -227
  454. package/dist/shared/flap/portal/types.js +0 -80
  455. package/dist/shared/flap/portal/writer.d.ts +0 -121
  456. package/dist/shared/flap/portal/writer.js +0 -265
  457. package/dist/shared/flap/portal-bundle-merkle/core/index.d.ts +0 -18
  458. package/dist/shared/flap/portal-bundle-merkle/core/index.js +0 -938
  459. package/dist/shared/flap/portal-bundle-merkle/swap/index.d.ts +0 -42
  460. package/dist/shared/flap/portal-bundle-merkle/swap/index.js +0 -1448
  461. package/dist/shared/flap/portal-bundle-merkle/swap/types.d.ts +0 -84
  462. package/dist/shared/flap/portal-bundle-merkle/utils/index.d.ts +0 -17
  463. package/dist/shared/flap/portal-bundle-merkle/utils/index.js +0 -1024
  464. package/dist/shared/flap/portal-bundle-merkle/utils/types.d.ts +0 -16
  465. package/dist/shared 2/abis/TaxToken.json +0 -105
  466. package/dist/shared 2/abis/TokenManager.json +0 -836
  467. package/dist/shared 2/abis/TokenManager2.json +0 -60
  468. package/dist/shared 2/abis/TokenManagerHelper3.json +0 -993
  469. package/dist/shared 2/abis/common.d.ts +0 -85
  470. package/dist/shared 2/abis/common.js +0 -254
  471. package/dist/shared 2/abis/index.d.ts +0 -8
  472. package/dist/shared 2/abis/index.js +0 -8
  473. package/dist/shared 2/clients/blockrazor.d.ts +0 -314
  474. package/dist/shared 2/clients/blockrazor.js +0 -596
  475. package/dist/shared 2/clients/club48.d.ts +0 -154
  476. package/dist/shared 2/clients/club48.js +0 -331
  477. package/dist/shared 2/clients/emitservice.d.ts +0 -47
  478. package/dist/shared 2/clients/emitservice.js +0 -44
  479. package/dist/shared 2/clients/four.d.ts +0 -132
  480. package/dist/shared 2/clients/four.js +0 -281
  481. package/dist/shared 2/clients/merkle.d.ts +0 -210
  482. package/dist/shared 2/clients/merkle.js +0 -400
  483. package/dist/shared 2/flap/__tests__/curve.test.js +0 -85
  484. package/dist/shared 2/flap/abi.d.ts +0 -4
  485. package/dist/shared 2/flap/abi.js +0 -4
  486. package/dist/shared 2/flap/constants.d.ts +0 -128
  487. package/dist/shared 2/flap/constants.js +0 -143
  488. package/dist/shared 2/flap/curve.d.ts +0 -33
  489. package/dist/shared 2/flap/curve.js +0 -84
  490. package/dist/shared 2/flap/errors.d.ts +0 -37
  491. package/dist/shared 2/flap/errors.js +0 -114
  492. package/dist/shared 2/flap/index.d.ts +0 -22
  493. package/dist/shared 2/flap/index.js +0 -33
  494. package/dist/shared 2/flap/ipfs.d.ts +0 -21
  495. package/dist/shared 2/flap/ipfs.js +0 -38
  496. package/dist/shared 2/flap/meta.d.ts +0 -30
  497. package/dist/shared 2/flap/meta.js +0 -195
  498. package/dist/shared 2/flap/permit.d.ts +0 -16
  499. package/dist/shared 2/flap/permit.js +0 -67
  500. package/dist/shared 2/flap/pinata.d.ts +0 -40
  501. package/dist/shared 2/flap/pinata.js +0 -106
  502. package/dist/shared 2/flap/portal-bundle-merkle/config.d.ts +0 -79
  503. package/dist/shared 2/flap/portal-bundle-merkle/config.js +0 -133
  504. package/dist/shared 2/flap/portal-bundle-merkle/core.d.ts +0 -18
  505. package/dist/shared 2/flap/portal-bundle-merkle/core.js +0 -938
  506. package/dist/shared 2/flap/portal-bundle-merkle/create-to-dex.d.ts +0 -125
  507. package/dist/shared 2/flap/portal-bundle-merkle/create-to-dex.js +0 -665
  508. package/dist/shared 2/flap/portal-bundle-merkle/curve-to-dex.d.ts +0 -88
  509. package/dist/shared 2/flap/portal-bundle-merkle/curve-to-dex.js +0 -446
  510. package/dist/shared 2/flap/portal-bundle-merkle/index.d.ts +0 -14
  511. package/dist/shared 2/flap/portal-bundle-merkle/index.js +0 -26
  512. package/dist/shared 2/flap/portal-bundle-merkle/pancake-proxy.d.ts +0 -28
  513. package/dist/shared 2/flap/portal-bundle-merkle/private.d.ts +0 -17
  514. package/dist/shared 2/flap/portal-bundle-merkle/private.js +0 -549
  515. package/dist/shared 2/flap/portal-bundle-merkle/swap-buy-first.d.ts +0 -65
  516. package/dist/shared 2/flap/portal-bundle-merkle/swap-buy-first.js +0 -831
  517. package/dist/shared 2/flap/portal-bundle-merkle/swap.d.ts +0 -201
  518. package/dist/shared 2/flap/portal-bundle-merkle/swap.js +0 -1359
  519. package/dist/shared 2/flap/portal-bundle-merkle/types.d.ts +0 -358
  520. package/dist/shared 2/flap/portal-bundle-merkle/utils.d.ts +0 -89
  521. package/dist/shared 2/flap/portal-bundle-merkle/utils.js +0 -963
  522. package/dist/shared 2/flap/portal-bundle.d.ts +0 -119
  523. package/dist/shared 2/flap/portal-bundle.js +0 -584
  524. package/dist/shared 2/flap/portal.d.ts +0 -392
  525. package/dist/shared 2/flap/portal.js +0 -559
  526. package/dist/shared 2/flap/vanity.d.ts +0 -48
  527. package/dist/shared 2/flap/vanity.js +0 -110
  528. package/dist/shared 2/flap/vault.d.ts +0 -240
  529. package/dist/shared 2/flap/vault.js +0 -366
  530. package/dist/shared 2/four/index.d.ts +0 -7
  531. package/dist/shared 2/four/index.js +0 -22
  532. package/dist/shared 2/four/tax-token.d.ts +0 -176
  533. package/dist/shared 2/four/tax-token.js +0 -302
  534. package/dist/shared 2/index.d.ts +0 -10
  535. package/dist/shared 2/index.js +0 -10
  536. package/dist/utils/__tests__/errors.test.js +0 -76
  537. package/dist/utils/erc20/index.d.ts +0 -242
  538. package/dist/utils/erc20/index.js +0 -645
  539. package/dist/utils/holders-maker/helpers.d.ts +0 -43
  540. package/dist/utils/holders-maker/helpers.js +0 -371
  541. package/dist/utils/holders-maker/index.d.ts +0 -26
  542. package/dist/utils/holders-maker/index.js +0 -218
  543. package/dist/utils/holders-maker/types.js +0 -4
  544. package/dist/utils/lp-inspect/index.d.ts +0 -44
  545. package/dist/utils/lp-inspect/index.js +0 -937
  546. package/dist/utils/quote-helpers/index.d.ts +0 -107
  547. package/dist/utils/quote-helpers/index.js +0 -346
  548. /package/dist/{chains/bsc/four/submit/types.js → __tests__/subpath-exports.test.d.ts} +0 -0
  549. /package/dist/{chains/bsc/four/swap/types.js → bundle-core/__tests__/config-helpers.test.d.ts} +0 -0
  550. /package/dist/{chains/bsc/four/utils/types.d.ts → bundle-core/__tests__/facade-parity.test.d.ts} +0 -0
  551. /package/dist/{chains/bsc/four/utils/types.js → bundle-core/__tests__/sign-context-helpers.test.d.ts} +0 -0
  552. /package/dist/{chains/bsc/pancake/bundle-buy-first/types.js → bundle-core/__tests__/sign-fixture.test.d.ts} +0 -0
  553. /package/dist/{chains/xlayer/eip7702/multi-hop-transfer/types.js → bundle-core/four-meme/types/buy-first.js} +0 -0
  554. /package/dist/{chains/xlayer/eip7702/volume/types.js → bundle-core/four-meme/types/core-flow.js} +0 -0
  555. /package/dist/{dex/direct-router/types.js → bundle-core/four-meme/types/index.js} +0 -0
  556. /package/dist/{shared 2/flap/__tests__/curve.test.d.ts → bundle-core/four-meme/types/swap-internal.js} +0 -0
  557. /package/dist/{chains/xlayer/eip7702/bundle-swap → bundle-core/four-meme}/types.js +0 -0
  558. /package/dist/{shared/flap/__tests__/curve.test.d.ts → bundle-core/types/index.js} +0 -0
  559. /package/dist/{shared 2/flap/portal-bundle-merkle → bundle-core}/types.js +0 -0
  560. /package/dist/{shared/flap/portal-bundle-merkle/core/types.d.ts → chains/xlayer/eip7702/multi-hop-transfer-helpers.js} +0 -0
  561. /package/dist/{shared/flap/portal-bundle-merkle/core → dex}/types.js +0 -0
  562. /package/dist/shared/{flap/portal-bundle-merkle/swap/types.js → foundation/tx/wallet-sign-patch.d.ts} +0 -0
  563. /package/dist/shared/{flap/portal-bundle-merkle/utils/types.js → foundation/types/airdrop-sweep.js} +0 -0
  564. /package/dist/{utils/__tests__/errors.test.d.ts → shared/foundation/types/erc20.js} +0 -0
  565. /package/dist/{utils/erc20/types.js → shared/foundation/types/holders-maker.js} +0 -0
  566. /package/dist/{utils/lp-inspect/types.js → shared/foundation/types/index.js} +0 -0
  567. /package/dist/{utils/quote-helpers/types.js → shared/foundation/types/lp-inspect.js} +0 -0
@@ -1,1066 +0,0 @@
1
- import { ethers, Contract, Wallet } from 'ethers';
2
- import { calculateSellAmount } from '../../../../utils/swap-helpers.js';
3
- import { NonceManager, getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../../../utils/bundle-helpers.js';
4
- import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA } from '../../../../utils/constants.js';
5
- import { V2_ROUTER_ABI, V3_ROUTER02_ABI, ERC20_BALANCE_ABI, ERC20_ABI } from '../../../../shared/abis/common.js';
6
- import { GAS_LIMITS, CHAINS } from '../../../../shared/constants/index.js';
7
- import { createPancakeContext, getGasLimit, getGasPrice, quoteSellOutput, buildSwapTransactions, calculateBuyerBudget, calculateProfitAmount, getERC20ToNativeQuote, planNonces, buildNoncePlanFromNonces, validateFinalBalances, generateDisperseHopPaths, buildNativeHopChain, buildERC20HopChain, buildBNBHopChainForERC20, } from './helpers.js';
8
- const PANCAKE_V2_ROUTER_ABI = V2_ROUTER_ABI;
9
- const PANCAKE_V3_ROUTER_ABI = V3_ROUTER02_ABI;
10
- const ERC20_BALANCE_OF_ABI = ERC20_BALANCE_ABI;
11
- const PANCAKE_V2_ROUTER_ADDRESS = ADDRESSES.BSC.PancakeV2Router;
12
- const PANCAKE_V3_ROUTER_ADDRESS = ADDRESSES.BSC.PancakeV3Router;
13
- const FLAT_FEE = 0n;
14
- const WBNB_ADDRESS = ADDRESSES.BSC.WBNB;
15
- const BRIBE_GAS_LIMIT = GAS_LIMITS.BRIBE;
16
- const NATIVE_TRANSFER_GAS_LIMIT = GAS_LIMITS.NATIVE_TRANSFER;
17
- const ERC20_TRANSFER_GAS_LIMIT_HOP = GAS_LIMITS.ERC20_TRANSFER;
18
- const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
19
- /* ====== pancakeBundleSwapMerkle ====== */
20
- export async function pancakeBundleSwapMerkle(params) {
21
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
22
- } = params;
23
- // ✅ 判断是否使用原生代币(BNB)或 ERC20 代币(如 USDT)
24
- const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
25
- const context = createPancakeContext(config);
26
- const seller = new Wallet(sellerPrivateKey, context.provider);
27
- const buyer = new Wallet(buyerPrivateKey, context.provider);
28
- const sameAddress = seller.address.toLowerCase() === buyer.address.toLowerCase();
29
- // ✅ 提前创建 NonceManager,供所有交易共享
30
- const nonceManager = new NonceManager(context.provider);
31
- const finalGasLimit = getGasLimit(config);
32
- const txType = config.txType ?? 0;
33
- // ✅ 并行获取 gasPrice 和卖出数量
34
- const [gasPrice, sellAmountResult] = await Promise.all([
35
- getGasPrice(context.provider, config),
36
- calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage)
37
- ]);
38
- const { amount: sellAmountWei, decimals } = sellAmountResult;
39
- const quoteResult = await quoteSellOutput({
40
- routeParams,
41
- sellAmountWei,
42
- provider: context.provider,
43
- v2RouterAddress: config.v2RouterAddress
44
- });
45
- const buyerBudget = await calculateBuyerBudget({
46
- buyer,
47
- quotedBNBOut: quoteResult.estimatedBNBOut,
48
- reserveGasBNB: config.reserveGasBNB,
49
- useNativeToken,
50
- quoteToken,
51
- quoteTokenDecimals,
52
- provider: context.provider
53
- });
54
- const swapUnsigned = await buildSwapTransactions({
55
- routeParams,
56
- sellAmountWei,
57
- buyAmountBNB: buyerBudget.buyAmountBNB,
58
- buyer,
59
- seller,
60
- tokenAddress,
61
- useNativeToken,
62
- v2RouterAddress: config.v2RouterAddress
63
- });
64
- // ✅ 修复:利润计算应基于 BNB 数量,不是 ERC20 数量
65
- // 如果输出是原生代币(BNB),直接使用报价结果
66
- // 如果输出是 ERC20(如 USDT),需要先转换为 BNB 等值
67
- let profitAmount;
68
- if (useNativeToken) {
69
- // 输出是 BNB,直接计算利润(根据 userType 动态调整)
70
- profitAmount = calculateProfitAmount(quoteResult.estimatedBNBOut, config.userType);
71
- // 利润计算完成
72
- }
73
- else {
74
- // 输出是 ERC20,需要先获取 ERC20 → BNB 的报价
75
- const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
76
- const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
77
- const estimatedBNBValue = await getERC20ToNativeQuote(context.provider, quoteToken, quoteResult.estimatedBNBOut, // 这实际上是 ERC20 数量
78
- version, fee);
79
- profitAmount = calculateProfitAmount(estimatedBNBValue, config.userType);
80
- // ERC20→BNB 报价完成
81
- }
82
- // ✅ 获取贿赂金额
83
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0
84
- ? ethers.parseEther(String(config.bribeAmount))
85
- : 0n;
86
- const needBribeTx = bribeAmount > 0n;
87
- // ✅ 使用共享的 NonceManager 规划 nonce
88
- // 如果前端传入了 startNonces,直接使用(性能优化)
89
- const noncePlan = startNonces && startNonces.length >= (sameAddress ? 1 : 2)
90
- ? buildNoncePlanFromNonces(startNonces, sameAddress, false, profitAmount > 0n, needBribeTx)
91
- : await planNonces({
92
- seller,
93
- buyer,
94
- sameAddress,
95
- approvalExists: false, // ✅ 已移除授权
96
- profitNeeded: profitAmount > 0n,
97
- needBribeTx,
98
- nonceManager
99
- });
100
- // ✅ 并行签名所有交易
101
- const signPromises = [];
102
- // 贿赂交易
103
- if (needBribeTx && noncePlan.bribeNonce !== undefined) {
104
- signPromises.push(seller.signTransaction({
105
- to: BLOCKRAZOR_BUILDER_EOA,
106
- value: bribeAmount,
107
- nonce: noncePlan.bribeNonce,
108
- gasPrice,
109
- gasLimit: BRIBE_GAS_LIMIT,
110
- chainId: context.chainId,
111
- type: txType
112
- }).then(tx => ({ type: 'bribe', tx })));
113
- }
114
- // 卖出交易
115
- signPromises.push(seller.signTransaction({
116
- ...swapUnsigned.sellUnsigned,
117
- from: seller.address,
118
- nonce: noncePlan.sellerNonce,
119
- gasLimit: finalGasLimit,
120
- gasPrice,
121
- chainId: context.chainId,
122
- type: txType
123
- }).then(tx => ({ type: 'sell', tx })));
124
- // 买入交易
125
- signPromises.push(buyer.signTransaction({
126
- ...swapUnsigned.buyUnsigned,
127
- from: buyer.address,
128
- nonce: noncePlan.buyerNonce,
129
- gasLimit: finalGasLimit,
130
- gasPrice,
131
- chainId: context.chainId,
132
- type: txType
133
- }).then(tx => ({ type: 'buy', tx })));
134
- // ✅ 并行执行所有签名
135
- const signedResults = await Promise.all(signPromises);
136
- // 按类型提取结果
137
- const bribeTx = signedResults.find(r => r.type === 'bribe')?.tx || null;
138
- const signedSell = signedResults.find(r => r.type === 'sell').tx;
139
- const signedBuy = signedResults.find(r => r.type === 'buy').tx;
140
- nonceManager.clearTemp();
141
- validateFinalBalances({
142
- sameAddress,
143
- buyerBalance: buyerBudget.buyerBalance,
144
- buyAmountBNB: buyerBudget.buyAmountBNB,
145
- reserveGas: buyerBudget.reserveGas,
146
- gasLimit: finalGasLimit,
147
- gasPrice,
148
- useNativeToken,
149
- quoteTokenDecimals,
150
- provider: context.provider,
151
- buyerAddress: buyer.address
152
- });
153
- // ✅ 组装顺序:贿赂 → 卖出 → 买入
154
- const signedTransactions = [];
155
- if (bribeTx)
156
- signedTransactions.push(bribeTx);
157
- signedTransactions.push(signedSell, signedBuy);
158
- // ✅ 利润多跳转账(强制 2 跳中转)
159
- let profitHopWallets;
160
- if (profitAmount > 0n && noncePlan.profitNonce !== undefined) {
161
- const profitHopResult = await buildProfitHopTransactions({
162
- provider: context.provider,
163
- payerWallet: seller,
164
- profitAmount,
165
- profitRecipient: PROFIT_CONFIG.RECIPIENT,
166
- hopCount: PROFIT_HOP_COUNT,
167
- gasPrice,
168
- chainId: context.chainId,
169
- txType,
170
- startNonce: noncePlan.profitNonce
171
- });
172
- signedTransactions.push(...profitHopResult.signedTransactions);
173
- profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
174
- }
175
- return {
176
- signedTransactions,
177
- profitHopWallets, // ✅ 导出利润多跳钱包
178
- metadata: {
179
- sellerAddress: seller.address,
180
- buyerAddress: buyer.address,
181
- sellAmount: ethers.formatUnits(sellAmountWei, decimals),
182
- buyAmount: useNativeToken
183
- ? ethers.formatEther(buyerBudget.buyAmountBNB)
184
- : ethers.formatUnits(buyerBudget.buyAmountBNB, quoteTokenDecimals),
185
- profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined
186
- }
187
- };
188
- }
189
- // ==================== 批量换手(一卖多买)====================
190
- /**
191
- * 批量换手参数(一卖多买)
192
- */
193
- /**
194
- * 批量换手结果
195
- */
196
- /**
197
- * PancakeSwap 批量换手(一卖多买)
198
- *
199
- * 功能:主钱包一次卖出 → 多个子钱包同时买入 → 在同一个区块中完成
200
- * 限制:最多 24 个买方(服务器限制 25 笔交易,包含 1 笔利润交易)
201
- *
202
- * 交易顺序:[授权(可选)] → [卖出] → [买入1, 买入2, ..., 买入N] → [利润]
203
- */
204
- export async function pancakeBatchSwapMerkle(params) {
205
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
206
- } = params;
207
- // ✅ 校验买方数量(最多 24 个)
208
- const MAX_BUYERS = 24;
209
- if (buyerPrivateKeys.length === 0) {
210
- throw new Error('至少需要一个买方钱包');
211
- }
212
- if (buyerPrivateKeys.length > MAX_BUYERS) {
213
- throw new Error(`买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`);
214
- }
215
- const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
216
- const context = createPancakeContext(config);
217
- const seller = new Wallet(sellerPrivateKey, context.provider);
218
- const buyers = buyerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
219
- // ✅ 创建共享资源
220
- const nonceManager = new NonceManager(context.provider);
221
- const finalGasLimit = getGasLimit(config);
222
- const txType = config.txType ?? 0;
223
- // ✅ 并行获取 gasPrice 和卖出数量
224
- const [gasPrice, sellAmountResult] = await Promise.all([
225
- getGasPrice(context.provider, config),
226
- calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage)
227
- ]);
228
- const { amount: sellAmountWei, decimals } = sellAmountResult;
229
- const quoteResult = await quoteSellOutput({
230
- routeParams,
231
- sellAmountWei,
232
- provider: context.provider,
233
- v2RouterAddress: config.v2RouterAddress
234
- });
235
- const estimatedBNBOut = quoteResult.estimatedBNBOut;
236
- // ✅ 计算每个买方的买入金额(已移除滑点保护:直接使用报价金额)
237
- let buyAmountsWei;
238
- const totalBuyAmount = estimatedBNBOut;
239
- if (buyerAmounts && buyerAmounts.length === buyers.length) {
240
- // 方式1:使用指定的买入金额(USDT)
241
- buyAmountsWei = buyerAmounts.map((amt) => useNativeToken
242
- ? ethers.parseEther(amt)
243
- : ethers.parseUnits(amt, quoteTokenDecimals));
244
- }
245
- else if (params.buyerRatios && params.buyerRatios.length === buyers.length) {
246
- // ✅ 方式2:按比例分配卖出所得
247
- // buyerRatios 如 [0.3, 0.5, 0.2] 表示第一个买方分 30%,第二个 50%,第三个 20%
248
- buyAmountsWei = params.buyerRatios.map((ratio, index) => {
249
- // 按比例计算每个买方的金额
250
- const amount = (totalBuyAmount * BigInt(Math.round(ratio * 10000))) / 10000n;
251
- return amount;
252
- });
253
- }
254
- else {
255
- // 方式3:平均分配
256
- const amountPerBuyer = totalBuyAmount / BigInt(buyers.length);
257
- buyAmountsWei = buyers.map(() => amountPerBuyer);
258
- }
259
- // ✅ 并行验证所有买方余额
260
- const reserveGas = ethers.parseEther((config.reserveGasBNB ?? 0.0005).toString());
261
- const erc20Contract = useNativeToken ? null : new Contract(quoteToken, ERC20_BALANCE_OF_ABI, context.provider);
262
- await Promise.all(buyers.map(async (buyer, i) => {
263
- const buyAmount = buyAmountsWei[i];
264
- if (useNativeToken) {
265
- const buyerBalance = await buyer.provider.getBalance(buyer.address);
266
- const required = buyAmount + FLAT_FEE + reserveGas;
267
- if (buyerBalance < required) {
268
- throw new Error(`买方 ${i + 1} 余额不足: 需要 ${ethers.formatEther(required)}, 实际 ${ethers.formatEther(buyerBalance)}`);
269
- }
270
- }
271
- else {
272
- const buyerBalance = await erc20Contract.balanceOf(buyer.address);
273
- const required = buyAmount + FLAT_FEE;
274
- if (buyerBalance < required) {
275
- throw new Error(`买方 ${i + 1} 代币余额不足: 需要 ${ethers.formatUnits(required, quoteTokenDecimals)}, 实际 ${ethers.formatUnits(buyerBalance, quoteTokenDecimals)}`);
276
- }
277
- }
278
- }));
279
- const deadline = getDeadline();
280
- const v3RouterIface = new ethers.Interface(PANCAKE_V3_ROUTER_ABI);
281
- const batchV2Addr = config.v2RouterAddress || PANCAKE_V2_ROUTER_ADDRESS;
282
- let sellUnsigned;
283
- if (routeParams.routeType === 'v2') {
284
- const { v2Path } = routeParams;
285
- const v2RouterSeller = new Contract(batchV2Addr, PANCAKE_V2_ROUTER_ABI, seller);
286
- if (useNativeToken) {
287
- // ✅ 原生代币模式(BNB):Token → WBNB → BNB
288
- sellUnsigned = await v2RouterSeller.swapExactTokensForETHSupportingFeeOnTransferTokens.populateTransaction(sellAmountWei, 0n, v2Path, seller.address, deadline);
289
- }
290
- else {
291
- // ✅ ERC20 模式(USDT):Token → USDT
292
- sellUnsigned = await v2RouterSeller.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(sellAmountWei, 0n, v2Path, seller.address, deadline);
293
- }
294
- }
295
- else if (routeParams.routeType === 'v3-single') {
296
- const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
297
- const v3RouterSeller = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, seller);
298
- const sellSwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
299
- tokenIn: v3TokenIn,
300
- tokenOut: v3TokenOut,
301
- fee: v3Fee,
302
- recipient: useNativeToken ? PANCAKE_V3_ROUTER_ADDRESS : seller.address,
303
- amountIn: sellAmountWei,
304
- amountOutMinimum: 0n,
305
- sqrtPriceLimitX96: 0n
306
- }]);
307
- if (useNativeToken) {
308
- // 原生代币:需要 unwrap WBNB
309
- const sellUnwrapData = v3RouterIface.encodeFunctionData('unwrapWETH9', [0n, seller.address]);
310
- sellUnsigned = await v3RouterSeller.multicall.populateTransaction(deadline, [sellSwapData, sellUnwrapData]);
311
- }
312
- else {
313
- // ERC20:直接接收代币
314
- sellUnsigned = await v3RouterSeller.multicall.populateTransaction(deadline, [sellSwapData]);
315
- }
316
- }
317
- else {
318
- throw new Error('V3 多跳路由暂不支持官方合约,请使用 V2 路由或 V3 单跳');
319
- }
320
- const buyUnsignedList = await Promise.all(buyers.map(async (buyer, i) => {
321
- const buyAmount = buyAmountsWei[i];
322
- const buyValue = useNativeToken ? buyAmount + FLAT_FEE : 0n;
323
- if (routeParams.routeType === 'v2') {
324
- const { v2Path } = routeParams;
325
- const reversePath = [...v2Path].reverse();
326
- const v2RouterBuyer = new Contract(batchV2Addr, PANCAKE_V2_ROUTER_ABI, buyer);
327
- if (useNativeToken) {
328
- // ✅ 原生代币模式(BNB):BNB → WBNB → Token
329
- return await v2RouterBuyer.swapExactETHForTokensSupportingFeeOnTransferTokens.populateTransaction(0n, reversePath, buyer.address, deadline, { value: buyValue });
330
- }
331
- else {
332
- // ✅ ERC20 模式(USDT):USDT → Token
333
- return await v2RouterBuyer.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(buyAmount, 0n, reversePath, buyer.address, deadline);
334
- }
335
- }
336
- else if (routeParams.routeType === 'v3-single') {
337
- const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
338
- const v3RouterBuyer = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, buyer);
339
- const buySwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
340
- tokenIn: v3TokenOut,
341
- tokenOut: v3TokenIn,
342
- fee: v3Fee,
343
- recipient: buyer.address,
344
- amountIn: buyAmount,
345
- amountOutMinimum: 0n,
346
- sqrtPriceLimitX96: 0n
347
- }]);
348
- return await v3RouterBuyer.multicall.populateTransaction(deadline, [buySwapData], { value: buyValue });
349
- }
350
- else {
351
- throw new Error('V3 多跳路由暂不支持官方合约,请使用 V2 路由或 V3 单跳');
352
- }
353
- }));
354
- // ✅ 获取贿赂金额
355
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0
356
- ? ethers.parseEther(String(config.bribeAmount))
357
- : 0n;
358
- // ✅ 规划 Nonce(贿赂和利润都由卖方发送)
359
- // 卖方: [贿赂(可选)] → [卖出] → [利润(可选)]
360
- let bribeNonce;
361
- let sellNonce;
362
- let buyerNonces;
363
- // ✅ 如果前端传入了 startNonces,直接使用(性能优化)
364
- if (startNonces && startNonces.length >= (1 + buyers.length)) {
365
- let sellerIdx = 0;
366
- if (bribeAmount > 0n) {
367
- bribeNonce = startNonces[0] + sellerIdx++;
368
- }
369
- sellNonce = startNonces[0] + sellerIdx;
370
- buyerNonces = startNonces.slice(1);
371
- }
372
- else {
373
- if (bribeAmount > 0n) {
374
- bribeNonce = await nonceManager.getNextNonce(seller);
375
- }
376
- sellNonce = await nonceManager.getNextNonce(seller);
377
- buyerNonces = await Promise.all(buyers.map((buyer) => nonceManager.getNextNonce(buyer)));
378
- }
379
- // ✅ 贿赂交易放在首位(由卖方发送)
380
- let bribeTx = null;
381
- if (bribeAmount > 0n && bribeNonce !== undefined) {
382
- bribeTx = await seller.signTransaction({
383
- to: BLOCKRAZOR_BUILDER_EOA,
384
- value: bribeAmount,
385
- nonce: bribeNonce,
386
- gasPrice,
387
- gasLimit: BRIBE_GAS_LIMIT,
388
- chainId: context.chainId,
389
- type: txType
390
- });
391
- }
392
- // ✅ 修复:利润计算应基于 BNB 数量,不是 ERC20 数量
393
- let profitAmount;
394
- if (useNativeToken) {
395
- profitAmount = calculateProfitAmount(estimatedBNBOut, config.userType);
396
- // 利润计算完成
397
- }
398
- else {
399
- const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
400
- const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
401
- const estimatedBNBValue = await getERC20ToNativeQuote(context.provider, quoteToken, estimatedBNBOut, version, fee);
402
- profitAmount = calculateProfitAmount(estimatedBNBValue, config.userType);
403
- // ERC20→BNB 报价完成
404
- }
405
- // 计算利润 nonce
406
- const profitNonce = profitAmount > 0n
407
- ? (startNonces && startNonces.length >= 1 ? sellNonce + 1 : await nonceManager.getNextNonce(seller))
408
- : undefined;
409
- nonceManager.clearTemp();
410
- // ✅ 并行签名所有交易
411
- // 1. 签名卖出交易
412
- const signedSellPromise = seller.signTransaction({
413
- ...sellUnsigned,
414
- from: seller.address,
415
- nonce: sellNonce,
416
- gasLimit: finalGasLimit,
417
- gasPrice,
418
- chainId: context.chainId,
419
- type: txType
420
- });
421
- // 2. 并行签名所有买入交易
422
- const signedBuyPromises = buyers.map((buyer, i) => buyer.signTransaction({
423
- ...buyUnsignedList[i],
424
- from: buyer.address,
425
- nonce: buyerNonces[i],
426
- gasLimit: finalGasLimit,
427
- gasPrice,
428
- chainId: context.chainId,
429
- type: txType
430
- }));
431
- // 3. 等待所有签名完成
432
- const [signedSell, ...signedBuys] = await Promise.all([
433
- signedSellPromise,
434
- ...signedBuyPromises
435
- ]);
436
- // 4. 按顺序组装交易数组:贿赂 → 卖出 → 买入
437
- const signedTransactions = [];
438
- if (bribeTx)
439
- signedTransactions.push(bribeTx); // 贿赂(首位)
440
- signedTransactions.push(signedSell); // 卖出
441
- signedTransactions.push(...signedBuys); // 多个买入
442
- // ✅ 利润多跳转账(强制 2 跳中转)
443
- let profitHopWallets;
444
- if (profitAmount > 0n && profitNonce !== undefined) {
445
- const profitHopResult = await buildProfitHopTransactions({
446
- provider: context.provider,
447
- payerWallet: seller,
448
- profitAmount,
449
- profitRecipient: PROFIT_CONFIG.RECIPIENT,
450
- hopCount: PROFIT_HOP_COUNT,
451
- gasPrice,
452
- chainId: context.chainId,
453
- txType,
454
- startNonce: profitNonce
455
- });
456
- signedTransactions.push(...profitHopResult.signedTransactions);
457
- profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
458
- }
459
- return {
460
- signedTransactions,
461
- profitHopWallets, // ✅ 导出利润多跳钱包
462
- metadata: {
463
- sellerAddress: seller.address,
464
- buyerAddresses: buyers.map((b) => b.address),
465
- sellAmount: ethers.formatUnits(sellAmountWei, decimals),
466
- buyAmounts: buyAmountsWei.map((amt) => useNativeToken
467
- ? ethers.formatEther(amt)
468
- : ethers.formatUnits(amt, quoteTokenDecimals)),
469
- profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined
470
- }
471
- };
472
- }
473
- // ==================== 快捷批量换手(资金自动流转)====================
474
- /**
475
- * 快捷批量换手参数
476
- * 特点:子钱包不需要预先有余额,资金来自主钱包卖出所得
477
- */
478
- /**
479
- * 快捷批量换手结果
480
- */
481
- /**
482
- * PancakeSwap 快捷批量换手(资金自动流转)
483
- *
484
- * 流程:[贿赂] → [卖出] → [转账多跳...] → [买入1, 买入2, ...] → [利润]
485
- *
486
- * 特点:
487
- * - 子钱包不需要预先有余额
488
- * - 资金来自主钱包卖出代币所得
489
- * - 提升资金利用率
490
- * - 支持 BNB 和 ERC20(如 USDT)两种模式
491
- * - ✅ 支持转账多跳,隐藏资金流向
492
- *
493
- * 限制:根据多跳数动态计算最大买方数量
494
- */
495
- export async function pancakeQuickBatchSwapMerkle(params) {
496
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, disperseHopCount = 0, // ✅ 转账多跳数(默认0=直接转账)
497
- startNonces // ✅ 可选:前端预获取的 nonces
498
- } = params;
499
- // ✅ 判断是否使用原生代币
500
- const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
501
- // ✅ 根据 chainId 获取正确的 Wrapped Native Token 地址
502
- const chainId = config.chainId ?? CHAINS.BSC.chainId;
503
- const WRAPPED_NATIVE = chainId === CHAINS.XLAYER.chainId
504
- ? ADDRESSES.XLAYER.WOKB.toLowerCase() // XLayer: WOKB
505
- : ADDRESSES.BSC.WBNB.toLowerCase(); // BSC: WBNB
506
- // ✅ 动态计算最大买方数量(根据多跳数)
507
- // 固定开销: 贿赂(1) + 卖出(1) + 利润多跳(PROFIT_HOP_COUNT + 1)
508
- // BNB 模式(无多跳): 转账(N) + 买入(N) = 2N
509
- // BNB 模式(有多跳H): 转账(N*(H+1)) + 买入(N) = N*(H+2)
510
- // ERC20 模式(无多跳): 转账(N) + 买入(N) = 2N
511
- // ERC20 模式(有多跳H): BNB转账(N*(H+1)) + ERC20转账(N*(H+1)) + 买入(N) = N*(2H+3)
512
- const fixedOverhead = 1 + 1 + PROFIT_HOP_COUNT + 1; // 贿赂 + 卖出 + 利润多跳
513
- const maxTxs = 50 - fixedOverhead;
514
- let MAX_BUYERS;
515
- if (useNativeToken) {
516
- // BNB 模式: N*(H+2) <= maxTxs => N <= maxTxs / (H+2)
517
- MAX_BUYERS = Math.floor(maxTxs / (disperseHopCount + 2));
518
- }
519
- else {
520
- // ERC20 模式: N*(2H+3) <= maxTxs => N <= maxTxs / (2H+3)
521
- MAX_BUYERS = Math.floor(maxTxs / (2 * disperseHopCount + 3));
522
- }
523
- MAX_BUYERS = Math.max(1, MAX_BUYERS); // 至少1个
524
- console.log(`[pancakeQuickBatchSwapMerkle] 多跳数: ${disperseHopCount}, 最大买方数: ${MAX_BUYERS}`);
525
- if (buyerPrivateKeys.length === 0) {
526
- throw new Error('至少需要一个买方钱包');
527
- }
528
- if (buyerPrivateKeys.length > MAX_BUYERS) {
529
- const mode = useNativeToken ? 'BNB' : 'ERC20';
530
- throw new Error(`资金利用率模式(${mode}, ${disperseHopCount}跳)买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`);
531
- }
532
- // ✅ 校验分配模式
533
- if (!buyerRatios && !buyerAmounts) {
534
- throw new Error('必须提供 buyerRatios 或 buyerAmounts');
535
- }
536
- if (buyerRatios && buyerRatios.length !== buyerPrivateKeys.length) {
537
- throw new Error(`buyerRatios 长度 (${buyerRatios.length}) 与 buyerPrivateKeys 长度 (${buyerPrivateKeys.length}) 不匹配`);
538
- }
539
- if (buyerAmounts && buyerAmounts.length !== buyerPrivateKeys.length) {
540
- throw new Error(`buyerAmounts 长度 (${buyerAmounts.length}) 与 buyerPrivateKeys 长度 (${buyerPrivateKeys.length}) 不匹配`);
541
- }
542
- const context = createPancakeContext(config);
543
- const seller = new Wallet(sellerPrivateKey, context.provider);
544
- const buyers = buyerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
545
- // ✅ 校验卖出路径输出代币是否匹配
546
- let sellOutputToken;
547
- if (routeParams.routeType === 'v2') {
548
- const { v2Path } = routeParams;
549
- sellOutputToken = v2Path[v2Path.length - 1];
550
- }
551
- else if (routeParams.routeType === 'v3-single') {
552
- const { v3TokenOut } = routeParams;
553
- sellOutputToken = v3TokenOut;
554
- }
555
- else if (routeParams.routeType === 'v3-multi') {
556
- const { v2Path } = routeParams;
557
- if (v2Path && v2Path.length > 0) {
558
- sellOutputToken = v2Path[v2Path.length - 1];
559
- }
560
- }
561
- // 校验输出代币
562
- const wrappedNativeName = chainId === CHAINS.XLAYER.chainId ? 'WOKB' : 'WBNB';
563
- if (useNativeToken) {
564
- // 原生代币模式:输出必须是 Wrapped Native Token(BSC: WBNB, XLayer: WOKB)
565
- if (!sellOutputToken || sellOutputToken.toLowerCase() !== WRAPPED_NATIVE) {
566
- throw new Error(`原生代币模式要求卖出路径以 ${wrappedNativeName} 结尾(当前输出: ${sellOutputToken || '未知'})。` +
567
- `请切换交易对或使用 ERC20 模式。`);
568
- }
569
- }
570
- else {
571
- // ERC20 模式:输出必须是指定的 quoteToken
572
- if (!sellOutputToken || sellOutputToken.toLowerCase() !== quoteToken.toLowerCase()) {
573
- throw new Error(`ERC20 模式要求卖出路径以 ${quoteToken} 结尾(当前输出: ${sellOutputToken || '未知'})。`);
574
- }
575
- }
576
- // ✅ 创建共享资源
577
- const nonceManager = new NonceManager(context.provider);
578
- const finalGasLimit = getGasLimit(config);
579
- const txType = config.txType ?? 0;
580
- const ERC20_TRANSFER_GAS = GAS_LIMITS.ERC20_TRANSFER; // ERC20 transfer 的 gas 限制
581
- // ✅ 并行获取 gasPrice 和卖出数量
582
- const [gasPrice, sellAmountResult] = await Promise.all([
583
- getGasPrice(context.provider, config),
584
- calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage)
585
- ]);
586
- const { amount: sellAmountWei, decimals } = sellAmountResult;
587
- // ✅ 调试日志
588
- console.log(`[pancakeQuickBatchSwapMerkle] 模式: ${useNativeToken ? 'BNB' : 'ERC20'}`);
589
- console.log(`[pancakeQuickBatchSwapMerkle] 卖出数量: ${ethers.formatUnits(sellAmountWei, decimals)}`);
590
- console.log(`[pancakeQuickBatchSwapMerkle] routeParams:`, JSON.stringify({
591
- routeType: routeParams.routeType,
592
- v2Path: routeParams.v2Path,
593
- v3TokenIn: routeParams.v3TokenIn,
594
- v3TokenOut: routeParams.v3TokenOut,
595
- v3Fee: routeParams.v3Fee
596
- }));
597
- const quoteResult = await quoteSellOutput({
598
- routeParams,
599
- sellAmountWei,
600
- provider: context.provider,
601
- v2RouterAddress: config.v2RouterAddress
602
- });
603
- const estimatedOutput = quoteResult.estimatedBNBOut;
604
- const outputFormatted = useNativeToken
605
- ? ethers.formatEther(estimatedOutput)
606
- : ethers.formatUnits(estimatedOutput, quoteTokenDecimals);
607
- console.log(`[pancakeQuickBatchSwapMerkle] 预估卖出所得: ${outputFormatted} ${useNativeToken ? 'BNB' : 'ERC20'}`);
608
- // ✅ 计算利润(万分之六)
609
- let profitAmount;
610
- if (useNativeToken) {
611
- profitAmount = calculateProfitAmount(estimatedOutput, config.userType);
612
- }
613
- else {
614
- // ERC20 模式:需要将 ERC20 价值转换为 BNB
615
- const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
616
- const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
617
- const estimatedBNBValue = await getERC20ToNativeQuote(context.provider, quoteToken, estimatedOutput, version, fee);
618
- profitAmount = calculateProfitAmount(estimatedBNBValue, config.userType);
619
- console.log(`[pancakeQuickBatchSwapMerkle] ERC20→BNB 报价: ${outputFormatted} → ${ethers.formatEther(estimatedBNBValue)} BNB`);
620
- }
621
- const distributableAmount = estimatedOutput - (useNativeToken ? profitAmount : 0n);
622
- // ✅ 计算每个买方分到的金额
623
- let transferAmountsWei;
624
- if (buyerAmounts && buyerAmounts.length === buyers.length) {
625
- // 数量模式
626
- transferAmountsWei = buyerAmounts.map((amt) => useNativeToken
627
- ? ethers.parseEther(amt)
628
- : ethers.parseUnits(amt, quoteTokenDecimals));
629
- const totalTransfer = transferAmountsWei.reduce((a, b) => a + b, 0n);
630
- if (totalTransfer > distributableAmount) {
631
- const formatted = useNativeToken
632
- ? ethers.formatEther(distributableAmount)
633
- : ethers.formatUnits(distributableAmount, quoteTokenDecimals);
634
- throw new Error(`指定的买入总金额超过可分配金额 (${formatted})`);
635
- }
636
- }
637
- else if (buyerRatios && buyerRatios.length === buyers.length) {
638
- // 比例模式
639
- transferAmountsWei = buyerRatios.map((ratio) => {
640
- return (distributableAmount * BigInt(Math.round(ratio * 10000))) / 10000n;
641
- });
642
- }
643
- else {
644
- throw new Error('必须提供 buyerRatios 或 buyerAmounts');
645
- }
646
- // ✅ 获取贿赂金额
647
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0
648
- ? ethers.parseEther(String(config.bribeAmount))
649
- : 0n;
650
- // ✅ 验证主钱包余额
651
- const sellerBalance = await seller.provider.getBalance(seller.address);
652
- let sellerGasCost;
653
- let sellerRequired;
654
- if (useNativeToken) {
655
- // BNB 模式:贿赂(BRIBE) + 卖出(gasLimit) + N个原生转账(BRIBE each) + 利润(BRIBE)
656
- sellerGasCost = gasPrice * (BRIBE_GAS_LIMIT + finalGasLimit + BRIBE_GAS_LIMIT * BigInt(buyers.length) + BRIBE_GAS_LIMIT);
657
- sellerRequired = bribeAmount + sellerGasCost;
658
- }
659
- else {
660
- // ERC20 模式:子钱包已预留 BNB,不需要主钱包转 Gas
661
- // 卖方 Gas: 贿赂(BRIBE) + 卖出(gasLimit) + N个ERC20转账(65000 each) + 利润(BRIBE)
662
- sellerGasCost = gasPrice * (BRIBE_GAS_LIMIT + finalGasLimit + ERC20_TRANSFER_GAS * BigInt(buyers.length) + BRIBE_GAS_LIMIT);
663
- sellerRequired = bribeAmount + sellerGasCost;
664
- }
665
- if (sellerBalance < sellerRequired) {
666
- throw new Error(`主钱包 BNB 余额不足: 需要约 ${ethers.formatEther(sellerRequired)} BNB (贿赂: ${ethers.formatEther(bribeAmount)}, Gas: ${ethers.formatEther(sellerGasCost)}), 实际 ${ethers.formatEther(sellerBalance)} BNB`);
667
- }
668
- // ==================== 规划 Nonce ====================
669
- // ✅ 如果前端传入了 startNonces,直接使用(性能优化)
670
- let sellerNonce = startNonces && startNonces.length > 0
671
- ? startNonces[0]
672
- : await nonceManager.getNextNonce(seller);
673
- const deadline = Math.floor(Date.now() / 1000) + 600;
674
- // ==================== 1. 贿赂交易 ====================
675
- let bribeTx = null;
676
- if (bribeAmount > 0n) {
677
- bribeTx = await seller.signTransaction({
678
- to: BLOCKRAZOR_BUILDER_EOA,
679
- value: bribeAmount,
680
- nonce: sellerNonce++,
681
- gasPrice,
682
- gasLimit: BRIBE_GAS_LIMIT,
683
- chainId: context.chainId,
684
- type: txType
685
- });
686
- console.log(`[pancakeQuickBatchSwapMerkle] 贿赂交易已签名`);
687
- }
688
- // ==================== 2. 卖出交易 ====================
689
- const v3RouterIface2 = new ethers.Interface(PANCAKE_V3_ROUTER_ABI);
690
- const quickV2Addr = config.v2RouterAddress || PANCAKE_V2_ROUTER_ADDRESS;
691
- let sellUnsigned;
692
- if (routeParams.routeType === 'v2') {
693
- const { v2Path } = routeParams;
694
- const v2RouterSeller = new Contract(quickV2Addr, PANCAKE_V2_ROUTER_ABI, seller);
695
- if (useNativeToken) {
696
- // ✅ 原生代币模式(BNB):Token → WBNB → BNB
697
- sellUnsigned = await v2RouterSeller.swapExactTokensForETHSupportingFeeOnTransferTokens.populateTransaction(sellAmountWei, 0n, v2Path, seller.address, deadline);
698
- }
699
- else {
700
- // ✅ ERC20 模式(USDT):Token → USDT
701
- sellUnsigned = await v2RouterSeller.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(sellAmountWei, 0n, v2Path, seller.address, deadline);
702
- }
703
- }
704
- else if (routeParams.routeType === 'v3-single') {
705
- const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
706
- const v3RouterSeller = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, seller);
707
- const sellSwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [{
708
- tokenIn: v3TokenIn,
709
- tokenOut: v3TokenOut,
710
- fee: v3Fee,
711
- recipient: useNativeToken ? PANCAKE_V3_ROUTER_ADDRESS : seller.address,
712
- amountIn: sellAmountWei,
713
- amountOutMinimum: 0n,
714
- sqrtPriceLimitX96: 0n
715
- }]);
716
- if (useNativeToken) {
717
- // 原生代币:需要 unwrap WBNB
718
- const sellUnwrapData = v3RouterIface2.encodeFunctionData('unwrapWETH9', [0n, seller.address]);
719
- sellUnsigned = await v3RouterSeller.multicall.populateTransaction(deadline, [sellSwapData, sellUnwrapData]);
720
- }
721
- else {
722
- // ERC20:直接接收代币
723
- sellUnsigned = await v3RouterSeller.multicall.populateTransaction(deadline, [sellSwapData]);
724
- }
725
- }
726
- else {
727
- throw new Error('V3 多跳路由暂不支持官方合约,请使用 V2 路由或 V3 单跳');
728
- }
729
- const signedSell = await seller.signTransaction({
730
- ...sellUnsigned,
731
- from: seller.address,
732
- nonce: sellerNonce++,
733
- gasLimit: finalGasLimit,
734
- gasPrice,
735
- chainId: context.chainId,
736
- type: txType
737
- });
738
- console.log(`[pancakeQuickBatchSwapMerkle] 卖出交易已签名`);
739
- // ==================== 3. 转账交易(支持多跳)====================
740
- const buyerGasCost = gasPrice * finalGasLimit;
741
- // ✅ 生成多跳路径
742
- const hopPaths = generateDisperseHopPaths(buyers.map((b) => b.address), disperseHopCount, context.provider);
743
- // 收集所有中间钱包信息
744
- const allHopWallets = [];
745
- hopPaths.forEach(path => {
746
- allHopWallets.push(...path.hopWalletsInfo);
747
- });
748
- let transferTxs = [];
749
- if (disperseHopCount === 0) {
750
- // ✅ 无多跳:直接转账
751
- const transferNonces = buyers.map((_, i) => sellerNonce + i);
752
- sellerNonce += buyers.length;
753
- if (useNativeToken) {
754
- transferTxs = await Promise.all(buyers.map((buyer, i) => {
755
- const transferValue = transferAmountsWei[i] + FLAT_FEE + buyerGasCost;
756
- return seller.signTransaction({
757
- to: buyer.address,
758
- value: transferValue,
759
- nonce: transferNonces[i],
760
- gasPrice,
761
- gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
762
- chainId: context.chainId,
763
- type: txType
764
- });
765
- }));
766
- }
767
- else {
768
- const erc20Interface = new ethers.Interface(ERC20_ABI);
769
- transferTxs = await Promise.all(buyers.map((buyer, i) => {
770
- const transferData = erc20Interface.encodeFunctionData('transfer', [
771
- buyer.address,
772
- transferAmountsWei[i]
773
- ]);
774
- return seller.signTransaction({
775
- to: quoteToken,
776
- data: transferData,
777
- value: 0n,
778
- nonce: transferNonces[i],
779
- gasPrice,
780
- gasLimit: ERC20_TRANSFER_GAS,
781
- chainId: context.chainId,
782
- type: txType
783
- });
784
- }));
785
- }
786
- }
787
- else {
788
- // ✅ 有多跳:构建多跳转账链
789
- if (useNativeToken) {
790
- // BNB 多跳转账
791
- // ✅ 修复:payer 每次只发送 1 笔交易(到第一个hop钱包),hop钱包用自己的nonce=0
792
- const hopChains = await Promise.all(hopPaths.map((path, i) => {
793
- const finalAmount = transferAmountsWei[i] + FLAT_FEE + buyerGasCost;
794
- const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
795
- return buildNativeHopChain(seller, path, finalAmount, gasPrice, context.chainId, txType, payerNonce);
796
- }));
797
- transferTxs = hopChains.flat();
798
- sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
799
- }
800
- else {
801
- // ERC20 多跳转账:先转 BNB(给中间钱包 gas),再转 ERC20
802
- // ✅ 修复:payer 每次只发送 1 笔交易(到第一个hop钱包),hop钱包用自己的nonce=0/1
803
- // 1. 构建 BNB 多跳链(为中间钱包和最终钱包预留 gas)
804
- const bnbHopChains = await Promise.all(hopPaths.map((path, i) => {
805
- // 最终钱包需要的 gas(用于买入交易)
806
- const finalGasAmount = buyerGasCost;
807
- const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
808
- return buildBNBHopChainForERC20(seller, path, finalGasAmount, gasPrice, context.chainId, txType, payerNonce);
809
- }));
810
- const bnbTxs = bnbHopChains.flat();
811
- sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
812
- // 2. 构建 ERC20 多跳链
813
- const erc20HopChains = await Promise.all(hopPaths.map((path, i) => {
814
- const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
815
- return buildERC20HopChain(seller, path, quoteToken, transferAmountsWei[i], gasPrice, context.chainId, txType, payerNonce);
816
- }));
817
- const erc20Txs = erc20HopChains.flat();
818
- sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
819
- transferTxs = [...bnbTxs, ...erc20Txs];
820
- }
821
- }
822
- console.log(`[pancakeQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名 (多跳数=${disperseHopCount})`);
823
- // ==================== 4. 买入交易 ====================
824
- // ✅ 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
825
- const buyerNonces = startNonces && startNonces.length > 1
826
- ? startNonces.slice(1)
827
- : await Promise.all(buyers.map((buyer) => nonceManager.getNextNonce(buyer)));
828
- const signedBuys = await Promise.all(buyers.map(async (buyer, i) => {
829
- const buyAmount = transferAmountsWei[i];
830
- // ✅ ERC20 模式:value = 0(通过代币授权支付)
831
- const buyValue = useNativeToken ? buyAmount + FLAT_FEE : 0n;
832
- let buyUnsigned;
833
- if (routeParams.routeType === 'v2') {
834
- const { v2Path } = routeParams;
835
- const reversePath = [...v2Path].reverse();
836
- const v2RouterBuyer = new Contract(quickV2Addr, PANCAKE_V2_ROUTER_ABI, buyer);
837
- if (useNativeToken) {
838
- buyUnsigned = await v2RouterBuyer.swapExactETHForTokensSupportingFeeOnTransferTokens.populateTransaction(0n, reversePath, buyer.address, deadline, { value: buyValue });
839
- }
840
- else {
841
- buyUnsigned = await v2RouterBuyer.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(buyAmount, 0n, reversePath, buyer.address, deadline);
842
- }
843
- }
844
- else if (routeParams.routeType === 'v3-single') {
845
- const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
846
- const v3RouterBuyer = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, buyer);
847
- const buySwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [{
848
- tokenIn: v3TokenOut,
849
- tokenOut: v3TokenIn,
850
- fee: v3Fee,
851
- recipient: buyer.address,
852
- amountIn: buyAmount,
853
- amountOutMinimum: 0n,
854
- sqrtPriceLimitX96: 0n
855
- }]);
856
- buyUnsigned = await v3RouterBuyer.multicall.populateTransaction(deadline, [buySwapData], { value: buyValue });
857
- }
858
- else {
859
- throw new Error('V3 多跳路由暂不支持官方合约,请使用 V2 路由或 V3 单跳');
860
- }
861
- return buyer.signTransaction({
862
- ...buyUnsigned,
863
- from: buyer.address,
864
- nonce: buyerNonces[i],
865
- gasLimit: finalGasLimit,
866
- gasPrice,
867
- chainId: context.chainId,
868
- type: txType
869
- });
870
- }));
871
- console.log(`[pancakeQuickBatchSwapMerkle] ${signedBuys.length} 笔买入交易已签名`);
872
- nonceManager.clearTemp();
873
- // ==================== 组装交易数组 ====================
874
- // BNB 模式:贿赂 → 卖出 → 转账 → 买入 → 利润多跳
875
- // ERC20 模式:贿赂 → 卖出 → ERC20转账 → BNB Gas转账 → 买入 → 利润多跳
876
- const signedTransactions = [];
877
- if (bribeTx)
878
- signedTransactions.push(bribeTx);
879
- signedTransactions.push(signedSell);
880
- signedTransactions.push(...transferTxs);
881
- signedTransactions.push(...signedBuys);
882
- // ==================== 5. 利润多跳转账(强制 2 跳中转)====================
883
- let profitHopWallets;
884
- if (profitAmount > 0n) {
885
- const profitHopResult = await buildProfitHopTransactions({
886
- provider: context.provider,
887
- payerWallet: seller,
888
- profitAmount,
889
- profitRecipient: PROFIT_CONFIG.RECIPIENT,
890
- hopCount: PROFIT_HOP_COUNT,
891
- gasPrice,
892
- chainId: context.chainId,
893
- txType,
894
- startNonce: sellerNonce++
895
- });
896
- signedTransactions.push(...profitHopResult.signedTransactions);
897
- profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
898
- // 多跳交易已签名
899
- }
900
- console.log(`[pancakeQuickBatchSwapMerkle] 交易组装完成: ${signedTransactions.length} 笔`);
901
- console.log(` - 贿赂: ${bribeTx ? 1 : 0}`);
902
- console.log(` - 卖出: 1`);
903
- console.log(` - 转账: ${transferTxs.length}`);
904
- console.log(` - 买入: ${signedBuys.length}`);
905
- const outputUnit = useNativeToken ? 'BNB' : 'ERC20';
906
- return {
907
- signedTransactions,
908
- disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅ 返回转账多跳钱包
909
- profitHopWallets, // ✅ 返回利润多跳钱包
910
- metadata: {
911
- sellerAddress: seller.address,
912
- buyerAddresses: buyers.map((b) => b.address),
913
- sellAmount: ethers.formatUnits(sellAmountWei, decimals),
914
- estimatedOutput: useNativeToken
915
- ? ethers.formatEther(estimatedOutput)
916
- : ethers.formatUnits(estimatedOutput, quoteTokenDecimals),
917
- transferAmounts: transferAmountsWei.map((amt) => useNativeToken
918
- ? ethers.formatEther(amt)
919
- : ethers.formatUnits(amt, quoteTokenDecimals)),
920
- profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined,
921
- useNativeToken,
922
- disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined // ✅ 返回多跳数
923
- }
924
- };
925
- }
926
- // ==================== 交叉换手(多卖多买,循环执行)====================
927
- /** 交叉换手参数(PancakeSwap V2/V3) */
928
- /** 交叉换手结果(PancakeSwap V2/V3) */
929
- /**
930
- * PancakeSwap 交叉换手(多卖多买,循环执行)
931
- * - 每个卖方单独卖出,买入金额由卖出所得等分分配给当轮买方
932
- * - 利润刮取、转账多跳逻辑继承 pancakeQuickBatchSwapMerkle
933
- * - 结果按顺序拼接 signedTransactions(可交由前端/后端顺序广播)
934
- * - ✅ 正确处理 nonce:同一钱包在多轮中使用时 nonce 自动递增
935
- */
936
- export async function pancakeCrossSwapMerkle(params) {
937
- const { sellerPrivateKeys, sellAmounts, buyerPrivateKeys, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, buyersPerSell, disperseHopCount = 0 } = params;
938
- if (sellerPrivateKeys.length === 0) {
939
- throw new Error('至少需要一个卖方');
940
- }
941
- if (sellerPrivateKeys.length !== sellAmounts.length) {
942
- throw new Error(`sellAmounts 长度 (${sellAmounts.length}) 必须与卖方数量 (${sellerPrivateKeys.length}) 一致`);
943
- }
944
- if (buyerPrivateKeys.length === 0) {
945
- throw new Error('至少需要一个买方');
946
- }
947
- // ✅ 创建 Provider 和 NonceManager
948
- const context = createPancakeContext(config);
949
- const nonceManager = new NonceManager(context.provider);
950
- // ✅ 预先获取所有钱包的初始 nonce
951
- const allSellerWallets = sellerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
952
- const allBuyerWallets = buyerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
953
- // 使用 Map 去重(同一私钥可能出现多次)
954
- const addressToNonce = new Map();
955
- // 获取所有卖方 nonce
956
- for (const wallet of allSellerWallets) {
957
- if (!addressToNonce.has(wallet.address)) {
958
- const nonce = await nonceManager.getNextNonce(wallet);
959
- addressToNonce.set(wallet.address, nonce);
960
- }
961
- }
962
- // 获取所有买方 nonce
963
- for (const wallet of allBuyerWallets) {
964
- if (!addressToNonce.has(wallet.address)) {
965
- const nonce = await nonceManager.getNextNonce(wallet);
966
- addressToNonce.set(wallet.address, nonce);
967
- }
968
- }
969
- console.log(`[pancakeCrossSwapMerkle] 初始化完成: ${sellerPrivateKeys.length} 卖方, ${buyerPrivateKeys.length} 买方`);
970
- const allSigned = [];
971
- const allDisperse = [];
972
- const allProfit = [];
973
- const rounds = [];
974
- // 轮流分配买方:每轮取 buyersPerSell 个(默认所有买方),不足则从头继续
975
- let buyerCursor = 0;
976
- const buyerBatchSize = Math.max(1, buyersPerSell ?? buyerPrivateKeys.length);
977
- // 判断是否使用原生代币
978
- const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
979
- // 获取贿赂金额
980
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0
981
- ? ethers.parseEther(String(config.bribeAmount))
982
- : 0n;
983
- const hasBribe = bribeAmount > 0n;
984
- for (let i = 0; i < sellerPrivateKeys.length; i++) {
985
- const sellerPk = sellerPrivateKeys[i];
986
- const sellAmount = sellAmounts[i];
987
- const sellerWallet = allSellerWallets[i];
988
- // 选取本轮买方私钥和钱包
989
- const roundBuyerPks = [];
990
- const roundBuyerWallets = [];
991
- for (let k = 0; k < buyerBatchSize; k++) {
992
- const idx = buyerCursor % buyerPrivateKeys.length;
993
- roundBuyerPks.push(buyerPrivateKeys[idx]);
994
- roundBuyerWallets.push(allBuyerWallets[idx]);
995
- buyerCursor++;
996
- }
997
- // ✅ 获取卖方当前 nonce
998
- const sellerNonce = addressToNonce.get(sellerWallet.address);
999
- // ✅ 获取并更新买方 nonces(每个买方本轮需要 1 个 nonce)
1000
- const roundBuyerNonces = roundBuyerWallets.map(w => {
1001
- const nonce = addressToNonce.get(w.address);
1002
- addressToNonce.set(w.address, nonce + 1); // 每个买方用 1 个 nonce
1003
- return nonce;
1004
- });
1005
- // 平分买入金额(使用比例模式,避免固定金额超出可分配金额)
1006
- const ratio = 1 / roundBuyerPks.length;
1007
- const buyerRatios = roundBuyerPks.map(() => ratio);
1008
- // ✅ 构建 startNonces: [sellerNonce, buyer1Nonce, buyer2Nonce, ...]
1009
- const startNonces = [sellerNonce, ...roundBuyerNonces];
1010
- // ✅ 预先计算卖方 nonce 消耗(精确计算)
1011
- // 卖方 nonce 消耗 = 贿赂(0/1) + 卖出(1) + 转账(N 或 N*2) + 利润(1)
1012
- const hasProfit = true; // 默认有利润刮取
1013
- let sellerNonceConsumed = 0;
1014
- if (hasBribe)
1015
- sellerNonceConsumed += 1; // 贿赂
1016
- sellerNonceConsumed += 1; // 卖出
1017
- if (disperseHopCount === 0) {
1018
- sellerNonceConsumed += roundBuyerPks.length; // 直接转账
1019
- }
1020
- else if (useNativeToken) {
1021
- sellerNonceConsumed += roundBuyerPks.length; // 原生多跳:seller→hop1
1022
- }
1023
- else {
1024
- sellerNonceConsumed += roundBuyerPks.length * 2; // ERC20 多跳:BNB + ERC20 两批
1025
- }
1026
- if (hasProfit)
1027
- sellerNonceConsumed += 1; // 利润
1028
- // 调用单卖多买的签名函数
1029
- const res = await pancakeQuickBatchSwapMerkle({
1030
- sellerPrivateKey: sellerPk,
1031
- sellAmount,
1032
- buyerPrivateKeys: roundBuyerPks,
1033
- buyerRatios,
1034
- tokenAddress,
1035
- routeParams,
1036
- config,
1037
- quoteToken,
1038
- quoteTokenDecimals,
1039
- disperseHopCount,
1040
- startNonces // ✅ 传入预计算的 nonces
1041
- });
1042
- // ✅ 更新卖方 nonce(使用精确计算的值)
1043
- addressToNonce.set(sellerWallet.address, sellerNonce + sellerNonceConsumed);
1044
- console.log(`[pancakeCrossSwapMerkle] 轮次 ${i + 1}: 卖方=${sellerWallet.address.slice(0, 10)}..., 买方=${roundBuyerPks.length}, 交易=${res.signedTransactions.length}`);
1045
- // 累积签名与中间钱包
1046
- allSigned.push(...res.signedTransactions);
1047
- if (res.disperseHopWallets)
1048
- allDisperse.push(...res.disperseHopWallets);
1049
- if (res.profitHopWallets)
1050
- allProfit.push(...res.profitHopWallets);
1051
- rounds.push({
1052
- sellerAddress: res.metadata?.sellerAddress || '',
1053
- buyerAddresses: res.metadata?.buyerAddresses || roundBuyerPks.map(() => ''),
1054
- sellAmount,
1055
- bundleHash: undefined
1056
- });
1057
- }
1058
- nonceManager.clearTemp();
1059
- console.log(`[pancakeCrossSwapMerkle] 完成: ${rounds.length} 轮, ${allSigned.length} 笔交易`);
1060
- return {
1061
- signedTransactions: allSigned,
1062
- rounds,
1063
- disperseHopWallets: allDisperse.length > 0 ? allDisperse : undefined,
1064
- profitHopWallets: allProfit.length > 0 ? allProfit : undefined
1065
- };
1066
- }