four-flap-meme-sdk 1.9.49 → 2.0.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 (530) 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/abis/common.js +74 -68
  5. package/dist/abis/flap/vault.js +9 -7
  6. package/dist/abis/index.d.ts +3 -4
  7. package/dist/abis/index.js +3 -4
  8. package/dist/bundle-core/__tests__/config-helpers.test.js +28 -0
  9. package/dist/bundle-core/__tests__/facade-parity.test.js +33 -0
  10. package/dist/bundle-core/__tests__/sign-context-helpers.test.d.ts +1 -0
  11. package/dist/bundle-core/__tests__/sign-context-helpers.test.js +60 -0
  12. package/dist/bundle-core/__tests__/sign-fixture.test.d.ts +1 -0
  13. package/dist/bundle-core/__tests__/sign-fixture.test.js +220 -0
  14. package/dist/bundle-core/__tests__/sign-fixtures.d.ts +10 -0
  15. package/dist/bundle-core/__tests__/sign-fixtures.js +16 -0
  16. package/dist/bundle-core/config-helpers.d.ts +36 -0
  17. package/dist/bundle-core/config-helpers.js +57 -0
  18. package/dist/bundle-core/errors.d.ts +50 -0
  19. package/dist/bundle-core/errors.js +34 -0
  20. package/dist/bundle-core/four-meme/approve-tokenmanager.d.ts +7 -0
  21. package/dist/bundle-core/four-meme/approve-tokenmanager.js +99 -0
  22. package/dist/bundle-core/four-meme/core-helpers.d.ts +8 -0
  23. package/dist/bundle-core/four-meme/core-helpers.js +40 -0
  24. package/dist/bundle-core/four-meme/core.d.ts +4 -0
  25. package/dist/bundle-core/four-meme/core.js +515 -0
  26. package/dist/bundle-core/four-meme/pancake-proxy.d.ts +28 -0
  27. package/dist/bundle-core/four-meme/pancake-proxy.js +679 -0
  28. package/dist/bundle-core/four-meme/private.d.ts +27 -0
  29. package/dist/bundle-core/four-meme/private.js +465 -0
  30. package/dist/bundle-core/four-meme/sign-context-helpers.d.ts +2 -0
  31. package/dist/bundle-core/four-meme/sign-context-helpers.js +2 -0
  32. package/dist/bundle-core/four-meme/swap-buy-first.d.ts +8 -0
  33. package/dist/bundle-core/four-meme/swap-buy-first.js +493 -0
  34. package/dist/bundle-core/four-meme/swap-hop-helpers.d.ts +6 -0
  35. package/dist/bundle-core/four-meme/swap-hop-helpers.js +63 -0
  36. package/dist/bundle-core/four-meme/swap-internal.d.ts +3 -0
  37. package/dist/bundle-core/four-meme/swap-internal.js +18 -0
  38. package/dist/bundle-core/four-meme/swap-sign-helpers.d.ts +27 -0
  39. package/dist/bundle-core/four-meme/swap-sign-helpers.js +105 -0
  40. package/dist/bundle-core/four-meme/swap.d.ts +17 -0
  41. package/dist/bundle-core/four-meme/swap.js +505 -0
  42. package/dist/bundle-core/four-meme/types/buy-first.d.ts +50 -0
  43. package/dist/bundle-core/four-meme/types/buy-first.js +1 -0
  44. package/dist/bundle-core/four-meme/types/core-flow.d.ts +63 -0
  45. package/dist/bundle-core/four-meme/types/core-flow.js +1 -0
  46. package/dist/bundle-core/four-meme/types/index.d.ts +600 -0
  47. package/dist/bundle-core/four-meme/types/index.js +1 -0
  48. package/dist/bundle-core/four-meme/types/swap-internal.d.ts +19 -0
  49. package/dist/bundle-core/four-meme/types/swap-internal.js +1 -0
  50. package/dist/bundle-core/four-meme/types.d.ts +1 -0
  51. package/dist/bundle-core/four-meme/types.js +1 -0
  52. package/dist/bundle-core/four-meme/utils-disperse.d.ts +7 -0
  53. package/dist/bundle-core/four-meme/utils-disperse.js +396 -0
  54. package/dist/bundle-core/four-meme/utils-pairwise.d.ts +8 -0
  55. package/dist/bundle-core/four-meme/utils-pairwise.js +328 -0
  56. package/dist/bundle-core/four-meme/utils-sweep.d.ts +8 -0
  57. package/dist/bundle-core/four-meme/utils-sweep.js +744 -0
  58. package/dist/bundle-core/index.d.ts +8 -0
  59. package/dist/bundle-core/index.js +8 -0
  60. package/dist/bundle-core/internal.d.ts +21 -0
  61. package/dist/bundle-core/internal.js +182 -0
  62. package/dist/bundle-core/sign-context-helpers.d.ts +25 -0
  63. package/dist/bundle-core/sign-context-helpers.js +67 -0
  64. package/dist/bundle-core/submit.d.ts +293 -0
  65. package/dist/bundle-core/submit.js +727 -0
  66. package/dist/bundle-core/types/index.d.ts +8 -0
  67. package/dist/bundle-core/types/index.js +1 -0
  68. package/dist/bundle-core/types.d.ts +1 -0
  69. package/dist/bundle-core/types.js +1 -0
  70. package/dist/chains/bsc/four/approve-tokenmanager.d.ts +1 -26
  71. package/dist/chains/bsc/four/approve-tokenmanager.js +1 -116
  72. package/dist/chains/bsc/four/config.d.ts +5 -70
  73. package/dist/chains/bsc/four/config.js +2 -115
  74. package/dist/chains/bsc/four/core.d.ts +1 -4
  75. package/dist/chains/bsc/four/core.js +1 -589
  76. package/dist/chains/bsc/four/disperse.d.ts +12 -0
  77. package/dist/chains/bsc/four/disperse.js +470 -0
  78. package/dist/chains/bsc/four/index.d.ts +6 -6
  79. package/dist/chains/bsc/four/index.js +6 -6
  80. package/dist/chains/bsc/four/internal.d.ts +2 -50
  81. package/dist/chains/bsc/four/internal.js +2 -237
  82. package/dist/chains/bsc/four/pairwise.d.ts +7 -0
  83. package/dist/chains/bsc/four/pairwise.js +308 -0
  84. package/dist/chains/bsc/four/pancake-proxy.d.ts +1 -28
  85. package/dist/chains/bsc/four/pancake-proxy.js +1 -688
  86. package/dist/chains/bsc/four/private.d.ts +1 -27
  87. package/dist/chains/bsc/four/private.js +1 -477
  88. package/dist/chains/bsc/four/submit.d.ts +2 -315
  89. package/dist/chains/bsc/four/submit.js +2 -746
  90. package/dist/chains/bsc/four/swap-buy-first.d.ts +2 -55
  91. package/dist/chains/bsc/four/swap-buy-first.js +2 -506
  92. package/dist/chains/bsc/four/swap-internal.d.ts +1 -3
  93. package/dist/chains/bsc/four/swap-internal.js +1 -18
  94. package/dist/chains/bsc/four/swap.d.ts +2 -144
  95. package/dist/chains/bsc/four/swap.js +2 -760
  96. package/dist/chains/bsc/four/sweep.d.ts +13 -0
  97. package/dist/chains/bsc/four/sweep.js +788 -0
  98. package/dist/chains/bsc/four/types.d.ts +1 -476
  99. package/dist/chains/bsc/four/utils-disperse.d.ts +1 -0
  100. package/dist/chains/bsc/four/utils-disperse.js +1 -0
  101. package/dist/chains/bsc/four/utils-pairwise.d.ts +1 -0
  102. package/dist/chains/bsc/four/utils-pairwise.js +1 -0
  103. package/dist/chains/bsc/four/utils-sweep.d.ts +1 -0
  104. package/dist/chains/bsc/four/utils-sweep.js +1 -0
  105. package/dist/chains/bsc/four/utils.d.ts +5 -18
  106. package/dist/chains/bsc/four/utils.js +5 -1534
  107. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.d.ts +159 -0
  108. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.js +117 -0
  109. package/dist/chains/bsc/pancake/bundle-buy-first.d.ts +1 -91
  110. package/dist/chains/bsc/pancake/bundle-buy-first.js +97 -207
  111. package/dist/chains/bsc/pancake/bundle-swap-helpers.d.ts +241 -0
  112. package/dist/chains/bsc/pancake/bundle-swap-helpers.js +565 -0
  113. package/dist/chains/bsc/pancake/bundle-swap.d.ts +1 -79
  114. package/dist/chains/bsc/pancake/bundle-swap.js +111 -686
  115. package/dist/chains/bsc/pancake/index.d.ts +4 -2
  116. package/dist/chains/bsc/pancake/index.js +1 -3
  117. package/dist/chains/bsc/platforms/iro/factory.js +3 -1
  118. package/dist/chains/bsc/platforms/iro/index.d.ts +5 -5
  119. package/dist/chains/bsc/platforms/iro/index.js +3 -3
  120. package/dist/chains/bsc/platforms/iro/pool.js +31 -10
  121. package/dist/chains/bsc/platforms/iro/token.js +4 -1
  122. package/dist/chains/eni/batch-router/bundle-approve.js +4 -3
  123. package/dist/chains/eni/batch-router/transfer.js +54 -23
  124. package/dist/chains/eni/batch-router/utils.js +32 -6
  125. package/dist/chains/eni/bundler/sign.js +4 -4
  126. package/dist/chains/eni/bundler/submit.js +1 -4
  127. package/dist/chains/eni/constants.js +1 -1
  128. package/dist/chains/eni/index.d.ts +1 -1
  129. package/dist/chains/eni/platforms/daoaas/create.js +2 -2
  130. package/dist/chains/eni/platforms/daoaas/index.d.ts +3 -3
  131. package/dist/chains/eni/platforms/daoaas/index.js +3 -3
  132. package/dist/chains/eni/platforms/daoaas/meta.js +8 -4
  133. package/dist/chains/eni/platforms/daoaas/portal-direct.js +28 -43
  134. package/dist/chains/eni/platforms/daoaas/portal.js +10 -6
  135. package/dist/chains/eni/platforms/dswap/liquidity.js +58 -26
  136. package/dist/chains/eni/platforms/fair-launch/index.d.ts +2 -2
  137. package/dist/chains/eni/platforms/fair-launch/index.js +1 -1
  138. package/dist/chains/eni/platforms/fair-launch/launcher.js +87 -47
  139. package/dist/chains/eni/platforms/fair-launch/pool.js +4 -1
  140. package/dist/chains/eni/platforms/fair-launch/presets.js +2 -2
  141. package/dist/chains/eni/platforms/iro/factory.js +3 -1
  142. package/dist/chains/eni/platforms/iro/index.d.ts +6 -6
  143. package/dist/chains/eni/platforms/iro/index.js +4 -4
  144. package/dist/chains/eni/platforms/iro/pool.js +90 -26
  145. package/dist/chains/eni/platforms/iro/token.js +107 -31
  146. package/dist/chains/eni/platforms/iro/whitelist.js +6 -18
  147. package/dist/chains/eni/submit.js +5 -13
  148. package/dist/chains/xlayer/eip7702/bundle-approve.d.ts +2 -26
  149. package/dist/chains/xlayer/eip7702/bundle-approve.js +11 -20
  150. package/dist/chains/xlayer/eip7702/bundle-buy.d.ts +2 -6
  151. package/dist/chains/xlayer/eip7702/bundle-buy.js +13 -51
  152. package/dist/chains/xlayer/eip7702/bundle-create.js +93 -56
  153. package/dist/chains/xlayer/eip7702/bundle-sell.d.ts +2 -6
  154. package/dist/chains/xlayer/eip7702/bundle-sell.js +26 -74
  155. package/dist/chains/xlayer/eip7702/bundle-swap.d.ts +3 -65
  156. package/dist/chains/xlayer/eip7702/bundle-swap.js +51 -68
  157. package/dist/chains/xlayer/eip7702/constants.d.ts +1 -16
  158. package/dist/chains/xlayer/eip7702/constants.js +3 -21
  159. package/dist/chains/xlayer/eip7702/index.d.ts +27 -46
  160. package/dist/chains/xlayer/eip7702/index.js +27 -81
  161. package/dist/chains/xlayer/eip7702/multi-hop-transfer-helpers.d.ts +79 -0
  162. package/dist/chains/xlayer/eip7702/multi-hop-transfer-helpers.js +1 -0
  163. package/dist/chains/xlayer/eip7702/multi-hop-transfer.d.ts +2 -203
  164. package/dist/chains/xlayer/eip7702/multi-hop-transfer.js +58 -291
  165. package/dist/chains/xlayer/eip7702/transfer-context-helpers.d.ts +26 -0
  166. package/dist/chains/xlayer/eip7702/transfer-context-helpers.js +57 -0
  167. package/dist/chains/xlayer/eip7702/types.d.ts +88 -0
  168. package/dist/chains/xlayer/eip7702/utils.d.ts +0 -3
  169. package/dist/chains/xlayer/eip7702/utils.js +23 -28
  170. package/dist/chains/xlayer/eip7702/volume-helpers.d.ts +148 -0
  171. package/dist/chains/xlayer/eip7702/volume-helpers.js +48 -0
  172. package/dist/chains/xlayer/eip7702/volume.d.ts +6 -184
  173. package/dist/chains/xlayer/eip7702/volume.js +83 -158
  174. package/dist/chains/xlayer/eoa/constants.js +1 -1
  175. package/dist/chains/xlayer/eoa/dex-helpers.js +5 -5
  176. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.d.ts +126 -0
  177. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.js +228 -0
  178. package/dist/chains/xlayer/eoa/eoa-bundle-swap.d.ts +1 -95
  179. package/dist/chains/xlayer/eoa/eoa-bundle-swap.js +64 -276
  180. package/dist/chains/xlayer/eoa/eoa-wash-volume.d.ts +1 -1
  181. package/dist/chains/xlayer/eoa/eoa-wash-volume.js +14 -14
  182. package/dist/chains/xlayer/eoa/index.d.ts +10 -6
  183. package/dist/chains/xlayer/eoa/index.js +8 -23
  184. package/dist/chains/xlayer/eoa/portal-ops.js +7 -2
  185. package/dist/chains/xlayer/eoa/router-manager.js +3 -3
  186. package/dist/chains/xlayer/eoa/types-core.d.ts +363 -0
  187. package/dist/chains/xlayer/eoa/types-core.js +53 -0
  188. package/dist/chains/xlayer/eoa/types-create.d.ts +413 -0
  189. package/dist/chains/xlayer/eoa/types-create.js +9 -0
  190. package/dist/chains/xlayer/eoa/types-volume.d.ts +209 -0
  191. package/dist/chains/xlayer/eoa/types-volume.js +13 -0
  192. package/dist/chains/xlayer/eoa/types.d.ts +2 -2
  193. package/dist/chains/xlayer/eoa/types.js +1 -3
  194. package/dist/contracts/helper3.d.ts +20 -17
  195. package/dist/contracts/helper3.js +56 -20
  196. package/dist/contracts/tm-bundle-helpers.d.ts +88 -0
  197. package/dist/contracts/tm-bundle-helpers.js +72 -0
  198. package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.d.ts +1 -26
  199. package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.js +1 -117
  200. package/dist/contracts/tm-bundle-merkle/config.d.ts +5 -70
  201. package/dist/contracts/tm-bundle-merkle/config.js +2 -115
  202. package/dist/contracts/tm-bundle-merkle/core.d.ts +1 -4
  203. package/dist/contracts/tm-bundle-merkle/core.js +1 -588
  204. package/dist/contracts/tm-bundle-merkle/index.d.ts +5 -5
  205. package/dist/contracts/tm-bundle-merkle/index.js +5 -5
  206. package/dist/contracts/tm-bundle-merkle/internal.d.ts +2 -50
  207. package/dist/contracts/tm-bundle-merkle/internal.js +2 -236
  208. package/dist/contracts/tm-bundle-merkle/pancake-proxy.d.ts +1 -28
  209. package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +1 -687
  210. package/dist/contracts/tm-bundle-merkle/private.d.ts +1 -27
  211. package/dist/contracts/tm-bundle-merkle/private.js +1 -476
  212. package/dist/contracts/tm-bundle-merkle/submit.d.ts +3 -314
  213. package/dist/contracts/tm-bundle-merkle/submit.js +3 -919
  214. package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +2 -55
  215. package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +2 -505
  216. package/dist/contracts/tm-bundle-merkle/swap-internal.d.ts +1 -3
  217. package/dist/contracts/tm-bundle-merkle/swap-internal.js +1 -18
  218. package/dist/contracts/tm-bundle-merkle/swap.d.ts +2 -144
  219. package/dist/contracts/tm-bundle-merkle/swap.js +2 -757
  220. package/dist/contracts/tm-bundle-merkle/types.d.ts +1 -476
  221. package/dist/contracts/tm-bundle-merkle/utils-disperse.d.ts +1 -0
  222. package/dist/contracts/tm-bundle-merkle/utils-disperse.js +1 -0
  223. package/dist/contracts/tm-bundle-merkle/utils-pairwise.d.ts +1 -0
  224. package/dist/contracts/tm-bundle-merkle/utils-pairwise.js +1 -0
  225. package/dist/contracts/tm-bundle-merkle/utils-sweep.d.ts +1 -0
  226. package/dist/contracts/tm-bundle-merkle/utils-sweep.js +1 -0
  227. package/dist/contracts/tm-bundle-merkle/utils.d.ts +5 -6
  228. package/dist/contracts/tm-bundle-merkle/utils.js +5 -6
  229. package/dist/contracts/tm-bundle.d.ts +3 -51
  230. package/dist/contracts/tm-bundle.js +102 -142
  231. package/dist/contracts/tm.d.ts +3 -2
  232. package/dist/contracts/tm.js +36 -32
  233. package/dist/contracts/tm1.js +9 -4
  234. package/dist/contracts/tm2.js +9 -4
  235. package/dist/dex/direct-router-helpers.d.ts +264 -0
  236. package/dist/dex/direct-router-helpers.js +539 -0
  237. package/dist/dex/direct-router.d.ts +3 -125
  238. package/dist/dex/direct-router.js +237 -652
  239. package/dist/dex/types.d.ts +81 -0
  240. package/dist/dex/types.js +1 -0
  241. package/dist/exports/root-bundle-and-tooling.d.ts +27 -0
  242. package/dist/exports/root-bundle-and-tooling.js +30 -0
  243. package/dist/exports/root-eni-and-bsc-iro.d.ts +26 -0
  244. package/dist/exports/root-eni-and-bsc-iro.js +66 -0
  245. package/dist/exports/root-foundations.d.ts +35 -0
  246. package/dist/exports/root-foundations.js +70 -0
  247. package/dist/exports/root-swap-dex-and-xlayer.d.ts +30 -0
  248. package/dist/exports/root-swap-dex-and-xlayer.js +78 -0
  249. package/dist/flows/create.d.ts +2 -2
  250. package/dist/flows/create.js +6 -6
  251. package/dist/flows/index.d.ts +1 -0
  252. package/dist/flows/index.js +1 -0
  253. package/dist/index.d.ts +20 -91
  254. package/dist/index.js +20 -215
  255. package/dist/shared/abis/common.d.ts +2 -83
  256. package/dist/shared/abis/common.js +2 -252
  257. package/dist/shared/abis/index.d.ts +5 -6
  258. package/dist/shared/abis/index.js +5 -7
  259. package/dist/shared/clients/blockrazor.js +41 -24
  260. package/dist/shared/clients/club48.js +30 -26
  261. package/dist/shared/clients/emitservice.js +2 -0
  262. package/dist/shared/clients/four.js +23 -18
  263. package/dist/shared/clients/index.d.ts +8 -0
  264. package/dist/shared/clients/index.js +8 -0
  265. package/dist/shared/clients/merkle.js +26 -30
  266. package/dist/shared/constants/addresses.d.ts +1 -1
  267. package/dist/shared/constants/addresses.js +11 -2
  268. package/dist/shared/constants/chains.d.ts +1 -1
  269. package/dist/shared/constants/chains.js +1 -1
  270. package/dist/shared/constants/gas.d.ts +1 -1
  271. package/dist/shared/constants/gas.js +2 -6
  272. package/dist/shared/constants/index.d.ts +1 -0
  273. package/dist/shared/constants/index.js +1 -0
  274. package/dist/shared/constants/quote.d.ts +30 -0
  275. package/dist/shared/constants/quote.js +37 -0
  276. package/dist/shared/flap/__tests__/curve.test.js +3 -3
  277. package/dist/shared/flap/abi.js +1 -1
  278. package/dist/shared/flap/constants.d.ts +1 -1
  279. package/dist/shared/flap/constants.js +2 -2
  280. package/dist/shared/flap/curve.js +3 -0
  281. package/dist/shared/flap/errors.d.ts +1 -4
  282. package/dist/shared/flap/errors.js +21 -3
  283. package/dist/shared/flap/index.d.ts +2 -2
  284. package/dist/shared/flap/index.js +2 -2
  285. package/dist/shared/flap/meta.d.ts +16 -18
  286. package/dist/shared/flap/meta.js +14 -26
  287. package/dist/shared/flap/permit.js +6 -5
  288. package/dist/shared/flap/pinata.d.ts +9 -2
  289. package/dist/shared/flap/pinata.js +20 -18
  290. package/dist/shared/flap/portal-bundle-merkle/config.d.ts +3 -72
  291. package/dist/shared/flap/portal-bundle-merkle/config.js +4 -124
  292. package/dist/shared/flap/portal-bundle-merkle/core-helpers.d.ts +32 -0
  293. package/dist/shared/flap/portal-bundle-merkle/core-helpers.js +83 -0
  294. package/dist/shared/flap/portal-bundle-merkle/core.d.ts +0 -4
  295. package/dist/shared/flap/portal-bundle-merkle/core.js +66 -156
  296. package/dist/shared/flap/portal-bundle-merkle/create-to-dex.js +81 -86
  297. package/dist/shared/flap/portal-bundle-merkle/curve-to-dex.js +100 -92
  298. package/dist/shared/flap/portal-bundle-merkle/index.d.ts +11 -7
  299. package/dist/shared/flap/portal-bundle-merkle/index.js +4 -7
  300. package/dist/shared/flap/portal-bundle-merkle/pancake-proxy.js +71 -68
  301. package/dist/shared/flap/portal-bundle-merkle/private.js +61 -114
  302. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.d.ts +125 -0
  303. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.js +113 -0
  304. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.d.ts +1 -64
  305. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.js +66 -247
  306. package/dist/shared/flap/portal-bundle-merkle/swap-helpers.d.ts +149 -0
  307. package/dist/shared/flap/portal-bundle-merkle/swap-helpers.js +259 -0
  308. package/dist/shared/flap/portal-bundle-merkle/swap.d.ts +2 -71
  309. package/dist/shared/flap/portal-bundle-merkle/swap.js +103 -410
  310. package/dist/shared/flap/portal-bundle-merkle/types.d.ts +73 -3
  311. package/dist/shared/flap/portal-bundle-merkle/utils-helpers.d.ts +100 -0
  312. package/dist/shared/flap/portal-bundle-merkle/utils-helpers.js +133 -0
  313. package/dist/shared/flap/portal-bundle-merkle/utils.d.ts +1 -80
  314. package/dist/shared/flap/portal-bundle-merkle/utils.js +145 -265
  315. package/dist/shared/flap/portal-bundle.js +54 -42
  316. package/dist/shared/flap/portal.js +32 -10
  317. package/dist/shared/flap/vanity.js +4 -7
  318. package/dist/shared/flap/vault.d.ts +1 -1
  319. package/dist/shared/flap/vault.js +54 -48
  320. package/dist/shared/flap 2/__tests__/curve.test.d.ts +1 -0
  321. package/dist/shared/flap 2/portal-bundle-merkle/types.js +1 -0
  322. package/dist/shared/foundation/dex/v3-path.d.ts +6 -0
  323. package/dist/shared/foundation/dex/v3-path.js +35 -0
  324. package/dist/shared/foundation/gas/bundle-gas.d.ts +39 -0
  325. package/dist/shared/foundation/gas/bundle-gas.js +93 -0
  326. package/dist/shared/foundation/gas/profit-hop.d.ts +20 -0
  327. package/dist/shared/foundation/gas/profit-hop.js +72 -0
  328. package/dist/shared/foundation/index.d.ts +13 -0
  329. package/dist/shared/foundation/index.js +12 -0
  330. package/dist/shared/foundation/nonce/nonce-manager.d.ts +17 -0
  331. package/dist/shared/foundation/nonce/nonce-manager.js +180 -0
  332. package/dist/shared/foundation/normalize-unknown.d.ts +9 -0
  333. package/dist/shared/foundation/normalize-unknown.js +29 -0
  334. package/dist/shared/foundation/sdk-logger.d.ts +13 -0
  335. package/dist/shared/foundation/sdk-logger.js +12 -0
  336. package/dist/shared/foundation/tx/build-request.d.ts +17 -0
  337. package/dist/shared/foundation/tx/build-request.js +25 -0
  338. package/dist/shared/foundation/tx/sign-batch.d.ts +5 -0
  339. package/dist/shared/foundation/tx/sign-batch.js +26 -0
  340. package/dist/shared/foundation/tx/wallet-sign-patch.d.ts +1 -0
  341. package/dist/shared/foundation/tx/wallet-sign-patch.js +18 -0
  342. package/dist/shared/foundation/types/airdrop-sweep.d.ts +79 -0
  343. package/dist/shared/foundation/types/airdrop-sweep.js +1 -0
  344. package/dist/shared/foundation/types/erc20.d.ts +65 -0
  345. package/dist/shared/foundation/types/erc20.js +1 -0
  346. package/dist/shared/foundation/types/holders-maker.d.ts +64 -0
  347. package/dist/shared/foundation/types/holders-maker.js +1 -0
  348. package/dist/shared/foundation/types/index.d.ts +7 -0
  349. package/dist/shared/foundation/types/index.js +1 -0
  350. package/dist/shared/foundation/types/lp-inspect.d.ts +102 -0
  351. package/dist/shared/foundation/types/lp-inspect.js +1 -0
  352. package/dist/shared/foundation/types/multicall.d.ts +5 -0
  353. package/dist/shared/foundation/types/multicall.js +1 -0
  354. package/dist/shared/foundation/types/private-sale.d.ts +35 -0
  355. package/dist/shared/foundation/types/private-sale.js +1 -0
  356. package/dist/shared/foundation/types/quote-helpers.d.ts +17 -0
  357. package/dist/shared/foundation/types/quote-helpers.js +1 -0
  358. package/dist/shared/four/tax-token.d.ts +1 -1
  359. package/dist/shared/four/tax-token.js +27 -7
  360. package/dist/shared/index.d.ts +4 -0
  361. package/dist/shared/index.js +4 -0
  362. package/dist/types/distribute.d.ts +72 -0
  363. package/dist/types/distribute.js +1 -0
  364. package/dist/types 2/errors.d.ts +27 -0
  365. package/dist/types 2/errors.js +34 -0
  366. package/dist/utils/airdrop-sweep-types.d.ts +1 -0
  367. package/dist/utils/airdrop-sweep-types.js +1 -0
  368. package/dist/utils/airdrop-sweep.d.ts +4 -76
  369. package/dist/utils/airdrop-sweep.js +38 -52
  370. package/dist/utils/bundle-helpers.d.ts +9 -243
  371. package/dist/utils/bundle-helpers.js +10 -584
  372. package/dist/utils/constants.d.ts +5 -61
  373. package/dist/utils/constants.js +5 -80
  374. package/dist/utils/contract-factory.d.ts +2 -4
  375. package/dist/utils/contract-factory.js +25 -18
  376. package/dist/utils/erc20-types.d.ts +1 -0
  377. package/dist/utils/erc20-types.js +1 -0
  378. package/dist/utils/erc20.d.ts +8 -90
  379. package/dist/utils/erc20.js +94 -153
  380. package/dist/utils/errors.d.ts +10 -22
  381. package/dist/utils/errors.js +61 -79
  382. package/dist/utils/holders-maker/addresses.d.ts +12 -0
  383. package/dist/utils/holders-maker/addresses.js +15 -0
  384. package/dist/utils/holders-maker/buy-tx.d.ts +44 -0
  385. package/dist/utils/holders-maker/buy-tx.js +278 -0
  386. package/dist/utils/holders-maker/constants.d.ts +6 -0
  387. package/dist/utils/holders-maker/constants.js +7 -0
  388. package/dist/utils/holders-maker/disperse.d.ts +18 -0
  389. package/dist/utils/holders-maker/disperse.js +90 -0
  390. package/dist/utils/holders-maker/routing.d.ts +4 -0
  391. package/dist/utils/holders-maker/routing.js +45 -0
  392. package/dist/utils/holders-maker/transfer-tx.d.ts +4 -0
  393. package/dist/utils/holders-maker/transfer-tx.js +67 -0
  394. package/dist/utils/holders-maker-helpers.d.ts +9 -0
  395. package/dist/utils/holders-maker-helpers.js +9 -0
  396. package/dist/utils/holders-maker-types.d.ts +1 -0
  397. package/dist/utils/holders-maker-types.js +1 -0
  398. package/dist/utils/holders-maker.d.ts +2 -138
  399. package/dist/utils/holders-maker.js +23 -651
  400. package/dist/utils/hop-chains.d.ts +35 -0
  401. package/dist/utils/hop-chains.js +215 -0
  402. package/dist/utils/lp-inspect-helpers.d.ts +9 -0
  403. package/dist/utils/lp-inspect-helpers.js +109 -0
  404. package/dist/utils/lp-inspect-types.d.ts +1 -0
  405. package/dist/utils/lp-inspect-types.js +1 -0
  406. package/dist/utils/lp-inspect.d.ts +2 -112
  407. package/dist/utils/lp-inspect.js +63 -195
  408. package/dist/utils/mpcExclusive.d.ts +2 -5
  409. package/dist/utils/mpcExclusive.js +4 -3
  410. package/dist/utils/private-sale-types.d.ts +1 -0
  411. package/dist/utils/private-sale-types.js +1 -0
  412. package/dist/utils/private-sale.d.ts +2 -58
  413. package/dist/utils/private-sale.js +2 -7
  414. package/dist/utils/provider-factory.d.ts +4 -0
  415. package/dist/utils/provider-factory.js +10 -0
  416. package/dist/utils/quote-helpers-types.d.ts +1 -0
  417. package/dist/utils/quote-helpers-types.js +1 -0
  418. package/dist/utils/quote-helpers.d.ts +4 -45
  419. package/dist/utils/quote-helpers.js +15 -65
  420. package/dist/utils/stealth-transfer.d.ts +2 -28
  421. package/dist/utils/stealth-transfer.js +30 -14
  422. package/dist/utils/swap-helpers.d.ts +0 -3
  423. package/dist/utils/swap-helpers.js +6 -9
  424. package/dist/utils/types/airdrop-sweep.d.ts +1 -0
  425. package/dist/utils/types/airdrop-sweep.js +1 -0
  426. package/dist/utils/types/contract-factory.d.ts +1 -0
  427. package/dist/utils/types/contract-factory.js +1 -0
  428. package/dist/utils/types/erc20.d.ts +1 -0
  429. package/dist/utils/types/erc20.js +1 -0
  430. package/dist/utils/types/errors.d.ts +1 -0
  431. package/dist/utils/types/errors.js +1 -0
  432. package/dist/utils/types/holders-maker.d.ts +1 -0
  433. package/dist/utils/types/holders-maker.js +1 -0
  434. package/dist/utils/types/hop-chains.d.ts +8 -0
  435. package/dist/utils/types/hop-chains.js +1 -0
  436. package/dist/utils/types/index.d.ts +13 -0
  437. package/dist/utils/types/index.js +1 -0
  438. package/dist/utils/types/lp-inspect.d.ts +1 -0
  439. package/dist/utils/types/lp-inspect.js +1 -0
  440. package/dist/utils/types/mpc-exclusive.d.ts +5 -0
  441. package/dist/utils/types/mpc-exclusive.js +1 -0
  442. package/dist/utils/types/private-sale.d.ts +1 -0
  443. package/dist/utils/types/private-sale.js +1 -0
  444. package/dist/utils/types/quote-helpers.d.ts +1 -0
  445. package/dist/utils/types/quote-helpers.js +1 -0
  446. package/dist/utils/types/stealth-transfer.d.ts +44 -0
  447. package/dist/utils/types/stealth-transfer.js +1 -0
  448. package/dist/utils/types/wallet.d.ts +25 -0
  449. package/dist/utils/types/wallet.js +1 -0
  450. package/dist/utils/wallet.d.ts +2 -25
  451. package/dist/utils/wallet.js +9 -10
  452. package/package.json +55 -2
  453. package/src/abis/contracts/TaxToken.json +969 -0
  454. package/src/abis/contracts/TokenManager.json +836 -0
  455. package/src/abis/contracts/TokenManager2.json +136 -0
  456. package/src/abis/contracts/TokenManagerHelper3.json +993 -0
  457. /package/dist/{shared 2/flap/__tests__/curve.test.d.ts → bundle-core/__tests__/config-helpers.test.d.ts} +0 -0
  458. /package/dist/{shared 2/flap/portal-bundle-merkle/types.js → bundle-core/__tests__/facade-parity.test.d.ts} +0 -0
  459. /package/dist/{shared 2/abis → shared/abis 2}/TaxToken.json +0 -0
  460. /package/dist/{shared 2/abis → shared/abis 2}/TokenManager.json +0 -0
  461. /package/dist/{shared 2/abis → shared/abis 2}/TokenManager2.json +0 -0
  462. /package/dist/{shared 2/abis → shared/abis 2}/TokenManagerHelper3.json +0 -0
  463. /package/dist/{shared 2/abis → shared/abis 2}/common.d.ts +0 -0
  464. /package/dist/{shared 2/abis → shared/abis 2}/common.js +0 -0
  465. /package/dist/{shared 2/abis → shared/abis 2}/index.d.ts +0 -0
  466. /package/dist/{shared 2/abis → shared/abis 2}/index.js +0 -0
  467. /package/dist/{shared 2/clients → shared/clients 2}/blockrazor.d.ts +0 -0
  468. /package/dist/{shared 2/clients → shared/clients 2}/blockrazor.js +0 -0
  469. /package/dist/{shared 2/clients → shared/clients 2}/club48.d.ts +0 -0
  470. /package/dist/{shared 2/clients → shared/clients 2}/club48.js +0 -0
  471. /package/dist/{shared 2/clients → shared/clients 2}/emitservice.d.ts +0 -0
  472. /package/dist/{shared 2/clients → shared/clients 2}/emitservice.js +0 -0
  473. /package/dist/{shared 2/clients → shared/clients 2}/four.d.ts +0 -0
  474. /package/dist/{shared 2/clients → shared/clients 2}/four.js +0 -0
  475. /package/dist/{shared 2/clients → shared/clients 2}/merkle.d.ts +0 -0
  476. /package/dist/{shared 2/clients → shared/clients 2}/merkle.js +0 -0
  477. /package/dist/{shared 2/flap → shared/flap 2}/__tests__/curve.test.js +0 -0
  478. /package/dist/{shared 2/flap → shared/flap 2}/abi.d.ts +0 -0
  479. /package/dist/{shared 2/flap → shared/flap 2}/abi.js +0 -0
  480. /package/dist/{shared 2/flap → shared/flap 2}/constants.d.ts +0 -0
  481. /package/dist/{shared 2/flap → shared/flap 2}/constants.js +0 -0
  482. /package/dist/{shared 2/flap → shared/flap 2}/curve.d.ts +0 -0
  483. /package/dist/{shared 2/flap → shared/flap 2}/curve.js +0 -0
  484. /package/dist/{shared 2/flap → shared/flap 2}/errors.d.ts +0 -0
  485. /package/dist/{shared 2/flap → shared/flap 2}/errors.js +0 -0
  486. /package/dist/{shared 2/flap → shared/flap 2}/index.d.ts +0 -0
  487. /package/dist/{shared 2/flap → shared/flap 2}/index.js +0 -0
  488. /package/dist/{shared 2/flap → shared/flap 2}/ipfs.d.ts +0 -0
  489. /package/dist/{shared 2/flap → shared/flap 2}/ipfs.js +0 -0
  490. /package/dist/{shared 2/flap → shared/flap 2}/meta.d.ts +0 -0
  491. /package/dist/{shared 2/flap → shared/flap 2}/meta.js +0 -0
  492. /package/dist/{shared 2/flap → shared/flap 2}/permit.d.ts +0 -0
  493. /package/dist/{shared 2/flap → shared/flap 2}/permit.js +0 -0
  494. /package/dist/{shared 2/flap → shared/flap 2}/pinata.d.ts +0 -0
  495. /package/dist/{shared 2/flap → shared/flap 2}/pinata.js +0 -0
  496. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/config.d.ts +0 -0
  497. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/config.js +0 -0
  498. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/core.d.ts +0 -0
  499. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/core.js +0 -0
  500. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/create-to-dex.d.ts +0 -0
  501. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/create-to-dex.js +0 -0
  502. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/curve-to-dex.d.ts +0 -0
  503. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/curve-to-dex.js +0 -0
  504. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/index.d.ts +0 -0
  505. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/index.js +0 -0
  506. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/pancake-proxy.d.ts +0 -0
  507. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/pancake-proxy.js +0 -0
  508. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/private.d.ts +0 -0
  509. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/private.js +0 -0
  510. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/swap-buy-first.d.ts +0 -0
  511. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/swap-buy-first.js +0 -0
  512. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/swap.d.ts +0 -0
  513. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/swap.js +0 -0
  514. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/types.d.ts +0 -0
  515. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/utils.d.ts +0 -0
  516. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/utils.js +0 -0
  517. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle.d.ts +0 -0
  518. /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle.js +0 -0
  519. /package/dist/{shared 2/flap → shared/flap 2}/portal.d.ts +0 -0
  520. /package/dist/{shared 2/flap → shared/flap 2}/portal.js +0 -0
  521. /package/dist/{shared 2/flap → shared/flap 2}/vanity.d.ts +0 -0
  522. /package/dist/{shared 2/flap → shared/flap 2}/vanity.js +0 -0
  523. /package/dist/{shared 2/flap → shared/flap 2}/vault.d.ts +0 -0
  524. /package/dist/{shared 2/flap → shared/flap 2}/vault.js +0 -0
  525. /package/dist/{shared 2/four → shared/four 2}/index.d.ts +0 -0
  526. /package/dist/{shared 2/four → shared/four 2}/index.js +0 -0
  527. /package/dist/{shared 2/four → shared/four 2}/tax-token.d.ts +0 -0
  528. /package/dist/{shared 2/four → shared/four 2}/tax-token.js +0 -0
  529. /package/dist/{shared 2/index.d.ts → shared/index 2.js} +0 -0
  530. /package/dist/{shared 2/index.js → shared/index.d 2.ts} +0 -0
@@ -1,585 +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
- // ==================== V2 报价 ====================
240
- if (routeParams.routeType === 'v2') {
241
- const { v2Path } = routeParams;
242
- const tokenIn = v2Path[0];
243
- const tokenOut = v2Path[v2Path.length - 1];
244
- const result = await quoteV2(provider, tokenIn, tokenOut, sellAmountWei, 'BSC', v2RouterAddress);
245
- if (result.amountOut > 0n) {
246
- return { estimatedBNBOut: result.amountOut };
247
- }
248
- throw new Error('V2 报价失败: 所有路径均无效');
249
- }
250
- // ==================== V3 单跳报价 ====================
251
- if (routeParams.routeType === 'v3-single') {
252
- const params = routeParams;
253
- // ✅ 只用 V3 报价,不 fallback 到 V2
254
- const result = await quoteV3(provider, params.v3TokenIn, params.v3TokenOut, sellAmountWei, 'BSC', params.v3Fee);
255
- if (result.amountOut > 0n) {
256
- return { estimatedBNBOut: result.amountOut };
257
- }
258
- // ❌ V3 报价失败时不再 fallback 到 V2,因为价格可能差异很大
259
- throw new Error(`V3 单跳报价失败: tokenIn=${params.v3TokenIn}, tokenOut=${params.v3TokenOut}, fee=${params.v3Fee}`);
260
- }
261
- // ==================== V3 多跳报价 ====================
262
- if (routeParams.routeType === 'v3-multi') {
263
- const params = routeParams;
264
- // ✅ V3 多跳:只用 V3 报价,不 fallback 到 V2
265
- if (params.v3LpAddresses && params.v3LpAddresses.length > 0) {
266
- const tokenIn = params.v3ExactTokenIn;
267
- const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
268
- const result = await quoteV3(provider, tokenIn, WBNB, sellAmountWei, 'BSC');
269
- if (result.amountOut > 0n) {
270
- return { estimatedBNBOut: result.amountOut };
271
- }
272
- }
273
- // ❌ V3 多跳报价失败时不再 fallback 到 V2,因为价格可能差异很大
274
- throw new Error(`V3 多跳报价失败: LPs=${params.v3LpAddresses?.join(', ')}, tokenIn=${params.v3ExactTokenIn}`);
275
- }
276
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
277
- throw new Error(`不支持的路由类型: ${routeParams.routeType}`);
278
- }
279
- async function buildSwapTransactions({ routeParams, sellAmountWei, buyAmountBNB, buyer, seller, useNativeToken = true, v2RouterAddress }) {
280
- const deadline = getDeadline();
281
- const buyValue = useNativeToken ? buyAmountBNB + FLAT_FEE : 0n;
282
- if (routeParams.routeType === 'v2') {
283
- const { v2Path } = routeParams;
284
- const reversePath = [...v2Path].reverse();
285
- const routerAddr = v2RouterAddress || PANCAKE_V2_ROUTER_ADDRESS;
286
- const v2RouterSeller = new Contract(routerAddr, PANCAKE_V2_ROUTER_ABI, seller);
287
- const v2RouterBuyer = new Contract(routerAddr, PANCAKE_V2_ROUTER_ABI, buyer);
288
- let sellUnsigned;
289
- let buyUnsigned;
290
- if (useNativeToken) {
291
- // ✅ 原生代币模式(BNB)
292
- // 卖出:Token → WBNB → BNB
293
- sellUnsigned = await v2RouterSeller.swapExactTokensForETHSupportingFeeOnTransferTokens.populateTransaction(sellAmountWei, 0n, v2Path, seller.address, deadline);
294
- // 买入:BNB → WBNB → Token
295
- buyUnsigned = await v2RouterBuyer.swapExactETHForTokensSupportingFeeOnTransferTokens.populateTransaction(0n, reversePath, buyer.address, deadline, { value: buyValue });
296
- }
297
- else {
298
- // ✅ ERC20 模式(如 USDT)
299
- // 卖出:Token → USDT
300
- sellUnsigned = await v2RouterSeller.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(sellAmountWei, 0n, v2Path, seller.address, deadline);
301
- // 买入:USDT → Token
302
- buyUnsigned = await v2RouterBuyer.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(buyAmountBNB, // USDT 数量
303
- 0n, reversePath, buyer.address, deadline);
304
- }
305
- return { sellUnsigned, buyUnsigned };
306
- }
307
- if (routeParams.routeType === 'v3-single') {
308
- const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
309
- const v3RouterIface = new ethers.Interface(PANCAKE_V3_ROUTER_ABI);
310
- const v3RouterSeller = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, seller);
311
- const v3RouterBuyer = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, buyer);
312
- // 卖出:Token → WBNB,需要 unwrapWETH9
313
- const sellSwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
314
- tokenIn: v3TokenIn,
315
- tokenOut: v3TokenOut,
316
- fee: v3Fee,
317
- recipient: PANCAKE_V3_ROUTER_ADDRESS, // 先发给 Router
318
- amountIn: sellAmountWei,
319
- amountOutMinimum: 0n,
320
- sqrtPriceLimitX96: 0n
321
- }]);
322
- const sellUnwrapData = v3RouterIface.encodeFunctionData('unwrapWETH9', [0n, seller.address]);
323
- const sellUnsigned = await v3RouterSeller.multicall.populateTransaction(deadline, [sellSwapData, sellUnwrapData]);
324
- // 买入:WBNB → Token
325
- const buySwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
326
- tokenIn: v3TokenOut,
327
- tokenOut: v3TokenIn,
328
- fee: v3Fee,
329
- recipient: buyer.address,
330
- amountIn: buyAmountBNB,
331
- amountOutMinimum: 0n,
332
- sqrtPriceLimitX96: 0n
333
- }]);
334
- const buyUnsigned = await v3RouterBuyer.multicall.populateTransaction(deadline, [buySwapData], { value: buyValue });
335
- return { sellUnsigned, buyUnsigned };
336
- }
337
- // V3 多跳暂不支持官方合约
338
- throw new Error('V3 多跳路由暂不支持官方合约,请使用 V2 路由或 V3 单跳');
339
- }
340
- async function calculateBuyerBudget({ buyer, quotedBNBOut, reserveGasBNB, useNativeToken = true, quoteToken, quoteTokenDecimals = 18, provider }) {
341
- const reserveGas = ethers.parseEther((reserveGasBNB ?? 0.0005).toString());
342
- // ✅ 已移除滑点保护:直接使用报价金额
343
- const buyAmountBNB = quotedBNBOut;
344
- // ✅ 根据是否使用原生代币获取不同的余额
345
- let buyerBalance;
346
- if (useNativeToken) {
347
- buyerBalance = await buyer.provider.getBalance(buyer.address);
348
- const requiredBalance = buyAmountBNB + FLAT_FEE + reserveGas;
349
- if (buyerBalance < requiredBalance) {
350
- throw new Error(`买方余额不足: 需要 ${ethers.formatEther(requiredBalance)} BNB, 实际 ${ethers.formatEther(buyerBalance)} BNB`);
351
- }
352
- return { buyerBalance, reserveGas, requiredBalance, buyAmountBNB, useNativeToken };
353
- }
354
- else {
355
- // ERC20 代币余额
356
- const erc20 = new Contract(quoteToken, ERC20_BALANCE_OF_ABI, provider || buyer.provider);
357
- buyerBalance = await erc20.balanceOf(buyer.address);
358
- const requiredBalance = buyAmountBNB + FLAT_FEE; // ERC20 不需要预留 Gas 在代币余额中
359
- if (buyerBalance < requiredBalance) {
360
- throw new Error(`买方代币余额不足: 需要 ${ethers.formatUnits(requiredBalance, quoteTokenDecimals)}, 实际 ${ethers.formatUnits(buyerBalance, quoteTokenDecimals)}`);
361
- }
362
- // ✅ ERC20 购买时,还需要检查买方是否有足够 BNB 支付 Gas
363
- const buyerBnbBalance = await buyer.provider.getBalance(buyer.address);
364
- if (buyerBnbBalance < reserveGas) {
365
- throw new Error(`买方 BNB 余额不足 (用于支付 Gas): 需要 ${ethers.formatEther(reserveGas)} BNB, 实际 ${ethers.formatEther(buyerBnbBalance)} BNB`);
366
- }
367
- return { buyerBalance, reserveGas, requiredBalance, buyAmountBNB, useNativeToken };
368
- }
369
- }
370
- /**
371
- * ✅ 从前端传入的 startNonces 构建 NoncePlan(用于性能优化)
372
- * 顺序:[sellerBaseNonce, buyerNonce]
373
- */
374
- function buildNoncePlanFromNonces(startNonces, sameAddress, approvalExists, profitNeeded, needBribeTx) {
375
- if (sameAddress) {
376
- let idx = 0;
377
- const bribeNonce = needBribeTx ? startNonces[0] + idx++ : undefined;
378
- if (approvalExists)
379
- idx++;
380
- const sellerNonce = startNonces[0] + idx++;
381
- const buyerNonce = startNonces[0] + idx++;
382
- const profitNonce = profitNeeded ? startNonces[0] + idx : undefined;
383
- return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
384
- }
385
- let sellerIdx = 0;
386
- const bribeNonce = needBribeTx ? startNonces[0] + sellerIdx++ : undefined;
387
- if (approvalExists)
388
- sellerIdx++;
389
- const sellerNonce = startNonces[0] + sellerIdx++;
390
- const profitNonce = profitNeeded ? startNonces[0] + sellerIdx : undefined;
391
- const buyerNonce = startNonces[1];
392
- return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
393
- }
394
- /**
395
- * ✅ 规划 nonce
396
- * 交易顺序:贿赂 → 授权 → 卖出 → 买入 → 利润
397
- * 贿赂和利润由卖方发送
398
- */
399
- async function planNonces({ seller, buyer, sameAddress, approvalExists, profitNeeded, needBribeTx, nonceManager }) {
400
- if (sameAddress) {
401
- // 同一地址:贿赂(可选) + 授权(可选) + 卖出 + 买入 + 利润(可选)
402
- const txCount = countTruthy([needBribeTx, approvalExists, true, true, profitNeeded]);
403
- const nonces = await nonceManager.getNextNonceBatch(buyer, txCount);
404
- let idx = 0;
405
- const bribeNonce = needBribeTx ? nonces[idx++] : undefined;
406
- if (approvalExists)
407
- idx++;
408
- const sellerNonce = nonces[idx++];
409
- const buyerNonce = nonces[idx++];
410
- const profitNonce = profitNeeded ? nonces[idx] : undefined;
411
- return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
412
- }
413
- if (needBribeTx || approvalExists || profitNeeded) {
414
- // 卖方需要多个 nonce:贿赂(可选) + 授权(可选) + 卖出 + 利润(可选)
415
- const sellerTxCount = countTruthy([needBribeTx, approvalExists, true, profitNeeded]);
416
- // ✅ 并行获取 seller 和 buyer 的 nonce
417
- const [sellerNonces, buyerNonce] = await Promise.all([
418
- nonceManager.getNextNonceBatch(seller, sellerTxCount),
419
- nonceManager.getNextNonce(buyer)
420
- ]);
421
- let idx = 0;
422
- const bribeNonce = needBribeTx ? sellerNonces[idx++] : undefined;
423
- if (approvalExists)
424
- idx++;
425
- const sellerNonce = sellerNonces[idx++];
426
- const profitNonce = profitNeeded ? sellerNonces[idx] : undefined;
427
- return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
428
- }
429
- // ✅ 并行获取 seller 和 buyer 的 nonce
430
- const [sellerNonce, buyerNonce] = await Promise.all([
431
- nonceManager.getNextNonce(seller),
432
- nonceManager.getNextNonce(buyer)
433
- ]);
434
- return { sellerNonce, buyerNonce };
435
- }
436
- /**
437
- * 根据 userType 计算利润率
438
- */
439
- function getProfitRateBps(userType) {
440
- if (userType === 'v0') {
441
- return getProfitRateBpsShared('v0Single'); // 0.06%
442
- }
443
- else if (userType === 'v1') {
444
- return getProfitRateBpsShared('v1Single'); // 0.05%
445
- }
446
- return getProfitRateBpsShared('v0Single'); // 默认 0.06%
447
- }
448
- function calculateProfitAmount(estimatedBNBOut, userType) {
449
- if (estimatedBNBOut <= 0n) {
450
- return 0n;
451
- }
452
- const rateBps = getProfitRateBps(userType);
453
- return (estimatedBNBOut * BigInt(rateBps)) / 10000n;
454
- }
455
- /**
456
- * ✅ 获取 ERC20 代币 → 原生代币(BNB)的报价
457
- * 用于将 ERC20 利润转换为 BNB
458
- * 使用共享的报价函数
459
- */
460
- async function getERC20ToNativeQuote(provider, tokenAddress, tokenAmount, version = 'v2', fee) {
461
- if (tokenAmount <= 0n)
462
- return 0n;
463
- const tokenLower = tokenAddress.toLowerCase();
464
- const wbnbLower = WBNB_ADDRESS.toLowerCase();
465
- // 如果代币本身就是 WBNB,直接返回
466
- if (tokenLower === wbnbLower) {
467
- return tokenAmount;
468
- }
469
- // 使用共享的报价函数
470
- if (version === 'v3') {
471
- const result = await quoteV3(provider, tokenAddress, WBNB_ADDRESS, tokenAmount, 'BSC', fee);
472
- if (result.amountOut > 0n) {
473
- return result.amountOut;
474
- }
475
- console.warn(`[getERC20ToNativeQuote] V3 报价失败`);
476
- return 0n;
477
- }
478
- // V2 报价
479
- const result = await quoteV2(provider, tokenAddress, WBNB_ADDRESS, tokenAmount, 'BSC');
480
- if (result.amountOut > 0n) {
481
- return result.amountOut;
482
- }
483
- console.warn(`[getERC20ToNativeQuote] V2 报价失败`);
484
- return 0n;
485
- }
486
- async function validateFinalBalances({ sameAddress, buyerBalance, buyAmountBNB, reserveGas, gasLimit, gasPrice, useNativeToken = true, quoteTokenDecimals = 18, provider, buyerAddress }) {
487
- const gasCost = gasLimit * gasPrice;
488
- if (sameAddress) {
489
- // 同一地址:需要足够的余额支付两笔交易
490
- if (useNativeToken) {
491
- const requiredCombined = buyAmountBNB + FLAT_FEE * 2n + gasCost * 2n;
492
- if (buyerBalance < requiredCombined) {
493
- throw new Error(`账户余额不足:\n - 需要: ${ethers.formatEther(requiredCombined)} BNB(含两笔Gas与两笔手续费)\n - 实际: ${ethers.formatEther(buyerBalance)} BNB`);
494
- }
495
- }
496
- else {
497
- // ERC20:检查代币余额 + BNB Gas 余额
498
- const requiredToken = buyAmountBNB + FLAT_FEE * 2n;
499
- if (buyerBalance < requiredToken) {
500
- throw new Error(`账户代币余额不足:\n - 需要: ${ethers.formatUnits(requiredToken, quoteTokenDecimals)}\n - 实际: ${ethers.formatUnits(buyerBalance, quoteTokenDecimals)}`);
501
- }
502
- // 检查 BNB Gas
503
- if (provider && buyerAddress) {
504
- const bnbBalance = await provider.getBalance(buyerAddress);
505
- const requiredGas = gasCost * 2n;
506
- if (bnbBalance < requiredGas) {
507
- throw new Error(`账户 BNB 余额不足 (用于支付 Gas):\n - 需要: ${ethers.formatEther(requiredGas)} BNB\n - 实际: ${ethers.formatEther(bnbBalance)} BNB`);
508
- }
509
- }
510
- }
511
- return;
512
- }
513
- // 不同地址
514
- if (useNativeToken) {
515
- const requiredBuyer = buyAmountBNB + FLAT_FEE + reserveGas;
516
- if (buyerBalance < requiredBuyer) {
517
- throw new Error(`买方余额不足:\n - 需要: ${ethers.formatEther(requiredBuyer)} BNB\n - 实际: ${ethers.formatEther(buyerBalance)} BNB`);
518
- }
519
- }
520
- // ERC20 余额已在 calculateBuyerBudget 中检查过
521
- }
522
- function countTruthy(values) {
523
- return values.filter(Boolean).length;
524
- }
525
- /**
526
- * PancakeSwap V2/V3 通用捆绑换手(Merkle Bundle)
527
- *
528
- * 功能:钱包A卖出代币 → 钱包B买入相同数量 → 原子执行
529
- * 适用于所有已迁移到外盘的代币(不区分Four/Flap)
2
+ * bundle-swap - 主函数
530
3
  */
4
+ import { GAS_LIMITS, CHAINS, getProfitRecipient } from '../../../shared/constants/index.js';
531
5
  import { ethers, Contract, Wallet } from 'ethers';
532
6
  import { calculateSellAmount } from '../../../utils/swap-helpers.js';
533
- import { NonceManager, getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../../utils/bundle-helpers.js';
534
- import { ADDRESSES, BLOCKRAZOR_BUILDER_EOA } from '../../../utils/constants.js';
535
- import { getProfitRecipient, getProfitRateBps as getProfitRateBpsShared } from '../../../shared/constants/index.js';
536
- import { quoteV2, quoteV3 } from '../../../utils/quote-helpers.js';
537
- import { V2_ROUTER_ABI, V3_ROUTER02_ABI, ERC20_BALANCE_ABI, ERC20_ABI } from '../../../shared/abis/common.js';
538
- import { generateWallets } from '../../../utils/wallet.js';
539
- /**
540
- * 获取 Gas Limit
541
- */
542
- function getGasLimit(config, defaultGas = 800000) {
543
- if (config.gasLimit !== undefined) {
544
- return typeof config.gasLimit === 'bigint' ? config.gasLimit : BigInt(config.gasLimit);
545
- }
546
- const multiplier = config.gasLimitMultiplier ?? 1.0;
547
- const calculatedGas = Math.ceil(defaultGas * multiplier);
548
- return BigInt(calculatedGas);
549
- }
550
- async function getGasPrice(provider, config) {
551
- const feeData = await provider.getFeeData();
552
- let gasPrice = feeData.gasPrice || ethers.parseUnits('3', 'gwei');
553
- if (config.minGasPriceGwei) {
554
- const minGas = ethers.parseUnits(config.minGasPriceGwei.toString(), 'gwei');
555
- if (gasPrice < minGas)
556
- gasPrice = minGas;
557
- }
558
- if (config.maxGasPriceGwei) {
559
- const maxGas = ethers.parseUnits(config.maxGasPriceGwei.toString(), 'gwei');
560
- if (gasPrice > maxGas)
561
- gasPrice = maxGas;
562
- }
563
- return gasPrice;
564
- }
565
- // ✅ ABI 别名(从公共模块导入)
566
- const PANCAKE_V2_ROUTER_ABI = V2_ROUTER_ABI;
567
- const PANCAKE_V3_ROUTER_ABI = V3_ROUTER02_ABI;
568
- const ERC20_BALANCE_OF_ABI = ERC20_BALANCE_ABI;
569
- // ✅ 使用官方 PancakeSwap Router 地址
570
- const PANCAKE_V2_ROUTER_ADDRESS = ADDRESSES.BSC.PancakeV2Router;
571
- const PANCAKE_V3_ROUTER_ADDRESS = ADDRESSES.BSC.PancakeV3Router;
572
- // 常量
573
- const FLAT_FEE = 0n;
574
- const WBNB_ADDRESS = ADDRESSES.BSC.WBNB;
575
- const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
576
- // ✅ ERC20_BALANCE_OF_ABI 已在文件开头定义
577
- /**
578
- * PancakeSwap捆绑换手(V2/V3通用)
579
- * ✅ 支持 quoteToken:传入 USDT 等地址时,卖出得到该代币,买入使用该代币
580
- */
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';
581
11
  export async function pancakeBundleSwapMerkle(params) {
582
- 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
583
13
  } = params;
584
14
  // ✅ 判断是否使用原生代币(BNB)或 ERC20 代币(如 USDT)
585
15
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
@@ -594,14 +24,14 @@ export async function pancakeBundleSwapMerkle(params) {
594
24
  // ✅ 并行获取 gasPrice 和卖出数量
595
25
  const [gasPrice, sellAmountResult] = await Promise.all([
596
26
  getGasPrice(context.provider, config),
597
- calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage)
27
+ calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage),
598
28
  ]);
599
29
  const { amount: sellAmountWei, decimals } = sellAmountResult;
600
30
  const quoteResult = await quoteSellOutput({
601
31
  routeParams,
602
32
  sellAmountWei,
603
33
  provider: context.provider,
604
- v2RouterAddress: config.v2RouterAddress
34
+ v2RouterAddress: config.v2RouterAddress,
605
35
  });
606
36
  const buyerBudget = await calculateBuyerBudget({
607
37
  buyer,
@@ -610,7 +40,7 @@ export async function pancakeBundleSwapMerkle(params) {
610
40
  useNativeToken,
611
41
  quoteToken,
612
42
  quoteTokenDecimals,
613
- provider: context.provider
43
+ provider: context.provider,
614
44
  });
615
45
  const swapUnsigned = await buildSwapTransactions({
616
46
  routeParams,
@@ -618,8 +48,9 @@ export async function pancakeBundleSwapMerkle(params) {
618
48
  buyAmountBNB: buyerBudget.buyAmountBNB,
619
49
  buyer,
620
50
  seller,
51
+ tokenAddress,
621
52
  useNativeToken,
622
- v2RouterAddress: config.v2RouterAddress
53
+ v2RouterAddress: config.v2RouterAddress,
623
54
  });
624
55
  // ✅ 修复:利润计算应基于 BNB 数量,不是 ERC20 数量
625
56
  // 如果输出是原生代币(BNB),直接使用报价结果
@@ -640,9 +71,7 @@ export async function pancakeBundleSwapMerkle(params) {
640
71
  // ERC20→BNB 报价完成
641
72
  }
642
73
  // ✅ 获取贿赂金额
643
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0
644
- ? ethers.parseEther(String(config.bribeAmount))
645
- : 0n;
74
+ const bribeAmount = config.bribeAmount && config.bribeAmount > 0 ? ethers.parseEther(String(config.bribeAmount)) : 0n;
646
75
  const needBribeTx = bribeAmount > 0n;
647
76
  // ✅ 使用共享的 NonceManager 规划 nonce
648
77
  // 如果前端传入了 startNonces,直接使用(性能优化)
@@ -655,48 +84,54 @@ export async function pancakeBundleSwapMerkle(params) {
655
84
  approvalExists: false, // ✅ 已移除授权
656
85
  profitNeeded: profitAmount > 0n,
657
86
  needBribeTx,
658
- nonceManager
87
+ nonceManager,
659
88
  });
660
89
  // ✅ 并行签名所有交易
661
90
  const signPromises = [];
662
91
  // 贿赂交易
663
92
  if (needBribeTx && noncePlan.bribeNonce !== undefined) {
664
- signPromises.push(seller.signTransaction({
93
+ signPromises.push(seller
94
+ .signTransaction({
665
95
  to: BLOCKRAZOR_BUILDER_EOA,
666
96
  value: bribeAmount,
667
97
  nonce: noncePlan.bribeNonce,
668
98
  gasPrice,
669
99
  gasLimit: BRIBE_GAS_LIMIT,
670
100
  chainId: context.chainId,
671
- type: txType
672
- }).then(tx => ({ type: 'bribe', tx })));
101
+ type: txType,
102
+ })
103
+ .then((tx) => ({ type: 'bribe', tx })));
673
104
  }
674
105
  // 卖出交易
675
- signPromises.push(seller.signTransaction({
106
+ signPromises.push(seller
107
+ .signTransaction({
676
108
  ...swapUnsigned.sellUnsigned,
677
109
  from: seller.address,
678
110
  nonce: noncePlan.sellerNonce,
679
111
  gasLimit: finalGasLimit,
680
112
  gasPrice,
681
113
  chainId: context.chainId,
682
- type: txType
683
- }).then(tx => ({ type: 'sell', tx })));
114
+ type: txType,
115
+ })
116
+ .then((tx) => ({ type: 'sell', tx })));
684
117
  // 买入交易
685
- signPromises.push(buyer.signTransaction({
118
+ signPromises.push(buyer
119
+ .signTransaction({
686
120
  ...swapUnsigned.buyUnsigned,
687
121
  from: buyer.address,
688
122
  nonce: noncePlan.buyerNonce,
689
123
  gasLimit: finalGasLimit,
690
124
  gasPrice,
691
125
  chainId: context.chainId,
692
- type: txType
693
- }).then(tx => ({ type: 'buy', tx })));
126
+ type: txType,
127
+ })
128
+ .then((tx) => ({ type: 'buy', tx })));
694
129
  // ✅ 并行执行所有签名
695
130
  const signedResults = await Promise.all(signPromises);
696
131
  // 按类型提取结果
697
- const bribeTx = signedResults.find(r => r.type === 'bribe')?.tx || null;
698
- const signedSell = signedResults.find(r => r.type === 'sell').tx;
699
- 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;
700
135
  nonceManager.clearTemp();
701
136
  validateFinalBalances({
702
137
  sameAddress,
@@ -708,7 +143,7 @@ export async function pancakeBundleSwapMerkle(params) {
708
143
  useNativeToken,
709
144
  quoteTokenDecimals,
710
145
  provider: context.provider,
711
- buyerAddress: buyer.address
146
+ buyerAddress: buyer.address,
712
147
  });
713
148
  // ✅ 组装顺序:贿赂 → 卖出 → 买入
714
149
  const signedTransactions = [];
@@ -727,7 +162,7 @@ export async function pancakeBundleSwapMerkle(params) {
727
162
  gasPrice,
728
163
  chainId: context.chainId,
729
164
  txType,
730
- startNonce: noncePlan.profitNonce
165
+ startNonce: noncePlan.profitNonce,
731
166
  });
732
167
  signedTransactions.push(...profitHopResult.signedTransactions);
733
168
  profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
@@ -742,8 +177,8 @@ export async function pancakeBundleSwapMerkle(params) {
742
177
  buyAmount: useNativeToken
743
178
  ? ethers.formatEther(buyerBudget.buyAmountBNB)
744
179
  : ethers.formatUnits(buyerBudget.buyAmountBNB, quoteTokenDecimals),
745
- profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined
746
- }
180
+ profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined,
181
+ },
747
182
  };
748
183
  }
749
184
  /**
@@ -755,7 +190,7 @@ export async function pancakeBundleSwapMerkle(params) {
755
190
  * 交易顺序:[授权(可选)] → [卖出] → [买入1, 买入2, ..., 买入N] → [利润]
756
191
  */
757
192
  export async function pancakeBatchSwapMerkle(params) {
758
- 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
759
194
  } = params;
760
195
  // ✅ 校验买方数量(最多 24 个)
761
196
  const MAX_BUYERS = 24;
@@ -768,7 +203,7 @@ export async function pancakeBatchSwapMerkle(params) {
768
203
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
769
204
  const context = createPancakeContext(config);
770
205
  const seller = new Wallet(sellerPrivateKey, context.provider);
771
- const buyers = buyerPrivateKeys.map(pk => new Wallet(pk, context.provider));
206
+ const buyers = buyerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
772
207
  // ✅ 创建共享资源
773
208
  const nonceManager = new NonceManager(context.provider);
774
209
  const finalGasLimit = getGasLimit(config);
@@ -776,14 +211,14 @@ export async function pancakeBatchSwapMerkle(params) {
776
211
  // ✅ 并行获取 gasPrice 和卖出数量
777
212
  const [gasPrice, sellAmountResult] = await Promise.all([
778
213
  getGasPrice(context.provider, config),
779
- calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage)
214
+ calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage),
780
215
  ]);
781
216
  const { amount: sellAmountWei, decimals } = sellAmountResult;
782
217
  const quoteResult = await quoteSellOutput({
783
218
  routeParams,
784
219
  sellAmountWei,
785
220
  provider: context.provider,
786
- v2RouterAddress: config.v2RouterAddress
221
+ v2RouterAddress: config.v2RouterAddress,
787
222
  });
788
223
  const estimatedBNBOut = quoteResult.estimatedBNBOut;
789
224
  // ✅ 计算每个买方的买入金额(已移除滑点保护:直接使用报价金额)
@@ -791,14 +226,12 @@ export async function pancakeBatchSwapMerkle(params) {
791
226
  const totalBuyAmount = estimatedBNBOut;
792
227
  if (buyerAmounts && buyerAmounts.length === buyers.length) {
793
228
  // 方式1:使用指定的买入金额(USDT)
794
- buyAmountsWei = buyerAmounts.map(amt => useNativeToken
795
- ? ethers.parseEther(amt)
796
- : ethers.parseUnits(amt, quoteTokenDecimals));
229
+ buyAmountsWei = buyerAmounts.map((amt) => useNativeToken ? ethers.parseEther(amt) : ethers.parseUnits(amt, quoteTokenDecimals));
797
230
  }
798
231
  else if (params.buyerRatios && params.buyerRatios.length === buyers.length) {
799
232
  // ✅ 方式2:按比例分配卖出所得
800
233
  // buyerRatios 如 [0.3, 0.5, 0.2] 表示第一个买方分 30%,第二个 50%,第三个 20%
801
- buyAmountsWei = params.buyerRatios.map((ratio, _index) => {
234
+ buyAmountsWei = params.buyerRatios.map((ratio) => {
802
235
  // 按比例计算每个买方的金额
803
236
  const amount = (totalBuyAmount * BigInt(Math.round(ratio * 10000))) / 10000n;
804
237
  return amount;
@@ -848,15 +281,17 @@ export async function pancakeBatchSwapMerkle(params) {
848
281
  else if (routeParams.routeType === 'v3-single') {
849
282
  const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
850
283
  const v3RouterSeller = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, seller);
851
- const sellSwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
284
+ const sellSwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [
285
+ {
852
286
  tokenIn: v3TokenIn,
853
287
  tokenOut: v3TokenOut,
854
288
  fee: v3Fee,
855
289
  recipient: useNativeToken ? PANCAKE_V3_ROUTER_ADDRESS : seller.address,
856
290
  amountIn: sellAmountWei,
857
291
  amountOutMinimum: 0n,
858
- sqrtPriceLimitX96: 0n
859
- }]);
292
+ sqrtPriceLimitX96: 0n,
293
+ },
294
+ ]);
860
295
  if (useNativeToken) {
861
296
  // 原生代币:需要 unwrap WBNB
862
297
  const sellUnwrapData = v3RouterIface.encodeFunctionData('unwrapWETH9', [0n, seller.address]);
@@ -889,15 +324,17 @@ export async function pancakeBatchSwapMerkle(params) {
889
324
  else if (routeParams.routeType === 'v3-single') {
890
325
  const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
891
326
  const v3RouterBuyer = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, buyer);
892
- const buySwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
327
+ const buySwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [
328
+ {
893
329
  tokenIn: v3TokenOut,
894
330
  tokenOut: v3TokenIn,
895
331
  fee: v3Fee,
896
332
  recipient: buyer.address,
897
333
  amountIn: buyAmount,
898
334
  amountOutMinimum: 0n,
899
- sqrtPriceLimitX96: 0n
900
- }]);
335
+ sqrtPriceLimitX96: 0n,
336
+ },
337
+ ]);
901
338
  return await v3RouterBuyer.multicall.populateTransaction(deadline, [buySwapData], { value: buyValue });
902
339
  }
903
340
  else {
@@ -905,16 +342,14 @@ export async function pancakeBatchSwapMerkle(params) {
905
342
  }
906
343
  }));
907
344
  // ✅ 获取贿赂金额
908
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0
909
- ? ethers.parseEther(String(config.bribeAmount))
910
- : 0n;
345
+ const bribeAmount = config.bribeAmount && config.bribeAmount > 0 ? ethers.parseEther(String(config.bribeAmount)) : 0n;
911
346
  // ✅ 规划 Nonce(贿赂和利润都由卖方发送)
912
347
  // 卖方: [贿赂(可选)] → [卖出] → [利润(可选)]
913
348
  let bribeNonce;
914
349
  let sellNonce;
915
350
  let buyerNonces;
916
351
  // ✅ 如果前端传入了 startNonces,直接使用(性能优化)
917
- if (startNonces && startNonces.length >= (1 + buyers.length)) {
352
+ if (startNonces && startNonces.length >= 1 + buyers.length) {
918
353
  let sellerIdx = 0;
919
354
  if (bribeAmount > 0n) {
920
355
  bribeNonce = startNonces[0] + sellerIdx++;
@@ -927,7 +362,7 @@ export async function pancakeBatchSwapMerkle(params) {
927
362
  bribeNonce = await nonceManager.getNextNonce(seller);
928
363
  }
929
364
  sellNonce = await nonceManager.getNextNonce(seller);
930
- buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
365
+ buyerNonces = await Promise.all(buyers.map((buyer) => nonceManager.getNextNonce(buyer)));
931
366
  }
932
367
  // ✅ 贿赂交易放在首位(由卖方发送)
933
368
  let bribeTx = null;
@@ -939,7 +374,7 @@ export async function pancakeBatchSwapMerkle(params) {
939
374
  gasPrice,
940
375
  gasLimit: BRIBE_GAS_LIMIT,
941
376
  chainId: context.chainId,
942
- type: txType
377
+ type: txType,
943
378
  });
944
379
  }
945
380
  // ✅ 修复:利润计算应基于 BNB 数量,不是 ERC20 数量
@@ -957,7 +392,9 @@ export async function pancakeBatchSwapMerkle(params) {
957
392
  }
958
393
  // 计算利润 nonce
959
394
  const profitNonce = profitAmount > 0n
960
- ? (startNonces && startNonces.length >= 1 ? sellNonce + 1 : await nonceManager.getNextNonce(seller))
395
+ ? startNonces && startNonces.length >= 1
396
+ ? sellNonce + 1
397
+ : await nonceManager.getNextNonce(seller)
961
398
  : undefined;
962
399
  nonceManager.clearTemp();
963
400
  // ✅ 并行签名所有交易
@@ -969,7 +406,7 @@ export async function pancakeBatchSwapMerkle(params) {
969
406
  gasLimit: finalGasLimit,
970
407
  gasPrice,
971
408
  chainId: context.chainId,
972
- type: txType
409
+ type: txType,
973
410
  });
974
411
  // 2. 并行签名所有买入交易
975
412
  const signedBuyPromises = buyers.map((buyer, i) => buyer.signTransaction({
@@ -979,13 +416,10 @@ export async function pancakeBatchSwapMerkle(params) {
979
416
  gasLimit: finalGasLimit,
980
417
  gasPrice,
981
418
  chainId: context.chainId,
982
- type: txType
419
+ type: txType,
983
420
  }));
984
421
  // 3. 等待所有签名完成
985
- const [signedSell, ...signedBuys] = await Promise.all([
986
- signedSellPromise,
987
- ...signedBuyPromises
988
- ]);
422
+ const [signedSell, ...signedBuys] = await Promise.all([signedSellPromise, ...signedBuyPromises]);
989
423
  // 4. 按顺序组装交易数组:贿赂 → 卖出 → 买入
990
424
  const signedTransactions = [];
991
425
  if (bribeTx)
@@ -1004,7 +438,7 @@ export async function pancakeBatchSwapMerkle(params) {
1004
438
  gasPrice,
1005
439
  chainId: context.chainId,
1006
440
  txType,
1007
- startNonce: profitNonce
441
+ startNonce: profitNonce,
1008
442
  });
1009
443
  signedTransactions.push(...profitHopResult.signedTransactions);
1010
444
  profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
@@ -1014,13 +448,11 @@ export async function pancakeBatchSwapMerkle(params) {
1014
448
  profitHopWallets, // ✅ 导出利润多跳钱包
1015
449
  metadata: {
1016
450
  sellerAddress: seller.address,
1017
- buyerAddresses: buyers.map(b => b.address),
451
+ buyerAddresses: buyers.map((b) => b.address),
1018
452
  sellAmount: ethers.formatUnits(sellAmountWei, decimals),
1019
- buyAmounts: buyAmountsWei.map(amt => useNativeToken
1020
- ? ethers.formatEther(amt)
1021
- : ethers.formatUnits(amt, quoteTokenDecimals)),
1022
- profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined
1023
- }
453
+ buyAmounts: buyAmountsWei.map((amt) => useNativeToken ? ethers.formatEther(amt) : ethers.formatUnits(amt, quoteTokenDecimals)),
454
+ profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined,
455
+ },
1024
456
  };
1025
457
  }
1026
458
  /**
@@ -1039,7 +471,7 @@ export async function pancakeBatchSwapMerkle(params) {
1039
471
  */
1040
472
  export async function pancakeQuickBatchSwapMerkle(params) {
1041
473
  const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, disperseHopCount = 0, // ✅ 转账多跳数(默认0=直接转账)
1042
- startNonces // ✅ 可选:前端预获取的 nonces
474
+ startNonces, // ✅ 可选:前端预获取的 nonces
1043
475
  } = params;
1044
476
  // ✅ 判断是否使用原生代币
1045
477
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
@@ -1085,7 +517,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1085
517
  }
1086
518
  const context = createPancakeContext(config);
1087
519
  const seller = new Wallet(sellerPrivateKey, context.provider);
1088
- const buyers = buyerPrivateKeys.map(pk => new Wallet(pk, context.provider));
520
+ const buyers = buyerPrivateKeys.map((pk) => new Wallet(pk, context.provider));
1089
521
  // ✅ 校验卖出路径输出代币是否匹配
1090
522
  let sellOutputToken;
1091
523
  if (routeParams.routeType === 'v2') {
@@ -1125,14 +557,14 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1125
557
  // ✅ 并行获取 gasPrice 和卖出数量
1126
558
  const [gasPrice, sellAmountResult] = await Promise.all([
1127
559
  getGasPrice(context.provider, config),
1128
- calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage)
560
+ calculateSellAmount(context.provider, tokenAddress, seller.address, sellAmount, sellPercentage),
1129
561
  ]);
1130
562
  const { amount: sellAmountWei, decimals } = sellAmountResult;
1131
563
  const quoteResult = await quoteSellOutput({
1132
564
  routeParams,
1133
565
  sellAmountWei,
1134
566
  provider: context.provider,
1135
- v2RouterAddress: config.v2RouterAddress
567
+ v2RouterAddress: config.v2RouterAddress,
1136
568
  });
1137
569
  const estimatedOutput = quoteResult.estimatedBNBOut;
1138
570
  // ✅ 计算利润(万分之六)
@@ -1152,9 +584,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1152
584
  let transferAmountsWei;
1153
585
  if (buyerAmounts && buyerAmounts.length === buyers.length) {
1154
586
  // 数量模式
1155
- transferAmountsWei = buyerAmounts.map(amt => useNativeToken
1156
- ? ethers.parseEther(amt)
1157
- : ethers.parseUnits(amt, quoteTokenDecimals));
587
+ transferAmountsWei = buyerAmounts.map((amt) => useNativeToken ? ethers.parseEther(amt) : ethers.parseUnits(amt, quoteTokenDecimals));
1158
588
  const totalTransfer = transferAmountsWei.reduce((a, b) => a + b, 0n);
1159
589
  if (totalTransfer > distributableAmount) {
1160
590
  const formatted = useNativeToken
@@ -1165,7 +595,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1165
595
  }
1166
596
  else if (buyerRatios && buyerRatios.length === buyers.length) {
1167
597
  // 比例模式
1168
- transferAmountsWei = buyerRatios.map(ratio => {
598
+ transferAmountsWei = buyerRatios.map((ratio) => {
1169
599
  return (distributableAmount * BigInt(Math.round(ratio * 10000))) / 10000n;
1170
600
  });
1171
601
  }
@@ -1173,22 +603,22 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1173
603
  throw new Error('必须提供 buyerRatios 或 buyerAmounts');
1174
604
  }
1175
605
  // ✅ 获取贿赂金额
1176
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0
1177
- ? ethers.parseEther(String(config.bribeAmount))
1178
- : 0n;
606
+ const bribeAmount = config.bribeAmount && config.bribeAmount > 0 ? ethers.parseEther(String(config.bribeAmount)) : 0n;
1179
607
  // ✅ 验证主钱包余额
1180
608
  const sellerBalance = await seller.provider.getBalance(seller.address);
1181
609
  let sellerGasCost;
1182
610
  let sellerRequired;
1183
611
  if (useNativeToken) {
1184
612
  // BNB 模式:贿赂(BRIBE) + 卖出(gasLimit) + N个原生转账(BRIBE each) + 利润(BRIBE)
1185
- 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);
1186
615
  sellerRequired = bribeAmount + sellerGasCost;
1187
616
  }
1188
617
  else {
1189
618
  // ERC20 模式:子钱包已预留 BNB,不需要主钱包转 Gas
1190
619
  // 卖方 Gas: 贿赂(BRIBE) + 卖出(gasLimit) + N个ERC20转账(65000 each) + 利润(BRIBE)
1191
- 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);
1192
622
  sellerRequired = bribeAmount + sellerGasCost;
1193
623
  }
1194
624
  if (sellerBalance < sellerRequired) {
@@ -1196,9 +626,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1196
626
  }
1197
627
  // ==================== 规划 Nonce ====================
1198
628
  // ✅ 如果前端传入了 startNonces,直接使用(性能优化)
1199
- let sellerNonce = startNonces && startNonces.length > 0
1200
- ? startNonces[0]
1201
- : await nonceManager.getNextNonce(seller);
629
+ let sellerNonce = startNonces && startNonces.length > 0 ? startNonces[0] : await nonceManager.getNextNonce(seller);
1202
630
  const deadline = Math.floor(Date.now() / 1000) + 600;
1203
631
  // ==================== 1. 贿赂交易 ====================
1204
632
  let bribeTx = null;
@@ -1210,7 +638,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1210
638
  gasPrice,
1211
639
  gasLimit: BRIBE_GAS_LIMIT,
1212
640
  chainId: context.chainId,
1213
- type: txType
641
+ type: txType,
1214
642
  });
1215
643
  }
1216
644
  // ==================== 2. 卖出交易 ====================
@@ -1232,15 +660,17 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1232
660
  else if (routeParams.routeType === 'v3-single') {
1233
661
  const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
1234
662
  const v3RouterSeller = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, seller);
1235
- const sellSwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [{
663
+ const sellSwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [
664
+ {
1236
665
  tokenIn: v3TokenIn,
1237
666
  tokenOut: v3TokenOut,
1238
667
  fee: v3Fee,
1239
668
  recipient: useNativeToken ? PANCAKE_V3_ROUTER_ADDRESS : seller.address,
1240
669
  amountIn: sellAmountWei,
1241
670
  amountOutMinimum: 0n,
1242
- sqrtPriceLimitX96: 0n
1243
- }]);
671
+ sqrtPriceLimitX96: 0n,
672
+ },
673
+ ]);
1244
674
  if (useNativeToken) {
1245
675
  // 原生代币:需要 unwrap WBNB
1246
676
  const sellUnwrapData = v3RouterIface2.encodeFunctionData('unwrapWETH9', [0n, seller.address]);
@@ -1261,15 +691,15 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1261
691
  gasLimit: finalGasLimit,
1262
692
  gasPrice,
1263
693
  chainId: context.chainId,
1264
- type: txType
694
+ type: txType,
1265
695
  });
1266
696
  // ==================== 3. 转账交易(支持多跳)====================
1267
697
  const buyerGasCost = gasPrice * finalGasLimit;
1268
698
  // ✅ 生成多跳路径
1269
- const hopPaths = generateDisperseHopPaths(buyers.map(b => b.address), disperseHopCount, context.provider);
699
+ const hopPaths = generateDisperseHopPaths(buyers.map((b) => b.address), disperseHopCount, context.provider);
1270
700
  // 收集所有中间钱包信息
1271
701
  const allHopWallets = [];
1272
- hopPaths.forEach(path => {
702
+ hopPaths.forEach((path) => {
1273
703
  allHopWallets.push(...path.hopWalletsInfo);
1274
704
  });
1275
705
  let transferTxs;
@@ -1287,17 +717,14 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1287
717
  gasPrice,
1288
718
  gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
1289
719
  chainId: context.chainId,
1290
- type: txType
720
+ type: txType,
1291
721
  });
1292
722
  }));
1293
723
  }
1294
724
  else {
1295
725
  const erc20Interface = new ethers.Interface(ERC20_ABI);
1296
726
  transferTxs = await Promise.all(buyers.map((buyer, i) => {
1297
- const transferData = erc20Interface.encodeFunctionData('transfer', [
1298
- buyer.address,
1299
- transferAmountsWei[i]
1300
- ]);
727
+ const transferData = erc20Interface.encodeFunctionData('transfer', [buyer.address, transferAmountsWei[i]]);
1301
728
  return seller.signTransaction({
1302
729
  to: quoteToken,
1303
730
  data: transferData,
@@ -1306,7 +733,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1306
733
  gasPrice,
1307
734
  gasLimit: ERC20_TRANSFER_GAS,
1308
735
  chainId: context.chainId,
1309
- type: txType
736
+ type: txType,
1310
737
  });
1311
738
  }));
1312
739
  }
@@ -1350,7 +777,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1350
777
  // ✅ 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
1351
778
  const buyerNonces = startNonces && startNonces.length > 1
1352
779
  ? startNonces.slice(1)
1353
- : await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
780
+ : await Promise.all(buyers.map((buyer) => nonceManager.getNextNonce(buyer)));
1354
781
  const signedBuys = await Promise.all(buyers.map(async (buyer, i) => {
1355
782
  const buyAmount = transferAmountsWei[i];
1356
783
  // ✅ ERC20 模式:value = 0(通过代币授权支付)
@@ -1370,15 +797,17 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1370
797
  else if (routeParams.routeType === 'v3-single') {
1371
798
  const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
1372
799
  const v3RouterBuyer = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, buyer);
1373
- const buySwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [{
800
+ const buySwapData = v3RouterIface2.encodeFunctionData('exactInputSingle', [
801
+ {
1374
802
  tokenIn: v3TokenOut,
1375
803
  tokenOut: v3TokenIn,
1376
804
  fee: v3Fee,
1377
805
  recipient: buyer.address,
1378
806
  amountIn: buyAmount,
1379
807
  amountOutMinimum: 0n,
1380
- sqrtPriceLimitX96: 0n
1381
- }]);
808
+ sqrtPriceLimitX96: 0n,
809
+ },
810
+ ]);
1382
811
  buyUnsigned = await v3RouterBuyer.multicall.populateTransaction(deadline, [buySwapData], { value: buyValue });
1383
812
  }
1384
813
  else {
@@ -1391,7 +820,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1391
820
  gasLimit: finalGasLimit,
1392
821
  gasPrice,
1393
822
  chainId: context.chainId,
1394
- type: txType
823
+ type: txType,
1395
824
  });
1396
825
  }));
1397
826
  nonceManager.clearTemp();
@@ -1416,7 +845,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1416
845
  gasPrice,
1417
846
  chainId: context.chainId,
1418
847
  txType,
1419
- startNonce: sellerNonce++
848
+ startNonce: sellerNonce++,
1420
849
  });
1421
850
  signedTransactions.push(...profitHopResult.signedTransactions);
1422
851
  profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
@@ -1428,18 +857,16 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1428
857
  profitHopWallets, // ✅ 返回利润多跳钱包
1429
858
  metadata: {
1430
859
  sellerAddress: seller.address,
1431
- buyerAddresses: buyers.map(b => b.address),
860
+ buyerAddresses: buyers.map((b) => b.address),
1432
861
  sellAmount: ethers.formatUnits(sellAmountWei, decimals),
1433
862
  estimatedOutput: useNativeToken
1434
863
  ? ethers.formatEther(estimatedOutput)
1435
864
  : ethers.formatUnits(estimatedOutput, quoteTokenDecimals),
1436
- transferAmounts: transferAmountsWei.map(amt => useNativeToken
1437
- ? ethers.formatEther(amt)
1438
- : ethers.formatUnits(amt, quoteTokenDecimals)),
865
+ transferAmounts: transferAmountsWei.map((amt) => useNativeToken ? ethers.formatEther(amt) : ethers.formatUnits(amt, quoteTokenDecimals)),
1439
866
  profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined,
1440
867
  useNativeToken,
1441
- disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined // ✅ 返回多跳数
1442
- }
868
+ disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined, // ✅ 返回多跳数
869
+ },
1443
870
  };
1444
871
  }
1445
872
  /**
@@ -1450,7 +877,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1450
877
  * - ✅ 正确处理 nonce:同一钱包在多轮中使用时 nonce 自动递增
1451
878
  */
1452
879
  export async function pancakeCrossSwapMerkle(params) {
1453
- 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;
1454
881
  if (sellerPrivateKeys.length === 0) {
1455
882
  throw new Error('至少需要一个卖方');
1456
883
  }
@@ -1464,8 +891,8 @@ export async function pancakeCrossSwapMerkle(params) {
1464
891
  const context = createPancakeContext(config);
1465
892
  const nonceManager = new NonceManager(context.provider);
1466
893
  // ✅ 预先获取所有钱包的初始 nonce
1467
- const allSellerWallets = sellerPrivateKeys.map(pk => new Wallet(pk, context.provider));
1468
- 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));
1469
896
  // 使用 Map 去重(同一私钥可能出现多次)
1470
897
  const addressToNonce = new Map();
1471
898
  // 获取所有卖方 nonce
@@ -1492,9 +919,7 @@ export async function pancakeCrossSwapMerkle(params) {
1492
919
  // 判断是否使用原生代币
1493
920
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
1494
921
  // 获取贿赂金额
1495
- const bribeAmount = config.bribeAmount && config.bribeAmount > 0
1496
- ? ethers.parseEther(String(config.bribeAmount))
1497
- : 0n;
922
+ const bribeAmount = config.bribeAmount && config.bribeAmount > 0 ? ethers.parseEther(String(config.bribeAmount)) : 0n;
1498
923
  const hasBribe = bribeAmount > 0n;
1499
924
  for (let i = 0; i < sellerPrivateKeys.length; i++) {
1500
925
  const sellerPk = sellerPrivateKeys[i];
@@ -1512,7 +937,7 @@ export async function pancakeCrossSwapMerkle(params) {
1512
937
  // ✅ 获取卖方当前 nonce
1513
938
  const sellerNonce = addressToNonce.get(sellerWallet.address);
1514
939
  // ✅ 获取并更新买方 nonces(每个买方本轮需要 1 个 nonce)
1515
- const roundBuyerNonces = roundBuyerWallets.map(w => {
940
+ const roundBuyerNonces = roundBuyerWallets.map((w) => {
1516
941
  const nonce = addressToNonce.get(w.address);
1517
942
  addressToNonce.set(w.address, nonce + 1); // 每个买方用 1 个 nonce
1518
943
  return nonce;
@@ -1552,7 +977,7 @@ export async function pancakeCrossSwapMerkle(params) {
1552
977
  quoteToken,
1553
978
  quoteTokenDecimals,
1554
979
  disperseHopCount,
1555
- startNonces // ✅ 传入预计算的 nonces
980
+ startNonces, // ✅ 传入预计算的 nonces
1556
981
  });
1557
982
  // ✅ 更新卖方 nonce(使用精确计算的值)
1558
983
  addressToNonce.set(sellerWallet.address, sellerNonce + sellerNonceConsumed);
@@ -1566,7 +991,7 @@ export async function pancakeCrossSwapMerkle(params) {
1566
991
  sellerAddress: res.metadata?.sellerAddress || '',
1567
992
  buyerAddresses: res.metadata?.buyerAddresses || roundBuyerPks.map(() => ''),
1568
993
  sellAmount,
1569
- bundleHash: undefined
994
+ bundleHash: undefined,
1570
995
  });
1571
996
  }
1572
997
  nonceManager.clearTemp();
@@ -1574,6 +999,6 @@ export async function pancakeCrossSwapMerkle(params) {
1574
999
  signedTransactions: allSigned,
1575
1000
  rounds,
1576
1001
  disperseHopWallets: allDisperse.length > 0 ? allDisperse : undefined,
1577
- profitHopWallets: allProfit.length > 0 ? allProfit : undefined
1002
+ profitHopWallets: allProfit.length > 0 ? allProfit : undefined,
1578
1003
  };
1579
1004
  }